import { randomUUID } from "crypto"; import { logger } from "../logging/logger"; interface Event { id: string type: string occurredAt: string payload?: Record } type EventHandler = (event: Event) => void | Promise; class EventBus { private handlers: Map = new Map(); /** * Register event listener * @param type * @param handler */ on(type: string, handler: EventHandler) { const handlers = this.handlers.get(type) ?? []; handlers.push(handler); this.handlers.set(type, handlers); } /** * Emit event of given type * @param type * @param payload */ async emit(type: string, payload?: Record) { const event: Event = { id: randomUUID(), type, occurredAt: new Date().toISOString(), payload } const handlers = this.handlers.get(type) ?? [] for (const h of handlers) { try { await h(event) } catch (error) { logger.error('app', 'Event handler failed', { type: event.type, id: event.id, error: error instanceof Error ? error.message : String(error), }) } } } } export const bus = new EventBus();