@rolandsall24/nest-mediator 0.7.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +650 -1349
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/lib/aggregate/aggregate-repository.base.d.ts +90 -0
- package/dist/lib/aggregate/aggregate-repository.base.d.ts.map +1 -0
- package/dist/lib/aggregate/aggregate-repository.base.js +161 -0
- package/dist/lib/aggregate/aggregate-repository.base.js.map +1 -0
- package/dist/lib/aggregate/aggregate-root.base.d.ts +105 -0
- package/dist/lib/aggregate/aggregate-root.base.d.ts.map +1 -0
- package/dist/lib/aggregate/aggregate-root.base.js +127 -0
- package/dist/lib/aggregate/aggregate-root.base.js.map +1 -0
- package/dist/lib/aggregate/index.d.ts +3 -0
- package/dist/lib/aggregate/index.d.ts.map +1 -0
- package/dist/lib/aggregate/index.js +19 -0
- package/dist/lib/aggregate/index.js.map +1 -0
- package/dist/lib/context/index.d.ts +2 -0
- package/dist/lib/context/index.d.ts.map +1 -0
- package/dist/lib/context/index.js +18 -0
- package/dist/lib/context/index.js.map +1 -0
- package/dist/lib/context/mediator-context.d.ts +78 -0
- package/dist/lib/context/mediator-context.d.ts.map +1 -0
- package/dist/lib/context/mediator-context.js +93 -0
- package/dist/lib/context/mediator-context.js.map +1 -0
- package/dist/lib/decorators/domain-event.decorator.d.ts +48 -0
- package/dist/lib/decorators/domain-event.decorator.d.ts.map +1 -0
- package/dist/lib/decorators/domain-event.decorator.js +60 -0
- package/dist/lib/decorators/domain-event.decorator.js.map +1 -0
- package/dist/lib/decorators/for-aggregate.decorator.d.ts +21 -0
- package/dist/lib/decorators/for-aggregate.decorator.d.ts.map +1 -0
- package/dist/lib/decorators/for-aggregate.decorator.js +29 -0
- package/dist/lib/decorators/for-aggregate.decorator.js.map +1 -0
- package/dist/lib/decorators/index.d.ts +2 -0
- package/dist/lib/decorators/index.d.ts.map +1 -1
- package/dist/lib/decorators/index.js +2 -0
- package/dist/lib/decorators/index.js.map +1 -1
- package/dist/lib/event-store/aggregate-info.extractor.d.ts +35 -0
- package/dist/lib/event-store/aggregate-info.extractor.d.ts.map +1 -0
- package/dist/lib/event-store/aggregate-info.extractor.js +41 -0
- package/dist/lib/event-store/aggregate-info.extractor.js.map +1 -0
- package/dist/lib/event-store/event-store-persistence.consumer.d.ts +33 -0
- package/dist/lib/event-store/event-store-persistence.consumer.d.ts.map +1 -0
- package/dist/lib/event-store/event-store-persistence.consumer.js +79 -0
- package/dist/lib/event-store/event-store-persistence.consumer.js.map +1 -0
- package/dist/lib/event-store/index.d.ts +6 -0
- package/dist/lib/event-store/index.d.ts.map +1 -0
- package/dist/lib/event-store/index.js +22 -0
- package/dist/lib/event-store/index.js.map +1 -0
- package/dist/lib/event-store/repositories/postgres-event-store.repository.d.ts +49 -0
- package/dist/lib/event-store/repositories/postgres-event-store.repository.d.ts.map +1 -0
- package/dist/lib/event-store/repositories/postgres-event-store.repository.js +145 -0
- package/dist/lib/event-store/repositories/postgres-event-store.repository.js.map +1 -0
- package/dist/lib/event-store/schema/postgres.schema.d.ts +15 -0
- package/dist/lib/event-store/schema/postgres.schema.d.ts.map +1 -0
- package/dist/lib/event-store/schema/postgres.schema.js +68 -0
- package/dist/lib/event-store/schema/postgres.schema.js.map +1 -0
- package/dist/lib/event-store/strategies/abstract-postgres-connection.strategy.d.ts +21 -0
- package/dist/lib/event-store/strategies/abstract-postgres-connection.strategy.d.ts.map +1 -0
- package/dist/lib/event-store/strategies/abstract-postgres-connection.strategy.js +36 -0
- package/dist/lib/event-store/strategies/abstract-postgres-connection.strategy.js.map +1 -0
- package/dist/lib/event-store/strategies/custom-repository.strategy.d.ts +20 -0
- package/dist/lib/event-store/strategies/custom-repository.strategy.d.ts.map +1 -0
- package/dist/lib/event-store/strategies/custom-repository.strategy.js +38 -0
- package/dist/lib/event-store/strategies/custom-repository.strategy.js.map +1 -0
- package/dist/lib/event-store/strategies/event-store-strategy.interface.d.ts +10 -0
- package/dist/lib/event-store/strategies/event-store-strategy.interface.d.ts.map +1 -0
- package/dist/lib/event-store/strategies/event-store-strategy.interface.js +3 -0
- package/dist/lib/event-store/strategies/event-store-strategy.interface.js.map +1 -0
- package/dist/lib/event-store/strategies/existing-pool.strategy.d.ts +14 -0
- package/dist/lib/event-store/strategies/existing-pool.strategy.d.ts.map +1 -0
- package/dist/lib/event-store/strategies/existing-pool.strategy.js +24 -0
- package/dist/lib/event-store/strategies/existing-pool.strategy.js.map +1 -0
- package/dist/lib/event-store/strategies/index.d.ts +17 -0
- package/dist/lib/event-store/strategies/index.d.ts.map +1 -0
- package/dist/lib/event-store/strategies/index.js +50 -0
- package/dist/lib/event-store/strategies/index.js.map +1 -0
- package/dist/lib/event-store/strategies/persistence-consumer.strategy.d.ts +11 -0
- package/dist/lib/event-store/strategies/persistence-consumer.strategy.d.ts.map +1 -0
- package/dist/lib/event-store/strategies/persistence-consumer.strategy.js +32 -0
- package/dist/lib/event-store/strategies/persistence-consumer.strategy.js.map +1 -0
- package/dist/lib/event-store/strategies/postgres-schema-manager.d.ts +11 -0
- package/dist/lib/event-store/strategies/postgres-schema-manager.d.ts.map +1 -0
- package/dist/lib/event-store/strategies/postgres-schema-manager.js +25 -0
- package/dist/lib/event-store/strategies/postgres-schema-manager.js.map +1 -0
- package/dist/lib/event-store/strategies/schema-manager.interface.d.ts +10 -0
- package/dist/lib/event-store/strategies/schema-manager.interface.d.ts.map +1 -0
- package/dist/lib/{interfaces/event-handler.interface.js → event-store/strategies/schema-manager.interface.js} +1 -1
- package/dist/lib/event-store/strategies/schema-manager.interface.js.map +1 -0
- package/dist/lib/event-store/strategies/url-connection.strategy.d.ts +14 -0
- package/dist/lib/event-store/strategies/url-connection.strategy.d.ts.map +1 -0
- package/dist/lib/event-store/strategies/url-connection.strategy.js +26 -0
- package/dist/lib/event-store/strategies/url-connection.strategy.js.map +1 -0
- package/dist/lib/interfaces/event-consumer.interface.d.ts +90 -11
- package/dist/lib/interfaces/event-consumer.interface.d.ts.map +1 -1
- package/dist/lib/interfaces/event-store.interface.d.ts +157 -0
- package/dist/lib/interfaces/event-store.interface.d.ts.map +1 -0
- package/dist/lib/interfaces/event-store.interface.js +23 -0
- package/dist/lib/interfaces/event-store.interface.js.map +1 -0
- package/dist/lib/interfaces/index.d.ts +1 -0
- package/dist/lib/interfaces/index.d.ts.map +1 -1
- package/dist/lib/interfaces/index.js +1 -0
- package/dist/lib/interfaces/index.js.map +1 -1
- package/dist/lib/nest-mediator.module.d.ts +20 -0
- package/dist/lib/nest-mediator.module.d.ts.map +1 -1
- package/dist/lib/nest-mediator.module.js +54 -6
- package/dist/lib/nest-mediator.module.js.map +1 -1
- package/dist/lib/services/event.bus.d.ts +35 -7
- package/dist/lib/services/event.bus.d.ts.map +1 -1
- package/dist/lib/services/event.bus.js +133 -56
- package/dist/lib/services/event.bus.js.map +1 -1
- package/dist/lib/services/mediator.bus.d.ts +13 -4
- package/dist/lib/services/mediator.bus.d.ts.map +1 -1
- package/dist/lib/services/mediator.bus.js +35 -5
- package/dist/lib/services/mediator.bus.js.map +1 -1
- package/package.json +44 -7
- package/dist/lib/interfaces/event-handler.interface.d.ts +0 -24
- package/dist/lib/interfaces/event-handler.interface.d.ts.map +0 -1
- package/dist/lib/interfaces/event-handler.interface.js.map +0 -1
- package/dist/tsconfig.lib.tsbuildinfo +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -3,5 +3,8 @@ export * from './lib/decorators/index.js';
|
|
|
3
3
|
export * from './lib/services/index.js';
|
|
4
4
|
export * from './lib/behaviors/index.js';
|
|
5
5
|
export * from './lib/exceptions/index.js';
|
|
6
|
+
export * from './lib/context/index.js';
|
|
7
|
+
export * from './lib/aggregate/index.js';
|
|
8
|
+
export * from './lib/event-store/index.js';
|
|
6
9
|
export * from './lib/nest-mediator.module.js';
|
|
7
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,2BAA2B,CAAC;AAG1C,cAAc,2BAA2B,CAAC;AAG1C,cAAc,yBAAyB,CAAC;AAGxC,cAAc,0BAA0B,CAAC;AAGzC,cAAc,2BAA2B,CAAC;AAG1C,cAAc,+BAA+B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,2BAA2B,CAAC;AAG1C,cAAc,2BAA2B,CAAC;AAG1C,cAAc,yBAAyB,CAAC;AAGxC,cAAc,0BAA0B,CAAC;AAGzC,cAAc,2BAA2B,CAAC;AAG1C,cAAc,wBAAwB,CAAC;AAGvC,cAAc,0BAA0B,CAAC;AAGzC,cAAc,4BAA4B,CAAC;AAG3C,cAAc,+BAA+B,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -24,6 +24,12 @@ __exportStar(require("./lib/services/index.js"), exports);
|
|
|
24
24
|
__exportStar(require("./lib/behaviors/index.js"), exports);
|
|
25
25
|
// Exceptions
|
|
26
26
|
__exportStar(require("./lib/exceptions/index.js"), exports);
|
|
27
|
+
// Context
|
|
28
|
+
__exportStar(require("./lib/context/index.js"), exports);
|
|
29
|
+
// Aggregate (Event Sourcing)
|
|
30
|
+
__exportStar(require("./lib/aggregate/index.js"), exports);
|
|
31
|
+
// Event Store
|
|
32
|
+
__exportStar(require("./lib/event-store/index.js"), exports);
|
|
27
33
|
// Module
|
|
28
34
|
__exportStar(require("./lib/nest-mediator.module.js"), exports);
|
|
29
35
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,aAAa;AACb,4DAA0C;AAE1C,aAAa;AACb,4DAA0C;AAE1C,WAAW;AACX,0DAAwC;AAExC,YAAY;AACZ,2DAAyC;AAEzC,aAAa;AACb,4DAA0C;AAE1C,SAAS;AACT,gEAA8C"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,aAAa;AACb,4DAA0C;AAE1C,aAAa;AACb,4DAA0C;AAE1C,WAAW;AACX,0DAAwC;AAExC,YAAY;AACZ,2DAAyC;AAEzC,aAAa;AACb,4DAA0C;AAE1C,UAAU;AACV,yDAAuC;AAEvC,6BAA6B;AAC7B,2DAAyC;AAEzC,cAAc;AACd,6DAA2C;AAE3C,SAAS;AACT,gEAA8C"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { IEvent, IEventBus, IEventStoreRepository } from '../interfaces/index.js';
|
|
2
|
+
import { AggregateRoot } from './aggregate-root.base.js';
|
|
3
|
+
/**
|
|
4
|
+
* Base class for aggregate repositories in event sourcing.
|
|
5
|
+
*
|
|
6
|
+
* Repositories handle loading and saving aggregates:
|
|
7
|
+
* - Loading: Replay events from event store to rebuild aggregate state
|
|
8
|
+
* - Saving: Publish uncommitted events via event bus (which persists + dispatches to consumers)
|
|
9
|
+
*
|
|
10
|
+
* Use the `@ForAggregate(AggregateClass)` decorator to eliminate all boilerplate.
|
|
11
|
+
* The decorator + global `@DomainEvent` registry provide:
|
|
12
|
+
* - `aggregateType` — derived from a temporary aggregate instance
|
|
13
|
+
* - `createEmptyAggregate()` — instantiates the aggregate class
|
|
14
|
+
* - `deserializeEvent()` — looks up event classes from the `@DomainEvent` registry
|
|
15
|
+
*
|
|
16
|
+
* @template TAggregate - The aggregate type
|
|
17
|
+
* @template TId - The aggregate's identifier type
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* @Injectable()
|
|
22
|
+
* @ForAggregate(OrderAggregate)
|
|
23
|
+
* export class OrderRepository extends AggregateRepository<OrderAggregate, string>
|
|
24
|
+
* implements IOrderRepository {}
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare abstract class AggregateRepository<TAggregate extends AggregateRoot<TId>, TId = string> {
|
|
28
|
+
private readonly logger;
|
|
29
|
+
protected readonly eventStore: IEventStoreRepository;
|
|
30
|
+
protected readonly eventBus: IEventBus;
|
|
31
|
+
/**
|
|
32
|
+
* The aggregate type name, derived from the aggregate class metadata.
|
|
33
|
+
* Lazily resolved on first access.
|
|
34
|
+
*/
|
|
35
|
+
private _aggregateType?;
|
|
36
|
+
protected get aggregateType(): string;
|
|
37
|
+
/**
|
|
38
|
+
* Create an empty aggregate instance for hydration.
|
|
39
|
+
* Derived from the `@ForAggregate` decorator metadata.
|
|
40
|
+
* Can be overridden for custom instantiation logic.
|
|
41
|
+
*/
|
|
42
|
+
protected createEmptyAggregate(): TAggregate;
|
|
43
|
+
/**
|
|
44
|
+
* Deserialize a stored event back to an event instance.
|
|
45
|
+
* Uses the global `@DomainEvent` registry to find the event class.
|
|
46
|
+
* Can be overridden for custom deserialization logic.
|
|
47
|
+
*
|
|
48
|
+
* Returns `null` for event types not registered for this aggregate.
|
|
49
|
+
* This is expected — side-effect events (e.g. InventoryReservedEvent)
|
|
50
|
+
* may be stored under the same aggregate ID but are not part of
|
|
51
|
+
* the aggregate's state and should be skipped during hydration.
|
|
52
|
+
*
|
|
53
|
+
* @param eventType - The event class name
|
|
54
|
+
* @param payload - The serialized event data
|
|
55
|
+
* @returns The deserialized event, or null if the event type is not registered
|
|
56
|
+
*/
|
|
57
|
+
protected deserializeEvent(eventType: string, payload: Record<string, unknown>): IEvent | null;
|
|
58
|
+
/**
|
|
59
|
+
* Find an aggregate by its ID.
|
|
60
|
+
* Returns null if the aggregate doesn't exist.
|
|
61
|
+
*
|
|
62
|
+
* @param id - The aggregate ID
|
|
63
|
+
* @returns The hydrated aggregate or null
|
|
64
|
+
*/
|
|
65
|
+
findById(id: TId): Promise<TAggregate | null>;
|
|
66
|
+
/**
|
|
67
|
+
* Get an aggregate by its ID.
|
|
68
|
+
* Throws an error if the aggregate doesn't exist.
|
|
69
|
+
*
|
|
70
|
+
* @param id - The aggregate ID
|
|
71
|
+
* @returns The hydrated aggregate
|
|
72
|
+
* @throws Error if aggregate not found
|
|
73
|
+
*/
|
|
74
|
+
getById(id: TId): Promise<TAggregate>;
|
|
75
|
+
/**
|
|
76
|
+
* Save an aggregate by publishing its uncommitted events.
|
|
77
|
+
*
|
|
78
|
+
* Each event is published via the event bus, which:
|
|
79
|
+
* 1. Persists the event to the event store (system phase)
|
|
80
|
+
* 2. Dispatches to critical consumers (sequential, with compensation)
|
|
81
|
+
* 3. Dispatches to non-critical consumers (parallel, fire-and-forget)
|
|
82
|
+
*
|
|
83
|
+
* After all events are successfully published, they are marked as committed.
|
|
84
|
+
*
|
|
85
|
+
* @param aggregate - The aggregate to save
|
|
86
|
+
* @throws Error if any event fails to publish (compensation will run for critical consumers)
|
|
87
|
+
*/
|
|
88
|
+
save(aggregate: TAggregate): Promise<void>;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=aggregate-repository.base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate-repository.base.d.ts","sourceRoot":"","sources":["../../../src/lib/aggregate/aggregate-repository.base.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,qBAAqB,EAA0B,MAAM,wBAAwB,CAAC;AAC1G,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAKzD;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,8BAAsB,mBAAmB,CACvC,UAAU,SAAS,aAAa,CAAC,GAAG,CAAC,EACrC,GAAG,GAAG,MAAM;IAEZ,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;IAG5D,SAAS,CAAC,QAAQ,CAAC,UAAU,EAAG,qBAAqB,CAAC;IAGtD,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAG,SAAS,CAAC;IAExC;;;OAGG;IACH,OAAO,CAAC,cAAc,CAAC,CAAS;IAEhC,SAAS,KAAK,aAAa,IAAI,MAAM,CAKpC;IAED;;;;OAIG;IACH,SAAS,CAAC,oBAAoB,IAAI,UAAU;IAY5C;;;;;;;;;;;;;OAaG;IACH,SAAS,CAAC,gBAAgB,CACxB,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,MAAM,GAAG,IAAI;IAchB;;;;;;OAMG;IACG,QAAQ,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAsBnD;;;;;;;OAOG;IACG,OAAO,CAAC,EAAE,EAAE,GAAG,GAAG,OAAO,CAAC,UAAU,CAAC;IAU3C;;;;;;;;;;;;OAYG;IACG,IAAI,CAAC,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;CAgBjD"}
|
|
@@ -0,0 +1,161 @@
|
|
|
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.AggregateRepository = void 0;
|
|
13
|
+
const common_1 = require("@nestjs/common");
|
|
14
|
+
const index_js_1 = require("../interfaces/index.js");
|
|
15
|
+
const for_aggregate_decorator_js_1 = require("../decorators/for-aggregate.decorator.js");
|
|
16
|
+
const domain_event_decorator_js_1 = require("../decorators/domain-event.decorator.js");
|
|
17
|
+
const mediator_bus_js_1 = require("../services/mediator.bus.js");
|
|
18
|
+
/**
|
|
19
|
+
* Base class for aggregate repositories in event sourcing.
|
|
20
|
+
*
|
|
21
|
+
* Repositories handle loading and saving aggregates:
|
|
22
|
+
* - Loading: Replay events from event store to rebuild aggregate state
|
|
23
|
+
* - Saving: Publish uncommitted events via event bus (which persists + dispatches to consumers)
|
|
24
|
+
*
|
|
25
|
+
* Use the `@ForAggregate(AggregateClass)` decorator to eliminate all boilerplate.
|
|
26
|
+
* The decorator + global `@DomainEvent` registry provide:
|
|
27
|
+
* - `aggregateType` — derived from a temporary aggregate instance
|
|
28
|
+
* - `createEmptyAggregate()` — instantiates the aggregate class
|
|
29
|
+
* - `deserializeEvent()` — looks up event classes from the `@DomainEvent` registry
|
|
30
|
+
*
|
|
31
|
+
* @template TAggregate - The aggregate type
|
|
32
|
+
* @template TId - The aggregate's identifier type
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```typescript
|
|
36
|
+
* @Injectable()
|
|
37
|
+
* @ForAggregate(OrderAggregate)
|
|
38
|
+
* export class OrderRepository extends AggregateRepository<OrderAggregate, string>
|
|
39
|
+
* implements IOrderRepository {}
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
class AggregateRepository {
|
|
43
|
+
constructor() {
|
|
44
|
+
this.logger = new common_1.Logger(this.constructor.name);
|
|
45
|
+
}
|
|
46
|
+
get aggregateType() {
|
|
47
|
+
if (!this._aggregateType) {
|
|
48
|
+
this._aggregateType = this.createEmptyAggregate().aggregateType;
|
|
49
|
+
}
|
|
50
|
+
return this._aggregateType;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create an empty aggregate instance for hydration.
|
|
54
|
+
* Derived from the `@ForAggregate` decorator metadata.
|
|
55
|
+
* Can be overridden for custom instantiation logic.
|
|
56
|
+
*/
|
|
57
|
+
createEmptyAggregate() {
|
|
58
|
+
const aggregateClass = Reflect.getMetadata(for_aggregate_decorator_js_1.AGGREGATE_CLASS_METADATA, this.constructor);
|
|
59
|
+
if (!aggregateClass) {
|
|
60
|
+
throw new Error(`${this.constructor.name}: Missing @ForAggregate() decorator. ` +
|
|
61
|
+
`Add @ForAggregate(YourAggregate) to your repository class, ` +
|
|
62
|
+
`or override createEmptyAggregate().`);
|
|
63
|
+
}
|
|
64
|
+
return new aggregateClass();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Deserialize a stored event back to an event instance.
|
|
68
|
+
* Uses the global `@DomainEvent` registry to find the event class.
|
|
69
|
+
* Can be overridden for custom deserialization logic.
|
|
70
|
+
*
|
|
71
|
+
* Returns `null` for event types not registered for this aggregate.
|
|
72
|
+
* This is expected — side-effect events (e.g. InventoryReservedEvent)
|
|
73
|
+
* may be stored under the same aggregate ID but are not part of
|
|
74
|
+
* the aggregate's state and should be skipped during hydration.
|
|
75
|
+
*
|
|
76
|
+
* @param eventType - The event class name
|
|
77
|
+
* @param payload - The serialized event data
|
|
78
|
+
* @returns The deserialized event, or null if the event type is not registered
|
|
79
|
+
*/
|
|
80
|
+
deserializeEvent(eventType, payload) {
|
|
81
|
+
const eventClasses = (0, domain_event_decorator_js_1.getEventClassesForAggregate)(this.aggregateType);
|
|
82
|
+
const EventClass = eventClasses.get(eventType);
|
|
83
|
+
if (!EventClass) {
|
|
84
|
+
this.logger.debug(`Skipping event type "${eventType}" — not registered for aggregate "${this.aggregateType}"`);
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
return Object.assign(Object.create(EventClass.prototype), payload);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Find an aggregate by its ID.
|
|
91
|
+
* Returns null if the aggregate doesn't exist.
|
|
92
|
+
*
|
|
93
|
+
* @param id - The aggregate ID
|
|
94
|
+
* @returns The hydrated aggregate or null
|
|
95
|
+
*/
|
|
96
|
+
async findById(id) {
|
|
97
|
+
const storedEvents = await this.eventStore.getEventsForAggregate(this.aggregateType, String(id));
|
|
98
|
+
if (storedEvents.length === 0) {
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
// Deserialize events, filtering out side-effect events not owned by this aggregate
|
|
102
|
+
const events = storedEvents
|
|
103
|
+
.map((stored) => this.deserializeEvent(stored.eventType, stored.payload))
|
|
104
|
+
.filter((event) => event !== null);
|
|
105
|
+
// Create aggregate and replay events
|
|
106
|
+
const aggregate = this.createEmptyAggregate();
|
|
107
|
+
aggregate.loadFromHistory(events);
|
|
108
|
+
return aggregate;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Get an aggregate by its ID.
|
|
112
|
+
* Throws an error if the aggregate doesn't exist.
|
|
113
|
+
*
|
|
114
|
+
* @param id - The aggregate ID
|
|
115
|
+
* @returns The hydrated aggregate
|
|
116
|
+
* @throws Error if aggregate not found
|
|
117
|
+
*/
|
|
118
|
+
async getById(id) {
|
|
119
|
+
const aggregate = await this.findById(id);
|
|
120
|
+
if (!aggregate) {
|
|
121
|
+
throw new Error(`${this.aggregateType} with id ${id} not found`);
|
|
122
|
+
}
|
|
123
|
+
return aggregate;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Save an aggregate by publishing its uncommitted events.
|
|
127
|
+
*
|
|
128
|
+
* Each event is published via the event bus, which:
|
|
129
|
+
* 1. Persists the event to the event store (system phase)
|
|
130
|
+
* 2. Dispatches to critical consumers (sequential, with compensation)
|
|
131
|
+
* 3. Dispatches to non-critical consumers (parallel, fire-and-forget)
|
|
132
|
+
*
|
|
133
|
+
* After all events are successfully published, they are marked as committed.
|
|
134
|
+
*
|
|
135
|
+
* @param aggregate - The aggregate to save
|
|
136
|
+
* @throws Error if any event fails to publish (compensation will run for critical consumers)
|
|
137
|
+
*/
|
|
138
|
+
async save(aggregate) {
|
|
139
|
+
const events = aggregate.getUncommittedEvents();
|
|
140
|
+
if (events.length === 0) {
|
|
141
|
+
return; // Nothing to save
|
|
142
|
+
}
|
|
143
|
+
// Publish each event through the event bus
|
|
144
|
+
// This triggers: persistence → critical consumers → non-critical consumers
|
|
145
|
+
for (const event of events) {
|
|
146
|
+
await this.eventBus.publish(event);
|
|
147
|
+
}
|
|
148
|
+
// Mark events as committed after successful publish
|
|
149
|
+
aggregate.markEventsAsCommitted();
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
exports.AggregateRepository = AggregateRepository;
|
|
153
|
+
__decorate([
|
|
154
|
+
(0, common_1.Inject)(index_js_1.EVENT_STORE_REPOSITORY),
|
|
155
|
+
__metadata("design:type", Object)
|
|
156
|
+
], AggregateRepository.prototype, "eventStore", void 0);
|
|
157
|
+
__decorate([
|
|
158
|
+
(0, common_1.Inject)(mediator_bus_js_1.MediatorBus),
|
|
159
|
+
__metadata("design:type", Object)
|
|
160
|
+
], AggregateRepository.prototype, "eventBus", void 0);
|
|
161
|
+
//# sourceMappingURL=aggregate-repository.base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate-repository.base.js","sourceRoot":"","sources":["../../../src/lib/aggregate/aggregate-repository.base.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { IEvent } from '../interfaces/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Base class for aggregate roots in event sourcing.
|
|
4
|
+
*
|
|
5
|
+
* Aggregates encapsulate domain logic and track uncommitted events.
|
|
6
|
+
* Events are applied to update state and tracked for later persistence.
|
|
7
|
+
*
|
|
8
|
+
* @template TId - The type of the aggregate's identifier
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* class OrderAggregate extends AggregateRoot<string> {
|
|
13
|
+
* private _id: string;
|
|
14
|
+
* private _status: 'draft' | 'placed' = 'draft';
|
|
15
|
+
*
|
|
16
|
+
* readonly aggregateType = 'Order';
|
|
17
|
+
* get id() { return this._id; }
|
|
18
|
+
*
|
|
19
|
+
* static create(orderId: string): OrderAggregate {
|
|
20
|
+
* const order = new OrderAggregate();
|
|
21
|
+
* order.apply(new OrderCreatedEvent(orderId));
|
|
22
|
+
* return order;
|
|
23
|
+
* }
|
|
24
|
+
*
|
|
25
|
+
* place(): void {
|
|
26
|
+
* if (this._status !== 'draft') throw new Error('Order already placed');
|
|
27
|
+
* this.apply(new OrderPlacedEvent(this._id));
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* // Event handlers
|
|
31
|
+
* applyOrderCreatedEvent(event: OrderCreatedEvent): void {
|
|
32
|
+
* this._id = event.orderId;
|
|
33
|
+
* }
|
|
34
|
+
*
|
|
35
|
+
* applyOrderPlacedEvent(event: OrderPlacedEvent): void {
|
|
36
|
+
* this._status = 'placed';
|
|
37
|
+
* }
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export declare abstract class AggregateRoot<TId = string> {
|
|
42
|
+
private readonly logger;
|
|
43
|
+
/**
|
|
44
|
+
* Events that have been applied but not yet persisted
|
|
45
|
+
*/
|
|
46
|
+
private _uncommittedEvents;
|
|
47
|
+
/**
|
|
48
|
+
* The current version (number of events applied from history)
|
|
49
|
+
*/
|
|
50
|
+
private _version;
|
|
51
|
+
/**
|
|
52
|
+
* The aggregate's unique identifier.
|
|
53
|
+
* Must be implemented by concrete classes.
|
|
54
|
+
*/
|
|
55
|
+
abstract readonly id: TId;
|
|
56
|
+
/**
|
|
57
|
+
* The aggregate type name (e.g., 'Order', 'User').
|
|
58
|
+
* Used for event store partitioning.
|
|
59
|
+
* Must be implemented by concrete classes.
|
|
60
|
+
*/
|
|
61
|
+
abstract readonly aggregateType: string;
|
|
62
|
+
/**
|
|
63
|
+
* Get the current version of the aggregate.
|
|
64
|
+
* This is the number of events that have been loaded from history.
|
|
65
|
+
*/
|
|
66
|
+
get version(): number;
|
|
67
|
+
/**
|
|
68
|
+
* Get all events that have been applied but not yet persisted.
|
|
69
|
+
* These should be published after saving the aggregate.
|
|
70
|
+
*/
|
|
71
|
+
getUncommittedEvents(): IEvent[];
|
|
72
|
+
/**
|
|
73
|
+
* Clear uncommitted events after they have been persisted.
|
|
74
|
+
* Call this after successfully publishing all events.
|
|
75
|
+
*/
|
|
76
|
+
markEventsAsCommitted(): void;
|
|
77
|
+
/**
|
|
78
|
+
* Rebuild the aggregate state from historical events.
|
|
79
|
+
* Used when loading an aggregate from the event store.
|
|
80
|
+
*
|
|
81
|
+
* @param events - The events to replay
|
|
82
|
+
*/
|
|
83
|
+
loadFromHistory(events: IEvent[]): void;
|
|
84
|
+
/**
|
|
85
|
+
* Apply a new event to the aggregate.
|
|
86
|
+
* Call this from command methods to record state changes.
|
|
87
|
+
*
|
|
88
|
+
* This method does two things:
|
|
89
|
+
* 1. Calls the matching handler method on your aggregate to update state.
|
|
90
|
+
* The handler is found by convention: `apply` + event class name.
|
|
91
|
+
* Example: `apply(new OrderPlacedEvent(...))` calls `this.applyOrderPlacedEvent(event)`.
|
|
92
|
+
* 2. Tracks the event as uncommitted so `AggregateRepository.save()` can publish it.
|
|
93
|
+
*
|
|
94
|
+
* @param event - The event to apply
|
|
95
|
+
*/
|
|
96
|
+
protected apply(event: IEvent): void;
|
|
97
|
+
/**
|
|
98
|
+
* Apply an event to update state and optionally track it.
|
|
99
|
+
*
|
|
100
|
+
* @param event - The event to apply
|
|
101
|
+
* @param isNew - Whether this is a new event (true) or from history (false)
|
|
102
|
+
*/
|
|
103
|
+
private applyEvent;
|
|
104
|
+
}
|
|
105
|
+
//# sourceMappingURL=aggregate-root.base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate-root.base.d.ts","sourceRoot":"","sources":["../../../src/lib/aggregate/aggregate-root.base.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAC;AAEhD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,8BAAsB,aAAa,CAAC,GAAG,GAAG,MAAM;IAC9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;IAE5D;;OAEG;IACH,OAAO,CAAC,kBAAkB,CAAgB;IAE1C;;OAEG;IACH,OAAO,CAAC,QAAQ,CAAa;IAE7B;;;OAGG;IACH,QAAQ,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC;IAE1B;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAExC;;;OAGG;IACH,IAAI,OAAO,IAAI,MAAM,CAEpB;IAED;;;OAGG;IACH,oBAAoB,IAAI,MAAM,EAAE;IAIhC;;;OAGG;IACH,qBAAqB,IAAI,IAAI;IAI7B;;;;;OAKG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI;IAOvC;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIpC;;;;;OAKG;IACH,OAAO,CAAC,UAAU;CAkBnB"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AggregateRoot = void 0;
|
|
4
|
+
const common_1 = require("@nestjs/common");
|
|
5
|
+
/**
|
|
6
|
+
* Base class for aggregate roots in event sourcing.
|
|
7
|
+
*
|
|
8
|
+
* Aggregates encapsulate domain logic and track uncommitted events.
|
|
9
|
+
* Events are applied to update state and tracked for later persistence.
|
|
10
|
+
*
|
|
11
|
+
* @template TId - The type of the aggregate's identifier
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* class OrderAggregate extends AggregateRoot<string> {
|
|
16
|
+
* private _id: string;
|
|
17
|
+
* private _status: 'draft' | 'placed' = 'draft';
|
|
18
|
+
*
|
|
19
|
+
* readonly aggregateType = 'Order';
|
|
20
|
+
* get id() { return this._id; }
|
|
21
|
+
*
|
|
22
|
+
* static create(orderId: string): OrderAggregate {
|
|
23
|
+
* const order = new OrderAggregate();
|
|
24
|
+
* order.apply(new OrderCreatedEvent(orderId));
|
|
25
|
+
* return order;
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* place(): void {
|
|
29
|
+
* if (this._status !== 'draft') throw new Error('Order already placed');
|
|
30
|
+
* this.apply(new OrderPlacedEvent(this._id));
|
|
31
|
+
* }
|
|
32
|
+
*
|
|
33
|
+
* // Event handlers
|
|
34
|
+
* applyOrderCreatedEvent(event: OrderCreatedEvent): void {
|
|
35
|
+
* this._id = event.orderId;
|
|
36
|
+
* }
|
|
37
|
+
*
|
|
38
|
+
* applyOrderPlacedEvent(event: OrderPlacedEvent): void {
|
|
39
|
+
* this._status = 'placed';
|
|
40
|
+
* }
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
class AggregateRoot {
|
|
45
|
+
constructor() {
|
|
46
|
+
this.logger = new common_1.Logger(this.constructor.name);
|
|
47
|
+
/**
|
|
48
|
+
* Events that have been applied but not yet persisted
|
|
49
|
+
*/
|
|
50
|
+
this._uncommittedEvents = [];
|
|
51
|
+
/**
|
|
52
|
+
* The current version (number of events applied from history)
|
|
53
|
+
*/
|
|
54
|
+
this._version = 0;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Get the current version of the aggregate.
|
|
58
|
+
* This is the number of events that have been loaded from history.
|
|
59
|
+
*/
|
|
60
|
+
get version() {
|
|
61
|
+
return this._version;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Get all events that have been applied but not yet persisted.
|
|
65
|
+
* These should be published after saving the aggregate.
|
|
66
|
+
*/
|
|
67
|
+
getUncommittedEvents() {
|
|
68
|
+
return [...this._uncommittedEvents];
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Clear uncommitted events after they have been persisted.
|
|
72
|
+
* Call this after successfully publishing all events.
|
|
73
|
+
*/
|
|
74
|
+
markEventsAsCommitted() {
|
|
75
|
+
this._uncommittedEvents = [];
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Rebuild the aggregate state from historical events.
|
|
79
|
+
* Used when loading an aggregate from the event store.
|
|
80
|
+
*
|
|
81
|
+
* @param events - The events to replay
|
|
82
|
+
*/
|
|
83
|
+
loadFromHistory(events) {
|
|
84
|
+
for (const event of events) {
|
|
85
|
+
this.applyEvent(event, false);
|
|
86
|
+
this._version++;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Apply a new event to the aggregate.
|
|
91
|
+
* Call this from command methods to record state changes.
|
|
92
|
+
*
|
|
93
|
+
* This method does two things:
|
|
94
|
+
* 1. Calls the matching handler method on your aggregate to update state.
|
|
95
|
+
* The handler is found by convention: `apply` + event class name.
|
|
96
|
+
* Example: `apply(new OrderPlacedEvent(...))` calls `this.applyOrderPlacedEvent(event)`.
|
|
97
|
+
* 2. Tracks the event as uncommitted so `AggregateRepository.save()` can publish it.
|
|
98
|
+
*
|
|
99
|
+
* @param event - The event to apply
|
|
100
|
+
*/
|
|
101
|
+
apply(event) {
|
|
102
|
+
this.applyEvent(event, true);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Apply an event to update state and optionally track it.
|
|
106
|
+
*
|
|
107
|
+
* @param event - The event to apply
|
|
108
|
+
* @param isNew - Whether this is a new event (true) or from history (false)
|
|
109
|
+
*/
|
|
110
|
+
applyEvent(event, isNew) {
|
|
111
|
+
// Build the handler method name: apply{EventClassName}
|
|
112
|
+
const handlerName = `apply${event.constructor.name}`;
|
|
113
|
+
const handler = this[handlerName];
|
|
114
|
+
if (typeof handler === 'function') {
|
|
115
|
+
handler.call(this, event);
|
|
116
|
+
}
|
|
117
|
+
else if (isNew) {
|
|
118
|
+
this.logger.warn(`${this.constructor.name} is missing "${handlerName}(event: ${event.constructor.name}): void" to apply state changes`);
|
|
119
|
+
}
|
|
120
|
+
if (isNew) {
|
|
121
|
+
this._uncommittedEvents.push(event);
|
|
122
|
+
this._version++;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
exports.AggregateRoot = AggregateRoot;
|
|
127
|
+
//# sourceMappingURL=aggregate-root.base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"aggregate-root.base.js","sourceRoot":"","sources":["../../../src/lib/aggregate/aggregate-root.base.ts"],"names":[],"mappings":";;;AAAA,2CAAwC;AAGxC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,MAAsB,aAAa;IAAnC;QACmB,WAAM,GAAG,IAAI,eAAM,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAE5D;;WAEG;QACK,uBAAkB,GAAa,EAAE,CAAC;QAE1C;;WAEG;QACK,aAAQ,GAAW,CAAC,CAAC;IA4F/B,CAAC;IA7EC;;;OAGG;IACH,IAAI,OAAO;QACT,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED;;;OAGG;IACH,oBAAoB;QAClB,OAAO,CAAC,GAAG,IAAI,CAAC,kBAAkB,CAAC,CAAC;IACtC,CAAC;IAED;;;OAGG;IACH,qBAAqB;QACnB,IAAI,CAAC,kBAAkB,GAAG,EAAE,CAAC;IAC/B,CAAC;IAED;;;;;OAKG;IACH,eAAe,CAAC,MAAgB;QAC9B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;YAC9B,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;IAED;;;;;;;;;;;OAWG;IACO,KAAK,CAAC,KAAa;QAC3B,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED;;;;;OAKG;IACK,UAAU,CAAC,KAAa,EAAE,KAAc;QAC9C,uDAAuD;QACvD,MAAM,WAAW,GAAG,QAAQ,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QACrD,MAAM,OAAO,GAAI,IAAgC,CAAC,WAAW,CAAC,CAAC;QAE/D,IAAI,OAAO,OAAO,KAAK,UAAU,EAAE,CAAC;YAClC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC5B,CAAC;aAAM,IAAI,KAAK,EAAE,CAAC;YACjB,IAAI,CAAC,MAAM,CAAC,IAAI,CACd,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,gBAAgB,WAAW,WAAW,KAAK,CAAC,WAAW,CAAC,IAAI,iCAAiC,CACtH,CAAC;QACJ,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACpC,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,CAAC;IACH,CAAC;CACF;AAvGD,sCAuGC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/aggregate/index.ts"],"names":[],"mappings":"AAAA,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./aggregate-root.base.js"), exports);
|
|
18
|
+
__exportStar(require("./aggregate-repository.base.js"), exports);
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/aggregate/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,2DAAyC;AACzC,iEAA+C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/context/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./mediator-context.js"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/context/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,wDAAsC"}
|