node-cqrs 0.16.3 → 0.17.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/CHANGELOG.md +53 -0
- package/README.md +2 -1
- package/dist/AbstractAggregate.js +178 -0
- package/dist/AbstractAggregate.js.map +1 -0
- package/dist/AbstractProjection.js +121 -0
- package/dist/AbstractProjection.js.map +1 -0
- package/dist/AbstractSaga.js +99 -0
- package/dist/AbstractSaga.js.map +1 -0
- package/dist/AggregateCommandHandler.js +85 -0
- package/dist/AggregateCommandHandler.js.map +1 -0
- package/dist/CommandBus.js +77 -0
- package/dist/CommandBus.js.map +1 -0
- package/dist/CqrsContainerBuilder.js +77 -0
- package/dist/CqrsContainerBuilder.js.map +1 -0
- package/dist/Event.js +43 -0
- package/dist/Event.js.map +1 -0
- package/dist/EventStore.js +229 -0
- package/dist/EventStore.js.map +1 -0
- package/dist/SagaEventHandler.js +117 -0
- package/dist/SagaEventHandler.js.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/infrastructure/InMemoryEventStorage.js +53 -0
- package/dist/infrastructure/InMemoryEventStorage.js.map +1 -0
- package/dist/infrastructure/InMemoryLock.js +68 -0
- package/dist/infrastructure/InMemoryLock.js.map +1 -0
- package/dist/infrastructure/InMemoryMessageBus.js +95 -0
- package/dist/infrastructure/InMemoryMessageBus.js.map +1 -0
- package/dist/infrastructure/InMemorySnapshotStorage.js +26 -0
- package/dist/infrastructure/InMemorySnapshotStorage.js.map +1 -0
- package/dist/infrastructure/InMemoryView.js +173 -0
- package/dist/infrastructure/InMemoryView.js.map +1 -0
- package/dist/infrastructure/utils/Deferred.js +38 -0
- package/dist/infrastructure/utils/Deferred.js.map +1 -0
- package/dist/infrastructure/utils/index.js +19 -0
- package/dist/infrastructure/utils/index.js.map +1 -0
- package/dist/infrastructure/utils/nextCycle.js +9 -0
- package/dist/infrastructure/utils/nextCycle.js.map +1 -0
- package/dist/interfaces.js +4 -0
- package/dist/interfaces.js.map +1 -0
- package/dist/utils/getClassName.js +10 -0
- package/dist/utils/getClassName.js.map +1 -0
- package/dist/utils/getHandledMessageTypes.js +18 -0
- package/dist/utils/getHandledMessageTypes.js.map +1 -0
- package/dist/utils/getHandler.js +20 -0
- package/dist/utils/getHandler.js.map +1 -0
- package/dist/utils/getMessageHandlerNames.js +38 -0
- package/dist/utils/getMessageHandlerNames.js.map +1 -0
- package/dist/utils/index.js +25 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/isClass.js +8 -0
- package/dist/utils/isClass.js.map +1 -0
- package/dist/utils/setupOneTimeEmitterSubscription.js +46 -0
- package/dist/utils/setupOneTimeEmitterSubscription.js.map +1 -0
- package/dist/utils/subscribe.js +39 -0
- package/dist/utils/subscribe.js.map +1 -0
- package/dist/utils/validateHandlers.js +21 -0
- package/dist/utils/validateHandlers.js.map +1 -0
- package/package.json +26 -17
- package/src/AbstractAggregate.ts +223 -0
- package/src/AbstractProjection.ts +172 -0
- package/src/AbstractSaga.ts +118 -0
- package/src/AggregateCommandHandler.ts +129 -0
- package/src/CommandBus.ts +98 -0
- package/src/CqrsContainerBuilder.ts +120 -0
- package/src/Event.ts +43 -0
- package/src/EventStore.ts +315 -0
- package/src/SagaEventHandler.ts +161 -0
- package/src/index.ts +26 -0
- package/src/infrastructure/InMemoryEventStorage.ts +68 -0
- package/src/infrastructure/InMemoryLock.ts +73 -0
- package/src/infrastructure/InMemoryMessageBus.ts +118 -0
- package/src/infrastructure/InMemorySnapshotStorage.ts +27 -0
- package/src/infrastructure/InMemoryView.ts +221 -0
- package/src/infrastructure/utils/Deferred.ts +41 -0
- package/src/infrastructure/utils/index.ts +2 -0
- package/src/infrastructure/utils/nextCycle.ts +4 -0
- package/src/interfaces.ts +328 -0
- package/src/utils/getClassName.ts +6 -0
- package/src/utils/{getHandledMessageTypes.js → getHandledMessageTypes.ts} +4 -8
- package/src/utils/{getHandler.js → getHandler.ts} +6 -7
- package/src/utils/{getMessageHandlerNames.js → getMessageHandlerNames.ts} +2 -9
- package/src/utils/index.ts +8 -0
- package/src/utils/{isClass.js → isClass.ts} +2 -4
- package/src/utils/setupOneTimeEmitterSubscription.ts +57 -0
- package/src/{subscribe.js → utils/subscribe.ts} +21 -18
- package/src/utils/{validateHandlers.js → validateHandlers.ts} +2 -8
- package/index.d.ts +0 -43
- package/index.js +0 -3
- package/jsconfig.json +0 -15
- package/src/AbstractAggregate.js +0 -277
- package/src/AbstractProjection.js +0 -192
- package/src/AbstractSaga.js +0 -171
- package/src/AggregateCommandHandler.js +0 -126
- package/src/CommandBus.js +0 -91
- package/src/CqrsContainerBuilder.js +0 -134
- package/src/EventStore.js +0 -457
- package/src/EventStream.js +0 -63
- package/src/SagaEventHandler.js +0 -141
- package/src/index.js +0 -21
- package/src/infrastructure/InMemoryEventStorage.js +0 -76
- package/src/infrastructure/InMemoryMessageBus.js +0 -132
- package/src/infrastructure/InMemorySnapshotStorage.js +0 -40
- package/src/infrastructure/InMemoryView.js +0 -265
- package/src/utils/getClassName.js +0 -11
- package/src/utils/index.js +0 -6
- package/src/utils/nullLogger.js +0 -8
- package/types/classes/AbstractAggregate.d.ts +0 -64
- package/types/classes/AbstractProjection.d.ts +0 -46
- package/types/classes/AbstractSaga.d.ts +0 -39
- package/types/classes/AggregateCommandHandler.d.ts +0 -21
- package/types/classes/CommandBus.d.ts +0 -17
- package/types/classes/CqrsContainerBuilder.d.ts +0 -26
- package/types/classes/EventStore.d.ts +0 -53
- package/types/classes/EventStream.d.ts +0 -18
- package/types/classes/InMemoryEventStorage.d.ts +0 -21
- package/types/classes/InMemoryMessageBus.d.ts +0 -30
- package/types/classes/InMemorySnapshotStorage.d.ts +0 -18
- package/types/classes/InMemoryView.d.ts +0 -57
- package/types/classes/SagaEventHandler.d.ts +0 -20
- package/types/interfaces/IAggregate.d.ts +0 -30
- package/types/interfaces/IAggregateSnapshotStorage.d.ts +0 -4
- package/types/interfaces/ICommandBus.d.ts +0 -6
- package/types/interfaces/ICommandHandler.d.ts +0 -3
- package/types/interfaces/IConcurrentView.d.ts +0 -22
- package/types/interfaces/IEventReceptor.d.ts +0 -3
- package/types/interfaces/IEventStorage.d.ts +0 -20
- package/types/interfaces/IEventStore.d.ts +0 -19
- package/types/interfaces/IEventStream.d.ts +0 -13
- package/types/interfaces/ILogger.d.ts +0 -3
- package/types/interfaces/IMessageBus.d.ts +0 -5
- package/types/interfaces/IObserver.d.ts +0 -11
- package/types/interfaces/IProjection.d.ts +0 -10
- package/types/interfaces/ISaga.d.ts +0 -27
- package/types/interfaces/Identifier.d.ts +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,56 @@
|
|
|
1
|
+
# [0.17.0](https://github.com/snatalenko/node-cqrs/compare/v1.0.0-rc.5...v0.17.0) (2025-08-12)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
# [1.0.0-rc.5](https://github.com/snatalenko/node-cqrs/compare/v1.0.0-rc.4...v1.0.0-rc.5) (2024-10-27)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Changes
|
|
9
|
+
|
|
10
|
+
* Add `InMemoryView.prototype.getSync` method ([5d4adb9](https://github.com/snatalenko/node-cqrs/commit/5d4adb9109c4c85edae2b0f3dfd995e8c51aef06))
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# [1.0.0-rc.4](https://github.com/snatalenko/node-cqrs/compare/v1.0.0-rc.3...v1.0.0-rc.4) (2024-10-02)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
# [1.0.0-rc.3](https://github.com/snatalenko/node-cqrs/compare/v1.0.0-rc.2...v1.0.0-rc.3) (2024-09-23)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# [1.0.0-rc.2](https://github.com/snatalenko/node-cqrs/compare/v1.0.0-rc.1...v1.0.0-rc.2) (2024-08-03)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
# [1.0.0-rc.1](https://github.com/snatalenko/node-cqrs/compare/v1.0.0-rc.0...v1.0.0-rc.1) (2024-08-03)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Build System
|
|
29
|
+
|
|
30
|
+
* Add NPM publishing script ([3372990](https://github.com/snatalenko/node-cqrs/commit/3372990ba2549695398e0949e35009396e660005))
|
|
31
|
+
* Suppress audit and test for tags ([574a00c](https://github.com/snatalenko/node-cqrs/commit/574a00cc53af009994ca4dd3278cb764743b4ad6))
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# [1.0.0-rc.0](https://github.com/snatalenko/node-cqrs/compare/v0.16.4...v1.0.0-rc.0) (2024-08-02)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
### Fixes
|
|
38
|
+
|
|
39
|
+
* Vulnerability in minimist dependency ([07b8c68](https://github.com/snatalenko/node-cqrs/commit/07b8c682fae4278965aa13a06caa994c037934e9))
|
|
40
|
+
|
|
41
|
+
### Refactoring
|
|
42
|
+
|
|
43
|
+
* Migrate to TS and Jest ([6737d55](https://github.com/snatalenko/node-cqrs/commit/6737d5566a9dc6314df0b20a65d32414fc503e54))
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
## [0.16.4](https://github.com/snatalenko/node-cqrs/compare/v0.16.3...v0.16.4) (2022-08-28)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
### Refactoring
|
|
50
|
+
|
|
51
|
+
* Use di package from npm ([0e8db91](https://github.com/snatalenko/node-cqrs/commit/0e8db91636541e95f804e2c266e2d8bbf0f49a8b))
|
|
52
|
+
|
|
53
|
+
|
|
1
54
|
## [0.16.3](https://github.com/snatalenko/node-cqrs/compare/v0.16.2...v0.16.3) (2022-01-28)
|
|
2
55
|
|
|
3
56
|
|
package/README.md
CHANGED
|
@@ -2,7 +2,8 @@ node-cqrs
|
|
|
2
2
|
=========
|
|
3
3
|
|
|
4
4
|
[](https://www.npmjs.com/package/node-cqrs)
|
|
5
|
-
[](https://github.com/snatalenko/node-cqrs/actions/workflows/audit.yml)
|
|
6
|
+
[](https://github.com/snatalenko/node-cqrs/actions/workflows/tests.yml)
|
|
6
7
|
[](https://coveralls.io/github/snatalenko/node-cqrs?branch=master)
|
|
7
8
|
[](https://www.npmjs.com/package/node-cqrs)
|
|
8
9
|
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AbstractAggregate = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
/**
|
|
6
|
+
* Deep-clone simple JS object
|
|
7
|
+
*/
|
|
8
|
+
function clone(obj) {
|
|
9
|
+
return JSON.parse(JSON.stringify(obj));
|
|
10
|
+
}
|
|
11
|
+
const SNAPSHOT_EVENT_TYPE = 'snapshot';
|
|
12
|
+
/**
|
|
13
|
+
* Base class for Aggregate definition
|
|
14
|
+
*/
|
|
15
|
+
class AbstractAggregate {
|
|
16
|
+
/**
|
|
17
|
+
* Optional list of commands handled by Aggregate.
|
|
18
|
+
*
|
|
19
|
+
* If not overridden in Aggregate implementation,
|
|
20
|
+
* `AggregateCommandHandler` will treat all public methods as command handlers
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* return ['createUser', 'changePassword'];
|
|
24
|
+
*/
|
|
25
|
+
static get handles() {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
#id;
|
|
29
|
+
#changes = [];
|
|
30
|
+
#version = 0;
|
|
31
|
+
#snapshotVersion;
|
|
32
|
+
/** Internal aggregate state */
|
|
33
|
+
state;
|
|
34
|
+
/** Command being handled by aggregate */
|
|
35
|
+
command;
|
|
36
|
+
/** Unique aggregate instance identifier */
|
|
37
|
+
get id() {
|
|
38
|
+
return this.#id;
|
|
39
|
+
}
|
|
40
|
+
/** Aggregate instance version */
|
|
41
|
+
get version() {
|
|
42
|
+
return this.#version;
|
|
43
|
+
}
|
|
44
|
+
/** Restored snapshot version */
|
|
45
|
+
get snapshotVersion() {
|
|
46
|
+
return this.#snapshotVersion;
|
|
47
|
+
}
|
|
48
|
+
/** Events emitted by Aggregate */
|
|
49
|
+
get changes() {
|
|
50
|
+
return [...this.#changes];
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Override to define whether an aggregate state snapshot should be taken
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* // create snapshot every 50 events
|
|
57
|
+
* return this.version % 50 === 0;
|
|
58
|
+
*/
|
|
59
|
+
get shouldTakeSnapshot() {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
constructor(options) {
|
|
63
|
+
const { id, state, events } = options;
|
|
64
|
+
if (!id)
|
|
65
|
+
throw new TypeError('id argument required');
|
|
66
|
+
if (state && typeof state !== 'object')
|
|
67
|
+
throw new TypeError('state argument, when provided, must be an Object');
|
|
68
|
+
if (events && !Array.isArray(events))
|
|
69
|
+
throw new TypeError('events argument, when provided, must be an Array');
|
|
70
|
+
this.#id = id;
|
|
71
|
+
(0, utils_1.validateHandlers)(this);
|
|
72
|
+
if (state)
|
|
73
|
+
this.state = state;
|
|
74
|
+
if (events)
|
|
75
|
+
events.forEach(event => this.mutate(event));
|
|
76
|
+
}
|
|
77
|
+
/** Pass command to command handler */
|
|
78
|
+
handle(command) {
|
|
79
|
+
if (!command)
|
|
80
|
+
throw new TypeError('command argument required');
|
|
81
|
+
if (!command.type)
|
|
82
|
+
throw new TypeError('command.type argument required');
|
|
83
|
+
const handler = (0, utils_1.getHandler)(this, command.type);
|
|
84
|
+
if (!handler)
|
|
85
|
+
throw new Error(`'${command.type}' handler is not defined or not a function`);
|
|
86
|
+
this.command = command;
|
|
87
|
+
return handler.call(this, command.payload, command.context);
|
|
88
|
+
}
|
|
89
|
+
/** Mutate aggregate state and increment aggregate version */
|
|
90
|
+
mutate(event) {
|
|
91
|
+
if (event.aggregateVersion !== undefined)
|
|
92
|
+
this.#version = event.aggregateVersion;
|
|
93
|
+
if (event.type === SNAPSHOT_EVENT_TYPE) {
|
|
94
|
+
this.#snapshotVersion = event.aggregateVersion;
|
|
95
|
+
this.restoreSnapshot(event);
|
|
96
|
+
}
|
|
97
|
+
else if (this.state) {
|
|
98
|
+
const handler = 'mutate' in this.state ?
|
|
99
|
+
this.state.mutate :
|
|
100
|
+
(0, utils_1.getHandler)(this.state, event.type);
|
|
101
|
+
if (handler)
|
|
102
|
+
handler.call(this.state, event);
|
|
103
|
+
}
|
|
104
|
+
this.#version += 1;
|
|
105
|
+
}
|
|
106
|
+
/** Format and register aggregate event and mutate aggregate state */
|
|
107
|
+
emit(type, payload) {
|
|
108
|
+
if (typeof type !== 'string' || !type.length)
|
|
109
|
+
throw new TypeError('type argument must be a non-empty string');
|
|
110
|
+
const event = this.makeEvent(type, payload, this.command);
|
|
111
|
+
this.emitRaw(event);
|
|
112
|
+
}
|
|
113
|
+
/** Format event based on a current aggregate state and a command being executed */
|
|
114
|
+
makeEvent(type, payload, sourceCommand) {
|
|
115
|
+
const event = {
|
|
116
|
+
aggregateId: this.id,
|
|
117
|
+
aggregateVersion: this.version,
|
|
118
|
+
type,
|
|
119
|
+
payload
|
|
120
|
+
};
|
|
121
|
+
if (sourceCommand) {
|
|
122
|
+
// augment event with command context
|
|
123
|
+
const { context, sagaId, sagaVersion } = sourceCommand;
|
|
124
|
+
if (context !== undefined)
|
|
125
|
+
event.context = context;
|
|
126
|
+
if (sagaId !== undefined)
|
|
127
|
+
event.sagaId = sagaId;
|
|
128
|
+
if (sagaVersion !== undefined)
|
|
129
|
+
event.sagaVersion = sagaVersion;
|
|
130
|
+
}
|
|
131
|
+
return event;
|
|
132
|
+
}
|
|
133
|
+
/** Register aggregate event and mutate aggregate state */
|
|
134
|
+
emitRaw(event) {
|
|
135
|
+
if (!event)
|
|
136
|
+
throw new TypeError('event argument required');
|
|
137
|
+
if (!event.aggregateId)
|
|
138
|
+
throw new TypeError('event.aggregateId argument required');
|
|
139
|
+
if (typeof event.aggregateVersion !== 'number')
|
|
140
|
+
throw new TypeError('event.aggregateVersion argument must be a Number');
|
|
141
|
+
if (typeof event.type !== 'string' || !event.type.length)
|
|
142
|
+
throw new TypeError('event.type argument must be a non-empty String');
|
|
143
|
+
this.mutate(event);
|
|
144
|
+
this.#changes.push(event);
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Take an aggregate state snapshot and add it to the changes queue
|
|
148
|
+
*/
|
|
149
|
+
takeSnapshot() {
|
|
150
|
+
this.emit(SNAPSHOT_EVENT_TYPE, this.makeSnapshot());
|
|
151
|
+
}
|
|
152
|
+
/** Create an aggregate state snapshot */
|
|
153
|
+
makeSnapshot() {
|
|
154
|
+
if (!this.state)
|
|
155
|
+
throw new Error('state property is empty, either define state or override makeSnapshot method');
|
|
156
|
+
return clone(this.state);
|
|
157
|
+
}
|
|
158
|
+
/** Restore aggregate state from a snapshot */
|
|
159
|
+
restoreSnapshot(snapshotEvent) {
|
|
160
|
+
if (!snapshotEvent)
|
|
161
|
+
throw new TypeError('snapshotEvent argument required');
|
|
162
|
+
if (!snapshotEvent.type)
|
|
163
|
+
throw new TypeError('snapshotEvent.type argument required');
|
|
164
|
+
if (!snapshotEvent.payload)
|
|
165
|
+
throw new TypeError('snapshotEvent.payload argument required');
|
|
166
|
+
if (snapshotEvent.type !== SNAPSHOT_EVENT_TYPE)
|
|
167
|
+
throw new Error(`${SNAPSHOT_EVENT_TYPE} event type expected`);
|
|
168
|
+
if (!this.state)
|
|
169
|
+
throw new Error('state property is empty, either defined state or override restoreSnapshot method');
|
|
170
|
+
Object.assign(this.state, clone(snapshotEvent.payload));
|
|
171
|
+
}
|
|
172
|
+
/** Get human-readable aggregate identifier */
|
|
173
|
+
toString() {
|
|
174
|
+
return `${(0, utils_1.getClassName)(this)} ${this.id} (v${this.version})`;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
exports.AbstractAggregate = AbstractAggregate;
|
|
178
|
+
//# sourceMappingURL=AbstractAggregate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AbstractAggregate.js","sourceRoot":"","sources":["../src/AbstractAggregate.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AbstractProjection = void 0;
|
|
4
|
+
const InMemoryView_1 = require("./infrastructure/InMemoryView");
|
|
5
|
+
const utils_1 = require("./utils");
|
|
6
|
+
const isProjectionView = (view) => 'ready' in view &&
|
|
7
|
+
'lock' in view &&
|
|
8
|
+
'unlock' in view &&
|
|
9
|
+
'once' in view;
|
|
10
|
+
const asProjectionView = (view) => (isProjectionView(view) ? view : undefined);
|
|
11
|
+
/**
|
|
12
|
+
* Base class for Projection definition
|
|
13
|
+
*/
|
|
14
|
+
class AbstractProjection {
|
|
15
|
+
/**
|
|
16
|
+
* Optional list of event types being handled by projection.
|
|
17
|
+
* Can be overridden in projection implementation.
|
|
18
|
+
* If not overridden, will detect event types from event handlers declared on the Projection class
|
|
19
|
+
*/
|
|
20
|
+
static get handles() {
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Default view associated with projection
|
|
25
|
+
*/
|
|
26
|
+
get view() {
|
|
27
|
+
if (!this.#view)
|
|
28
|
+
this.#view = this.#viewFactory();
|
|
29
|
+
return this.#view;
|
|
30
|
+
}
|
|
31
|
+
#viewFactory;
|
|
32
|
+
#view;
|
|
33
|
+
_logger;
|
|
34
|
+
get collectionName() {
|
|
35
|
+
return (0, utils_1.getClassName)(this);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Indicates if view should be restored from EventStore on start.
|
|
39
|
+
* Override for custom behavior.
|
|
40
|
+
*/
|
|
41
|
+
get shouldRestoreView() {
|
|
42
|
+
return (this.view instanceof Map)
|
|
43
|
+
|| (this.view instanceof InMemoryView_1.InMemoryView);
|
|
44
|
+
}
|
|
45
|
+
constructor({ view, viewFactory = InMemoryView_1.InMemoryView.factory, logger } = {}) {
|
|
46
|
+
(0, utils_1.validateHandlers)(this);
|
|
47
|
+
this.#viewFactory = view ?
|
|
48
|
+
() => view :
|
|
49
|
+
viewFactory;
|
|
50
|
+
this._logger = logger && 'child' in logger ?
|
|
51
|
+
logger.child({ service: (0, utils_1.getClassName)(this) }) :
|
|
52
|
+
logger;
|
|
53
|
+
}
|
|
54
|
+
/** Subscribe to event store */
|
|
55
|
+
async subscribe(eventStore) {
|
|
56
|
+
(0, utils_1.subscribe)(eventStore, this, {
|
|
57
|
+
masterHandler: (e) => this.project(e)
|
|
58
|
+
});
|
|
59
|
+
await this.restore(eventStore);
|
|
60
|
+
}
|
|
61
|
+
/** Pass event to projection event handler */
|
|
62
|
+
async project(event) {
|
|
63
|
+
const concurrentView = asProjectionView(this.view);
|
|
64
|
+
if (concurrentView && !concurrentView.ready)
|
|
65
|
+
await concurrentView.once('ready');
|
|
66
|
+
return this._project(event);
|
|
67
|
+
}
|
|
68
|
+
/** Pass event to projection event handler, without awaiting for restore operation to complete */
|
|
69
|
+
async _project(event) {
|
|
70
|
+
const handler = (0, utils_1.getHandler)(this, event.type);
|
|
71
|
+
if (!handler)
|
|
72
|
+
throw new Error(`'${event.type}' handler is not defined or not a function`);
|
|
73
|
+
return handler.call(this, event);
|
|
74
|
+
}
|
|
75
|
+
/** Restore projection view from event store */
|
|
76
|
+
async restore(eventStore) {
|
|
77
|
+
// lock the view to ensure same restoring procedure
|
|
78
|
+
// won't be performed by another projection instance
|
|
79
|
+
const concurrentView = asProjectionView(this.view);
|
|
80
|
+
if (concurrentView)
|
|
81
|
+
await concurrentView.lock();
|
|
82
|
+
const shouldRestore = await this.shouldRestoreView;
|
|
83
|
+
if (shouldRestore)
|
|
84
|
+
await this._restore(eventStore);
|
|
85
|
+
if (concurrentView)
|
|
86
|
+
concurrentView.unlock();
|
|
87
|
+
}
|
|
88
|
+
/** Restore projection view from event store */
|
|
89
|
+
async _restore(eventStore) {
|
|
90
|
+
if (!eventStore)
|
|
91
|
+
throw new TypeError('eventStore argument required');
|
|
92
|
+
if (typeof eventStore.getAllEvents !== 'function')
|
|
93
|
+
throw new TypeError('eventStore.getAllEvents must be a Function');
|
|
94
|
+
this._logger?.debug('retrieving events and restoring projection...');
|
|
95
|
+
const messageTypes = (0, utils_1.getHandledMessageTypes)(this);
|
|
96
|
+
const eventsIterable = eventStore.getAllEvents(messageTypes);
|
|
97
|
+
let eventsCount = 0;
|
|
98
|
+
const startTs = Date.now();
|
|
99
|
+
for await (const event of eventsIterable) {
|
|
100
|
+
try {
|
|
101
|
+
await this._project(event);
|
|
102
|
+
eventsCount += 1;
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
this._onRestoringError(err, event);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
this._logger?.info(`view restored (${this.view}) from ${eventsCount} event(s) in ${Date.now() - startTs} ms`);
|
|
109
|
+
}
|
|
110
|
+
/** Handle error on restoring. Logs and throws error by default */
|
|
111
|
+
_onRestoringError(error, event) {
|
|
112
|
+
this._logger?.error(`view restoring has failed (view will remain locked): ${error.message}`, {
|
|
113
|
+
service: (0, utils_1.getClassName)(this),
|
|
114
|
+
event,
|
|
115
|
+
stack: error.stack
|
|
116
|
+
});
|
|
117
|
+
throw error;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.AbstractProjection = AbstractProjection;
|
|
121
|
+
//# sourceMappingURL=AbstractProjection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AbstractProjection.js","sourceRoot":"","sources":["../src/AbstractProjection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AbstractSaga = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
/**
|
|
6
|
+
* Base class for Saga definition
|
|
7
|
+
*/
|
|
8
|
+
class AbstractSaga {
|
|
9
|
+
/** List of events that start new saga, must be overridden in Saga implementation */
|
|
10
|
+
static get startsWith() {
|
|
11
|
+
throw new Error('startsWith must be overridden to return a list of event types that start saga');
|
|
12
|
+
}
|
|
13
|
+
/** List of event types being handled by Saga, must be overridden in Saga implementation */
|
|
14
|
+
static get handles() {
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
/** Saga ID */
|
|
18
|
+
get id() {
|
|
19
|
+
return this.#id;
|
|
20
|
+
}
|
|
21
|
+
/** Saga version */
|
|
22
|
+
get version() {
|
|
23
|
+
return this.#version;
|
|
24
|
+
}
|
|
25
|
+
/** Command execution queue */
|
|
26
|
+
get uncommittedMessages() {
|
|
27
|
+
return Array.from(this.#messages);
|
|
28
|
+
}
|
|
29
|
+
#id;
|
|
30
|
+
#version = 0;
|
|
31
|
+
#messages = [];
|
|
32
|
+
/**
|
|
33
|
+
* Creates an instance of AbstractSaga
|
|
34
|
+
*/
|
|
35
|
+
constructor(options) {
|
|
36
|
+
if (!options)
|
|
37
|
+
throw new TypeError('options argument required');
|
|
38
|
+
if (!options.id)
|
|
39
|
+
throw new TypeError('options.id argument required');
|
|
40
|
+
this.#id = options.id;
|
|
41
|
+
(0, utils_1.validateHandlers)(this, 'startsWith');
|
|
42
|
+
(0, utils_1.validateHandlers)(this, 'handles');
|
|
43
|
+
if (options.events) {
|
|
44
|
+
options.events.forEach(e => this.apply(e));
|
|
45
|
+
this.resetUncommittedMessages();
|
|
46
|
+
}
|
|
47
|
+
Object.defineProperty(this, 'restored', { value: true });
|
|
48
|
+
}
|
|
49
|
+
/** Modify saga state by applying an event */
|
|
50
|
+
apply(event) {
|
|
51
|
+
if (!event)
|
|
52
|
+
throw new TypeError('event argument required');
|
|
53
|
+
if (!event.type)
|
|
54
|
+
throw new TypeError('event.type argument required');
|
|
55
|
+
const handler = (0, utils_1.getHandler)(this, event.type);
|
|
56
|
+
if (!handler)
|
|
57
|
+
throw new Error(`'${event.type}' handler is not defined or not a function`);
|
|
58
|
+
const r = handler.call(this, event);
|
|
59
|
+
if (r instanceof Promise) {
|
|
60
|
+
return r.then(() => {
|
|
61
|
+
this.#version += 1;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
this.#version += 1;
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
/** Format a command and put it to the execution queue */
|
|
68
|
+
enqueue(commandType, aggregateId, payload) {
|
|
69
|
+
if (typeof commandType !== 'string' || !commandType.length)
|
|
70
|
+
throw new TypeError('commandType argument must be a non-empty String');
|
|
71
|
+
if (!['string', 'number', 'undefined'].includes(typeof aggregateId))
|
|
72
|
+
throw new TypeError('aggregateId argument must be either string, number or undefined');
|
|
73
|
+
this.enqueueRaw({
|
|
74
|
+
aggregateId,
|
|
75
|
+
sagaId: this.id,
|
|
76
|
+
sagaVersion: this.version,
|
|
77
|
+
type: commandType,
|
|
78
|
+
payload
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
/** Put a command to the execution queue */
|
|
82
|
+
enqueueRaw(command) {
|
|
83
|
+
if (typeof command !== 'object' || !command)
|
|
84
|
+
throw new TypeError('command argument must be an Object');
|
|
85
|
+
if (typeof command.type !== 'string' || !command.type.length)
|
|
86
|
+
throw new TypeError('command.type argument must be a non-empty String');
|
|
87
|
+
this.#messages.push(command);
|
|
88
|
+
}
|
|
89
|
+
/** Clear the execution queue */
|
|
90
|
+
resetUncommittedMessages() {
|
|
91
|
+
this.#messages.length = 0;
|
|
92
|
+
}
|
|
93
|
+
/** Get human-readable Saga name */
|
|
94
|
+
toString() {
|
|
95
|
+
return `${(0, utils_1.getClassName)(this)} ${this.id} (v${this.version})`;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
exports.AbstractSaga = AbstractSaga;
|
|
99
|
+
//# sourceMappingURL=AbstractSaga.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AbstractSaga.js","sourceRoot":"","sources":["../src/AbstractSaga.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AggregateCommandHandler = void 0;
|
|
4
|
+
const utils_1 = require("./utils");
|
|
5
|
+
/**
|
|
6
|
+
* Aggregate command handler.
|
|
7
|
+
*
|
|
8
|
+
* Subscribes to event store and awaits aggregate commands.
|
|
9
|
+
* Upon command receiving creates an instance of aggregate,
|
|
10
|
+
* restores its state, passes command and commits emitted events to event store.
|
|
11
|
+
*/
|
|
12
|
+
class AggregateCommandHandler {
|
|
13
|
+
#eventStore;
|
|
14
|
+
#logger;
|
|
15
|
+
#aggregateFactory;
|
|
16
|
+
#handles;
|
|
17
|
+
constructor({ eventStore, aggregateType, aggregateFactory, handles, logger }) {
|
|
18
|
+
if (!eventStore)
|
|
19
|
+
throw new TypeError('eventStore argument required');
|
|
20
|
+
this.#eventStore = eventStore;
|
|
21
|
+
this.#logger = logger && 'child' in logger ?
|
|
22
|
+
logger.child({ service: (0, utils_1.getClassName)(this) }) :
|
|
23
|
+
logger;
|
|
24
|
+
if (aggregateType) {
|
|
25
|
+
const AggregateType = aggregateType;
|
|
26
|
+
this.#aggregateFactory = params => new AggregateType(params);
|
|
27
|
+
this.#handles = (0, utils_1.getHandledMessageTypes)(AggregateType);
|
|
28
|
+
}
|
|
29
|
+
else if (aggregateFactory) {
|
|
30
|
+
if (!Array.isArray(handles) || !handles.length)
|
|
31
|
+
throw new TypeError('handles argument must be an non-empty Array');
|
|
32
|
+
this.#aggregateFactory = aggregateFactory;
|
|
33
|
+
this.#handles = handles;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
throw new TypeError('either aggregateType or aggregateFactory is required');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/** Subscribe to all command types handled by aggregateType */
|
|
40
|
+
subscribe(commandBus) {
|
|
41
|
+
(0, utils_1.subscribe)(commandBus, this, {
|
|
42
|
+
messageTypes: this.#handles,
|
|
43
|
+
masterHandler: (c) => this.execute(c)
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
/** Restore aggregate from event store events */
|
|
47
|
+
async #restoreAggregate(id) {
|
|
48
|
+
if (!id)
|
|
49
|
+
throw new TypeError('id argument required');
|
|
50
|
+
const events = await this.#eventStore.getAggregateEvents(id);
|
|
51
|
+
const aggregate = this.#aggregateFactory({ id, events });
|
|
52
|
+
this.#logger?.info(`${aggregate} state restored from ${events.length} event(s)`);
|
|
53
|
+
return aggregate;
|
|
54
|
+
}
|
|
55
|
+
/** Create new aggregate with new Id generated by event store */
|
|
56
|
+
async #createAggregate() {
|
|
57
|
+
const id = await this.#eventStore.getNewId();
|
|
58
|
+
const aggregate = this.#aggregateFactory({ id });
|
|
59
|
+
this.#logger?.info(`${aggregate} created`);
|
|
60
|
+
return aggregate;
|
|
61
|
+
}
|
|
62
|
+
/** Pass a command to corresponding aggregate */
|
|
63
|
+
async execute(cmd) {
|
|
64
|
+
if (!cmd)
|
|
65
|
+
throw new TypeError('cmd argument required');
|
|
66
|
+
if (!cmd.type)
|
|
67
|
+
throw new TypeError('cmd.type argument required');
|
|
68
|
+
const aggregate = cmd.aggregateId ?
|
|
69
|
+
await this.#restoreAggregate(cmd.aggregateId) :
|
|
70
|
+
await this.#createAggregate();
|
|
71
|
+
await aggregate.handle(cmd);
|
|
72
|
+
let events = aggregate.changes;
|
|
73
|
+
this.#logger?.info(`${aggregate} "${cmd.type}" command processed, ${events.length} event(s) produced`);
|
|
74
|
+
if (!events.length)
|
|
75
|
+
return events;
|
|
76
|
+
if (aggregate.shouldTakeSnapshot && this.#eventStore.snapshotsSupported) {
|
|
77
|
+
aggregate.takeSnapshot();
|
|
78
|
+
events = aggregate.changes;
|
|
79
|
+
}
|
|
80
|
+
await this.#eventStore.commit(events);
|
|
81
|
+
return events;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
exports.AggregateCommandHandler = AggregateCommandHandler;
|
|
85
|
+
//# sourceMappingURL=AggregateCommandHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AggregateCommandHandler.js","sourceRoot":"","sources":["../src/AggregateCommandHandler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.CommandBus = void 0;
|
|
4
|
+
const InMemoryMessageBus_1 = require("./infrastructure/InMemoryMessageBus");
|
|
5
|
+
class CommandBus {
|
|
6
|
+
#logger;
|
|
7
|
+
#bus;
|
|
8
|
+
/**
|
|
9
|
+
* Creates an instance of CommandBus.
|
|
10
|
+
*/
|
|
11
|
+
constructor({ messageBus, logger }) {
|
|
12
|
+
this.#bus = messageBus ?? new InMemoryMessageBus_1.InMemoryMessageBus();
|
|
13
|
+
this.#logger = logger && 'child' in logger ?
|
|
14
|
+
logger.child({ service: 'CommandBus' }) :
|
|
15
|
+
logger;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Set up a command handler
|
|
19
|
+
*/
|
|
20
|
+
on(commandType, handler) {
|
|
21
|
+
if (typeof commandType !== 'string' || !commandType.length)
|
|
22
|
+
throw new TypeError('commandType argument must be a non-empty String');
|
|
23
|
+
if (typeof handler !== 'function')
|
|
24
|
+
throw new TypeError('handler argument must be a Function');
|
|
25
|
+
return this.#bus.on(commandType, handler);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Remove previously installed command handler
|
|
29
|
+
*/
|
|
30
|
+
off(commandType, handler) {
|
|
31
|
+
if (typeof commandType !== 'string' || !commandType.length)
|
|
32
|
+
throw new TypeError('commandType argument must be a non-empty String');
|
|
33
|
+
if (typeof handler !== 'function')
|
|
34
|
+
throw new TypeError('handler argument must be a Function');
|
|
35
|
+
return this.#bus.off(commandType, handler);
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Format and send a command for execution
|
|
39
|
+
*/
|
|
40
|
+
send(type, aggregateId, options, ...otherArgs) {
|
|
41
|
+
if (typeof type !== 'string' || !type.length)
|
|
42
|
+
throw new TypeError('type argument must be a non-empty String');
|
|
43
|
+
if (options && typeof options !== 'object')
|
|
44
|
+
throw new TypeError('options argument, when defined, must be an Object');
|
|
45
|
+
if (otherArgs.length > 1)
|
|
46
|
+
throw new TypeError('more than expected arguments supplied');
|
|
47
|
+
// obsolete. left for backward compatibility
|
|
48
|
+
const optionsContainContext = options && !('context' in options) && !('payload' in options);
|
|
49
|
+
if (otherArgs.length || optionsContainContext) {
|
|
50
|
+
const context = options;
|
|
51
|
+
const payload = otherArgs.length ? otherArgs[0] : undefined;
|
|
52
|
+
return this.sendRaw({ type, aggregateId, context, payload });
|
|
53
|
+
}
|
|
54
|
+
return this.sendRaw({ type, aggregateId, ...options });
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Send a command for execution
|
|
58
|
+
*/
|
|
59
|
+
sendRaw(command) {
|
|
60
|
+
if (!command)
|
|
61
|
+
throw new TypeError('command argument required');
|
|
62
|
+
if (!command.type)
|
|
63
|
+
throw new TypeError('command.type argument required');
|
|
64
|
+
this.#logger?.debug(`sending '${command.type}' command${command.aggregateId ? ` to ${command.aggregateId}` : ''}...`);
|
|
65
|
+
return this.#bus.send(command).then(r => {
|
|
66
|
+
this.#logger?.debug(`'${command.type}' ${command.aggregateId ? `on ${command.aggregateId}` : ''} processed`);
|
|
67
|
+
return r;
|
|
68
|
+
}, error => {
|
|
69
|
+
this.#logger?.warn(`'${command.type}' ${command.aggregateId ? `on ${command.aggregateId}` : ''} processing has failed: ${error.message}`, {
|
|
70
|
+
stack: error.stack
|
|
71
|
+
});
|
|
72
|
+
throw error;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.CommandBus = CommandBus;
|
|
77
|
+
//# sourceMappingURL=CommandBus.js.map
|