|
|
|
@@ -1,74 +1,116 @@
|
|
|
|
|
# @repo/core-events
|
|
|
|
|
|
|
|
|
|
[← Back to Root](../../README.md)
|
|
|
|
|
|
|
|
|
|
## Overview
|
|
|
|
|
# Event Bus (`@repo/core-events`)
|
|
|
|
|
|
|
|
|
|
`@repo/core-events` is the **decoupled Nervous System** of the ERP. It provides a highly performant, strictly typed Event Bus powered by `mitt` and React hooks.
|
|
|
|
|
The Global Pub/Sub & Hardware Integration Blueprint.
|
|
|
|
|
|
|
|
|
|
**This package is a pure tool.** It ships zero application-specific events. Each consuming app (`apps/web`, `apps/landing`, etc.) registers its own events autonomously using TypeScript Declaration Merging — the same Inversion of Control pattern used by `@repo/core-api`'s `createHttpClient` factory.
|
|
|
|
|
|
|
|
|
|
By routing communication through a centralized event bus, we achieve:
|
|
|
|
|
- **App Autonomy**: The core defines the bus. The app defines the contract. No circular knowledge.
|
|
|
|
|
- **Zero Coupling**: Publishers and subscribers don't need to import or know about each other.
|
|
|
|
|
- **Extreme Performance**: Components can subscribe to high-frequency data streams (like WebSockets) and update their own local state *without* triggering massive React tree re-renders.
|
|
|
|
|
- **Memory Safety**: The provided `useAppEvent` hook automatically handles subscription cleanup on component unmount, preventing the most common source of memory leaks in SPA architectures.
|
|
|
|
|
> This module provides a strictly-typed, global event bus for the monorepo ecosystem. It decouples cross-component communication and manages real-time hardware signals (such as printers and POS peripherals), ensuring a reactive and memory-safe architecture across all applications.
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Architecture
|
|
|
|
|
## 🧠 System Overview
|
|
|
|
|
|
|
|
|
|
`@repo/core-events` is the **decoupled Nervous System** of the ERP. It provides a highly performant, strictly-typed Event Bus powered by `mitt` and custom React hooks.
|
|
|
|
|
|
|
|
|
|
**This package is a pure tool.** It ships zero application-specific events. Each consuming app (`apps/web`, `apps/desktop`, etc.) registers its own events autonomously using **TypeScript Declaration Merging** — the exact same Inversion of Control (IoC) pattern utilized by our `@repo/core-api` factory and `@repo/core-storage` engine.
|
|
|
|
|
|
|
|
|
|
### Architectural Topology
|
|
|
|
|
|
|
|
|
|
### 1. Conceptual Topology: The Pub/Sub Data Flow
|
|
|
|
|
This diagram illustrates the high-level concept of our decoupled architecture, demonstrating how application-specific types merge into the core bus.
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
graph LR
|
|
|
|
|
%% ─── Styling Definitions (Dark-Mode Friendly Enterprise Palette) ───
|
|
|
|
|
classDef appEntity fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e3a8a
|
|
|
|
|
classDef coreEntity fill:#e2e8f0,stroke:#64748b,stroke-width:2px,color:#0f172a
|
|
|
|
|
classDef busEntity fill:#10b981,stroke:#047857,stroke-width:2px,color:#ffffff
|
|
|
|
|
|
|
|
|
|
%% ─── Nodes ───
|
|
|
|
|
TYPES[[App-Specific Event Types]]
|
|
|
|
|
PUB([Publisher Component])
|
|
|
|
|
BUS{Global Event Bus 'mitt'}
|
|
|
|
|
SUB([Subscriber Component])
|
|
|
|
|
|
|
|
|
|
%% ─── Flow ───
|
|
|
|
|
TYPES -.->|Declaration Merging| BUS
|
|
|
|
|
PUB ===>|emit 'event', payload| BUS
|
|
|
|
|
BUS ===>|useAppEvent 'event'| SUB
|
|
|
|
|
|
|
|
|
|
%% ─── Apply Styles ───
|
|
|
|
|
class TYPES,PUB,SUB appEntity;
|
|
|
|
|
class BUS busEntity;
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### 2. System Architecture: Core Engine vs. App Autonomy
|
|
|
|
|
This detailed diagram shows the exact boundaries between the @repo/core-events engine and the consuming application, highlighting real-world publishers (e.g., Cashier UI) and subscribers.
|
|
|
|
|
|
|
|
|
|
```mermaid
|
|
|
|
|
graph TD
|
|
|
|
|
%% ─── Styling Definitions (Dark-Mode Friendly Enterprise Palette) ───
|
|
|
|
|
classDef appComponent fill:#dbeafe,stroke:#3b82f6,stroke-width:2px,color:#1e3a8a
|
|
|
|
|
classDef injection fill:#f59e0b,stroke:#b45309,stroke-width:2px,color:#ffffff
|
|
|
|
|
classDef registry fill:#10b981,stroke:#047857,stroke-width:2px,color:#ffffff
|
|
|
|
|
classDef coreBus fill:#6366f1,stroke:#4338ca,stroke-width:2px,color:#ffffff
|
|
|
|
|
|
|
|
|
|
%% ─── Subgraphs ───
|
|
|
|
|
subgraph Core ["@repo/core-events (Pure Tool)"]
|
|
|
|
|
R["AppEventRegistry<br/>(empty interface)"]
|
|
|
|
|
T["AppEvents = mapped type"]
|
|
|
|
|
E((Event Bus<br/>mitt))
|
|
|
|
|
H[useAppEvent / usePublishEvent]
|
|
|
|
|
R --> T --> E
|
|
|
|
|
E --> H
|
|
|
|
|
R[AppEventRegistry Empty Interface]
|
|
|
|
|
T[AppEvents Mapped Type]
|
|
|
|
|
E((Global Event Bus mitt))
|
|
|
|
|
H[Hooks: useAppEvent / usePublishEvent]
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
subgraph Apps ["apps/web (App Autonomy)"]
|
|
|
|
|
D["events.d.ts<br/>declare module augmentation"]
|
|
|
|
|
A[Cashier UI]
|
|
|
|
|
B[Profile Settings]
|
|
|
|
|
C[WebSocket Client]
|
|
|
|
|
X[Electron IPC Bridge]
|
|
|
|
|
Y[IndexedDB Sync]
|
|
|
|
|
Z[Stock Grid Row]
|
|
|
|
|
D[[events.d.ts Declaration Merging]]
|
|
|
|
|
|
|
|
|
|
%% Publishers
|
|
|
|
|
A([Cashier UI])
|
|
|
|
|
B([Profile Settings])
|
|
|
|
|
C([WebSocket Client])
|
|
|
|
|
|
|
|
|
|
%% Subscribers
|
|
|
|
|
X([Electron IPC Bridge])
|
|
|
|
|
Y([IndexedDB Sync])
|
|
|
|
|
Z([Stock Grid Row])
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
D -. "merges into" .-> R
|
|
|
|
|
%% ─── Flow & Relationships ───
|
|
|
|
|
D -.->|Augments| R
|
|
|
|
|
R ---> T ---> E
|
|
|
|
|
E ---> H
|
|
|
|
|
|
|
|
|
|
A -- "DEVICE:PRINT_RECEIPT" --> E
|
|
|
|
|
B -- "AUTH:PROFILE_UPDATED" --> E
|
|
|
|
|
C -- "WS:STOCK_UPDATE" --> E
|
|
|
|
|
%% Emitting Events
|
|
|
|
|
A ===>|DEVICE:PRINT_RECEIPT| E
|
|
|
|
|
B ===>|AUTH:PROFILE_UPDATED| E
|
|
|
|
|
C ===>|WS:STOCK_UPDATE| E
|
|
|
|
|
|
|
|
|
|
E -.-> X
|
|
|
|
|
E -.-> Y
|
|
|
|
|
E -.-> Z
|
|
|
|
|
%% Subscribing to Events
|
|
|
|
|
E -.->|Triggers| X
|
|
|
|
|
E -.->|Triggers| Y
|
|
|
|
|
E -.->|Triggers| Z
|
|
|
|
|
|
|
|
|
|
%% Styling Subgraphs (Backgrounds)
|
|
|
|
|
style Core fill:#f8f9fa,stroke:#ced4da,stroke-width:2px,color:#495057
|
|
|
|
|
style Apps fill:#e7f5ff,stroke:#74c0fc,stroke-width:2px,color:#1864ab
|
|
|
|
|
%% ─── Apply Styles ───
|
|
|
|
|
class A,B,C,X,Y,Z appComponent;
|
|
|
|
|
class D injection;
|
|
|
|
|
class R,T registry;
|
|
|
|
|
class E,H coreBus;
|
|
|
|
|
|
|
|
|
|
%% Styling Core Engine (Purple) & Contracts (Green)
|
|
|
|
|
style R fill:#20c997,stroke:#089981,color:#fff
|
|
|
|
|
style T fill:#20c997,stroke:#089981,color:#fff
|
|
|
|
|
style E fill:#845ef7,stroke:#5f3dc4,color:#fff
|
|
|
|
|
style H fill:#845ef7,stroke:#5f3dc4,color:#fff
|
|
|
|
|
|
|
|
|
|
%% Styling App Injection (Orange) & Components (Blue)
|
|
|
|
|
style D fill:#fd7e14,stroke:#d9480f,color:#fff
|
|
|
|
|
style A fill:#339af0,stroke:#1864ab,color:#fff
|
|
|
|
|
style B fill:#339af0,stroke:#1864ab,color:#fff
|
|
|
|
|
style C fill:#339af0,stroke:#1864ab,color:#fff
|
|
|
|
|
style X fill:#339af0,stroke:#1864ab,color:#fff
|
|
|
|
|
style Y fill:#339af0,stroke:#1864ab,color:#fff
|
|
|
|
|
style Z fill:#339af0,stroke:#1864ab,color:#fff
|
|
|
|
|
%% ─── Subgraph Backgrounds (Transparent for Native GitHub Support) ───
|
|
|
|
|
style Core fill:transparent,stroke:#94a3b8,stroke-width:2px,stroke-dasharray: 5 5
|
|
|
|
|
style Apps fill:transparent,stroke:#3b82f6,stroke-width:2px,stroke-dasharray: 5 5
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Core Value Proposition
|
|
|
|
|
|
|
|
|
|
By routing communication through this centralized event bus, we achieve:
|
|
|
|
|
|
|
|
|
|
* **App Autonomy**: The core defines the engine. The app defines the contract. There is zero circular dependency.
|
|
|
|
|
* **Zero Coupling**: Publishers and subscribers do not need to import, reference, or know about each other's existence.
|
|
|
|
|
* **Extreme Performance**: Components can subscribe to high-frequency data streams (like WebSockets or hardware signals) and update their own local state *without* triggering massive React tree re-renders.
|
|
|
|
|
* **Memory Safety**: The provided `useAppEvent` hook automatically handles subscription cleanup on component unmount, proactively preventing the most common source of memory leaks in Single Page Architectures (SPAs).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Defining Events (Module Augmentation)
|
|
|
|
|