@beignet/provider-event-bus-memory 0.0.48 → 0.0.50

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @beignet/provider-event-bus-memory
2
2
 
3
+ ## 0.0.50
4
+
5
+ ### Patch Changes
6
+
7
+ - 6fe026a: Expose event-subscription readiness and asynchronous cleanup, await listener
8
+ registries during provider startup with bounded rollback, diagnose unsafe app
9
+ wiring, and make Redis subscription lifecycle failures observable with bounded
10
+ provider shutdown and recoverable channel state.
11
+
12
+ ## 0.0.49
13
+
14
+ ### Patch Changes
15
+
16
+ - e597d53: Require Node.js 22.12 or newer across every Beignet package, generated app,
17
+ and documented workflow.
18
+
3
19
  ## 0.0.48
4
20
 
5
21
  ## 0.0.47
package/README.md CHANGED
@@ -1,5 +1,8 @@
1
1
  # @beignet/provider-event-bus-memory
2
2
 
3
+ > **Runtime:** Beignet requires Node.js 22.12 or newer. Bun 1.3.14 or newer is
4
+ > supported for Beignet commands.
5
+
3
6
  > [!CAUTION]
4
7
  > Beignet is experimental alpha software. The `0.0.x` package line is for early
5
8
  > evaluation, and APIs may change between releases while the framework settles.
@@ -40,11 +43,13 @@ const UserRegistered = defineEvent("user.registered", {
40
43
  const eventBus = createMemoryEventBus();
41
44
 
42
45
  // Subscribe to events
43
- const unsubscribe = eventBus.subscribe(UserRegistered, (payload) => {
46
+ const subscription = eventBus.subscribe(UserRegistered, (payload) => {
44
47
  console.log(`User registered: ${payload.email}`);
45
48
  // Send welcome email, update analytics, etc.
46
49
  });
47
50
 
51
+ await subscription.ready;
52
+
48
53
  // Publish events
49
54
  await eventBus.publish(UserRegistered, {
50
55
  userId: "123",
@@ -52,7 +57,7 @@ await eventBus.publish(UserRegistered, {
52
57
  });
53
58
 
54
59
  // Unsubscribe when done
55
- unsubscribe();
60
+ await subscription.unsubscribe();
56
61
  ```
57
62
 
58
63
  ## Framework setup
@@ -113,14 +118,18 @@ const OrderPlaced = defineEvent("order.placed", {
113
118
  });
114
119
 
115
120
  // Subscribe to events in your application setup
116
- ctx.ports.eventBus.subscribe(OrderPlaced, async (payload) => {
117
- // Send order confirmation email
118
- await ctx.ports.mailer.send({
119
- to: customer.email,
120
- subject: "Order Confirmation",
121
- text: `Your order ${payload.orderId} has been placed!`,
122
- });
123
- });
121
+ const orderPlacedSubscription = ctx.ports.eventBus.subscribe(
122
+ OrderPlaced,
123
+ async (payload) => {
124
+ // Send order confirmation email
125
+ await ctx.ports.mailer.send({
126
+ to: customer.email,
127
+ subject: "Order Confirmation",
128
+ text: `Your order ${payload.orderId} has been placed!`,
129
+ });
130
+ },
131
+ );
132
+ await orderPlacedSubscription.ready;
124
133
 
125
134
  const placeOrder = useCase
126
135
  .command("orders.place")
@@ -139,6 +148,11 @@ const placeOrder = useCase
139
148
  return order;
140
149
  });
141
150
  });
151
+
152
+ // Call this from the application's shutdown hook.
153
+ export async function stopOrderListeners() {
154
+ await orderPlacedSubscription.unsubscribe();
155
+ }
142
156
  ```
143
157
 
144
158
  ## EventBus port API
@@ -165,18 +179,22 @@ The optional third `{ trace }` argument is transport metadata used by Beignet
165
179
  listeners. When `instrumentation` exposes a tracing port, the bus captures the
166
180
  active context automatically. Existing two-argument calls are unchanged.
167
181
 
168
- ### `subscribe<E>(event, handler): () => void`
182
+ ### `subscribe<E>(event, handler): EventSubscription`
169
183
 
170
- Subscribe to a domain event. Returns an unsubscribe function.
184
+ Subscribe to a domain event. The memory adapter is active synchronously, so
185
+ `ready` is already resolved. `unsubscribe()` is idempotent and removes local
186
+ delivery before its promise resolves.
171
187
 
172
188
  ```typescript
173
- const unsubscribe = eventBus.subscribe(UserRegistered, (payload, options) => {
189
+ const subscription = eventBus.subscribe(UserRegistered, (payload, options) => {
174
190
  console.log(`New user: ${payload.email}`);
175
191
  console.log(options?.trace?.traceparent);
176
192
  });
177
193
 
194
+ await subscription.ready;
195
+
178
196
  // Later, when you want to stop listening:
179
- unsubscribe();
197
+ await subscription.unsubscribe();
180
198
  ```
181
199
 
182
200
  ## TypeScript support
@@ -208,7 +226,8 @@ describe("User Registration", () => {
208
226
  const eventBus = createMemoryEventBus();
209
227
  const handler = mock(() => {});
210
228
 
211
- eventBus.subscribe(UserRegistered, handler);
229
+ const subscription = eventBus.subscribe(UserRegistered, handler);
230
+ await subscription.ready;
212
231
 
213
232
  // Perform registration
214
233
  await registerUser(ctx, { email: "test@example.com" });
@@ -217,6 +236,8 @@ describe("User Registration", () => {
217
236
  userId: expect.any(String),
218
237
  email: "test@example.com",
219
238
  });
239
+
240
+ await subscription.unsubscribe();
220
241
  });
221
242
  });
222
243
  ```
package/dist/index.d.ts CHANGED
@@ -14,15 +14,16 @@
14
14
  * const eventBus = createMemoryEventBus();
15
15
  *
16
16
  * // Subscribe to an event
17
- * const unsubscribe = eventBus.subscribe(UserRegistered, (payload) => {
17
+ * const subscription = eventBus.subscribe(UserRegistered, (payload) => {
18
18
  * console.log(`User registered: ${payload.email}`);
19
19
  * });
20
+ * await subscription.ready;
20
21
  *
21
22
  * // Publish an event
22
23
  * await eventBus.publish(UserRegistered, { userId: "123", email: "test@example.com" });
23
24
  *
24
25
  * // Unsubscribe when done
25
- * unsubscribe();
26
+ * await subscription.unsubscribe();
26
27
  * ```
27
28
  */
28
29
  import type { EventBusPort } from "@beignet/core/ports";
@@ -91,11 +92,13 @@ export interface MemoryEventBusProviderPorts {
91
92
  * ```ts
92
93
  * const eventBus = createMemoryEventBus();
93
94
  *
94
- * eventBus.subscribe(UserRegistered, (payload) => {
95
+ * const subscription = eventBus.subscribe(UserRegistered, (payload) => {
95
96
  * console.log(`User registered: ${payload.email}`);
96
97
  * });
98
+ * await subscription.ready;
97
99
  *
98
100
  * await eventBus.publish(UserRegistered, { userId: "123", email: "test@example.com" });
101
+ * await subscription.unsubscribe();
99
102
  * ```
100
103
  *
101
104
  * @example
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAGL,KAAK,6BAA6B,EACnC,MAAM,yBAAyB,CAAC;AAGjC;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,eAAe,CAAC,EAAE,6BAA6B,CAAC;IAEhD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAElC;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE,CACf,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,KACb,IAAI,CAAC;CACX;AAED;;GAEG;AACH,MAAM,WAAW,6BACf,SAAQ,IAAI,CAAC,qBAAqB,EAAE,iBAAiB,CAAC;IACtD;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,qBAA0B,GAClC,YAAY,CAoGd;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,GAAE,6BAAkC;;kBAiB5C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAGL,KAAK,6BAA6B,EACnC,MAAM,yBAAyB,CAAC;AAGjC;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG,gBAAgB,GAAG,iBAAiB,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,eAAe,CAAC,EAAE,6BAA6B,CAAC;IAEhD;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,sBAAsB,CAAC;IAElC;;;;;;;;;;;OAWG;IACH,cAAc,CAAC,EAAE,CACf,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,KACb,IAAI,CAAC;CACX;AAED;;GAEG;AACH,MAAM,WAAW,6BACf,SAAQ,IAAI,CAAC,qBAAqB,EAAE,iBAAiB,CAAC;IACtD;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;OAEG;IACH,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,GAAE,qBAA0B,GAClC,YAAY,CA0Gd;AAED;;GAEG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,GAAE,6BAAkC;;kBAiB5C"}
package/dist/index.js CHANGED
@@ -14,15 +14,16 @@
14
14
  * const eventBus = createMemoryEventBus();
15
15
  *
16
16
  * // Subscribe to an event
17
- * const unsubscribe = eventBus.subscribe(UserRegistered, (payload) => {
17
+ * const subscription = eventBus.subscribe(UserRegistered, (payload) => {
18
18
  * console.log(`User registered: ${payload.email}`);
19
19
  * });
20
+ * await subscription.ready;
20
21
  *
21
22
  * // Publish an event
22
23
  * await eventBus.publish(UserRegistered, { userId: "123", email: "test@example.com" });
23
24
  *
24
25
  * // Unsubscribe when done
25
- * unsubscribe();
26
+ * await subscription.unsubscribe();
26
27
  * ```
27
28
  */
28
29
  import { createProvider, createProviderInstrumentation, } from "@beignet/core/providers";
@@ -38,11 +39,13 @@ import { captureTraceCarrier, parseTraceCarrier } from "@beignet/core/tracing";
38
39
  * ```ts
39
40
  * const eventBus = createMemoryEventBus();
40
41
  *
41
- * eventBus.subscribe(UserRegistered, (payload) => {
42
+ * const subscription = eventBus.subscribe(UserRegistered, (payload) => {
42
43
  * console.log(`User registered: ${payload.email}`);
43
44
  * });
45
+ * await subscription.ready;
44
46
  *
45
47
  * await eventBus.publish(UserRegistered, { userId: "123", email: "test@example.com" });
48
+ * await subscription.unsubscribe();
46
49
  * ```
47
50
  *
48
51
  * @example
@@ -118,11 +121,18 @@ export function createMemoryEventBus(options = {}) {
118
121
  handlers.set(event.name, subs);
119
122
  }
120
123
  subs.add(handler);
121
- return () => {
122
- subs.delete(handler);
123
- if (subs.size === 0) {
124
- handlers.delete(event.name);
125
- }
124
+ let unsubscribed = false;
125
+ return {
126
+ ready: Promise.resolve(),
127
+ async unsubscribe() {
128
+ if (unsubscribed)
129
+ return;
130
+ unsubscribed = true;
131
+ subs.delete(handler);
132
+ if (subs.size === 0) {
133
+ handlers.delete(event.name);
134
+ }
135
+ },
126
136
  };
127
137
  },
128
138
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAIH,OAAO,EACL,cAAc,EACd,6BAA6B,GAE9B,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAkE/E;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,UAAU,oBAAoB,CAClC,UAAiC,EAAE;IAEnC,MAAM,cAAc,GAAG,OAAO,EAAE,cAAc,CAAC;IAC/C,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,gBAAgB,CAAC;IACtD,MAAM,eAAe,GAAG,6BAA6B,CACnD,OAAO,CAAC,eAAe,EACvB;QACE,YAAY,EAAE,kBAAkB;QAChC,OAAO,EAAE,UAAU;KACpB,CACF,CAAC;IAEF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAKrB,CAAC;IAEJ,MAAM,kBAAkB,GAAG,CACzB,KAAc,EACd,SAAiB,EACjB,OAAgB,EAChB,EAAE;QACF,IAAI,CAAC;YACH,cAAc,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,wFAAwF;QAC1F,CAAC;IACH,CAAC,CAAC;IAEF,OAAO;QACL,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,cAAc;YACpC,eAAe,CAAC,MAAM,CAAC;gBACrB,IAAI,EAAE,UAAU;gBAChB,SAAS,EAAE,KAAK,CAAC,IAAI;aACtB,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACtC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC;gBAAE,OAAO;YAErC,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC;YAC9B,MAAM,KAAK,GACT,iBAAiB,CAAC,cAAc,EAAE,KAAK,CAAC;gBACxC,mBAAmB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;YAC/C,MAAM,eAAe,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;YAEtD,IAAI,QAAQ,KAAK,iBAAiB,EAAE,CAAC;gBACnC,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;oBAClC,IAAI,CAAC;wBACH,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;wBACjD,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;4BAC/C,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;wBACjD,CAAC,CAAC,CAAC;oBACL,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;oBACjD,CAAC;gBACH,CAAC;gBAED,OAAO;YACT,CAAC;YAED,OAAO,CAAC,KAAK,IAAI,EAAE;gBACjB,KAAK,MAAM,OAAO,IAAI,WAAW,EAAE,CAAC;oBAClC,IAAI,CAAC;wBACH,MAAM,OAAO,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC;oBAC1C,CAAC;oBAAC,OAAO,KAAK,EAAE,CAAC;wBACf,kBAAkB,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;wBAC/C,IAAI,CAAC,cAAc;4BAAE,MAAM,KAAK,CAAC;oBACnC,CAAC;gBACH,CAAC;YACH,CAAC,CAAC,EAAE,CAAC;QACP,CAAC;QAED,SAAS,CAAC,KAAK,EAAE,OAAO;YACtB,IAAI,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,IAAI,GAAG,IAAI,GAAG,EAAE,CAAC;gBACjB,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACjC,CAAC;YAED,IAAI,CAAC,GAAG,CACN,OAGyB,CAC1B,CAAC;YAEF,OAAO,GAAG,EAAE;gBACV,IAAI,CAAC,MAAM,CACT,OAGyB,CAC1B,CAAC;gBACF,IAAI,IAAI,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;oBACpB,QAAQ,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC9B,CAAC;YACH,CAAC,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,4BAA4B,CAC1C,UAAyC,EAAE;IAE3C,MAAM,EAAE,IAAI,GAAG,kBAAkB,EAAE,GAAG,eAAe,EAAE,GAAG,OAAO,CAAC;IAElE,OAAO,cAAc,CAAC;QACpB,IAAI;QACJ,KAAK,CAAC,EAAE,KAAK,EAAE;YACb,OAAO;gBACL,KAAK,EAAE;oBACL,QAAQ,EAAE,oBAAoB,CAAC;wBAC7B,GAAG,eAAe;wBAClB,eAAe,EAAE,KAAK;qBACvB,CAAC;iBACmC;aACxC,CAAC;QACJ,CAAC;KACF,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@beignet/provider-event-bus-memory",
3
- "version": "0.0.48",
3
+ "version": "0.0.50",
4
4
  "type": "module",
5
5
  "description": "In-memory event bus provider for Beignet - implements EventBusPort for single-process applications",
6
6
  "main": "./dist/index.js",
@@ -50,7 +50,7 @@
50
50
  "access": "public"
51
51
  },
52
52
  "engines": {
53
- "node": ">=18.0.0"
53
+ "node": ">=22.12.0"
54
54
  },
55
55
  "peerDependencies": {
56
56
  "@beignet/core": ">=0.0.3 <1.0.0"
@@ -59,7 +59,7 @@
59
59
  "@beignet/core": "*",
60
60
  "@beignet/devtools": "*",
61
61
  "@types/bun": "^1.3.13",
62
- "@types/node": "^20.10.0",
62
+ "@types/node": "^22.0.0",
63
63
  "typescript": "^5.3.0",
64
64
  "zod": "^4.0.0"
65
65
  },
package/src/index.ts CHANGED
@@ -14,15 +14,16 @@
14
14
  * const eventBus = createMemoryEventBus();
15
15
  *
16
16
  * // Subscribe to an event
17
- * const unsubscribe = eventBus.subscribe(UserRegistered, (payload) => {
17
+ * const subscription = eventBus.subscribe(UserRegistered, (payload) => {
18
18
  * console.log(`User registered: ${payload.email}`);
19
19
  * });
20
+ * await subscription.ready;
20
21
  *
21
22
  * // Publish an event
22
23
  * await eventBus.publish(UserRegistered, { userId: "123", email: "test@example.com" });
23
24
  *
24
25
  * // Unsubscribe when done
25
- * unsubscribe();
26
+ * await subscription.unsubscribe();
26
27
  * ```
27
28
  */
28
29
 
@@ -110,11 +111,13 @@ export interface MemoryEventBusProviderPorts {
110
111
  * ```ts
111
112
  * const eventBus = createMemoryEventBus();
112
113
  *
113
- * eventBus.subscribe(UserRegistered, (payload) => {
114
+ * const subscription = eventBus.subscribe(UserRegistered, (payload) => {
114
115
  * console.log(`User registered: ${payload.email}`);
115
116
  * });
117
+ * await subscription.ready;
116
118
  *
117
119
  * await eventBus.publish(UserRegistered, { userId: "123", email: "test@example.com" });
120
+ * await subscription.unsubscribe();
118
121
  * ```
119
122
  *
120
123
  * @example
@@ -216,16 +219,22 @@ export function createMemoryEventBus(
216
219
  ) => void | Promise<void>,
217
220
  );
218
221
 
219
- return () => {
220
- subs.delete(
221
- handler as unknown as (
222
- payload: unknown,
223
- options?: EventPublishOptions,
224
- ) => void | Promise<void>,
225
- );
226
- if (subs.size === 0) {
227
- handlers.delete(event.name);
228
- }
222
+ let unsubscribed = false;
223
+ return {
224
+ ready: Promise.resolve(),
225
+ async unsubscribe() {
226
+ if (unsubscribed) return;
227
+ unsubscribed = true;
228
+ subs.delete(
229
+ handler as unknown as (
230
+ payload: unknown,
231
+ options?: EventPublishOptions,
232
+ ) => void | Promise<void>,
233
+ );
234
+ if (subs.size === 0) {
235
+ handlers.delete(event.name);
236
+ }
237
+ },
229
238
  };
230
239
  },
231
240
  };