@fluojs/cqrs 1.0.0-beta.1

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 (46) hide show
  1. package/LICENSE +21 -0
  2. package/README.ko.md +153 -0
  3. package/README.md +153 -0
  4. package/dist/buses/command-bus.d.ts +29 -0
  5. package/dist/buses/command-bus.d.ts.map +1 -0
  6. package/dist/buses/command-bus.js +122 -0
  7. package/dist/buses/event-bus.d.ts +49 -0
  8. package/dist/buses/event-bus.d.ts.map +1 -0
  9. package/dist/buses/event-bus.js +165 -0
  10. package/dist/buses/query-bus.d.ts +29 -0
  11. package/dist/buses/query-bus.d.ts.map +1 -0
  12. package/dist/buses/query-bus.js +122 -0
  13. package/dist/buses/saga-bus.d.ts +46 -0
  14. package/dist/buses/saga-bus.d.ts.map +1 -0
  15. package/dist/buses/saga-bus.js +225 -0
  16. package/dist/decorators.d.ts +48 -0
  17. package/dist/decorators.d.ts.map +1 -0
  18. package/dist/decorators.js +127 -0
  19. package/dist/discovery.d.ts +27 -0
  20. package/dist/discovery.d.ts.map +1 -0
  21. package/dist/discovery.js +84 -0
  22. package/dist/errors.d.ts +65 -0
  23. package/dist/errors.d.ts.map +1 -0
  24. package/dist/errors.js +99 -0
  25. package/dist/event-clone.d.ts +10 -0
  26. package/dist/event-clone.d.ts.map +1 -0
  27. package/dist/event-clone.js +15 -0
  28. package/dist/index.d.ts +11 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +9 -0
  31. package/dist/metadata.d.ts +87 -0
  32. package/dist/metadata.d.ts.map +1 -0
  33. package/dist/metadata.js +235 -0
  34. package/dist/module.d.ts +30 -0
  35. package/dist/module.d.ts.map +1 -0
  36. package/dist/module.js +74 -0
  37. package/dist/status.d.ts +17 -0
  38. package/dist/status.d.ts.map +1 -0
  39. package/dist/status.js +69 -0
  40. package/dist/tokens.d.ts +9 -0
  41. package/dist/tokens.d.ts.map +1 -0
  42. package/dist/tokens.js +6 -0
  43. package/dist/types.d.ts +161 -0
  44. package/dist/types.d.ts.map +1 -0
  45. package/dist/types.js +1 -0
  46. package/package.json +54 -0
@@ -0,0 +1,165 @@
1
+ let _initClass;
2
+ function _applyDecs(e, t, n, r, o, i) { var a, c, u, s, f, l, p, d = Symbol.metadata || Symbol.for("Symbol.metadata"), m = Object.defineProperty, h = Object.create, y = [h(null), h(null)], v = t.length; function g(t, n, r) { return function (o, i) { n && (i = o, o = e); for (var a = 0; a < t.length; a++) i = t[a].apply(o, r ? [i] : []); return r ? i : o; }; } function b(e, t, n, r) { if ("function" != typeof e && (r || void 0 !== e)) throw new TypeError(t + " must " + (n || "be") + " a function" + (r ? "" : " or undefined")); return e; } function applyDec(e, t, n, r, o, i, u, s, f, l, p) { function d(e) { if (!p(e)) throw new TypeError("Attempted to access private element on non-instance"); } var h = [].concat(t[0]), v = t[3], w = !u, D = 1 === o, S = 3 === o, j = 4 === o, E = 2 === o; function I(t, n, r) { return function (o, i) { return n && (i = o, o = e), r && r(o), P[t].call(o, i); }; } if (!w) { var P = {}, k = [], F = S ? "get" : j || D ? "set" : "value"; if (f ? (l || D ? P = { get: _setFunctionName(function () { return v(this); }, r, "get"), set: function (e) { t[4](this, e); } } : P[F] = v, l || _setFunctionName(P[F], r, E ? "" : F)) : l || (P = Object.getOwnPropertyDescriptor(e, r)), !l && !f) { if ((c = y[+s][r]) && 7 !== (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet"); y[+s][r] = o < 3 ? 1 : o; } } for (var N = e, O = h.length - 1; O >= 0; O -= n ? 2 : 1) { var T = b(h[O], "A decorator", "be", !0), z = n ? h[O - 1] : void 0, A = {}, H = { kind: ["field", "accessor", "method", "getter", "setter", "class"][o], name: r, metadata: a, addInitializer: function (e, t) { if (e.v) throw new TypeError("attempted to call addInitializer after decoration was finished"); b(t, "An initializer", "be", !0), i.push(t); }.bind(null, A) }; if (w) c = T.call(z, N, H), A.v = 1, b(c, "class decorators", "return") && (N = c);else if (H.static = s, H.private = f, c = H.access = { has: f ? p.bind() : function (e) { return r in e; } }, j || (c.get = f ? E ? function (e) { return d(e), P.value; } : I("get", 0, d) : function (e) { return e[r]; }), E || S || (c.set = f ? I("set", 0, d) : function (e, t) { e[r] = t; }), N = T.call(z, D ? { get: P.get, set: P.set } : P[F], H), A.v = 1, D) { if ("object" == typeof N && N) (c = b(N.get, "accessor.get")) && (P.get = c), (c = b(N.set, "accessor.set")) && (P.set = c), (c = b(N.init, "accessor.init")) && k.unshift(c);else if (void 0 !== N) throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined"); } else b(N, (l ? "field" : "method") + " decorators", "return") && (l ? k.unshift(N) : P[F] = N); } return o < 2 && u.push(g(k, s, 1), g(i, s, 0)), l || w || (f ? D ? u.splice(-1, 0, I("get", s), I("set", s)) : u.push(E ? P[F] : b.call.bind(P[F])) : m(e, r, P)), N; } function w(e) { return m(e, d, { configurable: !0, enumerable: !0, value: a }); } return void 0 !== i && (a = i[d]), a = h(null == a ? null : a), f = [], l = function (e) { e && f.push(g(e)); }, p = function (t, r) { for (var i = 0; i < n.length; i++) { var a = n[i], c = a[1], l = 7 & c; if ((8 & c) == t && !l == r) { var p = a[2], d = !!a[3], m = 16 & c; applyDec(t ? e : e.prototype, a, m, d ? "#" + p : _toPropertyKey(p), l, l < 2 ? [] : t ? s = s || [] : u = u || [], f, !!t, d, r, t && d ? function (t) { return _checkInRHS(t) === e; } : o); } } }, p(8, 0), p(0, 0), p(8, 1), p(0, 1), l(u), l(s), c = f, v || w(e), { e: c, get c() { var n = []; return v && [w(e = applyDec(e, [t], r, e.name, 5, n)), g(n, 1)]; } }; }
3
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
4
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
5
+ function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : ""); try { Object.defineProperty(e, "name", { configurable: !0, value: n ? n + " " + t : t }); } catch (e) {} return e; }
6
+ function _checkInRHS(e) { if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); return e; }
7
+ import { Inject, InvariantError } from '@fluojs/core';
8
+ import { EVENT_BUS as FLUO_EVENT_BUS } from '@fluojs/event-bus';
9
+ import { APPLICATION_LOGGER, COMPILED_MODULES, RUNTIME_CONTAINER } from '@fluojs/runtime/internal';
10
+ import { CqrsBusBase } from '../discovery.js';
11
+ import { createIsolatedEvent } from '../event-clone.js';
12
+ import { getEventHandlerMetadata } from '../metadata.js';
13
+ import { CqrsSagaLifecycleService } from './saga-bus.js';
14
+ import { createCqrsPlatformStatusSnapshot } from '../status.js';
15
+ function isEventHandler(value) {
16
+ if (typeof value !== 'object' || value === null) {
17
+ return false;
18
+ }
19
+ return typeof value.handle === 'function';
20
+ }
21
+
22
+ /**
23
+ * CQRS-facing event bus that dispatches local event handlers, sagas, and the shared event transport.
24
+ *
25
+ * This service keeps CQRS event handlers singleton-only, fans events into saga orchestration,
26
+ * and delegates the final publication step to `@fluojs/event-bus`.
27
+ */
28
+ let _CqrsEventBusService;
29
+ class CqrsEventBusService extends CqrsBusBase {
30
+ static {
31
+ [_CqrsEventBusService, _initClass] = _applyDecs(this, [Inject(FLUO_EVENT_BUS, CqrsSagaLifecycleService, RUNTIME_CONTAINER, COMPILED_MODULES, APPLICATION_LOGGER)], [], 0, void 0, CqrsBusBase).c;
32
+ }
33
+ descriptors = [];
34
+ discoveryPromise;
35
+ discovered = false;
36
+ lifecycleState = 'created';
37
+ constructor(eventBus, sagaService, runtimeContainer, compiledModules, logger) {
38
+ super(runtimeContainer, compiledModules, logger);
39
+ this.eventBus = eventBus;
40
+ this.sagaService = sagaService;
41
+ }
42
+ async onApplicationBootstrap() {
43
+ this.lifecycleState = 'discovering';
44
+ try {
45
+ await this.ensureDiscovered();
46
+ this.lifecycleState = 'ready';
47
+ } catch (error) {
48
+ this.lifecycleState = 'failed';
49
+ throw error;
50
+ }
51
+ }
52
+ async onApplicationShutdown() {
53
+ this.lifecycleState = 'stopping';
54
+ this.lifecycleState = 'stopped';
55
+ }
56
+
57
+ /**
58
+ * Creates a CQRS runtime status snapshot that includes local handler and saga state.
59
+ *
60
+ * @returns A structured snapshot describing CQRS event-handler discovery and saga lifecycle state.
61
+ */
62
+ createPlatformStatusSnapshot() {
63
+ const sagaSnapshot = this.sagaService.getRuntimeSnapshot();
64
+ return createCqrsPlatformStatusSnapshot({
65
+ eventHandlersDiscovered: this.descriptors.length,
66
+ inFlightSagaExecutions: sagaSnapshot.inFlightSagaExecutions,
67
+ lifecycleState: this.lifecycleState,
68
+ sagaLifecycleState: sagaSnapshot.lifecycleState,
69
+ sagasDiscovered: sagaSnapshot.sagasDiscovered
70
+ });
71
+ }
72
+
73
+ /**
74
+ * Publishes one event to matching CQRS handlers, sagas, and the shared event bus.
75
+ *
76
+ * @param event Event instance to publish.
77
+ * @returns A promise that resolves once all local CQRS side effects and delegated publication complete.
78
+ *
79
+ * @throws {InvariantError} When a discovered provider does not implement `handle(event)`.
80
+ */
81
+ async publish(event) {
82
+ await this.ensureDiscovered();
83
+ for (const descriptor of this.matchEventDescriptors(event)) {
84
+ const instance = await this.resolveHandlerInstance(descriptor.token);
85
+ if (!isEventHandler(instance)) {
86
+ throw new InvariantError(`Event handler ${descriptor.targetType.name} must implement handle(event).`);
87
+ }
88
+ await instance.handle(createIsolatedEvent(descriptor.eventType, event));
89
+ }
90
+ await this.sagaService.dispatch(event);
91
+ await this.eventBus.publish(event);
92
+ }
93
+
94
+ /**
95
+ * Publishes a batch of events sequentially through the CQRS event pipeline.
96
+ *
97
+ * @param events Event instances to publish in order.
98
+ * @returns A promise that resolves once all events are published.
99
+ */
100
+ async publishAll(events) {
101
+ for (const event of events) {
102
+ await this.publish(event);
103
+ }
104
+ }
105
+ matchEventDescriptors(event) {
106
+ return this.descriptors.filter(descriptor => event instanceof descriptor.eventType);
107
+ }
108
+ async ensureDiscovered() {
109
+ if (this.discovered) {
110
+ return;
111
+ }
112
+ if (this.discoveryPromise) {
113
+ await this.discoveryPromise;
114
+ return;
115
+ }
116
+ this.discoveryPromise = this.discoverHandlers();
117
+ await this.discoveryPromise;
118
+ }
119
+ async discoverHandlers() {
120
+ try {
121
+ this.descriptors = this.discoverEventDescriptors();
122
+ this.handlerInstances.clear();
123
+ for (const descriptor of this.descriptors) {
124
+ await this.preloadHandlerInstance(descriptor.token);
125
+ }
126
+ this.discovered = true;
127
+ } finally {
128
+ this.discoveryPromise = undefined;
129
+ }
130
+ }
131
+ discoverEventDescriptors() {
132
+ const descriptors = [];
133
+ const seenByTarget = new WeakMap();
134
+ for (const candidate of this.discoveryCandidates()) {
135
+ const metadata = getEventHandlerMetadata(candidate.targetType);
136
+ if (!metadata) {
137
+ continue;
138
+ }
139
+ if (candidate.scope !== 'singleton') {
140
+ this.logger.warn(`${candidate.targetType.name} in module ${candidate.moduleName} declares @EventHandler() but is registered with ${candidate.scope} scope. Event handlers are registered only for singleton providers.`, 'CqrsEventBusService');
141
+ continue;
142
+ }
143
+ const seenEventTypes = seenByTarget.get(candidate.targetType) ?? new Set();
144
+ if (seenEventTypes.has(metadata.eventType)) {
145
+ continue;
146
+ }
147
+ seenEventTypes.add(metadata.eventType);
148
+ seenByTarget.set(candidate.targetType, seenEventTypes);
149
+ const alreadyRegistered = descriptors.some(descriptor => descriptor.eventType === metadata.eventType && descriptor.targetType === candidate.targetType);
150
+ if (!alreadyRegistered) {
151
+ descriptors.push({
152
+ eventType: metadata.eventType,
153
+ moduleName: candidate.moduleName,
154
+ targetType: candidate.targetType,
155
+ token: candidate.token
156
+ });
157
+ }
158
+ }
159
+ return descriptors;
160
+ }
161
+ static {
162
+ _initClass();
163
+ }
164
+ }
165
+ export { _CqrsEventBusService as CqrsEventBusService };
@@ -0,0 +1,29 @@
1
+ import { type OnApplicationBootstrap } from '@fluojs/runtime';
2
+ import { CqrsBusBase } from '../discovery.js';
3
+ import type { IQuery, QueryBus } from '../types.js';
4
+ /**
5
+ * Discovers and executes query handlers during bootstrap and runtime dispatch.
6
+ *
7
+ * The query bus resolves singleton handlers only, warns on unsupported scopes,
8
+ * and preserves the one-query-to-one-handler contract used by the CQRS surface.
9
+ */
10
+ export declare class QueryBusLifecycleService extends CqrsBusBase implements QueryBus, OnApplicationBootstrap {
11
+ private descriptors;
12
+ private discoveryPromise;
13
+ private discovered;
14
+ onApplicationBootstrap(): Promise<void>;
15
+ /**
16
+ * Executes one query by dispatching it to the discovered handler for its constructor.
17
+ *
18
+ * @param query Query instance to execute.
19
+ * @returns The resolved handler result.
20
+ *
21
+ * @throws {QueryHandlerNotFoundException} When no handler is registered for the query type.
22
+ * @throws {InvariantError} When the resolved provider does not implement `execute(query)`.
23
+ */
24
+ execute<TQuery extends IQuery<TResult>, TResult = unknown>(query: TQuery): Promise<TResult>;
25
+ private ensureDiscovered;
26
+ private discoverHandlers;
27
+ private discoverQueryDescriptors;
28
+ }
29
+ //# sourceMappingURL=query-bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-bus.d.ts","sourceRoot":"","sources":["../../src/buses/query-bus.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,sBAAsB,EAC5B,MAAM,iBAAiB,CAAC;AAKzB,OAAO,EAAE,WAAW,EAAiC,MAAM,iBAAiB,CAAC;AAC7E,OAAO,KAAK,EACV,MAAM,EAEN,QAAQ,EAGT,MAAM,aAAa,CAAC;AAUrB;;;;;GAKG;AACH,qBACa,wBAAyB,SAAQ,WAAY,YAAW,QAAQ,EAAE,sBAAsB;IACnG,OAAO,CAAC,WAAW,CAAgD;IACnE,OAAO,CAAC,gBAAgB,CAA4B;IACpD,OAAO,CAAC,UAAU,CAAS;IAErB,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAI7C;;;;;;;;OAQG;IACG,OAAO,CAAC,MAAM,SAAS,MAAM,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;YAmBnF,gBAAgB;YAchB,gBAAgB;IAe9B,OAAO,CAAC,wBAAwB;CAmDjC"}
@@ -0,0 +1,122 @@
1
+ let _initClass;
2
+ function _applyDecs(e, t, n, r, o, i) { var a, c, u, s, f, l, p, d = Symbol.metadata || Symbol.for("Symbol.metadata"), m = Object.defineProperty, h = Object.create, y = [h(null), h(null)], v = t.length; function g(t, n, r) { return function (o, i) { n && (i = o, o = e); for (var a = 0; a < t.length; a++) i = t[a].apply(o, r ? [i] : []); return r ? i : o; }; } function b(e, t, n, r) { if ("function" != typeof e && (r || void 0 !== e)) throw new TypeError(t + " must " + (n || "be") + " a function" + (r ? "" : " or undefined")); return e; } function applyDec(e, t, n, r, o, i, u, s, f, l, p) { function d(e) { if (!p(e)) throw new TypeError("Attempted to access private element on non-instance"); } var h = [].concat(t[0]), v = t[3], w = !u, D = 1 === o, S = 3 === o, j = 4 === o, E = 2 === o; function I(t, n, r) { return function (o, i) { return n && (i = o, o = e), r && r(o), P[t].call(o, i); }; } if (!w) { var P = {}, k = [], F = S ? "get" : j || D ? "set" : "value"; if (f ? (l || D ? P = { get: _setFunctionName(function () { return v(this); }, r, "get"), set: function (e) { t[4](this, e); } } : P[F] = v, l || _setFunctionName(P[F], r, E ? "" : F)) : l || (P = Object.getOwnPropertyDescriptor(e, r)), !l && !f) { if ((c = y[+s][r]) && 7 !== (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet"); y[+s][r] = o < 3 ? 1 : o; } } for (var N = e, O = h.length - 1; O >= 0; O -= n ? 2 : 1) { var T = b(h[O], "A decorator", "be", !0), z = n ? h[O - 1] : void 0, A = {}, H = { kind: ["field", "accessor", "method", "getter", "setter", "class"][o], name: r, metadata: a, addInitializer: function (e, t) { if (e.v) throw new TypeError("attempted to call addInitializer after decoration was finished"); b(t, "An initializer", "be", !0), i.push(t); }.bind(null, A) }; if (w) c = T.call(z, N, H), A.v = 1, b(c, "class decorators", "return") && (N = c);else if (H.static = s, H.private = f, c = H.access = { has: f ? p.bind() : function (e) { return r in e; } }, j || (c.get = f ? E ? function (e) { return d(e), P.value; } : I("get", 0, d) : function (e) { return e[r]; }), E || S || (c.set = f ? I("set", 0, d) : function (e, t) { e[r] = t; }), N = T.call(z, D ? { get: P.get, set: P.set } : P[F], H), A.v = 1, D) { if ("object" == typeof N && N) (c = b(N.get, "accessor.get")) && (P.get = c), (c = b(N.set, "accessor.set")) && (P.set = c), (c = b(N.init, "accessor.init")) && k.unshift(c);else if (void 0 !== N) throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined"); } else b(N, (l ? "field" : "method") + " decorators", "return") && (l ? k.unshift(N) : P[F] = N); } return o < 2 && u.push(g(k, s, 1), g(i, s, 0)), l || w || (f ? D ? u.splice(-1, 0, I("get", s), I("set", s)) : u.push(E ? P[F] : b.call.bind(P[F])) : m(e, r, P)), N; } function w(e) { return m(e, d, { configurable: !0, enumerable: !0, value: a }); } return void 0 !== i && (a = i[d]), a = h(null == a ? null : a), f = [], l = function (e) { e && f.push(g(e)); }, p = function (t, r) { for (var i = 0; i < n.length; i++) { var a = n[i], c = a[1], l = 7 & c; if ((8 & c) == t && !l == r) { var p = a[2], d = !!a[3], m = 16 & c; applyDec(t ? e : e.prototype, a, m, d ? "#" + p : _toPropertyKey(p), l, l < 2 ? [] : t ? s = s || [] : u = u || [], f, !!t, d, r, t && d ? function (t) { return _checkInRHS(t) === e; } : o); } } }, p(8, 0), p(0, 0), p(8, 1), p(0, 1), l(u), l(s), c = f, v || w(e), { e: c, get c() { var n = []; return v && [w(e = applyDec(e, [t], r, e.name, 5, n)), g(n, 1)]; } }; }
3
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
4
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
5
+ function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : ""); try { Object.defineProperty(e, "name", { configurable: !0, value: n ? n + " " + t : t }); } catch (e) {} return e; }
6
+ function _checkInRHS(e) { if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); return e; }
7
+ import { Inject, InvariantError } from '@fluojs/core';
8
+ import { APPLICATION_LOGGER, COMPILED_MODULES, RUNTIME_CONTAINER } from '@fluojs/runtime/internal';
9
+ import { DuplicateQueryHandlerError, QueryHandlerNotFoundException } from '../errors.js';
10
+ import { getQueryHandlerMetadata } from '../metadata.js';
11
+ import { CqrsBusBase, createDuplicateHandlerMessage } from '../discovery.js';
12
+ function isQueryHandler(value) {
13
+ if (typeof value !== 'object' || value === null) {
14
+ return false;
15
+ }
16
+ return typeof value.execute === 'function';
17
+ }
18
+
19
+ /**
20
+ * Discovers and executes query handlers during bootstrap and runtime dispatch.
21
+ *
22
+ * The query bus resolves singleton handlers only, warns on unsupported scopes,
23
+ * and preserves the one-query-to-one-handler contract used by the CQRS surface.
24
+ */
25
+ let _QueryBusLifecycleSer;
26
+ class QueryBusLifecycleService extends CqrsBusBase {
27
+ static {
28
+ [_QueryBusLifecycleSer, _initClass] = _applyDecs(this, [Inject(RUNTIME_CONTAINER, COMPILED_MODULES, APPLICATION_LOGGER)], [], 0, void 0, CqrsBusBase).c;
29
+ }
30
+ descriptors = new Map();
31
+ discoveryPromise;
32
+ discovered = false;
33
+ async onApplicationBootstrap() {
34
+ await this.ensureDiscovered();
35
+ }
36
+
37
+ /**
38
+ * Executes one query by dispatching it to the discovered handler for its constructor.
39
+ *
40
+ * @param query Query instance to execute.
41
+ * @returns The resolved handler result.
42
+ *
43
+ * @throws {QueryHandlerNotFoundException} When no handler is registered for the query type.
44
+ * @throws {InvariantError} When the resolved provider does not implement `execute(query)`.
45
+ */
46
+ async execute(query) {
47
+ await this.ensureDiscovered();
48
+ const queryType = query.constructor;
49
+ const descriptor = this.descriptors.get(queryType);
50
+ if (!descriptor) {
51
+ throw new QueryHandlerNotFoundException(`No query handler registered for ${queryType.name}.`);
52
+ }
53
+ const instance = await this.resolveHandlerInstance(descriptor.token);
54
+ if (!isQueryHandler(instance)) {
55
+ throw new InvariantError(`Query handler ${descriptor.targetType.name} must implement execute(query).`);
56
+ }
57
+ return await instance.execute(query);
58
+ }
59
+ async ensureDiscovered() {
60
+ if (this.discovered) {
61
+ return;
62
+ }
63
+ if (this.discoveryPromise) {
64
+ await this.discoveryPromise;
65
+ return;
66
+ }
67
+ this.discoveryPromise = this.discoverHandlers();
68
+ await this.discoveryPromise;
69
+ }
70
+ async discoverHandlers() {
71
+ try {
72
+ this.descriptors = this.discoverQueryDescriptors();
73
+ this.handlerInstances.clear();
74
+ for (const descriptor of this.descriptors.values()) {
75
+ await this.preloadHandlerInstance(descriptor.token);
76
+ }
77
+ this.discovered = true;
78
+ } finally {
79
+ this.discoveryPromise = undefined;
80
+ }
81
+ }
82
+ discoverQueryDescriptors() {
83
+ const descriptors = new Map();
84
+ const seenByTarget = new WeakMap();
85
+ for (const candidate of this.discoveryCandidates()) {
86
+ const metadata = getQueryHandlerMetadata(candidate.targetType);
87
+ if (!metadata) {
88
+ continue;
89
+ }
90
+ if (candidate.scope !== 'singleton') {
91
+ this.logger.warn(`${candidate.targetType.name} in module ${candidate.moduleName} declares @QueryHandler() but is registered with ${candidate.scope} scope. Query handlers are registered only for singleton providers.`, 'QueryBusLifecycleService');
92
+ continue;
93
+ }
94
+ const seenQueryTypes = seenByTarget.get(candidate.targetType) ?? new Set();
95
+ if (seenQueryTypes.has(metadata.queryType)) {
96
+ continue;
97
+ }
98
+ seenQueryTypes.add(metadata.queryType);
99
+ seenByTarget.set(candidate.targetType, seenQueryTypes);
100
+ const existing = descriptors.get(metadata.queryType);
101
+ if (existing && existing.targetType !== candidate.targetType) {
102
+ throw new DuplicateQueryHandlerError(createDuplicateHandlerMessage('query', metadata.queryType, existing, {
103
+ moduleName: candidate.moduleName,
104
+ targetType: candidate.targetType
105
+ }));
106
+ }
107
+ if (!existing) {
108
+ descriptors.set(metadata.queryType, {
109
+ moduleName: candidate.moduleName,
110
+ queryType: metadata.queryType,
111
+ targetType: candidate.targetType,
112
+ token: candidate.token
113
+ });
114
+ }
115
+ }
116
+ return descriptors;
117
+ }
118
+ static {
119
+ _initClass();
120
+ }
121
+ }
122
+ export { _QueryBusLifecycleSer as QueryBusLifecycleService };
@@ -0,0 +1,46 @@
1
+ import type { OnApplicationBootstrap, OnApplicationShutdown } from '@fluojs/runtime';
2
+ import { CqrsBusBase } from '../discovery.js';
3
+ import type { IEvent } from '../types.js';
4
+ /**
5
+ * Runtime saga coordinator that discovers `@Saga()` providers and serializes execution per saga token.
6
+ *
7
+ * The service prevents re-entrant dispatch loops within the same async context and waits for
8
+ * in-flight saga chains during shutdown so lifecycle guarantees remain predictable.
9
+ */
10
+ export declare class CqrsSagaLifecycleService extends CqrsBusBase implements OnApplicationBootstrap, OnApplicationShutdown {
11
+ private descriptorsByEvent;
12
+ private discoveryPromise;
13
+ private discovered;
14
+ private readonly executionChains;
15
+ private lifecycleState;
16
+ private readonly pendingDispatches;
17
+ private readonly dispatchContext;
18
+ onApplicationBootstrap(): Promise<void>;
19
+ onApplicationShutdown(): Promise<void>;
20
+ /**
21
+ * Returns an internal runtime snapshot used by the CQRS event bus and diagnostics.
22
+ *
23
+ * @returns Current discovery state, in-flight execution count, lifecycle state, and discovered saga count.
24
+ */
25
+ getRuntimeSnapshot(): {
26
+ discovered: boolean;
27
+ inFlightSagaExecutions: number;
28
+ lifecycleState: 'created' | 'discovering' | 'ready' | 'stopping' | 'stopped' | 'failed';
29
+ sagasDiscovered: number;
30
+ };
31
+ /**
32
+ * Dispatches one event to every matching saga descriptor.
33
+ *
34
+ * @param event Event instance that may trigger one or more sagas.
35
+ * @returns A promise that resolves once all matching saga chains for the event complete.
36
+ */
37
+ dispatch<TEvent extends IEvent>(event: TEvent): Promise<void>;
38
+ private matchSagaDescriptors;
39
+ private dispatchWithOrdering;
40
+ private runInDispatchContext;
41
+ private invokeSaga;
42
+ private ensureDiscovered;
43
+ private discoverHandlers;
44
+ private discoverSagaDescriptors;
45
+ }
46
+ //# sourceMappingURL=saga-bus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"saga-bus.d.ts","sourceRoot":"","sources":["../../src/buses/saga-bus.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,sBAAsB,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAGrF,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAI9C,OAAO,KAAK,EAAiB,MAAM,EAAyB,MAAM,aAAa,CAAC;AA0BhF;;;;;GAKG;AACH,qBACa,wBAAyB,SAAQ,WAAY,YAAW,sBAAsB,EAAE,qBAAqB;IAChH,OAAO,CAAC,kBAAkB,CAA8C;IACxE,OAAO,CAAC,gBAAgB,CAA4B;IACpD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmC;IACnE,OAAO,CAAC,cAAc,CAAsF;IAC5G,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAA4B;IAC9D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgD;IAE1E,sBAAsB,IAAI,OAAO,CAAC,IAAI,CAAC;IAYvC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAiB5C;;;;OAIG;IACH,kBAAkB,IAAI;QACpB,UAAU,EAAE,OAAO,CAAC;QACpB,sBAAsB,EAAE,MAAM,CAAC;QAC/B,cAAc,EAAE,SAAS,GAAG,aAAa,GAAG,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,QAAQ,CAAC;QACxF,eAAe,EAAE,MAAM,CAAC;KACzB;IASD;;;;;OAKG;IACG,QAAQ,CAAC,MAAM,SAAS,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYnE,OAAO,CAAC,oBAAoB;YAYd,oBAAoB;YA+CpB,oBAAoB;YAepB,UAAU;YAoBV,gBAAgB;YAchB,gBAAgB;IAiB9B,OAAO,CAAC,uBAAuB;CA+ChC"}
@@ -0,0 +1,225 @@
1
+ let _initClass;
2
+ function _applyDecs(e, t, n, r, o, i) { var a, c, u, s, f, l, p, d = Symbol.metadata || Symbol.for("Symbol.metadata"), m = Object.defineProperty, h = Object.create, y = [h(null), h(null)], v = t.length; function g(t, n, r) { return function (o, i) { n && (i = o, o = e); for (var a = 0; a < t.length; a++) i = t[a].apply(o, r ? [i] : []); return r ? i : o; }; } function b(e, t, n, r) { if ("function" != typeof e && (r || void 0 !== e)) throw new TypeError(t + " must " + (n || "be") + " a function" + (r ? "" : " or undefined")); return e; } function applyDec(e, t, n, r, o, i, u, s, f, l, p) { function d(e) { if (!p(e)) throw new TypeError("Attempted to access private element on non-instance"); } var h = [].concat(t[0]), v = t[3], w = !u, D = 1 === o, S = 3 === o, j = 4 === o, E = 2 === o; function I(t, n, r) { return function (o, i) { return n && (i = o, o = e), r && r(o), P[t].call(o, i); }; } if (!w) { var P = {}, k = [], F = S ? "get" : j || D ? "set" : "value"; if (f ? (l || D ? P = { get: _setFunctionName(function () { return v(this); }, r, "get"), set: function (e) { t[4](this, e); } } : P[F] = v, l || _setFunctionName(P[F], r, E ? "" : F)) : l || (P = Object.getOwnPropertyDescriptor(e, r)), !l && !f) { if ((c = y[+s][r]) && 7 !== (c ^ o)) throw Error("Decorating two elements with the same name (" + P[F].name + ") is not supported yet"); y[+s][r] = o < 3 ? 1 : o; } } for (var N = e, O = h.length - 1; O >= 0; O -= n ? 2 : 1) { var T = b(h[O], "A decorator", "be", !0), z = n ? h[O - 1] : void 0, A = {}, H = { kind: ["field", "accessor", "method", "getter", "setter", "class"][o], name: r, metadata: a, addInitializer: function (e, t) { if (e.v) throw new TypeError("attempted to call addInitializer after decoration was finished"); b(t, "An initializer", "be", !0), i.push(t); }.bind(null, A) }; if (w) c = T.call(z, N, H), A.v = 1, b(c, "class decorators", "return") && (N = c);else if (H.static = s, H.private = f, c = H.access = { has: f ? p.bind() : function (e) { return r in e; } }, j || (c.get = f ? E ? function (e) { return d(e), P.value; } : I("get", 0, d) : function (e) { return e[r]; }), E || S || (c.set = f ? I("set", 0, d) : function (e, t) { e[r] = t; }), N = T.call(z, D ? { get: P.get, set: P.set } : P[F], H), A.v = 1, D) { if ("object" == typeof N && N) (c = b(N.get, "accessor.get")) && (P.get = c), (c = b(N.set, "accessor.set")) && (P.set = c), (c = b(N.init, "accessor.init")) && k.unshift(c);else if (void 0 !== N) throw new TypeError("accessor decorators must return an object with get, set, or init properties or undefined"); } else b(N, (l ? "field" : "method") + " decorators", "return") && (l ? k.unshift(N) : P[F] = N); } return o < 2 && u.push(g(k, s, 1), g(i, s, 0)), l || w || (f ? D ? u.splice(-1, 0, I("get", s), I("set", s)) : u.push(E ? P[F] : b.call.bind(P[F])) : m(e, r, P)), N; } function w(e) { return m(e, d, { configurable: !0, enumerable: !0, value: a }); } return void 0 !== i && (a = i[d]), a = h(null == a ? null : a), f = [], l = function (e) { e && f.push(g(e)); }, p = function (t, r) { for (var i = 0; i < n.length; i++) { var a = n[i], c = a[1], l = 7 & c; if ((8 & c) == t && !l == r) { var p = a[2], d = !!a[3], m = 16 & c; applyDec(t ? e : e.prototype, a, m, d ? "#" + p : _toPropertyKey(p), l, l < 2 ? [] : t ? s = s || [] : u = u || [], f, !!t, d, r, t && d ? function (t) { return _checkInRHS(t) === e; } : o); } } }, p(8, 0), p(0, 0), p(8, 1), p(0, 1), l(u), l(s), c = f, v || w(e), { e: c, get c() { var n = []; return v && [w(e = applyDec(e, [t], r, e.name, 5, n)), g(n, 1)]; } }; }
3
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; }
4
+ function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
5
+ function _setFunctionName(e, t, n) { "symbol" == typeof t && (t = (t = t.description) ? "[" + t + "]" : ""); try { Object.defineProperty(e, "name", { configurable: !0, value: n ? n + " " + t : t }); } catch (e) {} return e; }
6
+ function _checkInRHS(e) { if (Object(e) !== e) throw TypeError("right-hand side of 'in' should be an object, got " + (null !== e ? typeof e : "null")); return e; }
7
+ import { AsyncLocalStorage } from 'node:async_hooks';
8
+ import { Inject, InvariantError, FluoError } from '@fluojs/core';
9
+ import { APPLICATION_LOGGER, COMPILED_MODULES, RUNTIME_CONTAINER } from '@fluojs/runtime/internal';
10
+ import { CqrsBusBase } from '../discovery.js';
11
+ import { SagaExecutionError, SagaTopologyError } from '../errors.js';
12
+ import { createIsolatedEvent } from '../event-clone.js';
13
+ import { getSagaMetadata } from '../metadata.js';
14
+ const MAX_NESTED_SAGA_DEPTH = 32;
15
+ function isSaga(value) {
16
+ if (typeof value !== 'object' || value === null) {
17
+ return false;
18
+ }
19
+ return typeof value.handle === 'function';
20
+ }
21
+ function toErrorMessage(error) {
22
+ if (error instanceof Error) {
23
+ return error.message;
24
+ }
25
+ return String(error);
26
+ }
27
+
28
+ /**
29
+ * Runtime saga coordinator that discovers `@Saga()` providers and serializes execution per saga token.
30
+ *
31
+ * The service prevents re-entrant dispatch loops within the same async context and waits for
32
+ * in-flight saga chains during shutdown so lifecycle guarantees remain predictable.
33
+ */
34
+ let _CqrsSagaLifecycleSer;
35
+ class CqrsSagaLifecycleService extends CqrsBusBase {
36
+ static {
37
+ [_CqrsSagaLifecycleSer, _initClass] = _applyDecs(this, [Inject(RUNTIME_CONTAINER, COMPILED_MODULES, APPLICATION_LOGGER)], [], 0, void 0, CqrsBusBase).c;
38
+ }
39
+ descriptorsByEvent = new Map();
40
+ discoveryPromise;
41
+ discovered = false;
42
+ executionChains = new Map();
43
+ lifecycleState = 'created';
44
+ pendingDispatches = new Set();
45
+ dispatchContext = new AsyncLocalStorage();
46
+ async onApplicationBootstrap() {
47
+ this.lifecycleState = 'discovering';
48
+ try {
49
+ await this.ensureDiscovered();
50
+ this.lifecycleState = 'ready';
51
+ } catch (error) {
52
+ this.lifecycleState = 'failed';
53
+ throw error;
54
+ }
55
+ }
56
+ async onApplicationShutdown() {
57
+ this.lifecycleState = 'stopping';
58
+ while (this.pendingDispatches.size > 0) {
59
+ await Promise.allSettled(Array.from(this.pendingDispatches));
60
+ }
61
+ await Promise.allSettled(this.executionChains.values());
62
+ this.executionChains.clear();
63
+ this.handlerInstances.clear();
64
+ this.descriptorsByEvent.clear();
65
+ this.discovered = false;
66
+ this.discoveryPromise = undefined;
67
+ this.lifecycleState = 'stopped';
68
+ }
69
+
70
+ /**
71
+ * Returns an internal runtime snapshot used by the CQRS event bus and diagnostics.
72
+ *
73
+ * @returns Current discovery state, in-flight execution count, lifecycle state, and discovered saga count.
74
+ */
75
+ getRuntimeSnapshot() {
76
+ return {
77
+ discovered: this.discovered,
78
+ inFlightSagaExecutions: this.pendingDispatches.size,
79
+ lifecycleState: this.lifecycleState,
80
+ sagasDiscovered: new Set(Array.from(this.descriptorsByEvent.values()).flatMap(descriptors => descriptors.map(d => d.token))).size
81
+ };
82
+ }
83
+
84
+ /**
85
+ * Dispatches one event to every matching saga descriptor.
86
+ *
87
+ * @param event Event instance that may trigger one or more sagas.
88
+ * @returns A promise that resolves once all matching saga chains for the event complete.
89
+ */
90
+ async dispatch(event) {
91
+ await this.ensureDiscovered();
92
+ const descriptors = this.matchSagaDescriptors(event);
93
+ if (descriptors.length === 0) {
94
+ return;
95
+ }
96
+ await Promise.all(descriptors.map(descriptor => this.dispatchWithOrdering(descriptor, event)));
97
+ }
98
+ matchSagaDescriptors(event) {
99
+ const descriptors = [];
100
+ for (const [eventType, eventDescriptors] of this.descriptorsByEvent.entries()) {
101
+ if (event instanceof eventType) {
102
+ descriptors.push(...eventDescriptors);
103
+ }
104
+ }
105
+ return descriptors;
106
+ }
107
+ async dispatchWithOrdering(descriptor, event) {
108
+ const activeContext = this.dispatchContext.getStore();
109
+ const routeLabel = `${descriptor.targetType.name}(${descriptor.eventType.name})`;
110
+ const isActiveRoute = activeContext?.activeRoutes.some(route => route.token === descriptor.token && route.eventType === descriptor.eventType);
111
+ const isActiveToken = activeContext?.activeRoutes.some(route => route.token === descriptor.token) ?? false;
112
+ if (isActiveRoute) {
113
+ throw new SagaTopologyError(`Saga ${descriptor.targetType.name} re-entered an unsafe cycle while handling ${descriptor.eventType.name}. ` + `Active saga path: ${[...(activeContext?.path ?? []), routeLabel].join(' -> ')}.`);
114
+ }
115
+ if ((activeContext?.depth ?? 0) >= MAX_NESTED_SAGA_DEPTH) {
116
+ 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.');
117
+ }
118
+ if (isActiveToken) {
119
+ await this.runInDispatchContext(activeContext, descriptor, routeLabel, async () => {
120
+ await this.invokeSaga(descriptor, event);
121
+ });
122
+ return;
123
+ }
124
+ const previous = this.executionChains.get(descriptor.token) ?? Promise.resolve();
125
+ const current = previous.then(async () => {
126
+ await this.runInDispatchContext(activeContext, descriptor, routeLabel, async () => {
127
+ await this.invokeSaga(descriptor, event);
128
+ });
129
+ });
130
+ this.executionChains.set(descriptor.token, current.catch(() => undefined));
131
+ this.pendingDispatches.add(current);
132
+ try {
133
+ await current;
134
+ } finally {
135
+ this.pendingDispatches.delete(current);
136
+ }
137
+ }
138
+ async runInDispatchContext(activeContext, descriptor, routeLabel, callback) {
139
+ const nextContext = {
140
+ activeRoutes: [...(activeContext?.activeRoutes ?? []), {
141
+ eventType: descriptor.eventType,
142
+ token: descriptor.token
143
+ }],
144
+ depth: (activeContext?.depth ?? 0) + 1,
145
+ path: [...(activeContext?.path ?? []), routeLabel]
146
+ };
147
+ await this.dispatchContext.run(nextContext, callback);
148
+ }
149
+ async invokeSaga(descriptor, event) {
150
+ const instance = await this.resolveHandlerInstance(descriptor.token);
151
+ if (!isSaga(instance)) {
152
+ throw new InvariantError(`Saga ${descriptor.targetType.name} must implement handle(event).`);
153
+ }
154
+ try {
155
+ await instance.handle(createIsolatedEvent(descriptor.eventType, event));
156
+ } catch (error) {
157
+ if (error instanceof FluoError) {
158
+ throw error;
159
+ }
160
+ throw new SagaExecutionError(`Saga ${descriptor.targetType.name} failed while handling ${descriptor.eventType.name}: ${toErrorMessage(error)}`);
161
+ }
162
+ }
163
+ async ensureDiscovered() {
164
+ if (this.discovered) {
165
+ return;
166
+ }
167
+ if (this.discoveryPromise) {
168
+ await this.discoveryPromise;
169
+ return;
170
+ }
171
+ this.discoveryPromise = this.discoverHandlers();
172
+ await this.discoveryPromise;
173
+ }
174
+ async discoverHandlers() {
175
+ try {
176
+ this.descriptorsByEvent = this.discoverSagaDescriptors();
177
+ this.handlerInstances.clear();
178
+ for (const descriptors of this.descriptorsByEvent.values()) {
179
+ for (const descriptor of descriptors) {
180
+ await this.preloadHandlerInstance(descriptor.token);
181
+ }
182
+ }
183
+ this.discovered = true;
184
+ } finally {
185
+ this.discoveryPromise = undefined;
186
+ }
187
+ }
188
+ discoverSagaDescriptors() {
189
+ const descriptorsByEvent = new Map();
190
+ const seenByTarget = new WeakMap();
191
+ for (const candidate of this.discoveryCandidates()) {
192
+ const metadata = getSagaMetadata(candidate.targetType);
193
+ if (!metadata) {
194
+ continue;
195
+ }
196
+ if (candidate.scope !== 'singleton') {
197
+ this.logger.warn(`${candidate.targetType.name} in module ${candidate.moduleName} declares @Saga() but is registered with ${candidate.scope} scope. Sagas are registered only for singleton providers.`, 'CqrsSagaLifecycleService');
198
+ continue;
199
+ }
200
+ const seenEventTypes = seenByTarget.get(candidate.targetType) ?? new Set();
201
+ for (const eventType of metadata.eventTypes) {
202
+ if (seenEventTypes.has(eventType)) {
203
+ continue;
204
+ }
205
+ seenEventTypes.add(eventType);
206
+ const descriptors = descriptorsByEvent.get(eventType) ?? [];
207
+ if (!descriptors.some(descriptor => descriptor.targetType === candidate.targetType)) {
208
+ descriptors.push({
209
+ eventType,
210
+ moduleName: candidate.moduleName,
211
+ targetType: candidate.targetType,
212
+ token: candidate.token
213
+ });
214
+ descriptorsByEvent.set(eventType, descriptors);
215
+ }
216
+ }
217
+ seenByTarget.set(candidate.targetType, seenEventTypes);
218
+ }
219
+ return descriptorsByEvent;
220
+ }
221
+ static {
222
+ _initClass();
223
+ }
224
+ }
225
+ export { _CqrsSagaLifecycleSer as CqrsSagaLifecycleService };
@@ -0,0 +1,48 @@
1
+ import type { CommandType, CqrsEventType, QueryType } from './types.js';
2
+ type ClassDecoratorLike = (value: Function, context: ClassDecoratorContext) => void;
3
+ /**
4
+ * Associates a singleton provider class with one command type.
5
+ *
6
+ * @param commandType Command constructor handled by the decorated class.
7
+ * @returns A class decorator that stores command-handler metadata for discovery.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * import { CommandHandler, type ICommandHandler } from '@fluojs/cqrs';
12
+ *
13
+ * class CreateUserCommand {
14
+ * constructor(public readonly name: string) {}
15
+ * }
16
+ *
17
+ * @CommandHandler(CreateUserCommand)
18
+ * export class CreateUserHandler implements ICommandHandler<CreateUserCommand, string> {
19
+ * async execute(command: CreateUserCommand) {
20
+ * return command.name;
21
+ * }
22
+ * }
23
+ * ```
24
+ */
25
+ export declare function CommandHandler(commandType: CommandType): ClassDecoratorLike;
26
+ /**
27
+ * Associates a singleton provider class with one query type.
28
+ *
29
+ * @param queryType Query constructor handled by the decorated class.
30
+ * @returns A class decorator that stores query-handler metadata for discovery.
31
+ */
32
+ export declare function QueryHandler(queryType: QueryType): ClassDecoratorLike;
33
+ /**
34
+ * Associates a singleton provider class with one event type.
35
+ *
36
+ * @param eventType Event constructor handled by the decorated class.
37
+ * @returns A class decorator that stores event-handler metadata for discovery.
38
+ */
39
+ export declare function EventHandler(eventType: CqrsEventType): ClassDecoratorLike;
40
+ /**
41
+ * Marks a singleton provider class as a saga listener for one or more event types.
42
+ *
43
+ * @param eventTypeOrTypes One event constructor or a list of constructors that should trigger the saga.
44
+ * @returns A class decorator that stores saga metadata for discovery.
45
+ */
46
+ export declare function Saga(eventTypeOrTypes: CqrsEventType | readonly CqrsEventType[]): ClassDecoratorLike;
47
+ export {};
48
+ //# sourceMappingURL=decorators.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decorators.d.ts","sourceRoot":"","sources":["../src/decorators.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAEV,WAAW,EACX,aAAa,EAGb,SAAS,EAEV,MAAM,YAAY,CAAC;AAEpB,KAAK,kBAAkB,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAC;AA0DpF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,WAAW,GAAG,kBAAkB,CAU3E;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,kBAAkB,CAUrE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,aAAa,GAAG,kBAAkB,CAUzE;AAED;;;;;GAKG;AACH,wBAAgB,IAAI,CAAC,gBAAgB,EAAE,aAAa,GAAG,SAAS,aAAa,EAAE,GAAG,kBAAkB,CAYnG"}