@fluojs/cqrs 1.1.2 → 2.0.0

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.
Files changed (42) hide show
  1. package/README.ko.md +7 -7
  2. package/README.md +7 -7
  3. package/dist/buses/command-bus.d.ts +9 -2
  4. package/dist/buses/command-bus.d.ts.map +1 -1
  5. package/dist/buses/command-bus.js +54 -24
  6. package/dist/buses/event-bus.d.ts +6 -7
  7. package/dist/buses/event-bus.d.ts.map +1 -1
  8. package/dist/buses/event-bus.js +52 -74
  9. package/dist/buses/event-handler-discovery.d.ts +12 -0
  10. package/dist/buses/event-handler-discovery.d.ts.map +1 -0
  11. package/dist/buses/event-handler-discovery.js +35 -0
  12. package/dist/buses/publish-drain-tracker.d.ts +38 -0
  13. package/dist/buses/publish-drain-tracker.d.ts.map +1 -0
  14. package/dist/buses/publish-drain-tracker.js +86 -0
  15. package/dist/buses/query-bus.d.ts +9 -2
  16. package/dist/buses/query-bus.d.ts.map +1 -1
  17. package/dist/buses/query-bus.js +54 -24
  18. package/dist/buses/saga-bus.d.ts +8 -9
  19. package/dist/buses/saga-bus.d.ts.map +1 -1
  20. package/dist/buses/saga-bus.js +37 -96
  21. package/dist/buses/saga-discovery.d.ts +12 -0
  22. package/dist/buses/saga-discovery.d.ts.map +1 -0
  23. package/dist/buses/saga-discovery.js +39 -0
  24. package/dist/buses/saga-drain.d.ts +9 -0
  25. package/dist/buses/saga-drain.d.ts.map +1 -0
  26. package/dist/buses/saga-drain.js +34 -0
  27. package/dist/buses/saga-topology.d.ts +15 -0
  28. package/dist/buses/saga-topology.d.ts.map +1 -0
  29. package/dist/buses/saga-topology.js +39 -0
  30. package/dist/discovery.d.ts +16 -0
  31. package/dist/discovery.d.ts.map +1 -1
  32. package/dist/discovery.js +16 -9
  33. package/dist/dispatch-context.d.ts +33 -0
  34. package/dist/dispatch-context.d.ts.map +1 -0
  35. package/dist/dispatch-context.js +42 -0
  36. package/dist/module.d.ts.map +1 -1
  37. package/dist/module.js +8 -1
  38. package/dist/test-setup.d.ts +2 -0
  39. package/dist/test-setup.d.ts.map +1 -0
  40. package/dist/test-setup.js +4 -0
  41. package/dist/types.d.ts +1 -1
  42. package/package.json +5 -5
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Waits until a mutable set of saga tasks becomes quiescent within one deadline.
3
+ *
4
+ * @param pendingDispatches Live saga task set owned by the lifecycle service.
5
+ * @param timeoutMs Maximum drain duration in milliseconds.
6
+ * @returns `true` when all current and late-added tasks settle before the deadline.
7
+ */
8
+ export async function drainPendingSagaDispatches(pendingDispatches, timeoutMs) {
9
+ const deadline = Date.now() + timeoutMs;
10
+ while (pendingDispatches.size > 0) {
11
+ const remainingTimeoutMs = deadline - Date.now();
12
+ if (remainingTimeoutMs <= 0) {
13
+ return false;
14
+ }
15
+ if (!(await awaitSagaTasks([...pendingDispatches], remainingTimeoutMs))) {
16
+ return false;
17
+ }
18
+ }
19
+ return true;
20
+ }
21
+ async function awaitSagaTasks(activeWork, timeoutMs) {
22
+ let timeoutId;
23
+ const timeout = new Promise(resolve => {
24
+ timeoutId = setTimeout(() => resolve(false), timeoutMs);
25
+ });
26
+ const drain = Promise.allSettled(activeWork).then(() => true);
27
+ try {
28
+ return await Promise.race([drain, timeout]);
29
+ } finally {
30
+ if (timeoutId) {
31
+ clearTimeout(timeoutId);
32
+ }
33
+ }
34
+ }
@@ -0,0 +1,15 @@
1
+ import type { CqrsDispatchContext, SagaDescriptor } from '../types.js';
2
+ /** Result of entering one guarded saga route. */
3
+ export interface SagaTopologyEntry {
4
+ readonly context: CqrsDispatchContext;
5
+ readonly reentrantToken: boolean;
6
+ }
7
+ /**
8
+ * Validates and enters one saga route using private immutable context state.
9
+ *
10
+ * @param context Opaque context passed through the active CQRS pipeline.
11
+ * @param descriptor Saga route selected for the current event.
12
+ * @returns The next opaque context and whether the same provider token is already active.
13
+ */
14
+ export declare function enterSagaTopology(context: CqrsDispatchContext | undefined, descriptor: SagaDescriptor): SagaTopologyEntry;
15
+ //# sourceMappingURL=saga-topology.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"saga-topology.d.ts","sourceRoot":"","sources":["../../src/buses/saga-topology.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAIvE,iDAAiD;AACjD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,mBAAmB,GAAG,SAAS,EACxC,UAAU,EAAE,cAAc,GACzB,iBAAiB,CAiCnB"}
@@ -0,0 +1,39 @@
1
+ import { createInternalCqrsDispatchContext, getInternalCqrsDispatchContextState } from '../dispatch-context.js';
2
+ import { SagaTopologyError } from '../errors.js';
3
+ const MAX_NESTED_SAGA_DEPTH = 32;
4
+
5
+ /** Result of entering one guarded saga route. */
6
+
7
+ /**
8
+ * Validates and enters one saga route using private immutable context state.
9
+ *
10
+ * @param context Opaque context passed through the active CQRS pipeline.
11
+ * @param descriptor Saga route selected for the current event.
12
+ * @returns The next opaque context and whether the same provider token is already active.
13
+ */
14
+ export function enterSagaTopology(context, descriptor) {
15
+ const internalState = getInternalCqrsDispatchContextState(context);
16
+ const activeTopology = internalState?.sagaTopology;
17
+ const routeLabel = `${descriptor.targetType.name}(${descriptor.eventType.name})`;
18
+ const reenteredRoute = activeTopology?.activeRoutes.some(route => route.token === descriptor.token && route.eventType === descriptor.eventType);
19
+ if (reenteredRoute) {
20
+ throw new SagaTopologyError(`Saga ${descriptor.targetType.name} re-entered an unsafe cycle while handling ${descriptor.eventType.name}. ` + `Active saga path: ${[...(activeTopology?.path ?? []), routeLabel].join(' -> ')}.`);
21
+ }
22
+ if ((activeTopology?.depth ?? 0) >= MAX_NESTED_SAGA_DEPTH) {
23
+ throw new SagaTopologyError(`Saga ${descriptor.targetType.name} exceeded the maximum nested saga depth of ${MAX_NESTED_SAGA_DEPTH} while handling ${descriptor.eventType.name}. ` + 'Keep in-process saga graphs acyclic and externally bounded.');
24
+ }
25
+ return {
26
+ context: createInternalCqrsDispatchContext({
27
+ publishDrainToken: internalState?.publishDrainToken,
28
+ sagaTopology: {
29
+ activeRoutes: [...(activeTopology?.activeRoutes ?? []), {
30
+ eventType: descriptor.eventType,
31
+ token: descriptor.token
32
+ }],
33
+ depth: (activeTopology?.depth ?? 0) + 1,
34
+ path: [...(activeTopology?.path ?? []), routeLabel]
35
+ }
36
+ }),
37
+ reentrantToken: activeTopology?.activeRoutes.some(route => route.token === descriptor.token) ?? false
38
+ };
39
+ }
@@ -22,10 +22,26 @@ export interface DiscoveryCandidate {
22
22
  export declare function createDuplicateHandlerMessage(kind: 'command' | 'query' | 'event', messageType: Function, first: {
23
23
  moduleName: string;
24
24
  targetType: Function;
25
+ token: Token;
25
26
  }, second: {
26
27
  moduleName: string;
27
28
  targetType: Function;
29
+ token: Token;
28
30
  }): string;
31
+ /**
32
+ * Checks whether two discovered handler candidates refer to the same provider registration.
33
+ *
34
+ * @param first The first handler registration.
35
+ * @param second The second handler registration.
36
+ * @returns Whether both target type and provider token match.
37
+ */
38
+ export declare function isSameHandlerRegistration(first: {
39
+ targetType: Function;
40
+ token: Token;
41
+ }, second: {
42
+ targetType: Function;
43
+ token: Token;
44
+ }): boolean;
29
45
  /**
30
46
  * Represents the cqrs bus base.
31
47
  */
@@ -1 +1 @@
1
- {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;IAC7C,UAAU,EAAE,QAAQ,CAAC;IACrB,KAAK,EAAE,KAAK,CAAC;CACd;AAkBD;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,EACnC,WAAW,EAAE,QAAQ,EACrB,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,QAAQ,CAAA;CAAE,EACnD,MAAM,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,QAAQ,CAAA;CAAE,GACnD,MAAM,CAER;AAED;;GAEG;AACH,8BAAsB,WAAW;IAI7B,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,SAAS;IAC9C,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,SAAS,cAAc,EAAE;IAC7D,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,iBAAiB;IAL9C,SAAS,CAAC,QAAQ,CAAC,gBAAgB,+BAAsC;gBAGpD,gBAAgB,EAAE,SAAS,EAC3B,eAAe,EAAE,SAAS,cAAc,EAAE,EAC1C,MAAM,EAAE,iBAAiB;IAG9C,SAAS,CAAC,mBAAmB,IAAI,kBAAkB,EAAE;cAsCrC,sBAAsB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;cAgBnD,sBAAsB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;CAiBvE"}
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../src/discovery.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,KAAK,KAAK,EAAE,MAAM,cAAc,CAAC;AAE3D,OAAO,KAAK,EAAE,SAAS,EAAY,MAAM,YAAY,CAAC;AACtD,OAAO,KAAK,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEzE;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;IAC7C,UAAU,EAAE,QAAQ,CAAC;IACrB,KAAK,EAAE,KAAK,CAAC;CACd;AAkBD;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,IAAI,EAAE,SAAS,GAAG,OAAO,GAAG,OAAO,EACnC,WAAW,EAAE,QAAQ,EACrB,KAAK,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,EACjE,MAAM,EAAE;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GACjE,MAAM,CAER;AAMD;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE;IAAE,UAAU,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,EAC7C,MAAM,EAAE;IAAE,UAAU,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,GAC7C,OAAO,CAET;AAED;;GAEG;AACH,8BAAsB,WAAW;IAI7B,SAAS,CAAC,QAAQ,CAAC,gBAAgB,EAAE,SAAS;IAC9C,SAAS,CAAC,QAAQ,CAAC,eAAe,EAAE,SAAS,cAAc,EAAE;IAC7D,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,iBAAiB;IAL9C,SAAS,CAAC,QAAQ,CAAC,gBAAgB,+BAAsC;gBAGpD,gBAAgB,EAAE,SAAS,EAC3B,eAAe,EAAE,SAAS,cAAc,EAAE,EAC1C,MAAM,EAAE,iBAAiB;IAG9C,SAAS,CAAC,mBAAmB,IAAI,kBAAkB,EAAE;cA6BrC,sBAAsB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;cAgBnD,sBAAsB,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;CAiBvE"}
package/dist/discovery.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { formatTokenName } from '@fluojs/core';
1
2
  import { getClassDiMetadata } from '@fluojs/core/internal';
2
3
 
3
4
  /**
@@ -27,7 +28,21 @@ function isClassProvider(provider) {
27
28
  * @returns The create duplicate handler message result.
28
29
  */
29
30
  export function createDuplicateHandlerMessage(kind, messageType, first, second) {
30
- return `Duplicate ${kind} handler for ${messageType.name} was discovered in ${first.moduleName}.${first.targetType.name} and ${second.moduleName}.${second.targetType.name}.`;
31
+ return `Duplicate ${kind} handler for ${messageType.name} was discovered in ${describeHandlerRegistration(first)} and ${describeHandlerRegistration(second)}.`;
32
+ }
33
+ function describeHandlerRegistration(registration) {
34
+ return `${registration.moduleName}.${registration.targetType.name} [token: ${formatTokenName(registration.token)}]`;
35
+ }
36
+
37
+ /**
38
+ * Checks whether two discovered handler candidates refer to the same provider registration.
39
+ *
40
+ * @param first The first handler registration.
41
+ * @param second The second handler registration.
42
+ * @returns Whether both target type and provider token match.
43
+ */
44
+ export function isSameHandlerRegistration(first, second) {
45
+ return first.targetType === second.targetType && first.token === second.token;
31
46
  }
32
47
 
33
48
  /**
@@ -62,14 +77,6 @@ export class CqrsBusBase {
62
77
  });
63
78
  }
64
79
  }
65
- for (const controller of compiledModule.definition.controllers ?? []) {
66
- candidates.push({
67
- moduleName: compiledModule.type.name,
68
- scope: scopeFromProvider(controller),
69
- targetType: controller,
70
- token: controller
71
- });
72
- }
73
80
  }
74
81
  return candidates;
75
82
  }
@@ -0,0 +1,33 @@
1
+ import type { Token } from '@fluojs/core';
2
+ import type { CqrsDispatchContext, CqrsEventType } from './types.js';
3
+ /** One active saga route retained in private CQRS dispatch state. */
4
+ export interface CqrsDispatchRoute {
5
+ readonly eventType: CqrsEventType;
6
+ readonly token: Token;
7
+ }
8
+ /** Private saga topology state associated with an opaque dispatch context. */
9
+ export interface CqrsSagaTopologyState {
10
+ readonly activeRoutes: readonly CqrsDispatchRoute[];
11
+ readonly depth: number;
12
+ readonly path: readonly string[];
13
+ }
14
+ /** Private state carried by an internally created dispatch context. */
15
+ export interface InternalCqrsDispatchContextState {
16
+ readonly publishDrainToken: symbol | undefined;
17
+ readonly sagaTopology: CqrsSagaTopologyState | undefined;
18
+ }
19
+ /**
20
+ * Creates an opaque immutable dispatch context and retains its state in a private weak map.
21
+ *
22
+ * @param state Internal publish-drain and saga-topology state.
23
+ * @returns A frozen fieldless context safe to pass through application handlers.
24
+ */
25
+ export declare function createInternalCqrsDispatchContext(state: InternalCqrsDispatchContextState): CqrsDispatchContext;
26
+ /**
27
+ * Reads private state only for context values created by CQRS internals.
28
+ *
29
+ * @param context Optional public dispatch context received from a handler or saga.
30
+ * @returns The immutable internal state, or `undefined` for caller-created values.
31
+ */
32
+ export declare function getInternalCqrsDispatchContextState(context: CqrsDispatchContext | undefined): InternalCqrsDispatchContextState | undefined;
33
+ //# sourceMappingURL=dispatch-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dispatch-context.d.ts","sourceRoot":"","sources":["../src/dispatch-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,KAAK,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAErE,qEAAqE;AACrE,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,SAAS,EAAE,aAAa,CAAC;IAClC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;CACvB;AAED,8EAA8E;AAC9E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,YAAY,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACpD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;CAClC;AAED,uEAAuE;AACvE,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,YAAY,EAAE,qBAAqB,GAAG,SAAS,CAAC;CAC1D;AAcD;;;;;GAKG;AACH,wBAAgB,iCAAiC,CAAC,KAAK,EAAE,gCAAgC,GAAG,mBAAmB,CAU9G;AAED;;;;;GAKG;AACH,wBAAgB,mCAAmC,CACjD,OAAO,EAAE,mBAAmB,GAAG,SAAS,GACvC,gCAAgC,GAAG,SAAS,CAE9C"}
@@ -0,0 +1,42 @@
1
+ /** One active saga route retained in private CQRS dispatch state. */
2
+
3
+ /** Private saga topology state associated with an opaque dispatch context. */
4
+
5
+ /** Private state carried by an internally created dispatch context. */
6
+
7
+ const internalContextStates = new WeakMap();
8
+ function freezeSagaTopology(state) {
9
+ return Object.freeze({
10
+ activeRoutes: Object.freeze(state.activeRoutes.map(route => Object.freeze({
11
+ eventType: route.eventType,
12
+ token: route.token
13
+ }))),
14
+ depth: state.depth,
15
+ path: Object.freeze([...state.path])
16
+ });
17
+ }
18
+
19
+ /**
20
+ * Creates an opaque immutable dispatch context and retains its state in a private weak map.
21
+ *
22
+ * @param state Internal publish-drain and saga-topology state.
23
+ * @returns A frozen fieldless context safe to pass through application handlers.
24
+ */
25
+ export function createInternalCqrsDispatchContext(state) {
26
+ const context = Object.freeze({});
27
+ internalContextStates.set(context, Object.freeze({
28
+ publishDrainToken: state.publishDrainToken,
29
+ sagaTopology: state.sagaTopology ? freezeSagaTopology(state.sagaTopology) : undefined
30
+ }));
31
+ return context;
32
+ }
33
+
34
+ /**
35
+ * Reads private state only for context values created by CQRS internals.
36
+ *
37
+ * @param context Optional public dispatch context received from a handler or saga.
38
+ * @returns The immutable internal state, or `undefined` for caller-created values.
39
+ */
40
+ export function getInternalCqrsDispatchContextState(context) {
41
+ return context ? internalContextStates.get(context) : undefined;
42
+ }
@@ -1 +1 @@
1
- {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAOhE,OAAO,KAAK,EACV,mBAAmB,EAEnB,iBAAiB,EAIjB,iBAAiB,EACjB,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB,4FAA4F;AAC5F,MAAM,WAAW,iBAAiB;IAChC,eAAe,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACjD,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,aAAa,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC7C,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC7C,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7B,8GAA8G;IAC9G,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAgGD,iFAAiF;AACjF,qBAAa,UAAU;IACrB;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU;CAiB5D"}
1
+ {"version":3,"file":"module.d.ts","sourceRoot":"","sources":["../src/module.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAOhE,OAAO,KAAK,EACV,mBAAmB,EAEnB,iBAAiB,EAIjB,iBAAiB,EACjB,SAAS,EACV,MAAM,YAAY,CAAC;AAEpB,4FAA4F;AAC5F,MAAM,WAAW,iBAAiB;IAChC,eAAe,CAAC,EAAE,SAAS,mBAAmB,EAAE,CAAC;IACjD,QAAQ,CAAC,EAAE,qBAAqB,CAAC;IACjC,aAAa,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC7C,iFAAiF;IACjF,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,aAAa,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAC7C,KAAK,CAAC,EAAE,SAAS,SAAS,EAAE,CAAC;IAC7B,8GAA8G;IAC9G,QAAQ,CAAC,EAAE;QACT,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAyGD,iFAAiF;AACjF,qBAAa,UAAU;IACrB;;;;;OAKG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,GAAE,iBAAsB,GAAG,UAAU;CAiB5D"}
package/dist/module.js CHANGED
@@ -24,6 +24,13 @@ function collectOptionHandlerProviders(options) {
24
24
  }
25
25
  return providers;
26
26
  }
27
+ function resolveDelegatedEventBusOptions(options) {
28
+ const eventBusOptions = options.eventBus ?? {};
29
+ return {
30
+ ...eventBusOptions,
31
+ global: eventBusOptions.global ?? options.global ?? true
32
+ };
33
+ }
27
34
  function assertCommandBusService(service) {
28
35
  if (!(service instanceof CommandBusLifecycleService)) {
29
36
  throw new TypeError('CQRS command bus alias expected CommandBusLifecycleService.');
@@ -94,7 +101,7 @@ export class CqrsModule {
94
101
  return defineModule(CqrsModuleDefinition, {
95
102
  exports: [CommandBusLifecycleService, QueryBusLifecycleService, CqrsEventBusService, COMMAND_BUS, QUERY_BUS, EVENT_BUS],
96
103
  global: options.global ?? true,
97
- imports: [EventBusModule.forRoot(options.eventBus)],
104
+ imports: [EventBusModule.forRoot(resolveDelegatedEventBusOptions(options))],
98
105
  providers: createCqrsProviders(options)
99
106
  });
100
107
  }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test-setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-setup.d.ts","sourceRoot":"","sources":["../src/test-setup.ts"],"names":[],"mappings":""}
@@ -0,0 +1,4 @@
1
+ import { afterEach, vi } from 'vitest';
2
+ afterEach(() => {
3
+ vi.useRealTimers();
4
+ });
package/dist/types.d.ts CHANGED
@@ -59,7 +59,7 @@ export interface ISaga<TEvent extends IEvent = IEvent> {
59
59
  * CQRS passes this value to command handlers, query handlers, event handlers, and sagas when a
60
60
  * nested dispatch chain is active. Application code should pass the value through unchanged to
61
61
  * nested `execute(...)`, `publish(...)`, or `publishAll(...)` calls. The context intentionally
62
- * exposes no public topology fields and should not be inspected or constructed by callers.
62
+ * exposes no public topology fields, and caller-shaped objects cannot supply trusted runtime state.
63
63
  */
64
64
  export interface CqrsDispatchContext {
65
65
  }
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "saga",
10
10
  "event-sourcing"
11
11
  ],
12
- "version": "1.1.2",
12
+ "version": "2.0.0",
13
13
  "private": false,
14
14
  "license": "MIT",
15
15
  "repository": {
@@ -36,10 +36,10 @@
36
36
  "dist"
37
37
  ],
38
38
  "dependencies": {
39
- "@fluojs/core": "^1.0.3",
40
- "@fluojs/di": "^1.1.0",
41
- "@fluojs/event-bus": "^1.0.1",
42
- "@fluojs/runtime": "^1.1.8"
39
+ "@fluojs/core": "^1.1.0",
40
+ "@fluojs/di": "^2.0.0",
41
+ "@fluojs/event-bus": "^2.0.0",
42
+ "@fluojs/runtime": "^2.0.1"
43
43
  },
44
44
  "devDependencies": {
45
45
  "vitest": "^3.2.4"