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.
Files changed (135) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/README.md +2 -1
  3. package/dist/AbstractAggregate.js +178 -0
  4. package/dist/AbstractAggregate.js.map +1 -0
  5. package/dist/AbstractProjection.js +121 -0
  6. package/dist/AbstractProjection.js.map +1 -0
  7. package/dist/AbstractSaga.js +99 -0
  8. package/dist/AbstractSaga.js.map +1 -0
  9. package/dist/AggregateCommandHandler.js +85 -0
  10. package/dist/AggregateCommandHandler.js.map +1 -0
  11. package/dist/CommandBus.js +77 -0
  12. package/dist/CommandBus.js.map +1 -0
  13. package/dist/CqrsContainerBuilder.js +77 -0
  14. package/dist/CqrsContainerBuilder.js.map +1 -0
  15. package/dist/Event.js +43 -0
  16. package/dist/Event.js.map +1 -0
  17. package/dist/EventStore.js +229 -0
  18. package/dist/EventStore.js.map +1 -0
  19. package/dist/SagaEventHandler.js +117 -0
  20. package/dist/SagaEventHandler.js.map +1 -0
  21. package/dist/index.js +39 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/infrastructure/InMemoryEventStorage.js +53 -0
  24. package/dist/infrastructure/InMemoryEventStorage.js.map +1 -0
  25. package/dist/infrastructure/InMemoryLock.js +68 -0
  26. package/dist/infrastructure/InMemoryLock.js.map +1 -0
  27. package/dist/infrastructure/InMemoryMessageBus.js +95 -0
  28. package/dist/infrastructure/InMemoryMessageBus.js.map +1 -0
  29. package/dist/infrastructure/InMemorySnapshotStorage.js +26 -0
  30. package/dist/infrastructure/InMemorySnapshotStorage.js.map +1 -0
  31. package/dist/infrastructure/InMemoryView.js +173 -0
  32. package/dist/infrastructure/InMemoryView.js.map +1 -0
  33. package/dist/infrastructure/utils/Deferred.js +38 -0
  34. package/dist/infrastructure/utils/Deferred.js.map +1 -0
  35. package/dist/infrastructure/utils/index.js +19 -0
  36. package/dist/infrastructure/utils/index.js.map +1 -0
  37. package/dist/infrastructure/utils/nextCycle.js +9 -0
  38. package/dist/infrastructure/utils/nextCycle.js.map +1 -0
  39. package/dist/interfaces.js +4 -0
  40. package/dist/interfaces.js.map +1 -0
  41. package/dist/utils/getClassName.js +10 -0
  42. package/dist/utils/getClassName.js.map +1 -0
  43. package/dist/utils/getHandledMessageTypes.js +18 -0
  44. package/dist/utils/getHandledMessageTypes.js.map +1 -0
  45. package/dist/utils/getHandler.js +20 -0
  46. package/dist/utils/getHandler.js.map +1 -0
  47. package/dist/utils/getMessageHandlerNames.js +38 -0
  48. package/dist/utils/getMessageHandlerNames.js.map +1 -0
  49. package/dist/utils/index.js +25 -0
  50. package/dist/utils/index.js.map +1 -0
  51. package/dist/utils/isClass.js +8 -0
  52. package/dist/utils/isClass.js.map +1 -0
  53. package/dist/utils/setupOneTimeEmitterSubscription.js +46 -0
  54. package/dist/utils/setupOneTimeEmitterSubscription.js.map +1 -0
  55. package/dist/utils/subscribe.js +39 -0
  56. package/dist/utils/subscribe.js.map +1 -0
  57. package/dist/utils/validateHandlers.js +21 -0
  58. package/dist/utils/validateHandlers.js.map +1 -0
  59. package/package.json +26 -17
  60. package/src/AbstractAggregate.ts +223 -0
  61. package/src/AbstractProjection.ts +172 -0
  62. package/src/AbstractSaga.ts +118 -0
  63. package/src/AggregateCommandHandler.ts +129 -0
  64. package/src/CommandBus.ts +98 -0
  65. package/src/CqrsContainerBuilder.ts +120 -0
  66. package/src/Event.ts +43 -0
  67. package/src/EventStore.ts +315 -0
  68. package/src/SagaEventHandler.ts +161 -0
  69. package/src/index.ts +26 -0
  70. package/src/infrastructure/InMemoryEventStorage.ts +68 -0
  71. package/src/infrastructure/InMemoryLock.ts +73 -0
  72. package/src/infrastructure/InMemoryMessageBus.ts +118 -0
  73. package/src/infrastructure/InMemorySnapshotStorage.ts +27 -0
  74. package/src/infrastructure/InMemoryView.ts +221 -0
  75. package/src/infrastructure/utils/Deferred.ts +41 -0
  76. package/src/infrastructure/utils/index.ts +2 -0
  77. package/src/infrastructure/utils/nextCycle.ts +4 -0
  78. package/src/interfaces.ts +328 -0
  79. package/src/utils/getClassName.ts +6 -0
  80. package/src/utils/{getHandledMessageTypes.js → getHandledMessageTypes.ts} +4 -8
  81. package/src/utils/{getHandler.js → getHandler.ts} +6 -7
  82. package/src/utils/{getMessageHandlerNames.js → getMessageHandlerNames.ts} +2 -9
  83. package/src/utils/index.ts +8 -0
  84. package/src/utils/{isClass.js → isClass.ts} +2 -4
  85. package/src/utils/setupOneTimeEmitterSubscription.ts +57 -0
  86. package/src/{subscribe.js → utils/subscribe.ts} +21 -18
  87. package/src/utils/{validateHandlers.js → validateHandlers.ts} +2 -8
  88. package/index.d.ts +0 -43
  89. package/index.js +0 -3
  90. package/jsconfig.json +0 -15
  91. package/src/AbstractAggregate.js +0 -277
  92. package/src/AbstractProjection.js +0 -192
  93. package/src/AbstractSaga.js +0 -171
  94. package/src/AggregateCommandHandler.js +0 -126
  95. package/src/CommandBus.js +0 -91
  96. package/src/CqrsContainerBuilder.js +0 -134
  97. package/src/EventStore.js +0 -457
  98. package/src/EventStream.js +0 -63
  99. package/src/SagaEventHandler.js +0 -141
  100. package/src/index.js +0 -21
  101. package/src/infrastructure/InMemoryEventStorage.js +0 -76
  102. package/src/infrastructure/InMemoryMessageBus.js +0 -132
  103. package/src/infrastructure/InMemorySnapshotStorage.js +0 -40
  104. package/src/infrastructure/InMemoryView.js +0 -265
  105. package/src/utils/getClassName.js +0 -11
  106. package/src/utils/index.js +0 -6
  107. package/src/utils/nullLogger.js +0 -8
  108. package/types/classes/AbstractAggregate.d.ts +0 -64
  109. package/types/classes/AbstractProjection.d.ts +0 -46
  110. package/types/classes/AbstractSaga.d.ts +0 -39
  111. package/types/classes/AggregateCommandHandler.d.ts +0 -21
  112. package/types/classes/CommandBus.d.ts +0 -17
  113. package/types/classes/CqrsContainerBuilder.d.ts +0 -26
  114. package/types/classes/EventStore.d.ts +0 -53
  115. package/types/classes/EventStream.d.ts +0 -18
  116. package/types/classes/InMemoryEventStorage.d.ts +0 -21
  117. package/types/classes/InMemoryMessageBus.d.ts +0 -30
  118. package/types/classes/InMemorySnapshotStorage.d.ts +0 -18
  119. package/types/classes/InMemoryView.d.ts +0 -57
  120. package/types/classes/SagaEventHandler.d.ts +0 -20
  121. package/types/interfaces/IAggregate.d.ts +0 -30
  122. package/types/interfaces/IAggregateSnapshotStorage.d.ts +0 -4
  123. package/types/interfaces/ICommandBus.d.ts +0 -6
  124. package/types/interfaces/ICommandHandler.d.ts +0 -3
  125. package/types/interfaces/IConcurrentView.d.ts +0 -22
  126. package/types/interfaces/IEventReceptor.d.ts +0 -3
  127. package/types/interfaces/IEventStorage.d.ts +0 -20
  128. package/types/interfaces/IEventStore.d.ts +0 -19
  129. package/types/interfaces/IEventStream.d.ts +0 -13
  130. package/types/interfaces/ILogger.d.ts +0 -3
  131. package/types/interfaces/IMessageBus.d.ts +0 -5
  132. package/types/interfaces/IObserver.d.ts +0 -11
  133. package/types/interfaces/IProjection.d.ts +0 -10
  134. package/types/interfaces/ISaga.d.ts +0 -27
  135. package/types/interfaces/Identifier.d.ts +0 -1
@@ -1,277 +0,0 @@
1
- 'use strict';
2
-
3
- const { validateHandlers, getHandler, getClassName } = require('./utils');
4
- const EventStream = require('./EventStream');
5
-
6
- /**
7
- * Deep-clone simple JS object
8
- * @template T
9
- * @param {T} obj
10
- * @returns {T}
11
- */
12
- const clone = obj => JSON.parse(JSON.stringify(obj));
13
-
14
- const SNAPSHOT_EVENT_TYPE = 'snapshot';
15
-
16
- const _id = Symbol('id');
17
- const _changes = Symbol('changes');
18
- const _version = Symbol('version');
19
- const _snapshotVersion = Symbol('snapshotVersion');
20
-
21
- /**
22
- * Base class for Aggregate definition
23
- *
24
- * @class AbstractAggregate
25
- * @implements {IAggregate}
26
- */
27
- class AbstractAggregate {
28
-
29
- /**
30
- * Optional list of commands handled by Aggregate.
31
- * Can be overridden in the aggregate implementation
32
- *
33
- * @type {string[]}
34
- * @readonly
35
- * @static
36
- * @example
37
- * return ['createUser', 'changePassword'];
38
- */
39
- static get handles() {
40
- return undefined;
41
- }
42
-
43
- /**
44
- * Aggregate ID
45
- *
46
- * @type {string|number}
47
- * @readonly
48
- */
49
- get id() {
50
- return this[_id];
51
- }
52
-
53
- /**
54
- * Aggregate Version
55
- *
56
- * @type {number}
57
- * @readonly
58
- */
59
- get version() {
60
- return this[_version];
61
- }
62
-
63
- /**
64
- * Aggregate Snapshot Version
65
- *
66
- * @type {number|undefined}
67
- * @readonly
68
- */
69
- get snapshotVersion() {
70
- return this[_snapshotVersion];
71
- }
72
-
73
- /**
74
- * Events emitted by Aggregate
75
- *
76
- * @type {IEventStream}
77
- * @readonly
78
- */
79
- get changes() {
80
- return new EventStream(this[_changes]);
81
- }
82
-
83
- /**
84
- * Override to define whether an aggregate state snapshot should be taken
85
- *
86
- * @type {boolean}
87
- * @readonly
88
- * @example
89
- * // create snapshot every 50 events
90
- * return this.version % 50 === 0;
91
- */
92
- get shouldTakeSnapshot() { // eslint-disable-line class-methods-use-this
93
- return false;
94
- }
95
-
96
- /**
97
- * Creates an instance of AbstractAggregate.
98
- *
99
- * @param {TAggregateConstructorParams} options
100
- */
101
- constructor(options) {
102
- const { id, state, events } = options;
103
- if (!id) throw new TypeError('id argument required');
104
- if (state && typeof state !== 'object') throw new TypeError('state argument, when provided, must be an Object');
105
- if (events && !Array.isArray(events)) throw new TypeError('events argument, when provided, must be an Array');
106
-
107
- this[_id] = id;
108
- this[_changes] = [];
109
- this[_version] = 0;
110
- this[_snapshotVersion] = 0;
111
-
112
- validateHandlers(this);
113
-
114
- if (state)
115
- this.state = state;
116
-
117
- if (events)
118
- events.forEach(event => this.mutate(event));
119
- }
120
-
121
- /**
122
- * Pass command to command handler
123
- *
124
- * @param {ICommand} command
125
- * @returns {any}
126
- */
127
- handle(command) {
128
- if (!command) throw new TypeError('command argument required');
129
- if (!command.type) throw new TypeError('command.type argument required');
130
-
131
- const handler = getHandler(this, command.type);
132
- if (!handler)
133
- throw new Error(`'${command.type}' handler is not defined or not a function`);
134
-
135
- this.command = command;
136
-
137
- return handler.call(this, command.payload, command.context);
138
- }
139
-
140
- /**
141
- * Mutate aggregate state and increment aggregate version
142
- *
143
- * @protected
144
- * @param {IEvent} event
145
- */
146
- mutate(event) {
147
- if ('aggregateVersion' in event)
148
- this[_version] = event.aggregateVersion;
149
-
150
- if (event.type === SNAPSHOT_EVENT_TYPE) {
151
- this[_snapshotVersion] = event.aggregateVersion;
152
- this.restoreSnapshot(event);
153
- }
154
- else if (this.state) {
155
- const handler = this.state.mutate || getHandler(this.state, event.type);
156
- if (handler)
157
- handler.call(this.state, event);
158
- }
159
-
160
- this[_version] += 1;
161
- }
162
-
163
- /**
164
- * Format and register aggregate event and mutate aggregate state
165
- *
166
- * @protected
167
- * @param {string} type - event type
168
- * @param {object} [payload] - event data
169
- */
170
- emit(type, payload) {
171
- if (typeof type !== 'string' || !type.length) throw new TypeError('type argument must be a non-empty string');
172
-
173
- const event = this.makeEvent(type, payload, this.command);
174
-
175
- this.emitRaw(event);
176
- }
177
-
178
- /**
179
- * Format event based on a current aggregate state
180
- * and a command being executed
181
- *
182
- * @protected
183
- * @param {string} type
184
- * @param {any} [payload]
185
- * @param {ICommand} [sourceCommand]
186
- * @returns {IEvent}
187
- */
188
- makeEvent(type, payload, sourceCommand) {
189
- /** @type {IEvent} */
190
- const event = {
191
- aggregateId: this.id,
192
- aggregateVersion: this.version,
193
- type,
194
- payload
195
- };
196
-
197
- if (sourceCommand) {
198
- // augment event with command context
199
- const { context, sagaId, sagaVersion } = sourceCommand;
200
- if (context !== undefined)
201
- event.context = context;
202
- if (sagaId !== undefined)
203
- event.sagaId = sagaId;
204
- if (sagaVersion !== undefined)
205
- event.sagaVersion = sagaVersion;
206
- }
207
-
208
- return event;
209
- }
210
-
211
- /**
212
- * Register aggregate event and mutate aggregate state
213
- *
214
- * @protected
215
- * @param {IEvent} event
216
- */
217
- emitRaw(event) {
218
- if (!event) throw new TypeError('event argument required');
219
- if (!event.aggregateId) throw new TypeError('event.aggregateId argument required');
220
- if (typeof event.aggregateVersion !== 'number') throw new TypeError('event.aggregateVersion argument must be a Number');
221
- if (typeof event.type !== 'string' || !event.type.length) throw new TypeError('event.type argument must be a non-empty String');
222
-
223
- this.mutate(event);
224
-
225
- this[_changes].push(event);
226
- }
227
-
228
- /**
229
- * Take an aggregate state snapshot and add it to the changes queue
230
- */
231
- takeSnapshot() {
232
- this.emit(SNAPSHOT_EVENT_TYPE, this.makeSnapshot());
233
- }
234
-
235
- /**
236
- * Create an aggregate state snapshot
237
- *
238
- * @protected
239
- * @returns {object}
240
- */
241
- makeSnapshot() {
242
- if (!this.state)
243
- throw new Error('state property is empty, either define state or override makeSnapshot method');
244
-
245
- return clone(this.state);
246
- }
247
-
248
- /**
249
- * Restore aggregate state from a snapshot
250
- *
251
- * @protected
252
- * @param {IEvent} snapshotEvent
253
- */
254
- restoreSnapshot(snapshotEvent) {
255
- if (!snapshotEvent) throw new TypeError('snapshotEvent argument required');
256
- if (!snapshotEvent.type) throw new TypeError('snapshotEvent.type argument required');
257
- if (!snapshotEvent.payload) throw new TypeError('snapshotEvent.payload argument required');
258
-
259
- if (snapshotEvent.type !== SNAPSHOT_EVENT_TYPE)
260
- throw new Error(`${SNAPSHOT_EVENT_TYPE} event type expected`);
261
- if (!this.state)
262
- throw new Error('state property is empty, either defined state or override restoreSnapshot method');
263
-
264
- Object.assign(this.state, clone(snapshotEvent.payload));
265
- }
266
-
267
- /**
268
- * Get human-readable aggregate identifier
269
- *
270
- * @returns {string}
271
- */
272
- toString() {
273
- return `${getClassName(this)} ${this.id} (v${this.version})`;
274
- }
275
- }
276
-
277
- module.exports = AbstractAggregate;
@@ -1,192 +0,0 @@
1
- 'use strict';
2
-
3
- const subscribe = require('./subscribe');
4
- const InMemoryView = require('./infrastructure/InMemoryView');
5
- const getHandledMessageTypes = require('./utils/getHandledMessageTypes');
6
- const { validateHandlers, getHandler, getClassName } = require('./utils');
7
- const nullLogger = require('./utils/nullLogger');
8
-
9
- /**
10
- * @param {any} view
11
- */
12
- const isConcurrentView = view =>
13
- typeof view.lock === 'function' &&
14
- typeof view.unlock === 'function' &&
15
- typeof view.once === 'function';
16
-
17
- /**
18
- * @param {any} view
19
- * @returns {IConcurrentView}
20
- */
21
- const asConcurrentView = view => (isConcurrentView(view) ? view : undefined);
22
-
23
- /**
24
- * Base class for Projection definition
25
- *
26
- * @class AbstractProjection
27
- * @implements {IProjection}
28
- */
29
- class AbstractProjection {
30
-
31
- /**
32
- * Optional list of event types being handled by projection.
33
- * Can be overridden in projection implementation.
34
- * If not overridden, will detect event types from event handlers declared on the Projection class
35
- *
36
- * @type {string[]}
37
- * @readonly
38
- * @static
39
- */
40
- static get handles() {
41
- return undefined;
42
- }
43
-
44
- /**
45
- * Default view associated with projection.
46
- * If not defined, an instance of `NodeCqrs.InMemoryView` is created on first access.
47
- *
48
- * @readonly
49
- */
50
- get view() {
51
- return this._view || (this._view = new InMemoryView());
52
- }
53
-
54
- /**
55
- * Indicates if view should be restored from EventStore on start.
56
- * Override for custom behavior.
57
- *
58
- * @type {boolean | Promise<boolean>}
59
- * @readonly
60
- */
61
- get shouldRestoreView() {
62
- return (this.view instanceof Map)
63
- || (this.view instanceof InMemoryView);
64
- }
65
-
66
- /**
67
- * Creates an instance of AbstractProjection
68
- *
69
- * @param {object} [options]
70
- * @param {any} [options.view]
71
- * @param {ILogger} [options.logger]
72
- */
73
- constructor(options) {
74
- validateHandlers(this);
75
-
76
- if (options && options.view)
77
- this._view = options.view;
78
-
79
- this._logger = (options && options.logger) || nullLogger;
80
- }
81
-
82
- /**
83
- * Subscribe to event store
84
- *
85
- * @param {IEventStore} eventStore
86
- * @return {Promise<void>}
87
- */
88
- async subscribe(eventStore) {
89
- subscribe(eventStore, this, {
90
- masterHandler: e => this.project(e)
91
- });
92
-
93
- await this.restore(eventStore);
94
- }
95
-
96
- /**
97
- * Pass event to projection event handler
98
- *
99
- * @param {IEvent} event
100
- * @returns {Promise<void>}
101
- */
102
- async project(event) {
103
- const concurrentView = asConcurrentView(this.view);
104
- if (concurrentView && !concurrentView.ready)
105
- await concurrentView.once('ready');
106
-
107
- return this._project(event);
108
- }
109
-
110
- /**
111
- * Pass event to projection event handler, without awaiting for restore operation to complete
112
- * @protected
113
- * @param {IEvent} event
114
- * @returns {Promise<void>}
115
- */
116
- async _project(event) {
117
- const handler = getHandler(this, event.type);
118
- if (!handler)
119
- throw new Error(`'${event.type}' handler is not defined or not a function`);
120
-
121
- return handler.call(this, event);
122
- }
123
-
124
- /**
125
- * Restore projection view from event store
126
- *
127
- * @param {IEventStore} eventStore
128
- * @return {Promise<void>}
129
- */
130
- async restore(eventStore) {
131
- // lock the view to ensure same restoring procedure
132
- // won't be performed by another projection instance
133
- const concurrentView = asConcurrentView(this.view);
134
- if (concurrentView)
135
- await concurrentView.lock();
136
-
137
- const shouldRestore = await this.shouldRestoreView;
138
- if (shouldRestore)
139
- await this._restore(eventStore);
140
-
141
- if (concurrentView)
142
- concurrentView.unlock();
143
- }
144
-
145
- /**
146
- * Restore projection view from event store
147
- * @protected
148
- * @param {IEventStore} eventStore
149
- * @return {Promise<void>}
150
- */
151
- async _restore(eventStore) {
152
- /* istanbul ignore if */
153
- if (!eventStore) throw new TypeError('eventStore argument required');
154
- /* istanbul ignore if */
155
- if (typeof eventStore.getAllEvents !== 'function') throw new TypeError('eventStore.getAllEvents must be a Function');
156
-
157
- const service = getClassName(this);
158
- this._logger.log('debug', 'retrieving events and restoring projection...', { service });
159
-
160
- const messageTypes = getHandledMessageTypes(this);
161
- const eventsIterable = eventStore.getAllEvents(messageTypes);
162
-
163
- for await (const event of eventsIterable) {
164
- try {
165
- await this._project(event);
166
- }
167
- catch (err) {
168
- this._onRestoringError(err, event);
169
- }
170
- }
171
-
172
- this._logger.log('info', `view restored (${this.view})`, { service });
173
- }
174
-
175
- /**
176
- * Handle error on restoring
177
- *
178
- * @protected
179
- * @param {Error} error
180
- * @param {IEvent} event
181
- */
182
- _onRestoringError(error, event) {
183
- this._logger.log('error', `view restoring has failed: ${error.message}`, {
184
- service: getClassName(this),
185
- event,
186
- stack: error.stack
187
- });
188
- throw error;
189
- }
190
- }
191
-
192
- module.exports = AbstractProjection;
@@ -1,171 +0,0 @@
1
- 'use strict';
2
-
3
- const { validateHandlers, getHandler, getClassName } = require('./utils');
4
-
5
- const _id = Symbol('id');
6
- const _version = Symbol('version');
7
- const _messages = Symbol('messages');
8
-
9
- /**
10
- * Base class for Saga definition
11
- *
12
- * @class AbstractSaga
13
- * @implements {ISaga}
14
- */
15
- class AbstractSaga {
16
-
17
- /**
18
- * List of events that start new saga, must be overridden in Saga implementation
19
- *
20
- * @type {string[]}
21
- * @readonly
22
- * @static
23
- */
24
- static get startsWith() {
25
- throw new Error('startsWith must be overridden to return a list of event types that start saga');
26
- }
27
-
28
- /**
29
- * List of event types being handled by Saga, must be overridden in Saga implementation
30
- *
31
- * @type {string[]}
32
- * @readonly
33
- * @static
34
- */
35
- static get handles() {
36
- return [];
37
- }
38
-
39
- /**
40
- * Saga ID
41
- *
42
- * @type {string|number}
43
- * @readonly
44
- */
45
- get id() {
46
- return this[_id];
47
- }
48
-
49
- /**
50
- * Saga version
51
- *
52
- * @type {number}
53
- * @readonly
54
- */
55
- get version() {
56
- return this[_version];
57
- }
58
-
59
- /**
60
- * Command execution queue
61
- *
62
- * @type {ICommand[]}
63
- * @readonly
64
- */
65
- get uncommittedMessages() {
66
- return Array.from(this[_messages]);
67
- }
68
-
69
- /**
70
- * Creates an instance of AbstractSaga
71
- *
72
- * @param {TSagaConstructorParams} options
73
- */
74
- constructor(options) {
75
- if (!options) throw new TypeError('options argument required');
76
- if (!options.id) throw new TypeError('options.id argument required');
77
-
78
- this[_id] = options.id;
79
- this[_version] = 0;
80
- this[_messages] = [];
81
-
82
- validateHandlers(this, 'startsWith');
83
- validateHandlers(this, 'handles');
84
-
85
- if (options.events) {
86
- options.events.forEach(e => this.apply(e));
87
- this.resetUncommittedMessages();
88
- }
89
-
90
- Object.defineProperty(this, 'restored', { value: true });
91
- }
92
-
93
- /**
94
- * Modify saga state by applying an event
95
- *
96
- * @param {IEvent} event
97
- * @returns {void|Promise<void>}
98
- */
99
- apply(event) {
100
- if (!event) throw new TypeError('event argument required');
101
- if (!event.type) throw new TypeError('event.type argument required');
102
-
103
- const handler = getHandler(this, event.type);
104
- if (!handler)
105
- throw new Error(`'${event.type}' handler is not defined or not a function`);
106
-
107
- const r = handler.call(this, event);
108
- if (r instanceof Promise) {
109
- return r.then(() => {
110
- this[_version] += 1;
111
- });
112
- }
113
-
114
- this[_version] += 1;
115
- return undefined;
116
- }
117
-
118
- /**
119
- * Format a command and put it to the execution queue
120
- *
121
- * @protected
122
- * @param {string} commandType
123
- * @param {string|number} aggregateId
124
- * @param {object} payload
125
- */
126
- enqueue(commandType, aggregateId, payload) {
127
- if (typeof commandType !== 'string' || !commandType.length)
128
- throw new TypeError('commandType argument must be a non-empty String');
129
- if (!['string', 'number', 'undefined'].includes(typeof aggregateId))
130
- throw new TypeError('aggregateId argument must be either string, number or undefined');
131
-
132
- this.enqueueRaw({
133
- aggregateId,
134
- sagaId: this.id,
135
- sagaVersion: this.version,
136
- type: commandType,
137
- payload
138
- });
139
- }
140
-
141
- /**
142
- * Put a command to the execution queue
143
- *
144
- * @protected
145
- * @param {ICommand} command
146
- */
147
- enqueueRaw(command) {
148
- if (typeof command !== 'object' || !command) throw new TypeError('command argument must be an Object');
149
- if (typeof command.type !== 'string' || !command.type.length) throw new TypeError('command.type argument must be a non-empty String');
150
-
151
- this[_messages].push(command);
152
- }
153
-
154
- /**
155
- * Clear the execution queue
156
- */
157
- resetUncommittedMessages() {
158
- this[_messages].length = 0;
159
- }
160
-
161
- /**
162
- * Get human-readable Saga name
163
- *
164
- * @returns {string}
165
- */
166
- toString() {
167
- return `${getClassName(this)} ${this.id} (v${this.version})`;
168
- }
169
- }
170
-
171
- module.exports = AbstractSaga;