@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.
- package/LICENSE +21 -0
- package/README.md +431 -0
- package/dist/decorators/integration-events-handler.decorator.d.ts +125 -0
- package/dist/decorators/integration-events-handler.decorator.js +57 -0
- package/dist/decorators/integration-events-handler.decorator.js.map +1 -0
- package/dist/decorators/transactional-events-handler.decorator.d.ts +138 -0
- package/dist/decorators/transactional-events-handler.decorator.js +65 -0
- package/dist/decorators/transactional-events-handler.decorator.js.map +1 -0
- package/dist/event-dispatcher/event-dispatcher.d.ts +100 -0
- package/dist/event-dispatcher/event-dispatcher.js +229 -0
- package/dist/event-dispatcher/event-dispatcher.js.map +1 -0
- package/dist/event-publisher/hybrid-event-publisher.d.ts +76 -0
- package/dist/event-publisher/hybrid-event-publisher.js +86 -0
- package/dist/event-publisher/hybrid-event-publisher.js.map +1 -0
- package/dist/event-publisher/transactional-event-publisher-adapter.d.ts +32 -0
- package/dist/event-publisher/transactional-event-publisher-adapter.js +72 -0
- package/dist/event-publisher/transactional-event-publisher-adapter.js.map +1 -0
- package/dist/event-publisher/transactional-event-publisher.d.ts +33 -0
- package/dist/event-publisher/transactional-event-publisher.js +58 -0
- package/dist/event-publisher/transactional-event-publisher.js.map +1 -0
- package/dist/handlers/bootstrap.d.ts +18 -0
- package/dist/handlers/bootstrap.js +39 -0
- package/dist/handlers/bootstrap.js.map +1 -0
- package/dist/handlers/handler-wrapper.d.ts +77 -0
- package/dist/handlers/handler-wrapper.js +183 -0
- package/dist/handlers/handler-wrapper.js.map +1 -0
- package/dist/handlers/integration-events-handler-scanner.d.ts +37 -0
- package/dist/handlers/integration-events-handler-scanner.js +144 -0
- package/dist/handlers/integration-events-handler-scanner.js.map +1 -0
- package/dist/handlers/listener-scanner.d.ts +33 -0
- package/dist/handlers/listener-scanner.js +86 -0
- package/dist/handlers/listener-scanner.js.map +1 -0
- package/dist/handlers/outbox-listener-registrar.d.ts +49 -0
- package/dist/handlers/outbox-listener-registrar.js +17 -0
- package/dist/handlers/outbox-listener-registrar.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/interfaces/integration-event-handler.interface.d.ts +35 -0
- package/dist/interfaces/integration-event-handler.interface.js +3 -0
- package/dist/interfaces/integration-event-handler.interface.js.map +1 -0
- package/dist/interfaces/transactional-event-handler.interface.d.ts +31 -0
- package/dist/interfaces/transactional-event-handler.interface.js +3 -0
- package/dist/interfaces/transactional-event-handler.interface.js.map +1 -0
- package/dist/module/cqrs-transactional.module.d.ts +92 -0
- package/dist/module/cqrs-transactional.module.js +137 -0
- package/dist/module/cqrs-transactional.module.js.map +1 -0
- package/dist/types/transactional-listener.types.d.ts +21 -0
- package/dist/types/transactional-listener.types.js +25 -0
- package/dist/types/transactional-listener.types.js.map +1 -0
- package/package.json +73 -0
|
@@ -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 __param = (this && this.__param) || function (paramIndex, decorator) {
|
|
12
|
+
return function (target, key) { decorator(target, key, paramIndex); }
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.HybridEventPublisher = exports.OUTBOX_PUBLICATION_SCHEDULER = void 0;
|
|
16
|
+
const common_1 = require("@nestjs/common");
|
|
17
|
+
const event_dispatcher_1 = require("../event-dispatcher/event-dispatcher");
|
|
18
|
+
/**
|
|
19
|
+
* DI token for the optional outbox scheduler injected into
|
|
20
|
+
* {@link HybridEventPublisher}. When unbound, the hybrid publisher
|
|
21
|
+
* delegates only to the in-memory dispatcher.
|
|
22
|
+
*/
|
|
23
|
+
exports.OUTBOX_PUBLICATION_SCHEDULER = Symbol('OUTBOX_PUBLICATION_SCHEDULER');
|
|
24
|
+
/**
|
|
25
|
+
* `IEventPublisher` implementation that routes aggregate-emitted
|
|
26
|
+
* events through BOTH the in-memory transactional dispatcher
|
|
27
|
+
* (`@TransactionalEventsHandler`) AND — when wired — the outbox
|
|
28
|
+
* (`@OutboxEventsHandler`, introduced in a later phase). Both paths
|
|
29
|
+
* run inside the surrounding transaction:
|
|
30
|
+
*
|
|
31
|
+
* - In-memory: the dispatcher attaches hooks to the current
|
|
32
|
+
* transaction so listeners fire at the configured phase
|
|
33
|
+
* (`AFTER_COMMIT` by default). No database rows are written.
|
|
34
|
+
* - Outbox: {@link OutboxPublicationScheduler.scheduleForPublication}
|
|
35
|
+
* buffers the event and flushes the buffer via one `beforeCommit`
|
|
36
|
+
* hook per transaction. Publication rows commit atomically with
|
|
37
|
+
* the business write; rollback skips the flush.
|
|
38
|
+
*
|
|
39
|
+
* When no outbox scheduler is bound, behaves identically to
|
|
40
|
+
* {@link TransactionalEventPublisher}. Callers get outbox semantics
|
|
41
|
+
* automatically as soon as the scheduler is wired — no code change
|
|
42
|
+
* at the call site.
|
|
43
|
+
*
|
|
44
|
+
* Important: the outbox path is best-effort from the perspective of
|
|
45
|
+
* `AggregateRoot.commit()`. `commit()` is synchronous, so we cannot
|
|
46
|
+
* await the DB write here. Errors raised while the `beforeCommit`
|
|
47
|
+
* hook flushes the buffer DO bubble up — they cause the transaction
|
|
48
|
+
* to roll back, which is the intended behavior.
|
|
49
|
+
*
|
|
50
|
+
* **Multi-dataSource (Phase 14.7).** The outbox scheduler is the
|
|
51
|
+
* smart-facade `OutboxEventPublisher` (DD-024). When wired,
|
|
52
|
+
* AggregateRoot events are routed to the per-dataSource publisher
|
|
53
|
+
* that owns the event class — the same routing semantics as
|
|
54
|
+
* `OutboxEventPublisher.publish()`. Multi-DS apps with multiple
|
|
55
|
+
* outbox stacks (one `OutboxModule.forRoot()` per dataSource per
|
|
56
|
+
* ADR-019) bind `OUTBOX_PUBLICATION_SCHEDULER` to the smart facade
|
|
57
|
+
* via `useExisting: OutboxEventPublisher`; the facade's internal
|
|
58
|
+
* Map fans out to the correct per-DS publisher.
|
|
59
|
+
*/
|
|
60
|
+
let HybridEventPublisher = class HybridEventPublisher {
|
|
61
|
+
dispatcher;
|
|
62
|
+
outbox;
|
|
63
|
+
constructor(dispatcher, outbox) {
|
|
64
|
+
this.dispatcher = dispatcher;
|
|
65
|
+
this.outbox = outbox;
|
|
66
|
+
}
|
|
67
|
+
publish(event) {
|
|
68
|
+
this.dispatcher.scheduleDispatch(event);
|
|
69
|
+
if (this.outbox !== undefined) {
|
|
70
|
+
this.outbox.scheduleForPublication(event);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
publishAll(events) {
|
|
74
|
+
for (const event of events) {
|
|
75
|
+
this.publish(event);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
exports.HybridEventPublisher = HybridEventPublisher;
|
|
80
|
+
exports.HybridEventPublisher = HybridEventPublisher = __decorate([
|
|
81
|
+
(0, common_1.Injectable)(),
|
|
82
|
+
__param(1, (0, common_1.Optional)()),
|
|
83
|
+
__param(1, (0, common_1.Inject)(exports.OUTBOX_PUBLICATION_SCHEDULER)),
|
|
84
|
+
__metadata("design:paramtypes", [event_dispatcher_1.TransactionalEventDispatcher, Object])
|
|
85
|
+
], HybridEventPublisher);
|
|
86
|
+
//# sourceMappingURL=hybrid-event-publisher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hybrid-event-publisher.js","sourceRoot":"","sources":["../../src/event-publisher/hybrid-event-publisher.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,2CAA8D;AAG9D,2EAAoF;AA2BpF;;;;GAIG;AACU,QAAA,4BAA4B,GAAG,MAAM,CAAC,8BAA8B,CAAC,CAAC;AAEnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEI,IAAM,oBAAoB,GAA1B,MAAM,oBAAoB;IAEZ;IAGA;IAJnB,YACmB,UAAwC,EAGxC,MAAmC;QAHnC,eAAU,GAAV,UAAU,CAA8B;QAGxC,WAAM,GAAN,MAAM,CAA6B;IACnD,CAAC;IAEJ,OAAO,CAAmB,KAAQ;QAChC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;QACxC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC9B,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,KAAK,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,UAAU,CAAmB,MAAW;QACtC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;CACF,CAAA;AApBY,oDAAoB;+BAApB,oBAAoB;IADhC,IAAA,mBAAU,GAAE;IAIR,WAAA,IAAA,iBAAQ,GAAE,CAAA;IACV,WAAA,IAAA,eAAM,EAAC,oCAA4B,CAAC,CAAA;qCAFR,+CAA4B;GAFhD,oBAAoB,CAoBhC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AggregateRoot, EventBus, EventPublisher, type IEventPublisher } from '@nestjs/cqrs';
|
|
2
|
+
type AggregateConstructor<T extends AggregateRoot> = new (...args: never[]) => T;
|
|
3
|
+
/**
|
|
4
|
+
* Drop-in replacement for `@nestjs/cqrs`'s `EventPublisher`. Wired
|
|
5
|
+
* automatically by `CqrsTransactionalModule` via
|
|
6
|
+
* `{ provide: EventPublisher, useFactory: ... }`.
|
|
7
|
+
*
|
|
8
|
+
* Override strategy:
|
|
9
|
+
* - `mergeObjectContext` / `mergeClassContext` replace `publish` and
|
|
10
|
+
* `publishAll` on the aggregate with calls into the injected
|
|
11
|
+
* {@link IEventPublisher} strategy —
|
|
12
|
+
* {@link HybridEventPublisher} (default, bridges to both the
|
|
13
|
+
* in-memory dispatcher and the outbox) or
|
|
14
|
+
* {@link TransactionalEventPublisher} (in-memory only, legacy).
|
|
15
|
+
* - The parent `EventPublisher.eventBus` is still injected (required
|
|
16
|
+
* by the base class constructor) but is not used by our override —
|
|
17
|
+
* events flow exclusively through the configured strategy.
|
|
18
|
+
*
|
|
19
|
+
* Note: consumers calling `eventBus.publish(...)` directly (outside of an
|
|
20
|
+
* aggregate) still go through the original `@nestjs/cqrs` `EventBus` and
|
|
21
|
+
* bypass phase-aware dispatching. Only aggregate-emitted events routed
|
|
22
|
+
* via `mergeObjectContext` / `mergeClassContext` get transactional
|
|
23
|
+
* semantics.
|
|
24
|
+
*/
|
|
25
|
+
export declare class TransactionalEventPublisherAdapter extends EventPublisher {
|
|
26
|
+
private readonly strategy;
|
|
27
|
+
constructor(strategy: IEventPublisher, eventBus: EventBus);
|
|
28
|
+
mergeClassContext<T extends AggregateConstructor<AggregateRoot>>(metatype: T): T;
|
|
29
|
+
mergeObjectContext<T extends AggregateRoot>(object: T): T;
|
|
30
|
+
}
|
|
31
|
+
export {};
|
|
32
|
+
//# sourceMappingURL=transactional-event-publisher-adapter.d.ts.map
|
|
@@ -0,0 +1,72 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.TransactionalEventPublisherAdapter = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const cqrs_1 = require("@nestjs/cqrs");
|
|
15
|
+
/**
|
|
16
|
+
* Drop-in replacement for `@nestjs/cqrs`'s `EventPublisher`. Wired
|
|
17
|
+
* automatically by `CqrsTransactionalModule` via
|
|
18
|
+
* `{ provide: EventPublisher, useFactory: ... }`.
|
|
19
|
+
*
|
|
20
|
+
* Override strategy:
|
|
21
|
+
* - `mergeObjectContext` / `mergeClassContext` replace `publish` and
|
|
22
|
+
* `publishAll` on the aggregate with calls into the injected
|
|
23
|
+
* {@link IEventPublisher} strategy —
|
|
24
|
+
* {@link HybridEventPublisher} (default, bridges to both the
|
|
25
|
+
* in-memory dispatcher and the outbox) or
|
|
26
|
+
* {@link TransactionalEventPublisher} (in-memory only, legacy).
|
|
27
|
+
* - The parent `EventPublisher.eventBus` is still injected (required
|
|
28
|
+
* by the base class constructor) but is not used by our override —
|
|
29
|
+
* events flow exclusively through the configured strategy.
|
|
30
|
+
*
|
|
31
|
+
* Note: consumers calling `eventBus.publish(...)` directly (outside of an
|
|
32
|
+
* aggregate) still go through the original `@nestjs/cqrs` `EventBus` and
|
|
33
|
+
* bypass phase-aware dispatching. Only aggregate-emitted events routed
|
|
34
|
+
* via `mergeObjectContext` / `mergeClassContext` get transactional
|
|
35
|
+
* semantics.
|
|
36
|
+
*/
|
|
37
|
+
let TransactionalEventPublisherAdapter = class TransactionalEventPublisherAdapter extends cqrs_1.EventPublisher {
|
|
38
|
+
strategy;
|
|
39
|
+
constructor(strategy, eventBus) {
|
|
40
|
+
super(eventBus);
|
|
41
|
+
this.strategy = strategy;
|
|
42
|
+
}
|
|
43
|
+
mergeClassContext(metatype) {
|
|
44
|
+
const strategy = this.strategy;
|
|
45
|
+
class TransactionalMerged extends metatype {
|
|
46
|
+
publish(event) {
|
|
47
|
+
strategy.publish(event);
|
|
48
|
+
}
|
|
49
|
+
publishAll(events) {
|
|
50
|
+
strategy.publishAll?.(events);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return TransactionalMerged;
|
|
54
|
+
}
|
|
55
|
+
mergeObjectContext(object) {
|
|
56
|
+
const strategy = this.strategy;
|
|
57
|
+
const host = object;
|
|
58
|
+
host.publish = (event) => {
|
|
59
|
+
strategy.publish(event);
|
|
60
|
+
};
|
|
61
|
+
host.publishAll = (events) => {
|
|
62
|
+
strategy.publishAll?.(events);
|
|
63
|
+
};
|
|
64
|
+
return object;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
exports.TransactionalEventPublisherAdapter = TransactionalEventPublisherAdapter;
|
|
68
|
+
exports.TransactionalEventPublisherAdapter = TransactionalEventPublisherAdapter = __decorate([
|
|
69
|
+
(0, common_1.Injectable)(),
|
|
70
|
+
__metadata("design:paramtypes", [Object, cqrs_1.EventBus])
|
|
71
|
+
], TransactionalEventPublisherAdapter);
|
|
72
|
+
//# sourceMappingURL=transactional-event-publisher-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transactional-event-publisher-adapter.js","sourceRoot":"","sources":["../../src/event-publisher/transactional-event-publisher-adapter.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAC5C,uCAMsB;AAOtB;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEI,IAAM,kCAAkC,GAAxC,MAAM,kCAAmC,SAAQ,qBAAc;IAEjD;IADnB,YACmB,QAAyB,EAC1C,QAAkB;QAElB,KAAK,CAAC,QAAQ,CAAC,CAAC;QAHC,aAAQ,GAAR,QAAQ,CAAiB;IAI5C,CAAC;IAED,iBAAiB,CAAgD,QAAW;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAE/B,MAAM,mBAAoB,SAAS,QAAgD;YACjF,OAAO,CAAwB,KAAa;gBAC1C,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC1B,CAAC;YACD,UAAU,CAAwB,MAAgB;gBAChD,QAAQ,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;SACF;QAED,OAAO,mBAAmC,CAAC;IAC7C,CAAC;IAED,kBAAkB,CAA0B,MAAS;QACnD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC/B,MAAM,IAAI,GAAG,MAGZ,CAAC;QACF,IAAI,CAAC,OAAO,GAAG,CAAC,KAAa,EAAQ,EAAE;YACrC,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC,CAAC;QACF,IAAI,CAAC,UAAU,GAAG,CAAC,MAAgB,EAAQ,EAAE;YAC3C,QAAQ,CAAC,UAAU,EAAE,CAAC,MAAM,CAAC,CAAC;QAChC,CAAC,CAAC;QACF,OAAO,MAAM,CAAC;IAChB,CAAC;CACF,CAAA;AArCY,gFAAkC;6CAAlC,kCAAkC;IAD9C,IAAA,mBAAU,GAAE;6CAIC,eAAQ;GAHT,kCAAkC,CAqC9C"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { IEvent, IEventPublisher } from '@nestjs/cqrs';
|
|
2
|
+
import { TransactionalEventDispatcher } from '../event-dispatcher/event-dispatcher';
|
|
3
|
+
/**
|
|
4
|
+
* `IEventPublisher` implementation that routes aggregate-emitted events
|
|
5
|
+
* to {@link TransactionalEventDispatcher} instead of pushing them straight
|
|
6
|
+
* into the `@nestjs/cqrs` `EventBus`.
|
|
7
|
+
*
|
|
8
|
+
* The dispatcher then attaches each event as a hook on the active
|
|
9
|
+
* transaction — so `AFTER_COMMIT` listeners only fire once the
|
|
10
|
+
* transaction commits, `AFTER_ROLLBACK` fires on rollback, etc.
|
|
11
|
+
*
|
|
12
|
+
* The class itself is the "strategy" half of the pair; it does not
|
|
13
|
+
* override `@nestjs/cqrs`'s `EventPublisher` by itself. The override is
|
|
14
|
+
* done by {@link TransactionalEventPublisherAdapter}, which injects this
|
|
15
|
+
* publisher into the aggregate-root merge path.
|
|
16
|
+
*/
|
|
17
|
+
export declare class TransactionalEventPublisher implements IEventPublisher {
|
|
18
|
+
private readonly dispatcher;
|
|
19
|
+
constructor(dispatcher: TransactionalEventDispatcher);
|
|
20
|
+
/**
|
|
21
|
+
* Route a single aggregate event through the dispatcher. Intentionally
|
|
22
|
+
* synchronous: `IEventPublisher.publish` may return anything, and the
|
|
23
|
+
* dispatcher's own scheduling is sync (hooks attach synchronously;
|
|
24
|
+
* invocation is deferred to commit/rollback time).
|
|
25
|
+
*/
|
|
26
|
+
publish<T extends IEvent>(event: T): void;
|
|
27
|
+
/**
|
|
28
|
+
* Route a list of aggregate events through the dispatcher, preserving
|
|
29
|
+
* their order (listeners fire in the order the aggregate emitted them).
|
|
30
|
+
*/
|
|
31
|
+
publishAll<T extends IEvent>(events: T[]): void;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=transactional-event-publisher.d.ts.map
|
|
@@ -0,0 +1,58 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.TransactionalEventPublisher = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const event_dispatcher_1 = require("../event-dispatcher/event-dispatcher");
|
|
15
|
+
/**
|
|
16
|
+
* `IEventPublisher` implementation that routes aggregate-emitted events
|
|
17
|
+
* to {@link TransactionalEventDispatcher} instead of pushing them straight
|
|
18
|
+
* into the `@nestjs/cqrs` `EventBus`.
|
|
19
|
+
*
|
|
20
|
+
* The dispatcher then attaches each event as a hook on the active
|
|
21
|
+
* transaction — so `AFTER_COMMIT` listeners only fire once the
|
|
22
|
+
* transaction commits, `AFTER_ROLLBACK` fires on rollback, etc.
|
|
23
|
+
*
|
|
24
|
+
* The class itself is the "strategy" half of the pair; it does not
|
|
25
|
+
* override `@nestjs/cqrs`'s `EventPublisher` by itself. The override is
|
|
26
|
+
* done by {@link TransactionalEventPublisherAdapter}, which injects this
|
|
27
|
+
* publisher into the aggregate-root merge path.
|
|
28
|
+
*/
|
|
29
|
+
let TransactionalEventPublisher = class TransactionalEventPublisher {
|
|
30
|
+
dispatcher;
|
|
31
|
+
constructor(dispatcher) {
|
|
32
|
+
this.dispatcher = dispatcher;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Route a single aggregate event through the dispatcher. Intentionally
|
|
36
|
+
* synchronous: `IEventPublisher.publish` may return anything, and the
|
|
37
|
+
* dispatcher's own scheduling is sync (hooks attach synchronously;
|
|
38
|
+
* invocation is deferred to commit/rollback time).
|
|
39
|
+
*/
|
|
40
|
+
publish(event) {
|
|
41
|
+
this.dispatcher.scheduleDispatch(event);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Route a list of aggregate events through the dispatcher, preserving
|
|
45
|
+
* their order (listeners fire in the order the aggregate emitted them).
|
|
46
|
+
*/
|
|
47
|
+
publishAll(events) {
|
|
48
|
+
for (const event of events) {
|
|
49
|
+
this.publish(event);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
exports.TransactionalEventPublisher = TransactionalEventPublisher;
|
|
54
|
+
exports.TransactionalEventPublisher = TransactionalEventPublisher = __decorate([
|
|
55
|
+
(0, common_1.Injectable)(),
|
|
56
|
+
__metadata("design:paramtypes", [event_dispatcher_1.TransactionalEventDispatcher])
|
|
57
|
+
], TransactionalEventPublisher);
|
|
58
|
+
//# sourceMappingURL=transactional-event-publisher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transactional-event-publisher.js","sourceRoot":"","sources":["../../src/event-publisher/transactional-event-publisher.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAA4C;AAG5C,2EAAoF;AAEpF;;;;;;;;;;;;;GAaG;AAEI,IAAM,2BAA2B,GAAjC,MAAM,2BAA2B;IACT;IAA7B,YAA6B,UAAwC;QAAxC,eAAU,GAAV,UAAU,CAA8B;IAAG,CAAC;IAEzE;;;;;OAKG;IACH,OAAO,CAAmB,KAAQ;QAChC,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC;IAED;;;OAGG;IACH,UAAU,CAAmB,MAAW;QACtC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;CACF,CAAA;AAtBY,kEAA2B;sCAA3B,2BAA2B;IADvC,IAAA,mBAAU,GAAE;qCAE8B,+CAA4B;GAD1D,2BAA2B,CAsBvC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { type OnApplicationBootstrap } from '@nestjs/common';
|
|
2
|
+
import { CqrsHandlerWrapper } from './handler-wrapper';
|
|
3
|
+
/**
|
|
4
|
+
* Fires `CqrsHandlerWrapper.wrapAll` at application bootstrap, after all
|
|
5
|
+
* `onModuleInit` hooks (including `@nestjs/cqrs`'s explorer) have
|
|
6
|
+
* completed. `@nestjs/cqrs`'s bus bindings resolve `instance.execute` at
|
|
7
|
+
* call time, so a late wrap still takes effect for every subsequent
|
|
8
|
+
* dispatch.
|
|
9
|
+
*
|
|
10
|
+
* Registered by `CqrsTransactionalModule` (added in a later iteration).
|
|
11
|
+
* Not intended for direct consumer instantiation.
|
|
12
|
+
*/
|
|
13
|
+
export declare class CqrsTransactionalBootstrap implements OnApplicationBootstrap {
|
|
14
|
+
private readonly wrapper;
|
|
15
|
+
constructor(wrapper: CqrsHandlerWrapper);
|
|
16
|
+
onApplicationBootstrap(): void;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=bootstrap.d.ts.map
|
|
@@ -0,0 +1,39 @@
|
|
|
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
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.CqrsTransactionalBootstrap = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const handler_wrapper_1 = require("./handler-wrapper");
|
|
15
|
+
/**
|
|
16
|
+
* Fires `CqrsHandlerWrapper.wrapAll` at application bootstrap, after all
|
|
17
|
+
* `onModuleInit` hooks (including `@nestjs/cqrs`'s explorer) have
|
|
18
|
+
* completed. `@nestjs/cqrs`'s bus bindings resolve `instance.execute` at
|
|
19
|
+
* call time, so a late wrap still takes effect for every subsequent
|
|
20
|
+
* dispatch.
|
|
21
|
+
*
|
|
22
|
+
* Registered by `CqrsTransactionalModule` (added in a later iteration).
|
|
23
|
+
* Not intended for direct consumer instantiation.
|
|
24
|
+
*/
|
|
25
|
+
let CqrsTransactionalBootstrap = class CqrsTransactionalBootstrap {
|
|
26
|
+
wrapper;
|
|
27
|
+
constructor(wrapper) {
|
|
28
|
+
this.wrapper = wrapper;
|
|
29
|
+
}
|
|
30
|
+
onApplicationBootstrap() {
|
|
31
|
+
this.wrapper.wrapAll();
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
exports.CqrsTransactionalBootstrap = CqrsTransactionalBootstrap;
|
|
35
|
+
exports.CqrsTransactionalBootstrap = CqrsTransactionalBootstrap = __decorate([
|
|
36
|
+
(0, common_1.Injectable)(),
|
|
37
|
+
__metadata("design:paramtypes", [handler_wrapper_1.CqrsHandlerWrapper])
|
|
38
|
+
], CqrsTransactionalBootstrap);
|
|
39
|
+
//# sourceMappingURL=bootstrap.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../src/handlers/bootstrap.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,2CAAyE;AAEzE,uDAAuD;AAEvD;;;;;;;;;GASG;AAEI,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;IACR;IAA7B,YAA6B,OAA2B;QAA3B,YAAO,GAAP,OAAO,CAAoB;IAAG,CAAC;IAE5D,sBAAsB;QACpB,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IACzB,CAAC;CACF,CAAA;AANY,gEAA0B;qCAA1B,0BAA0B;IADtC,IAAA,mBAAU,GAAE;qCAE2B,oCAAkB;GAD7C,0BAA0B,CAMtC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import 'reflect-metadata';
|
|
2
|
+
import { DiscoveryService } from '@nestjs/core';
|
|
3
|
+
import { TransactionManager, type TransactionalMetadata } from '@nestjs-transactional/core';
|
|
4
|
+
/**
|
|
5
|
+
* DI injection token for {@link HandlerWrapperOptions}. The wrapper reads
|
|
6
|
+
* options via this token so `CqrsTransactionalModule` can provide them
|
|
7
|
+
* synchronously or asynchronously.
|
|
8
|
+
*/
|
|
9
|
+
export declare const CQRS_HANDLER_WRAPPER_OPTIONS: unique symbol;
|
|
10
|
+
/**
|
|
11
|
+
* Options that control which CQRS handler kinds are wrapped and how the
|
|
12
|
+
* transaction is configured when the handler has no explicit
|
|
13
|
+
* `@Transactional()` metadata.
|
|
14
|
+
*/
|
|
15
|
+
export interface HandlerWrapperOptions {
|
|
16
|
+
/** Wrap `@CommandHandler`-decorated classes. Default: `true`. */
|
|
17
|
+
readonly wrapCommandHandlers?: boolean;
|
|
18
|
+
/** Wrap `@QueryHandler`-decorated classes. Default: `true`. */
|
|
19
|
+
readonly wrapQueryHandlers?: boolean;
|
|
20
|
+
/** Wrap `@EventsHandler`-decorated classes. Default: `true`. */
|
|
21
|
+
readonly wrapEventHandlers?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Fallback metadata applied to query handlers that carry no
|
|
24
|
+
* `@Transactional` annotation. Typically `{ readOnly: true }`. When
|
|
25
|
+
* omitted, undecorated query handlers are left unwrapped (no
|
|
26
|
+
* transaction).
|
|
27
|
+
*/
|
|
28
|
+
readonly defaultQueryOptions?: Partial<TransactionalMetadata>;
|
|
29
|
+
/**
|
|
30
|
+
* Fallback metadata applied to command handlers that carry no
|
|
31
|
+
* `@Transactional` annotation. When omitted, undecorated command
|
|
32
|
+
* handlers are left unwrapped.
|
|
33
|
+
*/
|
|
34
|
+
readonly defaultCommandOptions?: Partial<TransactionalMetadata>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Wraps the `execute` (or `handle`) method of every `@CommandHandler` /
|
|
38
|
+
* `@QueryHandler` / `@EventsHandler` instance with a transaction, using
|
|
39
|
+
* the handler's own `@Transactional` metadata where present or the
|
|
40
|
+
* kind-specific defaults from {@link HandlerWrapperOptions} otherwise.
|
|
41
|
+
*
|
|
42
|
+
* The replacement is an own-property assignment on each handler instance,
|
|
43
|
+
* shadowing the prototype method. `@nestjs/cqrs`'s buses resolve
|
|
44
|
+
* `instance.execute` / `instance.handle` at call time (late binding), so
|
|
45
|
+
* the wrap takes effect for every subsequent bus dispatch.
|
|
46
|
+
*
|
|
47
|
+
* Double-wrap prevention: each wrapped method is tagged with the shared
|
|
48
|
+
* `WRAPPED_MARKER` symbol. Other mechanisms in the coordinated wrapping
|
|
49
|
+
* triad (see ADR-005) honour the same marker.
|
|
50
|
+
*
|
|
51
|
+
* Limitation: only works with static-dependency-tree (singleton) handlers.
|
|
52
|
+
* Request-scoped handlers are resolved per-request by `@nestjs/cqrs`'s
|
|
53
|
+
* `ModuleRef.resolve`, which produces a fresh instance our wrap has not
|
|
54
|
+
* mutated.
|
|
55
|
+
*/
|
|
56
|
+
export declare class CqrsHandlerWrapper {
|
|
57
|
+
private readonly discovery;
|
|
58
|
+
private readonly manager;
|
|
59
|
+
private readonly options;
|
|
60
|
+
private readonly logger;
|
|
61
|
+
constructor(discovery: DiscoveryService, manager: TransactionManager, options: HandlerWrapperOptions);
|
|
62
|
+
/**
|
|
63
|
+
* Scan every provider and wrap handler methods. Safe to call multiple
|
|
64
|
+
* times — the `WRAPPED_MARKER` check guarantees idempotency.
|
|
65
|
+
*/
|
|
66
|
+
wrapAll(): void;
|
|
67
|
+
private classifyHandler;
|
|
68
|
+
private wrapHandler;
|
|
69
|
+
/**
|
|
70
|
+
* Priority order: method-level `@Transactional` > class-level
|
|
71
|
+
* `@Transactional` > kind-specific defaults. Returns `undefined` when
|
|
72
|
+
* nothing applies — the handler is then left unwrapped.
|
|
73
|
+
*/
|
|
74
|
+
private resolveMetadata;
|
|
75
|
+
private pickDefaults;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=handler-wrapper.d.ts.map
|
|
@@ -0,0 +1,183 @@
|
|
|
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 CqrsHandlerWrapper_1;
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.CqrsHandlerWrapper = exports.CQRS_HANDLER_WRAPPER_OPTIONS = void 0;
|
|
17
|
+
require("reflect-metadata");
|
|
18
|
+
const common_1 = require("@nestjs/common");
|
|
19
|
+
const core_1 = require("@nestjs/core");
|
|
20
|
+
const core_2 = require("@nestjs-transactional/core");
|
|
21
|
+
/**
|
|
22
|
+
* Metadata keys written by `@nestjs/cqrs`'s `@CommandHandler` /
|
|
23
|
+
* `@QueryHandler` / `@EventsHandler` decorators onto the handler class
|
|
24
|
+
* constructor. The package does NOT re-export these from its public
|
|
25
|
+
* barrel — we mirror them here because we read them at wrap time to
|
|
26
|
+
* identify CQRS handlers.
|
|
27
|
+
*
|
|
28
|
+
* Values must match the strings in
|
|
29
|
+
* `node_modules/@nestjs/cqrs/dist/decorators/constants.js`. Coupling to
|
|
30
|
+
* `@nestjs/cqrs` internals is explicitly accepted per DD-002
|
|
31
|
+
* (`docs/dd/002-no-fork-nestjs-cqrs.md`) — we prefer wrapping
|
|
32
|
+
* to forking.
|
|
33
|
+
*/
|
|
34
|
+
const COMMAND_HANDLER_METADATA = '__commandHandler__';
|
|
35
|
+
const QUERY_HANDLER_METADATA = '__queryHandler__';
|
|
36
|
+
const EVENTS_HANDLER_METADATA = '__eventsHandler__';
|
|
37
|
+
/**
|
|
38
|
+
* Process-global identity for the "already wrapped" marker, matching
|
|
39
|
+
* `WRAPPED_MARKER` in the core package. `Symbol.for` resolves to the same
|
|
40
|
+
* symbol across any copy of the package tree, so a method wrapped by
|
|
41
|
+
* `TransactionalMethodsBootstrap` (core) will still be recognized by us
|
|
42
|
+
* and vice versa. Core does not re-export this symbol from its public
|
|
43
|
+
* barrel; its JSDoc documents re-derivation via `Symbol.for` as supported.
|
|
44
|
+
*/
|
|
45
|
+
const WRAPPED_MARKER = Symbol.for('@nestjs-transactional/wrapped');
|
|
46
|
+
/**
|
|
47
|
+
* DI injection token for {@link HandlerWrapperOptions}. The wrapper reads
|
|
48
|
+
* options via this token so `CqrsTransactionalModule` can provide them
|
|
49
|
+
* synchronously or asynchronously.
|
|
50
|
+
*/
|
|
51
|
+
exports.CQRS_HANDLER_WRAPPER_OPTIONS = Symbol('CQRS_HANDLER_WRAPPER_OPTIONS');
|
|
52
|
+
/**
|
|
53
|
+
* Wraps the `execute` (or `handle`) method of every `@CommandHandler` /
|
|
54
|
+
* `@QueryHandler` / `@EventsHandler` instance with a transaction, using
|
|
55
|
+
* the handler's own `@Transactional` metadata where present or the
|
|
56
|
+
* kind-specific defaults from {@link HandlerWrapperOptions} otherwise.
|
|
57
|
+
*
|
|
58
|
+
* The replacement is an own-property assignment on each handler instance,
|
|
59
|
+
* shadowing the prototype method. `@nestjs/cqrs`'s buses resolve
|
|
60
|
+
* `instance.execute` / `instance.handle` at call time (late binding), so
|
|
61
|
+
* the wrap takes effect for every subsequent bus dispatch.
|
|
62
|
+
*
|
|
63
|
+
* Double-wrap prevention: each wrapped method is tagged with the shared
|
|
64
|
+
* `WRAPPED_MARKER` symbol. Other mechanisms in the coordinated wrapping
|
|
65
|
+
* triad (see ADR-005) honour the same marker.
|
|
66
|
+
*
|
|
67
|
+
* Limitation: only works with static-dependency-tree (singleton) handlers.
|
|
68
|
+
* Request-scoped handlers are resolved per-request by `@nestjs/cqrs`'s
|
|
69
|
+
* `ModuleRef.resolve`, which produces a fresh instance our wrap has not
|
|
70
|
+
* mutated.
|
|
71
|
+
*/
|
|
72
|
+
let CqrsHandlerWrapper = CqrsHandlerWrapper_1 = class CqrsHandlerWrapper {
|
|
73
|
+
discovery;
|
|
74
|
+
manager;
|
|
75
|
+
options;
|
|
76
|
+
logger = new common_1.Logger(CqrsHandlerWrapper_1.name);
|
|
77
|
+
constructor(discovery, manager, options) {
|
|
78
|
+
this.discovery = discovery;
|
|
79
|
+
this.manager = manager;
|
|
80
|
+
this.options = options;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Scan every provider and wrap handler methods. Safe to call multiple
|
|
84
|
+
* times — the `WRAPPED_MARKER` check guarantees idempotency.
|
|
85
|
+
*/
|
|
86
|
+
wrapAll() {
|
|
87
|
+
const providers = this.discovery.getProviders();
|
|
88
|
+
let wrappedCount = 0;
|
|
89
|
+
for (const wrapper of providers) {
|
|
90
|
+
if (wrapper.instance === null || wrapper.instance === undefined) {
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
if (typeof wrapper.metatype !== 'function') {
|
|
94
|
+
// Value / factory providers have no class constructor — nothing to
|
|
95
|
+
// classify as a CQRS handler.
|
|
96
|
+
continue;
|
|
97
|
+
}
|
|
98
|
+
const instance = wrapper.instance;
|
|
99
|
+
const metatype = wrapper.metatype;
|
|
100
|
+
const kind = this.classifyHandler(metatype);
|
|
101
|
+
if (kind === null) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
const methodName = kind === 'event' ? 'handle' : 'execute';
|
|
105
|
+
if (this.wrapHandler(instance, metatype, methodName, kind)) {
|
|
106
|
+
wrappedCount++;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
this.logger.log(`Wrapped ${wrappedCount} CQRS handler${wrappedCount === 1 ? '' : 's'} with @Transactional`);
|
|
110
|
+
}
|
|
111
|
+
classifyHandler(metatype) {
|
|
112
|
+
if (this.options.wrapCommandHandlers !== false &&
|
|
113
|
+
Reflect.hasMetadata(COMMAND_HANDLER_METADATA, metatype)) {
|
|
114
|
+
return 'command';
|
|
115
|
+
}
|
|
116
|
+
if (this.options.wrapQueryHandlers !== false &&
|
|
117
|
+
Reflect.hasMetadata(QUERY_HANDLER_METADATA, metatype)) {
|
|
118
|
+
return 'query';
|
|
119
|
+
}
|
|
120
|
+
if (this.options.wrapEventHandlers !== false &&
|
|
121
|
+
Reflect.hasMetadata(EVENTS_HANDLER_METADATA, metatype)) {
|
|
122
|
+
return 'event';
|
|
123
|
+
}
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
wrapHandler(instance, metatype, methodName, kind) {
|
|
127
|
+
const host = instance;
|
|
128
|
+
const currentMethod = host[methodName];
|
|
129
|
+
if (typeof currentMethod !== 'function') {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
if (Reflect.getMetadata(WRAPPED_MARKER, currentMethod) === true) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
const resolved = this.resolveMetadata(currentMethod, metatype, kind);
|
|
136
|
+
if (resolved === undefined) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
const boundOriginal = currentMethod.bind(instance);
|
|
140
|
+
const manager = this.manager;
|
|
141
|
+
const wrapped = (...args) => manager.run(resolved, () => Promise.resolve(boundOriginal(...args)));
|
|
142
|
+
Reflect.defineMetadata(WRAPPED_MARKER, true, wrapped);
|
|
143
|
+
Reflect.defineMetadata(core_2.TRANSACTIONAL_METADATA, resolved, wrapped);
|
|
144
|
+
host[methodName] = wrapped;
|
|
145
|
+
this.logger.debug(`Wrapped ${kind} handler ${instance.constructor.name}.${methodName} ` +
|
|
146
|
+
`(propagation=${resolved.propagation ?? core_2.PropagationMode.REQUIRED})`);
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Priority order: method-level `@Transactional` > class-level
|
|
151
|
+
* `@Transactional` > kind-specific defaults. Returns `undefined` when
|
|
152
|
+
* nothing applies — the handler is then left unwrapped.
|
|
153
|
+
*/
|
|
154
|
+
resolveMetadata(method, metatype, kind) {
|
|
155
|
+
const explicit = (0, core_2.getTransactionalMetadata)(method) ?? (0, core_2.getTransactionalMetadata)(metatype);
|
|
156
|
+
if (explicit !== undefined) {
|
|
157
|
+
return explicit;
|
|
158
|
+
}
|
|
159
|
+
const defaults = this.pickDefaults(kind);
|
|
160
|
+
if (defaults === undefined) {
|
|
161
|
+
return undefined;
|
|
162
|
+
}
|
|
163
|
+
return { propagation: core_2.PropagationMode.REQUIRED, ...defaults };
|
|
164
|
+
}
|
|
165
|
+
pickDefaults(kind) {
|
|
166
|
+
switch (kind) {
|
|
167
|
+
case 'query':
|
|
168
|
+
return this.options.defaultQueryOptions;
|
|
169
|
+
case 'command':
|
|
170
|
+
return this.options.defaultCommandOptions;
|
|
171
|
+
case 'event':
|
|
172
|
+
return undefined;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
exports.CqrsHandlerWrapper = CqrsHandlerWrapper;
|
|
177
|
+
exports.CqrsHandlerWrapper = CqrsHandlerWrapper = CqrsHandlerWrapper_1 = __decorate([
|
|
178
|
+
(0, common_1.Injectable)(),
|
|
179
|
+
__param(2, (0, common_1.Inject)(exports.CQRS_HANDLER_WRAPPER_OPTIONS)),
|
|
180
|
+
__metadata("design:paramtypes", [core_1.DiscoveryService,
|
|
181
|
+
core_2.TransactionManager, Object])
|
|
182
|
+
], CqrsHandlerWrapper);
|
|
183
|
+
//# sourceMappingURL=handler-wrapper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler-wrapper.js","sourceRoot":"","sources":["../../src/handlers/handler-wrapper.ts"],"names":[],"mappings":"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"}
|