refactor: decouple core-events registry by implementing consumer-side TypeScript module augmentation and reorganizing showcase demos
This commit is contained in:
@@ -1,82 +1,50 @@
|
||||
// ─── Event Payload Types ────────────────────────────────────────
|
||||
// ─── Application Event Registry (IoC Pattern) ──────────────────
|
||||
|
||||
/**
|
||||
* Receipt line item for the DEVICE:PRINT_RECEIPT event.
|
||||
*/
|
||||
export interface ReceiptItem {
|
||||
name: string;
|
||||
qty: number;
|
||||
price: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload for the DEVICE:PRINT_RECEIPT event.
|
||||
*/
|
||||
export interface PrintReceiptPayload {
|
||||
receiptId: string;
|
||||
items: ReceiptItem[];
|
||||
total: number;
|
||||
cashierName: string;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload for the WS:STOCK_UPDATE event.
|
||||
*/
|
||||
export interface StockUpdatePayload {
|
||||
id: string;
|
||||
price: number;
|
||||
change: number;
|
||||
volume: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Payload for the AUTH:PROFILE_UPDATED event.
|
||||
*/
|
||||
export interface ProfileUpdatedPayload {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
avatar: string;
|
||||
updatedAt: number;
|
||||
}
|
||||
|
||||
// ─── Application Event Registry ────────────────────────────────
|
||||
|
||||
/**
|
||||
* Central event registry for the entire application.
|
||||
* Open interface for application event registration.
|
||||
*
|
||||
* Every event in the system MUST be declared here with its payload
|
||||
* type. This provides:
|
||||
* **This interface is intentionally empty at the core level.**
|
||||
*
|
||||
* 1. **Compile-time safety** — typos in event names are caught by TS.
|
||||
* 2. **Payload validation** — publishers and subscribers agree on shape.
|
||||
* 3. **Discoverability** — `Ctrl+Click` any event to find its contract.
|
||||
* 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:
|
||||
*
|
||||
* **Naming convention**: `DOMAIN:ACTION` in `SCREAMING_SNAKE_CASE`.
|
||||
* - The core package provides the **tool** (bus, hooks, helpers).
|
||||
* - The app provides the **contract** (event names and payloads).
|
||||
*
|
||||
* **Extensibility**: To add events from feature modules, extend this
|
||||
* type using intersection:
|
||||
* ## How to register events
|
||||
*
|
||||
* Create a `.d.ts` file anywhere in your app's `src/` folder:
|
||||
*
|
||||
* ```ts
|
||||
* // In your feature module types:
|
||||
* type InventoryEvents = {
|
||||
* 'INVENTORY:LOW_STOCK': { productId: string; currentQty: number };
|
||||
* };
|
||||
* // Then merge into AppEvents in this file.
|
||||
* // 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<string, unknown>`
|
||||
* 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 = {
|
||||
// ── Device / Hardware ───────────────────────────────────────────
|
||||
'DEVICE:PRINT_RECEIPT': PrintReceiptPayload;
|
||||
|
||||
// ── WebSocket / Real-Time ───────────────────────────────────────
|
||||
'WS:STOCK_UPDATE': StockUpdatePayload;
|
||||
|
||||
// ── Auth / User ─────────────────────────────────────────────────
|
||||
'AUTH:PROFILE_UPDATED': ProfileUpdatedPayload;
|
||||
|
||||
// ── App Lifecycle ───────────────────────────────────────────────
|
||||
'APP:INITIALIZED': undefined;
|
||||
'APP:ERROR': { message: string; code?: string };
|
||||
[K in keyof AppEventRegistry]: AppEventRegistry[K];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user