Files
trackgo-fe/packages/core-events/src/event-bus.ts
T

68 lines
2.0 KiB
TypeScript

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<AppEvents>();
// ─── 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<K extends keyof AppEvents>(
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<K extends keyof AppEvents>(
type: K,
handler: (event: AppEvents[K]) => void,
): () => void {
eventBus.on(type, handler);
return () => eventBus.off(type, handler);
}