rich-domain
Version:
This package provide utils file and interfaces to assistant build a complex application with domain driving design
125 lines • 5.52 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const validate_context_event_name_util_1 = require("../utils/validate-context-event-name.util");
/**
* @description BrowserEventManager provides a global event management system
* utilizing the browser's Window and Event mechanisms. It allows subscribing to
* events that can be dispatched both synchronously and asynchronously, storing
* event states in sessionStorage and ensuring persistence across page reloads.
*/
class BrowserEventManager {
_window;
events;
static _instance;
/**
* @description Creates an instance of BrowserEventManager.
* Throws an error if the provided window object is not defined,
* as this manager is intended for browser environments.
* @param _window The browser's window object.
* @private
*/
constructor(_window) {
this._window = _window;
this.events = [];
if (typeof this._window === 'undefined') {
throw new Error('BrowserEventManager is not supported in the current environment.');
}
}
/**
* @description Returns a singleton instance of BrowserEventManager.
* If an instance has already been created, it returns the existing one.
* @param window The browser's window object.
* @returns The singleton instance of BrowserEventManager.
*/
static instance(window) {
if (BrowserEventManager._instance)
return BrowserEventManager._instance;
BrowserEventManager._instance = new BrowserEventManager(window);
return BrowserEventManager._instance;
}
/**
* @description Retrieves an event by name from the internal events list.
* @param eventName The name of the event to retrieve.
* @returns The matching EventType object if found, otherwise null.
* @private
*/
getEvent(eventName) {
const event = this.events.find((event) => event.eventName === eventName);
return event ?? null;
}
/**
* @description Subscribes a callback function to a given event.
* Ensures that the event subscription is persisted in sessionStorage,
* and cleans up the subscription when the browser unloads.
* @param eventName The name of the event to subscribe to.
* @param fn The callback function to execute when the event is dispatched.
*/
subscribe(eventName, fn) {
(0, validate_context_event_name_util_1.default)(eventName);
if (this.exists(eventName))
return;
this.events.push({ eventName, callback: fn });
this._window.sessionStorage.setItem('rich-domain-event:' + eventName, Date.now().toString());
this._window.addEventListener(eventName, fn);
this._window.addEventListener('beforeunload', () => {
this._window.sessionStorage.removeItem('rich-domain-event:' + eventName);
});
}
/**
* @description Checks if the given event name is already subscribed and persisted.
* @param eventName The name of the event.
* @returns `true` if the event is subscribed or exists in sessionStorage; otherwise, `false`.
*/
exists(eventName) {
const existsOnWindow = !!this._window.sessionStorage.getItem('rich-domain-event:' + eventName);
const existsInternal = !!this.events.find((evt) => evt.eventName === eventName);
return existsOnWindow || existsInternal;
}
/**
* @description Removes a subscribed event by name, cleaning up any related listeners and sessionStorage entries.
* @param eventName The name of the event to remove.
* @returns `true` if the event was found and removed successfully; otherwise, `false`.
*/
removerEvent(eventName) {
this._window.sessionStorage.removeItem('rich-domain-event:' + eventName);
const event = this.getEvent(eventName);
if (!event)
return false;
this.events = this.events.filter((ev) => ev.eventName !== eventName);
this._window.removeEventListener(eventName, event.callback);
return true;
}
/**
* @description Dispatches a custom event with the given name and optional arguments.
* Supports wildcard patterns by replacing `'*'` with `'.*'` to dispatch multiple matching events.
* @param eventName The name of the event to dispatch. Can include a wildcard `'*'`.
* @param args Additional arguments passed as the `detail` property of the dispatched event.
*/
dispatchEvent(eventName, ...args) {
(0, validate_context_event_name_util_1.default)(eventName);
// Handle wildcard events
if (eventName.includes('*')) {
const regex = new RegExp(eventName.replace('*', '.*'));
let i = 0;
while (this.events[i]) {
const localEventName = this.events[i].eventName;
const match = regex.test(localEventName);
if (match) {
this._window.dispatchEvent(new this._window.CustomEvent(localEventName, {
bubbles: true,
detail: args || []
}));
}
i++;
}
return;
}
// Dispatch a single event
this._window.dispatchEvent(new this._window.CustomEvent(eventName, {
bubbles: true,
detail: args || []
}));
}
}
exports.default = BrowserEventManager;
//# sourceMappingURL=browser-event-manager.js.map