refactor: decouple core-events registry by implementing consumer-side TypeScript module augmentation and reorganizing showcase demos

This commit is contained in:
Firman Ramdhani
2026-05-28 11:51:43 +07:00
parent 1c6d76bf4f
commit df229c9984
13 changed files with 264 additions and 140 deletions
@@ -36,7 +36,7 @@ interface StorageSyncListenerProps {
* ```
*
* 3. For bidirectional sync (storage event), consider adding a
* `STORAGE:PROFILE_LOADED` event to `AppEvents` that fires when
* `STORAGE:PROFILE_LOADED` event to `AppEventRegistry` that fires when
* the app reads the profile from IndexedDB on boot.
*
* 4. Error handling: In production, wrap the `setItem` call in a
@@ -9,11 +9,11 @@ import {
} from '@repo/ui/components';
// ── Showcase Components ──────────────────────────────────────────
import { CashierUI } from './printer/CashierUI';
import { PrinterListener } from './printer/PrinterListener';
import { LiveStockGrid } from './stock-grid/LiveStockGrid';
import { ProfileSettingsUI } from './auth-sync/ProfileSettingsUI';
import { StorageSyncListener } from './auth-sync/StorageSyncListener';
import { CashierUI } from './printer/cashier.ui';
import { PrinterListener } from './printer/printer.listener';
import { LiveStockGrid } from './stock-grid/live-stock-grid.ui';
import { ProfileSettingsUI } from './auth-sync/profile-settings.ui';
import { StorageSyncListener } from './auth-sync/storage-sync.listener';
// ─── Events Demo Page ───────────────────────────────────────────
@@ -1,7 +1,7 @@
import { useEffect, useMemo, useRef, useState } from 'react';
import { Button, Group, Badge, Text, Stack } from '@repo/ui/components';
import { StockRow } from './StockRow';
import { generateStockIds, startMockWebSocket } from './MockWebSocket';
import { StockRow } from './stock-row.ui';
import { generateStockIds, startMockWebSocket } from './mock-websocket.service';
// ─── Constants ──────────────────────────────────────────────────
+76
View File
@@ -0,0 +1,76 @@
/**
* App-level event registry for `apps/web`.
*
* This file uses TypeScript Declaration Merging (Module Augmentation)
* to extend the open `AppEventRegistry` interface exported by
* `@repo/core-events`. This is the IoC pattern in action:
*
* - `@repo/core-events` provides the bus, hooks, and helpers (the tool).
* - `apps/web` defines which events exist and their payload shapes (the contract).
*
* The core package has zero knowledge of these events. If `apps/web`
* is removed from the monorepo, the core package remains unchanged.
*
* **Adding new events**: Simply add new entries to `AppEventRegistry`
* below. TypeScript will automatically provide autocomplete and
* type safety across every `publish()` / `useAppEvent()` call in
* the web app.
*
* @see packages/core-events/src/events.registry.ts
*/
// This import turns this file from an ambient declaration into a
// module augmentation. Without it, `declare module` would REPLACE
// the module signature instead of merging into it.
import type {} from '@repo/core-events';
declare module '@repo/core-events' {
// ─── Payload Types ──────────────────────────────────────────
interface ReceiptItem {
name: string;
qty: number;
price: number;
}
interface PrintReceiptPayload {
receiptId: string;
items: ReceiptItem[];
total: number;
cashierName: string;
timestamp: number;
}
interface StockUpdatePayload {
id: string;
price: number;
change: number;
volume: number;
}
interface ProfileUpdatedPayload {
id: string;
name: string;
email: string;
avatar: string;
updatedAt: number;
}
// ─── Event Registry ─────────────────────────────────────────
interface AppEventRegistry {
// ── 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 };
}
}