export class EventEmitter { #listeners = new Map(); on(event, listener) { if (!this.#listeners.has(event)) { this.#listeners.set(event, new Set()); } this.#listeners.get(event).add(listener); return () => this.off(event, listener); // returns unsubscribe fn } once(event, listener) { const wrapper = (...args) => { listener(...args); this.off(event, wrapper); }; return this.on(event, wrapper); } off(event, listener) { this.#listeners.get(event)?.delete(listener); return this; } emit(event, ...args) { this.#listeners.get(event)?.forEach(l => l(...args)); return this; } clear(event) { if (event) this.#listeners.delete(event); else this.#listeners.clear(); return this; } }