@nestjs-transactional/cqrs 1.0.0-alpha.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 (51) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +431 -0
  3. package/dist/decorators/integration-events-handler.decorator.d.ts +125 -0
  4. package/dist/decorators/integration-events-handler.decorator.js +57 -0
  5. package/dist/decorators/integration-events-handler.decorator.js.map +1 -0
  6. package/dist/decorators/transactional-events-handler.decorator.d.ts +138 -0
  7. package/dist/decorators/transactional-events-handler.decorator.js +65 -0
  8. package/dist/decorators/transactional-events-handler.decorator.js.map +1 -0
  9. package/dist/event-dispatcher/event-dispatcher.d.ts +100 -0
  10. package/dist/event-dispatcher/event-dispatcher.js +229 -0
  11. package/dist/event-dispatcher/event-dispatcher.js.map +1 -0
  12. package/dist/event-publisher/hybrid-event-publisher.d.ts +76 -0
  13. package/dist/event-publisher/hybrid-event-publisher.js +86 -0
  14. package/dist/event-publisher/hybrid-event-publisher.js.map +1 -0
  15. package/dist/event-publisher/transactional-event-publisher-adapter.d.ts +32 -0
  16. package/dist/event-publisher/transactional-event-publisher-adapter.js +72 -0
  17. package/dist/event-publisher/transactional-event-publisher-adapter.js.map +1 -0
  18. package/dist/event-publisher/transactional-event-publisher.d.ts +33 -0
  19. package/dist/event-publisher/transactional-event-publisher.js +58 -0
  20. package/dist/event-publisher/transactional-event-publisher.js.map +1 -0
  21. package/dist/handlers/bootstrap.d.ts +18 -0
  22. package/dist/handlers/bootstrap.js +39 -0
  23. package/dist/handlers/bootstrap.js.map +1 -0
  24. package/dist/handlers/handler-wrapper.d.ts +77 -0
  25. package/dist/handlers/handler-wrapper.js +183 -0
  26. package/dist/handlers/handler-wrapper.js.map +1 -0
  27. package/dist/handlers/integration-events-handler-scanner.d.ts +37 -0
  28. package/dist/handlers/integration-events-handler-scanner.js +144 -0
  29. package/dist/handlers/integration-events-handler-scanner.js.map +1 -0
  30. package/dist/handlers/listener-scanner.d.ts +33 -0
  31. package/dist/handlers/listener-scanner.js +86 -0
  32. package/dist/handlers/listener-scanner.js.map +1 -0
  33. package/dist/handlers/outbox-listener-registrar.d.ts +49 -0
  34. package/dist/handlers/outbox-listener-registrar.js +17 -0
  35. package/dist/handlers/outbox-listener-registrar.js.map +1 -0
  36. package/dist/index.d.ts +16 -0
  37. package/dist/index.js +37 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/interfaces/integration-event-handler.interface.d.ts +35 -0
  40. package/dist/interfaces/integration-event-handler.interface.js +3 -0
  41. package/dist/interfaces/integration-event-handler.interface.js.map +1 -0
  42. package/dist/interfaces/transactional-event-handler.interface.d.ts +31 -0
  43. package/dist/interfaces/transactional-event-handler.interface.js +3 -0
  44. package/dist/interfaces/transactional-event-handler.interface.js.map +1 -0
  45. package/dist/module/cqrs-transactional.module.d.ts +92 -0
  46. package/dist/module/cqrs-transactional.module.js +137 -0
  47. package/dist/module/cqrs-transactional.module.js.map +1 -0
  48. package/dist/types/transactional-listener.types.d.ts +21 -0
  49. package/dist/types/transactional-listener.types.js +25 -0
  50. package/dist/types/transactional-listener.types.js.map +1 -0
  51. package/package.json +73 -0
@@ -0,0 +1,37 @@
1
+ import { type OnModuleInit } from '@nestjs/common';
2
+ import { DiscoveryService } from '@nestjs/core';
3
+ import { TransactionManager } from '@nestjs-transactional/core';
4
+ import { TransactionalEventDispatcher } from '../event-dispatcher/event-dispatcher';
5
+ import { type OutboxListenerRegistrar } from './outbox-listener-registrar';
6
+ /**
7
+ * Bootstrap-time scanner for `@IntegrationEventsHandler`-annotated
8
+ * classes. Decides at startup which delivery path to wire based on
9
+ * whether an {@link OutboxListenerRegistrar} is bound:
10
+ *
11
+ * - **Outbox bound** (typically via `OutboxModule` from
12
+ * `@nestjs-transactional/outbox`): the handler's `handle`
13
+ * method is registered with the outbox registry, wrapped in a
14
+ * `REQUIRES_NEW` transaction. Delivery is durable, at-least-once,
15
+ * retried on failure, survives restarts.
16
+ *
17
+ * - **Outbox not bound**: the handler is registered with
18
+ * {@link TransactionalEventDispatcher} for `AFTER_COMMIT` phase,
19
+ * `async: true` — and the scanner itself wraps the invocation in a
20
+ * fresh transaction so downstream writes commit or roll back
21
+ * independently, matching the outbox path as closely as in-memory
22
+ * dispatch allows (minus persistence).
23
+ *
24
+ * Consumer code is identical either way; only module wiring decides.
25
+ */
26
+ export declare class IntegrationEventsHandlerScanner implements OnModuleInit {
27
+ private readonly discovery;
28
+ private readonly dispatcher;
29
+ private readonly manager;
30
+ private readonly registrar?;
31
+ private readonly logger;
32
+ constructor(discovery: DiscoveryService, dispatcher: TransactionalEventDispatcher, manager: TransactionManager, registrar?: OutboxListenerRegistrar | undefined);
33
+ onModuleInit(): void;
34
+ private registerToOutbox;
35
+ private registerToDispatcher;
36
+ }
37
+ //# sourceMappingURL=integration-events-handler-scanner.d.ts.map
@@ -0,0 +1,144 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var IntegrationEventsHandlerScanner_1;
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.IntegrationEventsHandlerScanner = void 0;
17
+ const common_1 = require("@nestjs/common");
18
+ const core_1 = require("@nestjs/core");
19
+ const core_2 = require("@nestjs-transactional/core");
20
+ const integration_events_handler_decorator_1 = require("../decorators/integration-events-handler.decorator");
21
+ const event_dispatcher_1 = require("../event-dispatcher/event-dispatcher");
22
+ const transactional_listener_types_1 = require("../types/transactional-listener.types");
23
+ const outbox_listener_registrar_1 = require("./outbox-listener-registrar");
24
+ /**
25
+ * Bootstrap-time scanner for `@IntegrationEventsHandler`-annotated
26
+ * classes. Decides at startup which delivery path to wire based on
27
+ * whether an {@link OutboxListenerRegistrar} is bound:
28
+ *
29
+ * - **Outbox bound** (typically via `OutboxModule` from
30
+ * `@nestjs-transactional/outbox`): the handler's `handle`
31
+ * method is registered with the outbox registry, wrapped in a
32
+ * `REQUIRES_NEW` transaction. Delivery is durable, at-least-once,
33
+ * retried on failure, survives restarts.
34
+ *
35
+ * - **Outbox not bound**: the handler is registered with
36
+ * {@link TransactionalEventDispatcher} for `AFTER_COMMIT` phase,
37
+ * `async: true` — and the scanner itself wraps the invocation in a
38
+ * fresh transaction so downstream writes commit or roll back
39
+ * independently, matching the outbox path as closely as in-memory
40
+ * dispatch allows (minus persistence).
41
+ *
42
+ * Consumer code is identical either way; only module wiring decides.
43
+ */
44
+ let IntegrationEventsHandlerScanner = IntegrationEventsHandlerScanner_1 = class IntegrationEventsHandlerScanner {
45
+ discovery;
46
+ dispatcher;
47
+ manager;
48
+ registrar;
49
+ logger = new common_1.Logger(IntegrationEventsHandlerScanner_1.name);
50
+ constructor(discovery, dispatcher, manager, registrar) {
51
+ this.discovery = discovery;
52
+ this.dispatcher = dispatcher;
53
+ this.manager = manager;
54
+ this.registrar = registrar;
55
+ }
56
+ onModuleInit() {
57
+ const providers = this.discovery.getProviders();
58
+ for (const wrapper of providers) {
59
+ if (wrapper.metatype === null ||
60
+ typeof wrapper.metatype !== 'function' ||
61
+ wrapper.instance === null ||
62
+ wrapper.instance === undefined) {
63
+ continue;
64
+ }
65
+ const metadata = (0, integration_events_handler_decorator_1.getIntegrationEventsHandlerMetadata)(wrapper.metatype);
66
+ if (metadata === undefined) {
67
+ continue;
68
+ }
69
+ const instance = wrapper.instance;
70
+ const rawHandle = instance.handle;
71
+ if (typeof rawHandle !== 'function') {
72
+ const className = wrapper.metatype.name ?? 'anonymous';
73
+ this.logger.warn(`@IntegrationEventsHandler on ${className}: missing \`handle(event)\` method — skipping`);
74
+ continue;
75
+ }
76
+ const boundHandle = rawHandle.bind(instance);
77
+ if (this.registrar !== undefined) {
78
+ this.registerToOutbox(instance, metadata, boundHandle, this.registrar);
79
+ }
80
+ else {
81
+ this.registerToDispatcher(instance, metadata, boundHandle);
82
+ }
83
+ }
84
+ }
85
+ registerToOutbox(instance, metadata, boundHandle, registrar) {
86
+ const manager = this.manager;
87
+ const invoke = async (event) => {
88
+ await manager.run({ propagation: core_2.PropagationMode.REQUIRES_NEW }, async () => {
89
+ await boundHandle(event);
90
+ });
91
+ };
92
+ const baseId = metadata.id ?? instance.constructor.name;
93
+ for (const eventType of metadata.eventTypes) {
94
+ const listenerId = composeListenerId(baseId, eventType);
95
+ registrar.register({
96
+ id: listenerId,
97
+ eventType: eventType.name,
98
+ invoke,
99
+ });
100
+ this.logger.debug(`Registered ${instance.constructor.name}.handle for ${eventType.name} via outbox (id=${listenerId})`);
101
+ }
102
+ }
103
+ registerToDispatcher(instance, metadata, boundHandle) {
104
+ const manager = this.manager;
105
+ // Proxy preserves the original class name for dispatcher logs
106
+ // while exposing a `handle` that opens a fresh transaction per
107
+ // invocation — AFTER_COMMIT + async + a new tx, matching the
108
+ // outbox semantics as closely as in-memory dispatch permits.
109
+ const ctor = instance.constructor;
110
+ const proxy = Object.create(ctor.prototype);
111
+ proxy.handle = async (event) => {
112
+ await manager.run({}, async () => {
113
+ await boundHandle(event);
114
+ });
115
+ };
116
+ for (const eventType of metadata.eventTypes) {
117
+ this.dispatcher.registerListener(proxy, 'handle', {
118
+ eventType,
119
+ phase: transactional_listener_types_1.TransactionPhase.AFTER_COMMIT,
120
+ async: true,
121
+ fallbackExecution: false,
122
+ dataSource: metadata.dataSource,
123
+ });
124
+ }
125
+ }
126
+ };
127
+ exports.IntegrationEventsHandlerScanner = IntegrationEventsHandlerScanner;
128
+ exports.IntegrationEventsHandlerScanner = IntegrationEventsHandlerScanner = IntegrationEventsHandlerScanner_1 = __decorate([
129
+ (0, common_1.Injectable)(),
130
+ __param(3, (0, common_1.Optional)()),
131
+ __param(3, (0, common_1.Inject)(outbox_listener_registrar_1.OUTBOX_LISTENER_REGISTRAR)),
132
+ __metadata("design:paramtypes", [core_1.DiscoveryService,
133
+ event_dispatcher_1.TransactionalEventDispatcher,
134
+ core_2.TransactionManager, Object])
135
+ ], IntegrationEventsHandlerScanner);
136
+ /**
137
+ * Compose the stable listener id. Always ends with `#${EventName}`
138
+ * so a single class handling multiple event types gets distinct ids
139
+ * — the registry requires globally-unique ids.
140
+ */
141
+ function composeListenerId(baseId, eventType) {
142
+ return `${baseId}#${eventType.name}`;
143
+ }
144
+ //# sourceMappingURL=integration-events-handler-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration-events-handler-scanner.js","sourceRoot":"","sources":["../../src/handlers/integration-events-handler-scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import { type OnModuleInit } from '@nestjs/common';
2
+ import { DiscoveryService } from '@nestjs/core';
3
+ import { TransactionalEventDispatcher } from '../event-dispatcher/event-dispatcher';
4
+ /**
5
+ * Bootstrap-time scanner that walks every provider in the running
6
+ * Nest application, finds every class decorated with
7
+ * `@TransactionalEventsHandler`, and registers its `handle` method
8
+ * with the {@link TransactionalEventDispatcher} — one registration
9
+ * per event type listed in the decorator metadata.
10
+ *
11
+ * Scanning is class-level only. The handler class must expose a
12
+ * `handle(event): void | Promise<void>` method (enforce this at the
13
+ * type level by implementing `ITransactionalEventHandler`).
14
+ *
15
+ * `@IntegrationEventsHandler` is NOT processed here —
16
+ * `IntegrationEventsHandlerScanner` owns it, with smart routing to
17
+ * the outbox or this dispatcher depending on which provider is bound.
18
+ *
19
+ * Registration happens in `onModuleInit` so all providers have been
20
+ * instantiated by the time the scan runs. Providers with no instance
21
+ * or no metatype are skipped silently.
22
+ *
23
+ * Wired into the application by `CqrsTransactionalModule`. Not
24
+ * exported for direct consumer instantiation.
25
+ */
26
+ export declare class TransactionalListenerScanner implements OnModuleInit {
27
+ private readonly discovery;
28
+ private readonly dispatcher;
29
+ private readonly logger;
30
+ constructor(discovery: DiscoveryService, dispatcher: TransactionalEventDispatcher);
31
+ onModuleInit(): void;
32
+ }
33
+ //# sourceMappingURL=listener-scanner.d.ts.map
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var TransactionalListenerScanner_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.TransactionalListenerScanner = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const core_1 = require("@nestjs/core");
16
+ const transactional_events_handler_decorator_1 = require("../decorators/transactional-events-handler.decorator");
17
+ const event_dispatcher_1 = require("../event-dispatcher/event-dispatcher");
18
+ /**
19
+ * Bootstrap-time scanner that walks every provider in the running
20
+ * Nest application, finds every class decorated with
21
+ * `@TransactionalEventsHandler`, and registers its `handle` method
22
+ * with the {@link TransactionalEventDispatcher} — one registration
23
+ * per event type listed in the decorator metadata.
24
+ *
25
+ * Scanning is class-level only. The handler class must expose a
26
+ * `handle(event): void | Promise<void>` method (enforce this at the
27
+ * type level by implementing `ITransactionalEventHandler`).
28
+ *
29
+ * `@IntegrationEventsHandler` is NOT processed here —
30
+ * `IntegrationEventsHandlerScanner` owns it, with smart routing to
31
+ * the outbox or this dispatcher depending on which provider is bound.
32
+ *
33
+ * Registration happens in `onModuleInit` so all providers have been
34
+ * instantiated by the time the scan runs. Providers with no instance
35
+ * or no metatype are skipped silently.
36
+ *
37
+ * Wired into the application by `CqrsTransactionalModule`. Not
38
+ * exported for direct consumer instantiation.
39
+ */
40
+ let TransactionalListenerScanner = TransactionalListenerScanner_1 = class TransactionalListenerScanner {
41
+ discovery;
42
+ dispatcher;
43
+ logger = new common_1.Logger(TransactionalListenerScanner_1.name);
44
+ constructor(discovery, dispatcher) {
45
+ this.discovery = discovery;
46
+ this.dispatcher = dispatcher;
47
+ }
48
+ onModuleInit() {
49
+ const providers = this.discovery.getProviders();
50
+ for (const wrapper of providers) {
51
+ if (wrapper.metatype === null ||
52
+ typeof wrapper.metatype !== 'function' ||
53
+ wrapper.instance === null ||
54
+ wrapper.instance === undefined) {
55
+ continue;
56
+ }
57
+ const metadata = (0, transactional_events_handler_decorator_1.getTransactionalEventsHandlerMetadata)(wrapper.metatype);
58
+ if (metadata === undefined) {
59
+ continue;
60
+ }
61
+ const instance = wrapper.instance;
62
+ const handleMethod = instance.handle;
63
+ if (typeof handleMethod !== 'function') {
64
+ const className = wrapper.metatype.name ?? 'anonymous';
65
+ this.logger.warn(`@TransactionalEventsHandler on ${className}: missing \`handle(event)\` method — skipping`);
66
+ continue;
67
+ }
68
+ for (const eventType of metadata.eventTypes) {
69
+ this.dispatcher.registerListener(instance, 'handle', {
70
+ eventType,
71
+ phase: metadata.phase,
72
+ async: metadata.async,
73
+ fallbackExecution: metadata.fallbackExecution,
74
+ dataSource: metadata.dataSource,
75
+ });
76
+ }
77
+ }
78
+ }
79
+ };
80
+ exports.TransactionalListenerScanner = TransactionalListenerScanner;
81
+ exports.TransactionalListenerScanner = TransactionalListenerScanner = TransactionalListenerScanner_1 = __decorate([
82
+ (0, common_1.Injectable)(),
83
+ __metadata("design:paramtypes", [core_1.DiscoveryService,
84
+ event_dispatcher_1.TransactionalEventDispatcher])
85
+ ], TransactionalListenerScanner);
86
+ //# sourceMappingURL=listener-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"listener-scanner.js","sourceRoot":"","sources":["../../src/handlers/listener-scanner.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAuE;AACvE,uCAAgD;AAEhD,iHAA6G;AAC7G,2EAAoF;AAEpF;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEI,IAAM,4BAA4B,oCAAlC,MAAM,4BAA4B;IAIpB;IACA;IAJF,MAAM,GAAG,IAAI,eAAM,CAAC,8BAA4B,CAAC,IAAI,CAAC,CAAC;IAExE,YACmB,SAA2B,EAC3B,UAAwC;QADxC,cAAS,GAAT,SAAS,CAAkB;QAC3B,eAAU,GAAV,UAAU,CAA8B;IACxD,CAAC;IAEJ,YAAY;QACV,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC,YAAY,EAAE,CAAC;QAEhD,KAAK,MAAM,OAAO,IAAI,SAAS,EAAE,CAAC;YAChC,IACE,OAAO,CAAC,QAAQ,KAAK,IAAI;gBACzB,OAAO,OAAO,CAAC,QAAQ,KAAK,UAAU;gBACtC,OAAO,CAAC,QAAQ,KAAK,IAAI;gBACzB,OAAO,CAAC,QAAQ,KAAK,SAAS,EAC9B,CAAC;gBACD,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAG,IAAA,8EAAqC,EAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;YACzE,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAC3B,SAAS;YACX,CAAC;YAED,MAAM,QAAQ,GAAW,OAAO,CAAC,QAAkB,CAAC;YACpD,MAAM,YAAY,GAAI,QAAoC,CAAC,MAAM,CAAC;YAClE,IAAI,OAAO,YAAY,KAAK,UAAU,EAAE,CAAC;gBACvC,MAAM,SAAS,GAAI,OAAO,CAAC,QAA8B,CAAC,IAAI,IAAI,WAAW,CAAC;gBAC9E,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,kCAAkC,SAAS,+CAA+C,CAC3F,CAAC;gBACF,SAAS;YACX,CAAC;YAED,KAAK,MAAM,SAAS,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;gBAC5C,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,QAAQ,EAAE,QAAQ,EAAE;oBACnD,SAAS;oBACT,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,KAAK,EAAE,QAAQ,CAAC,KAAK;oBACrB,iBAAiB,EAAE,QAAQ,CAAC,iBAAiB;oBAC7C,UAAU,EAAE,QAAQ,CAAC,UAAU;iBAChC,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;CACF,CAAA;AA/CY,oEAA4B;uCAA5B,4BAA4B;IADxC,IAAA,mBAAU,GAAE;qCAKmB,uBAAgB;QACf,+CAA4B;GALhD,4BAA4B,CA+CxC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Minimal structural contract for an outbox listener registrar,
3
+ * declared here (and injected via {@link OUTBOX_LISTENER_REGISTRAR})
4
+ * rather than imported from `@nestjs-transactional/outbox`
5
+ * directly — keeps the cqrs package usable without the outbox stack.
6
+ *
7
+ * `@nestjs-transactional/outbox`'s `OutboxListenerRegistry`
8
+ * satisfies this interface structurally (its `register` method
9
+ * accepts exactly this shape). The outbox package's
10
+ * `MultiDsOutboxListenerRegistrar` (Phase 14.3.1) is a smarter
11
+ * implementation that walks every per-dataSource event-type registry
12
+ * to resolve which dataSource owns each listener's event class and
13
+ * routes the registration to the matching per-DS registry — so a
14
+ * single binding handles arbitrary multi-dataSource deployments.
15
+ *
16
+ * **Auto-binding (Phase 14.3.1).** `OutboxModule.forRoot` binds this
17
+ * token to `MultiDsOutboxListenerRegistrar` automatically on the
18
+ * first `forRoot` call. Consumers do NOT need to declare the binding
19
+ * themselves; the registrar is in place by the time the cqrs
20
+ * `IntegrationEventsHandlerScanner` runs its `onModuleInit`. Manual
21
+ * binding remains supported for advanced cases (custom routing
22
+ * policy, structural decoupling tests).
23
+ *
24
+ * Cross-package token identity is via `Symbol.for(...)` so the cqrs
25
+ * declaration and the outbox auto-binding refer to the same Symbol
26
+ * without either package importing from the other (Convention #8 —
27
+ * mirrors `WRAPPED_MARKER`).
28
+ */
29
+ export interface OutboxListenerRegistrar {
30
+ register(listener: {
31
+ readonly id: string;
32
+ readonly eventType: string;
33
+ readonly invoke: (event: unknown) => Promise<void>;
34
+ }): void;
35
+ }
36
+ /**
37
+ * DI token for the optional {@link OutboxListenerRegistrar} injected
38
+ * into `IntegrationEventsHandlerScanner`. When unbound, the scanner
39
+ * falls back to in-memory registration via
40
+ * {@link TransactionalEventDispatcher}.
41
+ *
42
+ * `Symbol.for(...)` (not `Symbol(...)`) — Phase 14.3.1: the outbox
43
+ * package auto-binds this token to its `MultiDsOutboxListenerRegistrar`
44
+ * via `Symbol.for` lookup on the same key. Both packages thereby
45
+ * refer to the same Symbol identity without a direct import in
46
+ * either direction.
47
+ */
48
+ export declare const OUTBOX_LISTENER_REGISTRAR: unique symbol;
49
+ //# sourceMappingURL=outbox-listener-registrar.d.ts.map
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OUTBOX_LISTENER_REGISTRAR = void 0;
4
+ /**
5
+ * DI token for the optional {@link OutboxListenerRegistrar} injected
6
+ * into `IntegrationEventsHandlerScanner`. When unbound, the scanner
7
+ * falls back to in-memory registration via
8
+ * {@link TransactionalEventDispatcher}.
9
+ *
10
+ * `Symbol.for(...)` (not `Symbol(...)`) — Phase 14.3.1: the outbox
11
+ * package auto-binds this token to its `MultiDsOutboxListenerRegistrar`
12
+ * via `Symbol.for` lookup on the same key. Both packages thereby
13
+ * refer to the same Symbol identity without a direct import in
14
+ * either direction.
15
+ */
16
+ exports.OUTBOX_LISTENER_REGISTRAR = Symbol.for('@nestjs-transactional/cqrs/outbox-listener-registrar');
17
+ //# sourceMappingURL=outbox-listener-registrar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox-listener-registrar.js","sourceRoot":"","sources":["../../src/handlers/outbox-listener-registrar.ts"],"names":[],"mappings":";;;AAoCA;;;;;;;;;;;GAWG;AACU,QAAA,yBAAyB,GAAG,MAAM,CAAC,GAAG,CACjD,sDAAsD,CACvD,CAAC"}
@@ -0,0 +1,16 @@
1
+ export { TransactionPhase } from './types/transactional-listener.types';
2
+ export { TRANSACTIONAL_EVENTS_HANDLER_METADATA, TransactionalEventsHandler, getTransactionalEventsHandlerMetadata, type TransactionalEventsHandlerMetadata, type TransactionalEventsHandlerOptions, } from './decorators/transactional-events-handler.decorator';
3
+ export { INTEGRATION_EVENTS_HANDLER_METADATA, IntegrationEventsHandler, getIntegrationEventsHandlerMetadata, type IntegrationEventsHandlerMetadata, type IntegrationEventsHandlerOptions, } from './decorators/integration-events-handler.decorator';
4
+ export type { ITransactionalEventHandler } from './interfaces/transactional-event-handler.interface';
5
+ export type { IIntegrationEventHandler } from './interfaces/integration-event-handler.interface';
6
+ export { TransactionalEventDispatcher, type DispatcherListenerMetadata, } from './event-dispatcher/event-dispatcher';
7
+ export { TransactionalListenerScanner } from './handlers/listener-scanner';
8
+ export { IntegrationEventsHandlerScanner } from './handlers/integration-events-handler-scanner';
9
+ export { OUTBOX_LISTENER_REGISTRAR, type OutboxListenerRegistrar, } from './handlers/outbox-listener-registrar';
10
+ export { CQRS_HANDLER_WRAPPER_OPTIONS, CqrsHandlerWrapper, type HandlerWrapperOptions, } from './handlers/handler-wrapper';
11
+ export { CqrsTransactionalBootstrap } from './handlers/bootstrap';
12
+ export { TransactionalEventPublisher } from './event-publisher/transactional-event-publisher';
13
+ export { TransactionalEventPublisherAdapter } from './event-publisher/transactional-event-publisher-adapter';
14
+ export { HybridEventPublisher, OUTBOX_PUBLICATION_SCHEDULER, type OutboxPublicationScheduler, } from './event-publisher/hybrid-event-publisher';
15
+ export { CQRS_TRANSACTIONAL_OPTIONS, CqrsTransactionalModule, type CqrsTransactionalOptions, } from './module/cqrs-transactional.module';
16
+ //# sourceMappingURL=index.d.ts.map
package/dist/index.js ADDED
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CqrsTransactionalModule = exports.CQRS_TRANSACTIONAL_OPTIONS = exports.OUTBOX_PUBLICATION_SCHEDULER = exports.HybridEventPublisher = exports.TransactionalEventPublisherAdapter = exports.TransactionalEventPublisher = exports.CqrsTransactionalBootstrap = exports.CqrsHandlerWrapper = exports.CQRS_HANDLER_WRAPPER_OPTIONS = exports.OUTBOX_LISTENER_REGISTRAR = exports.IntegrationEventsHandlerScanner = exports.TransactionalListenerScanner = exports.TransactionalEventDispatcher = exports.getIntegrationEventsHandlerMetadata = exports.IntegrationEventsHandler = exports.INTEGRATION_EVENTS_HANDLER_METADATA = exports.getTransactionalEventsHandlerMetadata = exports.TransactionalEventsHandler = exports.TRANSACTIONAL_EVENTS_HANDLER_METADATA = exports.TransactionPhase = void 0;
4
+ var transactional_listener_types_1 = require("./types/transactional-listener.types");
5
+ Object.defineProperty(exports, "TransactionPhase", { enumerable: true, get: function () { return transactional_listener_types_1.TransactionPhase; } });
6
+ var transactional_events_handler_decorator_1 = require("./decorators/transactional-events-handler.decorator");
7
+ Object.defineProperty(exports, "TRANSACTIONAL_EVENTS_HANDLER_METADATA", { enumerable: true, get: function () { return transactional_events_handler_decorator_1.TRANSACTIONAL_EVENTS_HANDLER_METADATA; } });
8
+ Object.defineProperty(exports, "TransactionalEventsHandler", { enumerable: true, get: function () { return transactional_events_handler_decorator_1.TransactionalEventsHandler; } });
9
+ Object.defineProperty(exports, "getTransactionalEventsHandlerMetadata", { enumerable: true, get: function () { return transactional_events_handler_decorator_1.getTransactionalEventsHandlerMetadata; } });
10
+ var integration_events_handler_decorator_1 = require("./decorators/integration-events-handler.decorator");
11
+ Object.defineProperty(exports, "INTEGRATION_EVENTS_HANDLER_METADATA", { enumerable: true, get: function () { return integration_events_handler_decorator_1.INTEGRATION_EVENTS_HANDLER_METADATA; } });
12
+ Object.defineProperty(exports, "IntegrationEventsHandler", { enumerable: true, get: function () { return integration_events_handler_decorator_1.IntegrationEventsHandler; } });
13
+ Object.defineProperty(exports, "getIntegrationEventsHandlerMetadata", { enumerable: true, get: function () { return integration_events_handler_decorator_1.getIntegrationEventsHandlerMetadata; } });
14
+ var event_dispatcher_1 = require("./event-dispatcher/event-dispatcher");
15
+ Object.defineProperty(exports, "TransactionalEventDispatcher", { enumerable: true, get: function () { return event_dispatcher_1.TransactionalEventDispatcher; } });
16
+ var listener_scanner_1 = require("./handlers/listener-scanner");
17
+ Object.defineProperty(exports, "TransactionalListenerScanner", { enumerable: true, get: function () { return listener_scanner_1.TransactionalListenerScanner; } });
18
+ var integration_events_handler_scanner_1 = require("./handlers/integration-events-handler-scanner");
19
+ Object.defineProperty(exports, "IntegrationEventsHandlerScanner", { enumerable: true, get: function () { return integration_events_handler_scanner_1.IntegrationEventsHandlerScanner; } });
20
+ var outbox_listener_registrar_1 = require("./handlers/outbox-listener-registrar");
21
+ Object.defineProperty(exports, "OUTBOX_LISTENER_REGISTRAR", { enumerable: true, get: function () { return outbox_listener_registrar_1.OUTBOX_LISTENER_REGISTRAR; } });
22
+ var handler_wrapper_1 = require("./handlers/handler-wrapper");
23
+ Object.defineProperty(exports, "CQRS_HANDLER_WRAPPER_OPTIONS", { enumerable: true, get: function () { return handler_wrapper_1.CQRS_HANDLER_WRAPPER_OPTIONS; } });
24
+ Object.defineProperty(exports, "CqrsHandlerWrapper", { enumerable: true, get: function () { return handler_wrapper_1.CqrsHandlerWrapper; } });
25
+ var bootstrap_1 = require("./handlers/bootstrap");
26
+ Object.defineProperty(exports, "CqrsTransactionalBootstrap", { enumerable: true, get: function () { return bootstrap_1.CqrsTransactionalBootstrap; } });
27
+ var transactional_event_publisher_1 = require("./event-publisher/transactional-event-publisher");
28
+ Object.defineProperty(exports, "TransactionalEventPublisher", { enumerable: true, get: function () { return transactional_event_publisher_1.TransactionalEventPublisher; } });
29
+ var transactional_event_publisher_adapter_1 = require("./event-publisher/transactional-event-publisher-adapter");
30
+ Object.defineProperty(exports, "TransactionalEventPublisherAdapter", { enumerable: true, get: function () { return transactional_event_publisher_adapter_1.TransactionalEventPublisherAdapter; } });
31
+ var hybrid_event_publisher_1 = require("./event-publisher/hybrid-event-publisher");
32
+ Object.defineProperty(exports, "HybridEventPublisher", { enumerable: true, get: function () { return hybrid_event_publisher_1.HybridEventPublisher; } });
33
+ Object.defineProperty(exports, "OUTBOX_PUBLICATION_SCHEDULER", { enumerable: true, get: function () { return hybrid_event_publisher_1.OUTBOX_PUBLICATION_SCHEDULER; } });
34
+ var cqrs_transactional_module_1 = require("./module/cqrs-transactional.module");
35
+ Object.defineProperty(exports, "CQRS_TRANSACTIONAL_OPTIONS", { enumerable: true, get: function () { return cqrs_transactional_module_1.CQRS_TRANSACTIONAL_OPTIONS; } });
36
+ Object.defineProperty(exports, "CqrsTransactionalModule", { enumerable: true, get: function () { return cqrs_transactional_module_1.CqrsTransactionalModule; } });
37
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,qFAAwE;AAA/D,gIAAA,gBAAgB,OAAA;AAEzB,8GAM6D;AAL3D,+JAAA,qCAAqC,OAAA;AACrC,oJAAA,0BAA0B,OAAA;AAC1B,+JAAA,qCAAqC,OAAA;AAKvC,0GAM2D;AALzD,2JAAA,mCAAmC,OAAA;AACnC,gJAAA,wBAAwB,OAAA;AACxB,2JAAA,mCAAmC,OAAA;AAQrC,wEAG6C;AAF3C,gIAAA,4BAA4B,OAAA;AAI9B,gEAA2E;AAAlE,gIAAA,4BAA4B,OAAA;AACrC,oGAAgG;AAAvF,qJAAA,+BAA+B,OAAA;AACxC,kFAG8C;AAF5C,sIAAA,yBAAyB,OAAA;AAI3B,8DAIoC;AAHlC,+HAAA,4BAA4B,OAAA;AAC5B,qHAAA,kBAAkB,OAAA;AAIpB,kDAAkE;AAAzD,uHAAA,0BAA0B,OAAA;AAEnC,iGAA8F;AAArF,4IAAA,2BAA2B,OAAA;AACpC,iHAA6G;AAApG,2JAAA,kCAAkC,OAAA;AAC3C,mFAIkD;AAHhD,8HAAA,oBAAoB,OAAA;AACpB,sIAAA,4BAA4B,OAAA;AAI9B,gFAI4C;AAH1C,uIAAA,0BAA0B,OAAA;AAC1B,oIAAA,uBAAuB,OAAA"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Contract implemented by classes annotated with
3
+ * `@IntegrationEventsHandler` — the smart-default decorator for
4
+ * cross-module / cross-service event handlers.
5
+ *
6
+ * The Spring Modulith equivalent is `@ApplicationModuleListener`.
7
+ * The name `@IntegrationEventsHandler` is preferred in the NestJS
8
+ * ecosystem because "Application Module" overlaps with NestJS's own
9
+ * `@Module()` (a DI concept), and "Integration events" is the
10
+ * established DDD/microservices term for the role this decorator
11
+ * plays.
12
+ *
13
+ * Shape is identical to {@link ITransactionalEventHandler}; the two
14
+ * interfaces exist separately as marker types so code can
15
+ * discriminate by intent (cross-module integration handler vs.
16
+ * intra-module transactional listener) even though both share the
17
+ * `handle(event)` contract.
18
+ *
19
+ * @example
20
+ * ```ts
21
+ * @IntegrationEventsHandler(OrderPlacedEvent)
22
+ * export class InventoryReservationHandler
23
+ * implements IIntegrationEventHandler<OrderPlacedEvent>
24
+ * {
25
+ * async handle(event: OrderPlacedEvent): Promise<void> {
26
+ * // durable when the outbox is wired, in-memory AFTER_COMMIT
27
+ * // fallback otherwise.
28
+ * }
29
+ * }
30
+ * ```
31
+ */
32
+ export interface IIntegrationEventHandler<T = any> {
33
+ handle(event: T): Promise<void> | void;
34
+ }
35
+ //# sourceMappingURL=integration-event-handler.interface.d.ts.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=integration-event-handler.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"integration-event-handler.interface.js","sourceRoot":"","sources":["../../src/interfaces/integration-event-handler.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Contract implemented by classes annotated with
3
+ * `@TransactionalEventsHandler`.
4
+ *
5
+ * The single `handle` method is invoked for each event of a type the
6
+ * class is registered for. When a handler listens to several event
7
+ * types, narrow the generic parameter to their union (e.g.
8
+ * `ITransactionalEventHandler<OrderPlaced | OrderCancelled>`) or
9
+ * leave it unbound for the most permissive shape.
10
+ *
11
+ * Mirrors the ergonomics of `IEventHandler` from `@nestjs/cqrs` —
12
+ * `any` as the default generic parameter is deliberate so that
13
+ * `implements ITransactionalEventHandler` without a type argument
14
+ * type-checks against any concrete event shape.
15
+ *
16
+ * @example
17
+ * ```ts
18
+ * @TransactionalEventsHandler(OrderPlacedEvent)
19
+ * export class OrderPlacedNotifier
20
+ * implements ITransactionalEventHandler<OrderPlacedEvent>
21
+ * {
22
+ * async handle(event: OrderPlacedEvent): Promise<void> {
23
+ * // ...
24
+ * }
25
+ * }
26
+ * ```
27
+ */
28
+ export interface ITransactionalEventHandler<T = any> {
29
+ handle(event: T): Promise<void> | void;
30
+ }
31
+ //# sourceMappingURL=transactional-event-handler.interface.d.ts.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=transactional-event-handler.interface.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transactional-event-handler.interface.js","sourceRoot":"","sources":["../../src/interfaces/transactional-event-handler.interface.ts"],"names":[],"mappings":""}
@@ -0,0 +1,92 @@
1
+ import { type DynamicModule } from '@nestjs/common';
2
+ import { type HandlerWrapperOptions } from '../handlers/handler-wrapper';
3
+ /**
4
+ * DI token for the resolved {@link CqrsTransactionalOptions} object.
5
+ * Consumers normally do not inject this directly — it is used by the
6
+ * module's internal factory to pass options to {@link CqrsHandlerWrapper}.
7
+ */
8
+ export declare const CQRS_TRANSACTIONAL_OPTIONS = "CQRS_TRANSACTIONAL_OPTIONS";
9
+ /**
10
+ * Options accepted by {@link CqrsTransactionalModule.forRoot}. Extends
11
+ * {@link HandlerWrapperOptions} with the flag controlling whether
12
+ * `@nestjs/cqrs`'s `EventPublisher` is overridden with
13
+ * {@link TransactionalEventPublisherAdapter}.
14
+ *
15
+ * Defaults:
16
+ * - `wrapCommandHandlers`: `true`
17
+ * - `wrapQueryHandlers`: `true`
18
+ * - `wrapEventHandlers`: `true`
19
+ * - `defaultQueryOptions`: `{ readOnly: true }`
20
+ * - `useTransactionalEventPublisher`: `true`
21
+ */
22
+ export interface CqrsTransactionalOptions extends HandlerWrapperOptions {
23
+ /**
24
+ * If `true` (default), overrides `@nestjs/cqrs`'s `EventPublisher`
25
+ * DI token with {@link TransactionalEventPublisherAdapter} so
26
+ * `AggregateRoot.commit()` routes events through the transactional
27
+ * dispatcher (phase-aware handlers). Set to `false` to leave the
28
+ * standard `EventPublisher` in place — useful when integrating
29
+ * progressively into an existing codebase.
30
+ */
31
+ readonly useTransactionalEventPublisher?: boolean;
32
+ }
33
+ /**
34
+ * NestJS module that wires the `@nestjs-transactional/cqrs` runtime:
35
+ *
36
+ * - {@link TransactionalEventDispatcher} for phase-aware event
37
+ * routing.
38
+ * - {@link TransactionalListenerScanner} for auto-registration of
39
+ * `@TransactionalEventsHandler`-decorated classes at module init.
40
+ * - {@link IntegrationEventsHandlerScanner} for
41
+ * `@IntegrationEventsHandler`-decorated classes, with smart routing
42
+ * to the outbox (when bound) or the dispatcher (otherwise).
43
+ * - {@link CqrsHandlerWrapper} + {@link CqrsTransactionalBootstrap}
44
+ * to wrap `@CommandHandler` / `@QueryHandler` / `@EventsHandler`
45
+ * execute/handle methods at application bootstrap.
46
+ * - {@link TransactionalEventPublisher} +
47
+ * {@link TransactionalEventPublisherAdapter} as the `EventPublisher`
48
+ * DI override so `AggregateRoot.commit()` flows through the
49
+ * dispatcher.
50
+ *
51
+ * Pair with `TransactionalModule.forRoot({ isGlobal: true })` at the
52
+ * application root. For TypeORM-backed applications, also register
53
+ * adapters with `TypeOrmTransactionalModule.forFeature(...)`.
54
+ *
55
+ * @example
56
+ * ```ts
57
+ * @Module({
58
+ * imports: [
59
+ * TransactionalModule.forRoot({ isGlobal: true }),
60
+ * TypeOrmTransactionalModule.forFeature({ dataSource: myDs }),
61
+ * CqrsModule,
62
+ * CqrsTransactionalModule.forRoot(),
63
+ * ],
64
+ * })
65
+ * export class AppModule {}
66
+ * ```
67
+ *
68
+ * **Multi-dataSource setups** (Phase 14.7): the cqrs runtime is
69
+ * dataSource-agnostic by design. There is exactly one
70
+ * `CqrsTransactionalModule.forRoot()` per application regardless of
71
+ * how many dataSources are configured — multi-DS routing emerges
72
+ * from the structural-port wiring, not from a per-DS module instance.
73
+ *
74
+ * Wire {@link OUTBOX_PUBLICATION_SCHEDULER} and
75
+ * {@link OUTBOX_LISTENER_REGISTRAR} to the outbox stack you want
76
+ * cqrs to delegate to (`useExisting: OutboxEventPublisher` /
77
+ * `useExisting: OutboxListenerRegistry`). Apps with multiple outbox
78
+ * stacks (one `OutboxModule.forRoot()` per dataSource — ADR-019)
79
+ * choose which one cqrs bridges to via the `useExisting` target.
80
+ *
81
+ * Known limitation in multi-DS deployments: the in-memory
82
+ * dispatcher's hook-attachment goes through
83
+ * `TransactionManager.registerBeforeCommit` / `registerAfterCommit`,
84
+ * which target the first-active transaction on the current async
85
+ * context (non-deterministic across simultaneously-active
86
+ * cross-dataSource transactions). For cross-DS event handling
87
+ * prefer the outbox path — see `docs/known-limitations.md`.
88
+ */
89
+ export declare class CqrsTransactionalModule {
90
+ static forRoot(options?: CqrsTransactionalOptions): DynamicModule;
91
+ }
92
+ //# sourceMappingURL=cqrs-transactional.module.d.ts.map