import mitt from 'mitt'; import type { AppEvents } from './events.registry'; // ─── Singleton Event Bus ──────────────────────────────────────── /** * Application-wide event bus — a strictly typed `mitt` instance. * * Prefer the `publish` / `subscribe` helper functions or the React * hooks (`useAppEvent`, `usePublishEvent`) over using this directly. * Direct access is provided for edge cases like middleware or testing. * * @example * ```ts * import { eventBus } from '@repo/core-events'; * eventBus.on('APP:ERROR', (e) => console.error(e.message)); * ``` */ export const eventBus = mitt(); // ─── Type-Safe Helpers ────────────────────────────────────────── /** * Emit (publish) a typed event to all subscribers. * * @param type - The event name from `AppEvents`. * @param event - The payload matching that event's type. * * @example * ```ts * publish('AUTH:PROFILE_UPDATED', { id: '1', name: 'Firman', ... }); * ``` */ export function publish( type: K, event: AppEvents[K], ): void { eventBus.emit(type, event); } /** * Subscribe to a typed event. * * Returns an `unsubscribe` function — call it to remove the handler. * For React components, prefer `useAppEvent` which handles cleanup * automatically on unmount. * * @param type - The event name from `AppEvents`. * @param handler - Callback receiving the typed payload. * @returns A function that removes this subscription. * * @example * ```ts * const unsub = subscribe('WS:STOCK_UPDATE', (data) => { * console.log(data.price); // fully typed * }); * // Later: * unsub(); * ``` */ export function subscribe( type: K, handler: (event: AppEvents[K]) => void, ): () => void { eventBus.on(type, handler); return () => eventBus.off(type, handler); }