// ─── Application Event Registry (IoC Pattern) ────────────────── /** * Open interface for application event registration. * * **This interface is intentionally empty at the core level.** * * Each consuming app (`apps/web`, `apps/landing`, etc.) is responsible * for registering its own events using TypeScript Declaration Merging * (Module Augmentation). This enforces Inversion of Control: * * - The core package provides the **tool** (bus, hooks, helpers). * - The app provides the **contract** (event names and payloads). * * ## How to register events * * Create a `.d.ts` file anywhere in your app's `src/` folder: * * ```ts * // apps/web/src/types/events.d.ts * declare module '@repo/core-events' { * interface AppEventRegistry { * 'DOMAIN:EVENT_NAME': { payload: string }; * } * } * ``` * * TypeScript will automatically merge all augmentations into a single * `AppEventRegistry` interface, giving you full autocomplete and * compile-time type safety across the entire app — without the core * package knowing anything about your events. * * **Naming convention**: `DOMAIN:ACTION` in `SCREAMING_SNAKE_CASE`. */ // eslint-disable-next-line @typescript-eslint/no-empty-interface export interface AppEventRegistry {} /** * Resolved event map consumed by `mitt` and all public APIs. * * This type alias bridges the open `AppEventRegistry` interface * (which supports declaration merging) to the `Record` * constraint that `mitt` requires. * * You should never reference this type directly in consumer code. * Use `AppEventRegistry` for augmentation and let the core handle the rest. */ export type AppEvents = { [K in keyof AppEventRegistry]: AppEventRegistry[K]; };