diff --git a/lib/core/Emitter.js b/lib/core/Emitter.js new file mode 100644 index 0000000..93f37ab --- /dev/null +++ b/lib/core/Emitter.js @@ -0,0 +1,69 @@ +class Emitter { + #listeners; + constructor() { + this.#listeners = {}; + } + + /** + * Registers a callback function for the specified event. + * + * @param {string} event - The name of the event. + * @param {Function} callback - The callback function to be executed when the event is triggered. + */ + on(event, callback) { + if (!this.#listeners[event]) { + this.#listeners[event] = []; + } + this.#listeners[event].push(callback); + } + + /** + * Removes an event listener callback for the specified event. + * If no callback is provided, removes all callbacks for the event. + * + * @param {string} event - The name of the event. + * @param {Function} [callback] - The callback function to be removed. + */ + off(event, callback = undefined) { + if (typeof event != 'string') { + throw new TypeError('event must be a string'); + return; + } + + if ( + !Array.isArray(this.#listeners[event]) || + this.#listeners[event].length === 0 + ) { + throw new TypeError( + `listener for \`${event}\` is not an array or empty` + ); + } + + if (!callback) { + this.#listeners[event] = undefined; + return; + } + + this.#listeners[event] = this.#listeners[event].filter( + (listener) => listener !== callback + ); + } + + /** + * Emits an event and invokes all registered listeners for that event. + * + * @param {string} event - The name of the event to emit. + * @param {...any} args - The arguments to pass to the event listeners. + */ + emit(event, ...args) { + if (!this.#listeners[event]) { + return; + } + + for (const callback of this.#listeners[event]) { + callback(this, ...args); + } + } +} + +export default Emitter;