@event-nest/core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/README.md +11 -0
  2. package/package.json +25 -0
  3. package/src/index.d.ts +12 -0
  4. package/src/index.js +16 -0
  5. package/src/index.js.map +1 -0
  6. package/src/lib/decorators/event-name-conflict-exception.d.ts +3 -0
  7. package/src/lib/decorators/event-name-conflict-exception.js +10 -0
  8. package/src/lib/decorators/event-name-conflict-exception.js.map +1 -0
  9. package/src/lib/decorators/event-processor.d.ts +5 -0
  10. package/src/lib/decorators/event-processor.js +27 -0
  11. package/src/lib/decorators/event-processor.js.map +1 -0
  12. package/src/lib/decorators/registered-event.d.ts +13 -0
  13. package/src/lib/decorators/registered-event.js +37 -0
  14. package/src/lib/decorators/registered-event.js.map +1 -0
  15. package/src/lib/domain/aggregate-root.d.ts +48 -0
  16. package/src/lib/domain/aggregate-root.js +109 -0
  17. package/src/lib/domain/aggregate-root.js.map +1 -0
  18. package/src/lib/domain/missing-event-processor-exception.d.ts +3 -0
  19. package/src/lib/domain/missing-event-processor-exception.js +10 -0
  20. package/src/lib/domain/missing-event-processor-exception.js.map +1 -0
  21. package/src/lib/storage/abstract-event-store.d.ts +11 -0
  22. package/src/lib/storage/abstract-event-store.js +33 -0
  23. package/src/lib/storage/abstract-event-store.js.map +1 -0
  24. package/src/lib/storage/event-payload.d.ts +3 -0
  25. package/src/lib/storage/event-payload.js +3 -0
  26. package/src/lib/storage/event-payload.js.map +1 -0
  27. package/src/lib/storage/event-store.d.ts +10 -0
  28. package/src/lib/storage/event-store.js +5 -0
  29. package/src/lib/storage/event-store.js.map +1 -0
  30. package/src/lib/storage/id-generation-exception.d.ts +3 -0
  31. package/src/lib/storage/id-generation-exception.js +10 -0
  32. package/src/lib/storage/id-generation-exception.js.map +1 -0
  33. package/src/lib/storage/stored-aggregate-root.d.ts +5 -0
  34. package/src/lib/storage/stored-aggregate-root.js +11 -0
  35. package/src/lib/storage/stored-aggregate-root.js.map +1 -0
  36. package/src/lib/storage/stored-event.d.ts +19 -0
  37. package/src/lib/storage/stored-event.js +50 -0
  38. package/src/lib/storage/stored-event.js.map +1 -0
  39. package/src/lib/utils/type-utils.d.ts +2 -0
  40. package/src/lib/utils/type-utils.js +12 -0
  41. package/src/lib/utils/type-utils.js.map +1 -0
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # core
2
+
3
+ This library was generated with [Nx](https://nx.dev).
4
+
5
+ ## Building
6
+
7
+ Run `nx build core` to build the library.
8
+
9
+ ## Running unit tests
10
+
11
+ Run `nx test core` to execute the unit tests via [Jest](https://jestjs.io).
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@event-nest/core",
3
+ "version": "0.0.1",
4
+ "license": "MIT",
5
+ "author": "Nick Tsitlakidis",
6
+ "description": "Event sourcing module for NestJS. It provides a set of decorators and interfaces to help you build your event sourcing application.",
7
+ "keywords": [
8
+ "nestjs",
9
+ "event sourcing",
10
+ "cqrs",
11
+ "ddd"
12
+ ],
13
+ "type": "commonjs",
14
+ "peerDependencies": {
15
+ "@nestjs/common": "^10.0.2",
16
+ "@nestjs/core": "^10.0.2",
17
+ "tslib": "2.5.3"
18
+ },
19
+ "dependencies": {
20
+ "class-transformer": "^0.5.1",
21
+ "reflect-metadata": "^0.1.13"
22
+ },
23
+ "main": "./src/index.js",
24
+ "types": "./src/index.d.ts"
25
+ }
package/src/index.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ export * from "./lib/decorators/event-name-conflict-exception";
2
+ export * from "./lib/decorators/event-processor";
3
+ export * from "./lib/decorators/registered-event";
4
+ export * from "./lib/domain/aggregate-root";
5
+ export * from "./lib/domain/missing-event-processor-exception";
6
+ export * from "./lib/storage/abstract-event-store";
7
+ export * from "./lib/storage/event-store";
8
+ export * from "./lib/storage/event-payload";
9
+ export * from "./lib/storage/id-generation-exception";
10
+ export * from "./lib/storage/stored-event";
11
+ export * from "./lib/storage/stored-aggregate-root";
12
+ export * from "./lib/utils/type-utils";
package/src/index.js ADDED
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ tslib_1.__exportStar(require("./lib/decorators/event-name-conflict-exception"), exports);
5
+ tslib_1.__exportStar(require("./lib/decorators/event-processor"), exports);
6
+ tslib_1.__exportStar(require("./lib/decorators/registered-event"), exports);
7
+ tslib_1.__exportStar(require("./lib/domain/aggregate-root"), exports);
8
+ tslib_1.__exportStar(require("./lib/domain/missing-event-processor-exception"), exports);
9
+ tslib_1.__exportStar(require("./lib/storage/abstract-event-store"), exports);
10
+ tslib_1.__exportStar(require("./lib/storage/event-store"), exports);
11
+ tslib_1.__exportStar(require("./lib/storage/event-payload"), exports);
12
+ tslib_1.__exportStar(require("./lib/storage/id-generation-exception"), exports);
13
+ tslib_1.__exportStar(require("./lib/storage/stored-event"), exports);
14
+ tslib_1.__exportStar(require("./lib/storage/stored-aggregate-root"), exports);
15
+ tslib_1.__exportStar(require("./lib/utils/type-utils"), exports);
16
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../libs/core/src/index.ts"],"names":[],"mappings":";;;AAAA,yFAA+D;AAC/D,2EAAiD;AACjD,4EAAkD;AAElD,sEAA4C;AAC5C,yFAA+D;AAE/D,6EAAmD;AACnD,oEAA0C;AAC1C,sEAA4C;AAC5C,gFAAsD;AACtD,qEAA2C;AAC3C,8EAAoD;AAEpD,iEAAuC"}
@@ -0,0 +1,3 @@
1
+ export declare class EventNameConflictException extends Error {
2
+ constructor(name: string);
3
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventNameConflictException = void 0;
4
+ class EventNameConflictException extends Error {
5
+ constructor(name) {
6
+ super(`${name} is already registered as RegisteredEvent. Use another name`);
7
+ }
8
+ }
9
+ exports.EventNameConflictException = EventNameConflictException;
10
+ //# sourceMappingURL=event-name-conflict-exception.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-name-conflict-exception.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/decorators/event-name-conflict-exception.ts"],"names":[],"mappings":";;;AAAA,MAAa,0BAA2B,SAAQ,KAAK;IACjD,YAAY,IAAY;QACpB,KAAK,CAAC,GAAG,IAAI,6DAA6D,CAAC,CAAC;IAChF,CAAC;CACJ;AAJD,gEAIC"}
@@ -0,0 +1,5 @@
1
+ import "reflect-metadata";
2
+ import { AggregateRoot } from "../domain/aggregate-root";
3
+ import { ClassConstructor } from "class-transformer";
4
+ export declare function getProcessFunctionKey(entity: AggregateRoot, eventClass: ClassConstructor<unknown>): string | undefined;
5
+ export declare function EventProcessor(eventClass: ClassConstructor<unknown>): PropertyDecorator;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EventProcessor = exports.getProcessFunctionKey = void 0;
4
+ require("reflect-metadata");
5
+ const METADATA_KEY = "process-event-meta";
6
+ function getProcessFunctionKey(entity, eventClass) {
7
+ const metadataKeys = Reflect.getMetadataKeys(entity);
8
+ if (!metadataKeys || metadataKeys.length == 0) {
9
+ return undefined;
10
+ }
11
+ const matchingKey = metadataKeys.find((metadataKey) => {
12
+ const metadata = Reflect.getMetadata(metadataKey, entity);
13
+ return metadata.eventClass === eventClass;
14
+ });
15
+ if (!matchingKey) {
16
+ return undefined;
17
+ }
18
+ return Reflect.getMetadata(matchingKey, entity).key;
19
+ }
20
+ exports.getProcessFunctionKey = getProcessFunctionKey;
21
+ function EventProcessor(eventClass) {
22
+ return (propertyParent, propertyKey) => {
23
+ Reflect.defineMetadata(METADATA_KEY + "-" + propertyKey.toString(), { eventClass: eventClass, key: propertyKey }, propertyParent);
24
+ };
25
+ }
26
+ exports.EventProcessor = EventProcessor;
27
+ //# sourceMappingURL=event-processor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-processor.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/decorators/event-processor.ts"],"names":[],"mappings":";;;AAAA,4BAA0B;AAI1B,MAAM,YAAY,GAAG,oBAAoB,CAAC;AAE1C,SAAgB,qBAAqB,CACjC,MAAqB,EACrB,UAAqC;IAErC,MAAM,YAAY,GAAG,OAAO,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC;IACrD,IAAI,CAAC,YAAY,IAAI,YAAY,CAAC,MAAM,IAAI,CAAC,EAAE;QAC3C,OAAO,SAAS,CAAC;KACpB;IAED,MAAM,WAAW,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE;QAClD,MAAM,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QAC1D,OAAO,QAAQ,CAAC,UAAU,KAAK,UAAU,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,WAAW,EAAE;QACd,OAAO,SAAS,CAAC;KACpB;IAED,OAAO,OAAO,CAAC,WAAW,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC;AACxD,CAAC;AAnBD,sDAmBC;AAED,SAAgB,cAAc,CAAC,UAAqC;IAChE,OAAO,CAAC,cAAc,EAAE,WAAW,EAAE,EAAE;QACnC,OAAO,CAAC,cAAc,CAClB,YAAY,GAAG,GAAG,GAAG,WAAW,CAAC,QAAQ,EAAE,EAC3C,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,EAAE,WAAW,EAAE,EAC5C,cAAc,CACjB,CAAC;IACN,CAAC,CAAC;AACN,CAAC;AARD,wCAQC"}
@@ -0,0 +1,13 @@
1
+ import { ClassConstructor } from "class-transformer";
2
+ import { EventPayload } from "../storage/event-payload";
3
+ export declare function RegisteredEvent(eventName: string): ClassDecorator;
4
+ /**
5
+ * Returns the event name that matches the class of the provided object.
6
+ * @param target
7
+ */
8
+ export declare function getEventName(target: EventPayload): string | undefined;
9
+ /**
10
+ * Returns the class that matches the provided name. Or undefined.
11
+ * @param name The event name to be checked.
12
+ */
13
+ export declare function getEventClass<T>(name: string): ClassConstructor<T> | undefined;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getEventClass = exports.getEventName = exports.RegisteredEvent = void 0;
4
+ const event_name_conflict_exception_1 = require("./event-name-conflict-exception");
5
+ const type_utils_1 = require("../utils/type-utils");
6
+ const REGISTRATIONS = [];
7
+ function RegisteredEvent(eventName) {
8
+ return (target) => {
9
+ if (REGISTRATIONS.some((registration) => registration.eventName === eventName)) {
10
+ throw new event_name_conflict_exception_1.EventNameConflictException(eventName);
11
+ }
12
+ REGISTRATIONS.push({
13
+ eventName: eventName,
14
+ eventClass: target
15
+ });
16
+ };
17
+ }
18
+ exports.RegisteredEvent = RegisteredEvent;
19
+ /**
20
+ * Returns the event name that matches the class of the provided object.
21
+ * @param target
22
+ */
23
+ function getEventName(target) {
24
+ const found = REGISTRATIONS.find((registration) => registration.eventClass === target.constructor);
25
+ return found ? found.eventName : undefined;
26
+ }
27
+ exports.getEventName = getEventName;
28
+ /**
29
+ * Returns the class that matches the provided name. Or undefined.
30
+ * @param name The event name to be checked.
31
+ */
32
+ function getEventClass(name) {
33
+ const found = REGISTRATIONS.find((registration) => registration.eventName === name);
34
+ return (0, type_utils_1.isNil)(found) ? undefined : found.eventClass;
35
+ }
36
+ exports.getEventClass = getEventClass;
37
+ //# sourceMappingURL=registered-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registered-event.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/decorators/registered-event.ts"],"names":[],"mappings":";;;AACA,mFAA6E;AAE7E,oDAA4C;AAO5C,MAAM,aAAa,GAA6B,EAAE,CAAC;AAEnD,SAAgB,eAAe,CAAC,SAAiB;IAC7C,OAAO,CAAC,MAAM,EAAE,EAAE;QACd,IAAI,aAAa,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC,SAAS,KAAK,SAAS,CAAC,EAAE;YAC5E,MAAM,IAAI,0DAA0B,CAAC,SAAS,CAAC,CAAC;SACnD;QACD,aAAa,CAAC,IAAI,CAAC;YACf,SAAS,EAAE,SAAS;YACpB,UAAU,EAAE,MAAM;SACrB,CAAC,CAAC;IACP,CAAC,CAAC;AACN,CAAC;AAVD,0CAUC;AAED;;;GAGG;AACH,SAAgB,YAAY,CAAC,MAAoB;IAC7C,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC,UAAU,KAAK,MAAM,CAAC,WAAW,CAAC,CAAC;IACnG,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;AAC/C,CAAC;AAHD,oCAGC;AAED;;;GAGG;AACH,SAAgB,aAAa,CAAI,IAAY;IACzC,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC,SAAS,KAAK,IAAI,CAAC,CAAC;IACpF,OAAO,IAAA,kBAAK,EAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAE,KAAK,CAAC,UAAkC,CAAC;AAChF,CAAC;AAHD,sCAGC"}
@@ -0,0 +1,48 @@
1
+ import { EventPayload } from "../storage/event-payload";
2
+ import { Logger } from "@nestjs/common";
3
+ import { StoredEvent } from "../storage/stored-event";
4
+ export declare abstract class AggregateRoot {
5
+ private readonly _id;
6
+ private _appliedEvents;
7
+ private _version;
8
+ private readonly _logger;
9
+ protected constructor(_id: string, events?: Array<StoredEvent>, logger?: Logger);
10
+ get id(): string;
11
+ get version(): number;
12
+ get logger(): Logger;
13
+ /**
14
+ * Publishes all the provided events using a connected event publisher. To connect a publisher, use the
15
+ * EventStoreConnector. Normally this should never be called by application logic once the connector is used.
16
+ * If a publisher is not connected, the method will return a rejected promise.
17
+ * @param events The events to be published
18
+ */
19
+ publish(events: Array<EventPayload>): Promise<Array<StoredEvent>>;
20
+ /**
21
+ * All the events that have been previously applied will be committed once this method runs. The commit phase has the
22
+ * effect of publishing all the events. After publishing, the applied events will be deleted so that the next commit
23
+ * publishes newer events.
24
+ * During publishing, the events will be saved to Mongo and after the successful save, all the application event
25
+ * handlers will be called to take care of async updates.
26
+ * Call this once all the events you want, have been applied.
27
+ */
28
+ commit(): Promise<AggregateRoot>;
29
+ /**
30
+ * Adds an event to the currently applied events of the entity. This will not publish the event. Use the commit
31
+ * method once all the events you want are appliec.
32
+ * @param event The event to be applied
33
+ */
34
+ apply(event: EventPayload): void;
35
+ /**
36
+ * Returns a clone array of all the currently applied events of the entity.
37
+ */
38
+ get appliedEvents(): Array<EventPayload>;
39
+ /**
40
+ * Used when a set of events have been retrieved from the database. These events can be passed to the method and the
41
+ * method will trigger all the matching EventProcessor functions of the entity to populate the object based on
42
+ * application logic.
43
+ * @param events The events that will be sent to EventProcessors
44
+ */
45
+ processEvents(events: Array<StoredEvent>): void;
46
+ protected resolveVersion(events: Array<StoredEvent>): void;
47
+ protected sortEvents(events: Array<StoredEvent>): Array<StoredEvent>;
48
+ }
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AggregateRoot = void 0;
4
+ const common_1 = require("@nestjs/common");
5
+ const registered_event_1 = require("../decorators/registered-event");
6
+ const event_processor_1 = require("../decorators/event-processor");
7
+ const missing_event_processor_exception_1 = require("./missing-event-processor-exception");
8
+ const type_utils_1 = require("../utils/type-utils");
9
+ class AggregateRoot {
10
+ constructor(_id, events = [], logger) {
11
+ this._id = _id;
12
+ this._appliedEvents = [];
13
+ this._version = 0;
14
+ if (events && events.length > 0) {
15
+ this.processEvents(events);
16
+ }
17
+ this._logger = (0, type_utils_1.isNil)(logger) ? new common_1.Logger(AggregateRoot.name) : logger;
18
+ }
19
+ get id() {
20
+ return this._id;
21
+ }
22
+ get version() {
23
+ return this._version;
24
+ }
25
+ get logger() {
26
+ return this._logger;
27
+ }
28
+ /**
29
+ * Publishes all the provided events using a connected event publisher. To connect a publisher, use the
30
+ * EventStoreConnector. Normally this should never be called by application logic once the connector is used.
31
+ * If a publisher is not connected, the method will return a rejected promise.
32
+ * @param events The events to be published
33
+ */
34
+ publish(events) {
35
+ this.logger.error("There is no event publisher assigned");
36
+ return Promise.reject("There is no event publisher assigned");
37
+ }
38
+ /**
39
+ * All the events that have been previously applied will be committed once this method runs. The commit phase has the
40
+ * effect of publishing all the events. After publishing, the applied events will be deleted so that the next commit
41
+ * publishes newer events.
42
+ * During publishing, the events will be saved to Mongo and after the successful save, all the application event
43
+ * handlers will be called to take care of async updates.
44
+ * Call this once all the events you want, have been applied.
45
+ */
46
+ commit() {
47
+ const toPublish = this._appliedEvents.slice(0);
48
+ this._appliedEvents = [];
49
+ if (toPublish.length > 0) {
50
+ return this.publish(toPublish).then(() => Promise.resolve(this));
51
+ }
52
+ return Promise.resolve(this);
53
+ }
54
+ /**
55
+ * Adds an event to the currently applied events of the entity. This will not publish the event. Use the commit
56
+ * method once all the events you want are appliec.
57
+ * @param event The event to be applied
58
+ */
59
+ apply(event) {
60
+ event.aggregateRootId = this.id;
61
+ this._appliedEvents.push(event);
62
+ }
63
+ /**
64
+ * Returns a clone array of all the currently applied events of the entity.
65
+ */
66
+ get appliedEvents() {
67
+ return this._appliedEvents.slice(0);
68
+ }
69
+ /**
70
+ * Used when a set of events have been retrieved from the database. These events can be passed to the method and the
71
+ * method will trigger all the matching EventProcessor functions of the entity to populate the object based on
72
+ * application logic.
73
+ * @param events The events that will be sent to EventProcessors
74
+ */
75
+ processEvents(events) {
76
+ if (events.length > 0) {
77
+ this.sortEvents(events).forEach((ev) => {
78
+ try {
79
+ const eventClass = (0, registered_event_1.getEventClass)(ev.eventName);
80
+ if (!eventClass) {
81
+ this.logger.error(`Found event name with no handler : ${ev.eventName}.`);
82
+ throw new missing_event_processor_exception_1.MissingEventProcessor(ev.eventName, this._id);
83
+ }
84
+ const processorKey = (0, event_processor_1.getProcessFunctionKey)(this, eventClass);
85
+ if (!processorKey) {
86
+ this.logger.error(`Found event name with no handler : ${ev.eventName}.`);
87
+ throw new missing_event_processor_exception_1.MissingEventProcessor(ev.eventName, this._id);
88
+ }
89
+ const mappedEvent = ev.getPayloadAs(eventClass);
90
+ this[processorKey](mappedEvent);
91
+ }
92
+ catch (error) {
93
+ this.logger.error(`Unable to process domain event : ${ev.eventName}.`);
94
+ throw error;
95
+ }
96
+ });
97
+ this.resolveVersion(events);
98
+ }
99
+ }
100
+ resolveVersion(events) {
101
+ const sorted = events.sort((e1, e2) => e1.aggregateRootVersion - e2.aggregateRootVersion);
102
+ this._version = sorted.slice(-1)[0].aggregateRootVersion;
103
+ }
104
+ sortEvents(events) {
105
+ return events.sort((e1, e2) => e1.aggregateRootVersion - e2.aggregateRootVersion);
106
+ }
107
+ }
108
+ exports.AggregateRoot = AggregateRoot;
109
+ //# sourceMappingURL=aggregate-root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"aggregate-root.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/domain/aggregate-root.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare class MissingEventProcessor extends Error {
2
+ constructor(eventName: string, aggregateRootId: string);
3
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MissingEventProcessor = void 0;
4
+ class MissingEventProcessor extends Error {
5
+ constructor(eventName, aggregateRootId) {
6
+ super(`Missing event processor for event : ${eventName} of aggregate root : ${aggregateRootId}`);
7
+ }
8
+ }
9
+ exports.MissingEventProcessor = MissingEventProcessor;
10
+ //# sourceMappingURL=missing-event-processor-exception.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"missing-event-processor-exception.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/domain/missing-event-processor-exception.ts"],"names":[],"mappings":";;;AAAA,MAAa,qBAAsB,SAAQ,KAAK;IAC5C,YAAY,SAAiB,EAAE,eAAuB;QAClD,KAAK,CAAC,uCAAuC,SAAS,wBAAwB,eAAe,EAAE,CAAC,CAAC;IACrG,CAAC;CACJ;AAJD,sDAIC"}
@@ -0,0 +1,11 @@
1
+ import { EventStore } from "./event-store";
2
+ import { StoredEvent } from "./stored-event";
3
+ import { AggregateRoot } from "../domain/aggregate-root";
4
+ import { StoredAggregateRoot } from "./stored-aggregate-root";
5
+ export declare abstract class AbstractEventStore implements EventStore {
6
+ protected constructor();
7
+ abstract findByAggregateRootId(id: string): Promise<Array<StoredEvent>>;
8
+ abstract save(events: Array<StoredEvent>, aggregate: StoredAggregateRoot): Promise<Array<StoredEvent>>;
9
+ abstract generateEntityId(): Promise<string>;
10
+ addPublisher<T extends AggregateRoot>(aggregateRoot: T): T;
11
+ }
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AbstractEventStore = void 0;
4
+ const stored_event_1 = require("./stored-event");
5
+ const stored_aggregate_root_1 = require("./stored-aggregate-root");
6
+ const id_generation_exception_1 = require("./id-generation-exception");
7
+ class AbstractEventStore {
8
+ // eslint-disable-next-line @typescript-eslint/no-empty-function
9
+ constructor() { }
10
+ addPublisher(aggregateRoot) {
11
+ aggregateRoot.publish = async (events) => {
12
+ if (events.length == 0) {
13
+ return Promise.resolve([]);
14
+ }
15
+ const ids = await Promise.all(events.map(() => this.generateEntityId()));
16
+ if (ids.length !== events.length) {
17
+ throw new id_generation_exception_1.IdGenerationException(ids.length, events.length);
18
+ }
19
+ const storedEvents = events.map((serializable) => {
20
+ const id = ids.pop();
21
+ return stored_event_1.StoredEvent.fromPublishedEvent(id, aggregateRoot.id, serializable);
22
+ });
23
+ const toStore = new stored_aggregate_root_1.StoredAggregateRoot(aggregateRoot.id, aggregateRoot.version);
24
+ return this.save(storedEvents, toStore).then((savedEvents) => {
25
+ //this._eventBus.publishAll(events);
26
+ return Promise.resolve(savedEvents);
27
+ });
28
+ };
29
+ return aggregateRoot;
30
+ }
31
+ }
32
+ exports.AbstractEventStore = AbstractEventStore;
33
+ //# sourceMappingURL=abstract-event-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abstract-event-store.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/storage/abstract-event-store.ts"],"names":[],"mappings":";;;AACA,iDAA6C;AAG7C,mEAA8D;AAC9D,uEAAkE;AAElE,MAAsB,kBAAkB;IACpC,gEAAgE;IAChE,gBAAyB,CAAC;IAQ1B,YAAY,CAA0B,aAAgB;QAClD,aAAa,CAAC,OAAO,GAAG,KAAK,EAAE,MAA2B,EAAE,EAAE;YAC1D,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE;gBACpB,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;aAC9B;YAED,MAAM,GAAG,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC;YACzE,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,EAAE;gBAC9B,MAAM,IAAI,+CAAqB,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;aAC9D;YACD,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,YAAY,EAAE,EAAE;gBAC7C,MAAM,EAAE,GAAG,GAAG,CAAC,GAAG,EAAG,CAAC;gBACtB,OAAO,0BAAW,CAAC,kBAAkB,CAAC,EAAE,EAAE,aAAa,CAAC,EAAE,EAAE,YAAY,CAAC,CAAC;YAC9E,CAAC,CAAC,CAAC;YAEH,MAAM,OAAO,GAAG,IAAI,2CAAmB,CAAC,aAAa,CAAC,EAAE,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC;YACjF,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,EAAE;gBACzD,oCAAoC;gBACpC,OAAO,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;YACxC,CAAC,CAAC,CAAC;QACP,CAAC,CAAC;QACF,OAAO,aAAa,CAAC;IACzB,CAAC;CACJ;AAjCD,gDAiCC"}
@@ -0,0 +1,3 @@
1
+ export interface EventPayload {
2
+ aggregateRootId: string;
3
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=event-payload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-payload.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/storage/event-payload.ts"],"names":[],"mappings":""}
@@ -0,0 +1,10 @@
1
+ import { StoredEvent } from "./stored-event";
2
+ import { StoredAggregateRoot } from "./stored-aggregate-root";
3
+ import { AggregateRoot } from "../domain/aggregate-root";
4
+ export declare const EVENT_STORE: unique symbol;
5
+ export interface EventStore {
6
+ addPublisher<T extends AggregateRoot>(aggregateRoot: T): T;
7
+ findByAggregateRootId(id: string): Promise<Array<StoredEvent>>;
8
+ save(events: Array<StoredEvent>, aggregate: StoredAggregateRoot): Promise<Array<StoredEvent>>;
9
+ generateEntityId(): Promise<string>;
10
+ }
@@ -0,0 +1,5 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EVENT_STORE = void 0;
4
+ exports.EVENT_STORE = Symbol("EVENT_NEST_EVENT_STORE");
5
+ //# sourceMappingURL=event-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-store.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/storage/event-store.ts"],"names":[],"mappings":";;;AAIa,QAAA,WAAW,GAAG,MAAM,CAAC,wBAAwB,CAAC,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare class IdGenerationException extends Error {
2
+ constructor(idsLength: number, expectedLength: number);
3
+ }
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.IdGenerationException = void 0;
4
+ class IdGenerationException extends Error {
5
+ constructor(idsLength, expectedLength) {
6
+ super(`Unexpected mismatch of required ids. Generated: ${idsLength}, expected: ${expectedLength}`);
7
+ }
8
+ }
9
+ exports.IdGenerationException = IdGenerationException;
10
+ //# sourceMappingURL=id-generation-exception.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"id-generation-exception.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/storage/id-generation-exception.ts"],"names":[],"mappings":";;;AAAA,MAAa,qBAAsB,SAAQ,KAAK;IAC5C,YAAY,SAAiB,EAAE,cAAsB;QACjD,KAAK,CAAC,mDAAmD,SAAS,eAAe,cAAc,EAAE,CAAC,CAAC;IACvG,CAAC;CACJ;AAJD,sDAIC"}
@@ -0,0 +1,5 @@
1
+ export declare class StoredAggregateRoot {
2
+ id: string;
3
+ version: number;
4
+ constructor(id: string, version: number);
5
+ }
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StoredAggregateRoot = void 0;
4
+ class StoredAggregateRoot {
5
+ constructor(id, version) {
6
+ this.id = id;
7
+ this.version = version;
8
+ }
9
+ }
10
+ exports.StoredAggregateRoot = StoredAggregateRoot;
11
+ //# sourceMappingURL=stored-aggregate-root.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stored-aggregate-root.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/storage/stored-aggregate-root.ts"],"names":[],"mappings":";;;AAAA,MAAa,mBAAmB;IAC5B,YAAmB,EAAU,EAAS,OAAe;QAAlC,OAAE,GAAF,EAAE,CAAQ;QAAS,YAAO,GAAP,OAAO,CAAQ;IAAG,CAAC;CAC5D;AAFD,kDAEC"}
@@ -0,0 +1,19 @@
1
+ import { ClassConstructor } from "class-transformer";
2
+ import { EventPayload } from "./event-payload";
3
+ export declare class StoredEvent {
4
+ aggregateRootVersion: number;
5
+ private readonly _id;
6
+ private readonly _aggregateRootId;
7
+ private _createdAt;
8
+ private _payload;
9
+ private _eventName;
10
+ private constructor();
11
+ static fromPublishedEvent(id: string, aggregateRootId: string, publishedEvent: EventPayload): StoredEvent;
12
+ static fromStorage(id: string, aggregateRootId: string, eventName: string, createdAt: Date, aggregateRootVersion: number, payload: unknown): StoredEvent;
13
+ getPayloadAs<T>(payloadClass: ClassConstructor<T>): T;
14
+ get payload(): unknown;
15
+ get id(): string;
16
+ get aggregateRootId(): string;
17
+ get createdAt(): Date;
18
+ get eventName(): string;
19
+ }
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StoredEvent = void 0;
4
+ const class_transformer_1 = require("class-transformer");
5
+ const registered_event_1 = require("../decorators/registered-event");
6
+ const type_utils_1 = require("../utils/type-utils");
7
+ class StoredEvent {
8
+ constructor(id, aggregateRootId) {
9
+ this._aggregateRootId = aggregateRootId;
10
+ this._id = id;
11
+ }
12
+ static fromPublishedEvent(id, aggregateRootId, publishedEvent) {
13
+ const newEvent = new StoredEvent(id, aggregateRootId);
14
+ newEvent._createdAt = new Date(new Date().toUTCString());
15
+ const eventName = (0, registered_event_1.getEventName)(publishedEvent);
16
+ if (!(0, type_utils_1.isNil)(eventName)) {
17
+ newEvent._payload = (0, class_transformer_1.instanceToPlain)(publishedEvent);
18
+ newEvent._eventName = eventName;
19
+ }
20
+ return newEvent;
21
+ }
22
+ static fromStorage(id, aggregateRootId, eventName, createdAt, aggregateRootVersion, payload) {
23
+ const newEvent = new StoredEvent(id, aggregateRootId);
24
+ newEvent._eventName = eventName;
25
+ newEvent._createdAt = createdAt;
26
+ newEvent.aggregateRootVersion = aggregateRootVersion;
27
+ newEvent._payload = payload;
28
+ return newEvent;
29
+ }
30
+ getPayloadAs(payloadClass) {
31
+ return (0, class_transformer_1.plainToClass)(payloadClass, this._payload);
32
+ }
33
+ get payload() {
34
+ return this._payload;
35
+ }
36
+ get id() {
37
+ return this._id;
38
+ }
39
+ get aggregateRootId() {
40
+ return this._aggregateRootId;
41
+ }
42
+ get createdAt() {
43
+ return this._createdAt;
44
+ }
45
+ get eventName() {
46
+ return this._eventName;
47
+ }
48
+ }
49
+ exports.StoredEvent = StoredEvent;
50
+ //# sourceMappingURL=stored-event.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stored-event.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/storage/stored-event.ts"],"names":[],"mappings":";;;AAAA,yDAAoF;AAEpF,qEAA8D;AAC9D,oDAA4C;AAE5C,MAAa,WAAW;IASpB,YAAoB,EAAU,EAAE,eAAuB;QACnD,IAAI,CAAC,gBAAgB,GAAG,eAAe,CAAC;QACxC,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;IAClB,CAAC;IAED,MAAM,CAAC,kBAAkB,CAAC,EAAU,EAAE,eAAuB,EAAE,cAA4B;QACvF,MAAM,QAAQ,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,eAAe,CAAC,CAAC;QACtD,QAAQ,CAAC,UAAU,GAAG,IAAI,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QAEzD,MAAM,SAAS,GAAG,IAAA,+BAAY,EAAC,cAAc,CAAC,CAAC;QAC/C,IAAI,CAAC,IAAA,kBAAK,EAAC,SAAS,CAAC,EAAE;YACnB,QAAQ,CAAC,QAAQ,GAAG,IAAA,mCAAe,EAAC,cAAc,CAAC,CAAC;YACpD,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC;SACnC;QACD,OAAO,QAAQ,CAAC;IACpB,CAAC;IAED,MAAM,CAAC,WAAW,CACd,EAAU,EACV,eAAuB,EACvB,SAAiB,EACjB,SAAe,EACf,oBAA4B,EAC5B,OAAgB;QAEhB,MAAM,QAAQ,GAAG,IAAI,WAAW,CAAC,EAAE,EAAE,eAAe,CAAC,CAAC;QACtD,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC;QAChC,QAAQ,CAAC,UAAU,GAAG,SAAS,CAAC;QAChC,QAAQ,CAAC,oBAAoB,GAAG,oBAAoB,CAAC;QACrD,QAAQ,CAAC,QAAQ,GAAG,OAAO,CAAC;QAC5B,OAAO,QAAQ,CAAC;IACpB,CAAC;IAEM,YAAY,CAAI,YAAiC;QACpD,OAAO,IAAA,gCAAY,EAAC,YAAY,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,OAAO;QACP,OAAO,IAAI,CAAC,QAAQ,CAAC;IACzB,CAAC;IAED,IAAI,EAAE;QACF,OAAO,IAAI,CAAC,GAAG,CAAC;IACpB,CAAC;IAED,IAAI,eAAe;QACf,OAAO,IAAI,CAAC,gBAAgB,CAAC;IACjC,CAAC;IAED,IAAI,SAAS;QACT,OAAO,IAAI,CAAC,UAAU,CAAC;IAC3B,CAAC;IAED,IAAI,SAAS;QACT,OAAO,IAAI,CAAC,UAAU,CAAC;IAC3B,CAAC;CACJ;AAjED,kCAiEC"}
@@ -0,0 +1,2 @@
1
+ export declare function isNil(toCheck: unknown): toCheck is null | undefined;
2
+ export declare function hasAllValues<T>(toCheck: Array<T | null | undefined>): toCheck is Array<T>;
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hasAllValues = exports.isNil = void 0;
4
+ function isNil(toCheck) {
5
+ return toCheck === null || toCheck === undefined;
6
+ }
7
+ exports.isNil = isNil;
8
+ function hasAllValues(toCheck) {
9
+ return toCheck.every((item) => !isNil(item));
10
+ }
11
+ exports.hasAllValues = hasAllValues;
12
+ //# sourceMappingURL=type-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-utils.js","sourceRoot":"","sources":["../../../../../../libs/core/src/lib/utils/type-utils.ts"],"names":[],"mappings":";;;AAAA,SAAgB,KAAK,CAAC,OAAgB;IAClC,OAAO,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,SAAS,CAAC;AACrD,CAAC;AAFD,sBAEC;AAED,SAAgB,YAAY,CAAI,OAAoC;IAChE,OAAO,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACjD,CAAC;AAFD,oCAEC"}