68 lines
2.0 KiB
TypeScript
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);
|
|
}
|