export interface EventEmitterOptions { logger?: (log: string, payload?: EventPayload) => void; } export type EventHandler = | ((payload: EventPayload) => Promise | void) | null | undefined; export class EventEmitter { private handlerCount = 0; private handlers: Array> = []; private options?: EventEmitterOptions; constructor(options?: EventEmitterOptions) { this.options = options; } public get numberOfHandlers() { return this.handlers.filter(h => !!h).length; } public async emit(payload: EventPayload): Promise { const promises: Array> = []; this.options?.logger?.('emit', payload); for (const handler of this.handlers) { if (handler) { const res = handler(payload) as Promise; if (typeof res?.then === 'function') { promises.push(res); } } } await Promise.all(promises); } public on(handler: EventHandler): number { this.options?.logger?.('on'); this.handlers.push(handler); // eslint-disable-next-line no-plusplus return this.handlerCount++; } public off(handlerId: number) { this.delete(handlerId); } public delete(handlerId: number) { this.options?.logger?.('off'); this.handlers[handlerId] = null; } }