@yuva-devlab/events 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +144 -0
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# 📬 @yuva-devlab/events
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@yuva-devlab/events)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](https://www.typescriptlang.org)
|
|
6
|
+
|
|
7
|
+
> Standardized domain event envelopes, in-memory event bus, transactional outbox pattern, and distributed idempotency stores for reliable event-driven architecture across the DevLab platform.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- ✉️ **Standardized Event Envelopes (`DomainEvent`)**: Uniform structure with event ID, timestamp, topic, correlation context, and typed payload.
|
|
14
|
+
- 🚌 **In-Memory Event Bus (`InMemoryEventBus`)**: Decoupled publish/subscribe bus with asynchronous dispatch, wildcard topic matching, and error isolation.
|
|
15
|
+
- 📦 **Transactional Outbox Pattern (`OutboxRelay`, `IOutboxStore`)**: Guarantee at-least-once message delivery without dual-write race conditions.
|
|
16
|
+
- 🛡️ **Distributed Idempotency (`IdempotencyStore`)**: Deduplicate concurrent webhook deliveries, command executions, and payment callbacks.
|
|
17
|
+
- 🔍 **Correlation & Trace Propagation**: Carries `correlationId`, `causationId`, `tenantId`, and `userId` across event chains.
|
|
18
|
+
- 📦 **Dual ESM & CJS Build**: Clean consumption across Node.js event subscribers, serverless workers, and agent runtimes.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## Table of Contents
|
|
23
|
+
|
|
24
|
+
1. [Installation](#installation)
|
|
25
|
+
2. [Quick Start](#quick-start)
|
|
26
|
+
3. [Domain Events & Envelopes](#domain-events--envelopes)
|
|
27
|
+
4. [In-Memory Event Bus](#in-memory-event-bus)
|
|
28
|
+
5. [Transactional Outbox Pattern](#transactional-outbox-pattern)
|
|
29
|
+
6. [Idempotency Guard](#idempotency-guard)
|
|
30
|
+
7. [Author & Attribution](#author--attribution)
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Installation
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# pnpm (recommended)
|
|
38
|
+
pnpm add @yuva-devlab/events
|
|
39
|
+
|
|
40
|
+
# npm
|
|
41
|
+
npm install @yuva-devlab/events
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
### Publishing and Subscribing to Events
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { InMemoryEventBus, createDomainEvent } from "@yuva-devlab/events";
|
|
52
|
+
|
|
53
|
+
// 1. Initialize bus
|
|
54
|
+
const bus = new InMemoryEventBus();
|
|
55
|
+
|
|
56
|
+
// 2. Subscribe to user signup events
|
|
57
|
+
bus.subscribe("user.created", async (event) => {
|
|
58
|
+
console.log(`Sending welcome email to: ${event.payload.email}`);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// 3. Publish an event
|
|
62
|
+
const event = createDomainEvent({
|
|
63
|
+
topic: "user.created",
|
|
64
|
+
source: "auth-service",
|
|
65
|
+
tenantId: "tenant_apex",
|
|
66
|
+
payload: {
|
|
67
|
+
userId: "usr_9912",
|
|
68
|
+
email: "alex@example.com",
|
|
69
|
+
role: "DEVELOPER",
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
await bus.publish(event);
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
|
|
78
|
+
## Domain Events & Envelopes
|
|
79
|
+
|
|
80
|
+
Every event follows a strict, observable schema:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
export interface DomainEvent<T = unknown> {
|
|
84
|
+
id: string; // Unique event UUIDv4
|
|
85
|
+
topic: string; // Dot-separated topic (e.g., "billing.invoice.paid")
|
|
86
|
+
source: string; // Service origin (e.g., "billing-service")
|
|
87
|
+
timestamp: string; // ISO-8601 creation time
|
|
88
|
+
correlationId?: string; // Trace correlation across microservices
|
|
89
|
+
tenantId?: string; // Tenant boundary
|
|
90
|
+
payload: T; // Strongly typed payload
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Transactional Outbox Pattern
|
|
97
|
+
|
|
98
|
+
Eliminate the distributed dual-write problem by saving outbox records inside your primary database transaction and relaying them asynchronously:
|
|
99
|
+
|
|
100
|
+
```typescript
|
|
101
|
+
import { OutboxRelay, IOutboxStore } from "@yuva-devlab/events";
|
|
102
|
+
|
|
103
|
+
// Implement or inject your database store (PostgreSQL / Prisma)
|
|
104
|
+
const store: IOutboxStore = getDatabaseOutboxStore();
|
|
105
|
+
|
|
106
|
+
const relay = new OutboxRelay(store, bus, {
|
|
107
|
+
batchSize: 50,
|
|
108
|
+
pollIntervalMs: 1000,
|
|
109
|
+
maxRetries: 5,
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// Start background poller
|
|
113
|
+
await relay.start();
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
---
|
|
117
|
+
|
|
118
|
+
## Idempotency Guard
|
|
119
|
+
|
|
120
|
+
Prevent duplicate execution when webhooks or requests are retried:
|
|
121
|
+
|
|
122
|
+
```typescript
|
|
123
|
+
import { InMemoryIdempotencyStore } from "@yuva-devlab/events";
|
|
124
|
+
|
|
125
|
+
const idempotency = new InMemoryIdempotencyStore({ ttlSeconds: 86400 });
|
|
126
|
+
|
|
127
|
+
async function handleWebhook(idempotencyKey: string, payload: unknown) {
|
|
128
|
+
const isDuplicate = await idempotency.has(idempotencyKey);
|
|
129
|
+
if (isDuplicate) {
|
|
130
|
+
console.warn(`Duplicate event received for key: ${idempotencyKey}`);
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
await idempotency.record(idempotencyKey);
|
|
135
|
+
await processPayment(payload);
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
## Author & Attribution
|
|
142
|
+
|
|
143
|
+
- **Author**: Yuva DevLab (`yuva.devlab@gmail.com`)
|
|
144
|
+
- **License**: MIT
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yuva-devlab/events",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"description": "Standardized domain event envelopes, in-memory event bus, transactional outbox pattern, and idempotency for DevLab",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
"license": "MIT",
|
|
27
27
|
"dependencies": {
|
|
28
28
|
"@yuva-devlab/errors": "0.2.0",
|
|
29
|
-
"@yuva-devlab/logger": "1.
|
|
29
|
+
"@yuva-devlab/logger": "1.3.0",
|
|
30
30
|
"@yuva-devlab/regex": "0.3.0",
|
|
31
31
|
"zod": "^3.25.76"
|
|
32
32
|
},
|