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
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
export type Identifier = string | number;
|
|
2
|
+
|
|
3
|
+
export interface IMessage<TPayload = any> {
|
|
4
|
+
/** Event or command type */
|
|
5
|
+
type: string;
|
|
6
|
+
|
|
7
|
+
aggregateId?: Identifier;
|
|
8
|
+
aggregateVersion?: number;
|
|
9
|
+
|
|
10
|
+
sagaId?: Identifier;
|
|
11
|
+
sagaVersion?: number;
|
|
12
|
+
|
|
13
|
+
payload?: TPayload;
|
|
14
|
+
context?: any;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type ICommand<TPayload = any> = IMessage<TPayload>;
|
|
18
|
+
|
|
19
|
+
export type IEvent<TPayload = any> = IMessage<TPayload> & {
|
|
20
|
+
/** Unique event identifier */
|
|
21
|
+
id?: string;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* @deprecated Try to use `IEventStream` instead
|
|
26
|
+
*/
|
|
27
|
+
export type IEventSet = ReadonlyArray<Readonly<IEvent>>;
|
|
28
|
+
|
|
29
|
+
export type IEventStream = AsyncIterableIterator<Readonly<IEvent>>;
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Minimum aggregate interface, as it's used by default `AggregateCommandHandler`
|
|
34
|
+
*/
|
|
35
|
+
export interface IAggregate {
|
|
36
|
+
|
|
37
|
+
/** Unique aggregate identifier */
|
|
38
|
+
readonly id: Identifier;
|
|
39
|
+
|
|
40
|
+
/** Main entry point for aggregate commands */
|
|
41
|
+
handle(command: ICommand): void | Promise<void>;
|
|
42
|
+
|
|
43
|
+
/** List of events emitted by Aggregate as a result of handling command(s) */
|
|
44
|
+
readonly changes: IEventSet;
|
|
45
|
+
|
|
46
|
+
/** An indicator if aggregate snapshot should be taken */
|
|
47
|
+
readonly shouldTakeSnapshot?: boolean;
|
|
48
|
+
|
|
49
|
+
/** Take an aggregate state snapshot and add it to the changes queue */
|
|
50
|
+
takeSnapshot(): void;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface IMutableAggregateState {
|
|
54
|
+
// schemaVersion?: number;
|
|
55
|
+
// constructor: IAggregateStateConstructor;
|
|
56
|
+
mutate(event: IEvent): void;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// export interface IAggregateStateConstructor extends Function {
|
|
60
|
+
// schemaVersion?: number;
|
|
61
|
+
// new(): IAggregateState;
|
|
62
|
+
// }
|
|
63
|
+
|
|
64
|
+
export type IAggregateConstructorParams<TState extends IMutableAggregateState | object | void> = {
|
|
65
|
+
/** Unique aggregate identifier */
|
|
66
|
+
id: Identifier,
|
|
67
|
+
|
|
68
|
+
/** Aggregate events, logged after latest snapshot */
|
|
69
|
+
events?: IEventSet,
|
|
70
|
+
|
|
71
|
+
/** Aggregate state instance */
|
|
72
|
+
state?: TState
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export interface IAggregateConstructor<TState extends IMutableAggregateState | object | void> {
|
|
76
|
+
readonly handles?: string[];
|
|
77
|
+
new(options: IAggregateConstructorParams<TState>): IAggregate;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export type IAggregateFactory<TState extends IMutableAggregateState | object | void> =
|
|
81
|
+
(options: IAggregateConstructorParams<TState>) => IAggregate;
|
|
82
|
+
|
|
83
|
+
export interface ISaga {
|
|
84
|
+
/** Unique Saga ID */
|
|
85
|
+
readonly id: Identifier;
|
|
86
|
+
|
|
87
|
+
/** List of commands emitted by Saga */
|
|
88
|
+
readonly uncommittedMessages: ICommand[];
|
|
89
|
+
|
|
90
|
+
/** Main entry point for Saga events */
|
|
91
|
+
apply(event: IEvent): void | Promise<void>;
|
|
92
|
+
|
|
93
|
+
/** Reset emitted commands when they are not longer needed */
|
|
94
|
+
resetUncommittedMessages(): void;
|
|
95
|
+
|
|
96
|
+
onError?(error: Error, options: { event: IEvent, command: ICommand }): void;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export type ISagaConstructorParams = {
|
|
100
|
+
id: Identifier,
|
|
101
|
+
events?: IEventSet
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export type ISagaFactory = (options: ISagaConstructorParams) => ISaga;
|
|
105
|
+
|
|
106
|
+
export interface ISagaConstructor {
|
|
107
|
+
new(options: ISagaConstructorParams): ISaga;
|
|
108
|
+
|
|
109
|
+
/** List of event types that trigger new saga start */
|
|
110
|
+
readonly startsWith: string[];
|
|
111
|
+
|
|
112
|
+
/** List of events being handled by Saga */
|
|
113
|
+
readonly handles: string[];
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export interface IMessageHandler {
|
|
117
|
+
(...args: any[]): any | Promise<any>
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export interface IObservable {
|
|
121
|
+
on(type: string, handler: IMessageHandler): void;
|
|
122
|
+
|
|
123
|
+
off(type: string, handler: IMessageHandler): void;
|
|
124
|
+
|
|
125
|
+
queue?(name: string): IObservable;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export interface IObserver {
|
|
129
|
+
subscribe(observable: IObservable): void;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/** Commands */
|
|
133
|
+
|
|
134
|
+
export interface ICommandBus extends IObservable {
|
|
135
|
+
send(commandType: string, aggregateId: Identifier, options: { payload?: object, context?: object }):
|
|
136
|
+
Promise<IEventSet>;
|
|
137
|
+
|
|
138
|
+
sendRaw(command: ICommand):
|
|
139
|
+
Promise<IEventSet>;
|
|
140
|
+
|
|
141
|
+
on(type: string, handler: IMessageHandler): void;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export interface ICommandHandler extends IObserver {
|
|
145
|
+
subscribe(commandBus: ICommandBus): void;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Events */
|
|
149
|
+
|
|
150
|
+
export type IEventQueryFilter = {
|
|
151
|
+
/** Get events emitted after this specific event */
|
|
152
|
+
afterEvent?: IEvent;
|
|
153
|
+
|
|
154
|
+
/** Get events emitted before this specific event */
|
|
155
|
+
beforeEvent?: IEvent;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export interface IEventStorage {
|
|
159
|
+
/**
|
|
160
|
+
* Create unique identifier
|
|
161
|
+
*/
|
|
162
|
+
getNewId(): Identifier | Promise<Identifier>;
|
|
163
|
+
|
|
164
|
+
commitEvents(events: IEventSet): Promise<IEventSet>;
|
|
165
|
+
|
|
166
|
+
getEvents(eventTypes?: Readonly<string[]>): IEventStream;
|
|
167
|
+
|
|
168
|
+
getAggregateEvents(aggregateId: Identifier, options?: { snapshot?: IEvent }): Promise<IEventSet>;
|
|
169
|
+
|
|
170
|
+
getSagaEvents(sagaId: Identifier, options: Pick<IEventQueryFilter, "beforeEvent">): Promise<IEventSet>;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface IEventStore extends IObservable {
|
|
174
|
+
readonly snapshotsSupported?: boolean;
|
|
175
|
+
|
|
176
|
+
getNewId(): Identifier | Promise<Identifier>;
|
|
177
|
+
|
|
178
|
+
commit(events: IEventSet): Promise<IEventSet>;
|
|
179
|
+
|
|
180
|
+
getAllEvents(eventTypes?: Readonly<string[]>): IEventStream;
|
|
181
|
+
|
|
182
|
+
getAggregateEvents(aggregateId: Identifier, options?: { snapshot?: IEvent }): Promise<IEventSet>;
|
|
183
|
+
|
|
184
|
+
getSagaEvents(sagaId: Identifier, options: Pick<IEventQueryFilter, "beforeEvent">): Promise<IEventSet>;
|
|
185
|
+
|
|
186
|
+
once(messageTypes: string | string[], handler?: IMessageHandler, filter?: (e: IEvent) => boolean): Promise<IEvent>;
|
|
187
|
+
|
|
188
|
+
queue(name: string): IObservable;
|
|
189
|
+
|
|
190
|
+
registerSagaStarters(startsWith: string[] | undefined): void;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export interface IEventReceptor extends IObserver {
|
|
194
|
+
subscribe(eventStore: IEventStore): void;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
export interface IMessageBus extends IObservable {
|
|
198
|
+
send(command: ICommand): Promise<any>;
|
|
199
|
+
publish(event: IEvent): Promise<any>;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
/** Projection */
|
|
204
|
+
|
|
205
|
+
export interface IProjection<TView extends object> extends IObserver {
|
|
206
|
+
readonly view: TView;
|
|
207
|
+
|
|
208
|
+
subscribe(eventStore: IEventStore): Promise<void>;
|
|
209
|
+
|
|
210
|
+
project(event: IEvent): Promise<void>;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
export interface IProjectionConstructor {
|
|
214
|
+
new(c?: any): IProjection<any>;
|
|
215
|
+
readonly handles?: string[];
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// export type ProjectionViewFactoryParams = {
|
|
219
|
+
// schemaVersion: string,
|
|
220
|
+
// collectionName: string
|
|
221
|
+
// }
|
|
222
|
+
|
|
223
|
+
export interface IViewFactory<TView> {
|
|
224
|
+
(): TView;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface ILockable {
|
|
228
|
+
lock(): Promise<any>;
|
|
229
|
+
unlock(): Promise<any>;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
export interface ILockableWithIndication extends ILockable {
|
|
233
|
+
locked: Readonly<boolean>;
|
|
234
|
+
once(event: 'unlocked'): Promise<void>;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export interface IProjectionView extends ILockable {
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Indicates if view is ready for new events projecting
|
|
241
|
+
*/
|
|
242
|
+
ready: boolean;
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Lock the view for external reads/writes
|
|
246
|
+
*/
|
|
247
|
+
lock(): Promise<boolean>;
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Unlock external read/write operations
|
|
251
|
+
*/
|
|
252
|
+
unlock(): Promise<void>;
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Wait till the view is ready to accept new events
|
|
256
|
+
*/
|
|
257
|
+
once(eventType: "ready"): Promise<void>;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export interface IPersistentView extends IProjectionView {
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* Get last projected event
|
|
264
|
+
*/
|
|
265
|
+
getLastEvent(): Promise<IEvent | undefined>;
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Mark event as projecting to prevent its handling by another
|
|
269
|
+
* projection instance working with the same storage.
|
|
270
|
+
*
|
|
271
|
+
* @returns False value if event is already processing or processed
|
|
272
|
+
*/
|
|
273
|
+
tryMarkAsProjecting(event: IEvent<any>): Promise<boolean>;
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Mark event as projected
|
|
277
|
+
*/
|
|
278
|
+
markAsProjected(event: IEvent<any>): Promise<void>;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
/** Snapshots */
|
|
283
|
+
|
|
284
|
+
type TSnapshot<TPayload = object> = {
|
|
285
|
+
/**
|
|
286
|
+
* Schema version of the data stored in `state` property.
|
|
287
|
+
* Snapshots with older schema versions must be passed thru a data migration before applying for a newer schema
|
|
288
|
+
*/
|
|
289
|
+
schemaVersion: string | number;
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Last event that was processed before making a snapshot
|
|
293
|
+
*/
|
|
294
|
+
lastEvent: IEvent;
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Snapshot data
|
|
298
|
+
*/
|
|
299
|
+
data: TPayload;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
interface ISnapshotStorage {
|
|
303
|
+
getSnapshot(id: Identifier): Promise<TSnapshot>;
|
|
304
|
+
saveSnapshot(id: Identifier, snapshot: TSnapshot): Promise<void>;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
type ISnapshotEvent<TPayload> = IEvent<TSnapshot<TPayload>>;
|
|
308
|
+
|
|
309
|
+
export interface IAggregateSnapshotStorage {
|
|
310
|
+
getAggregateSnapshot<TState>(aggregateId: Identifier): Promise<IEvent<TState> | undefined> | IEvent<TState> | undefined;
|
|
311
|
+
|
|
312
|
+
saveAggregateSnapshot<TState>(snapshotEvent: IEvent<TState>): Promise<void> | void;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
/** Interfaces */
|
|
317
|
+
|
|
318
|
+
export interface ILogger {
|
|
319
|
+
log(level: 'debug' | 'info' | 'warn' | 'error', message: string, meta?: { [key: string]: any }): void;
|
|
320
|
+
debug(message: string, meta?: { [key: string]: any }): void;
|
|
321
|
+
info(message: string, meta?: { [key: string]: any }): void;
|
|
322
|
+
warn(message: string, meta?: { [key: string]: any }): void;
|
|
323
|
+
error(message: string, meta?: { [key: string]: any }): void;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export interface IExtendableLogger extends ILogger {
|
|
327
|
+
child(meta?: { [key: string]: any }): IExtendableLogger;
|
|
328
|
+
}
|
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const getMessageHandlerNames = require('./getMessageHandlerNames');
|
|
1
|
+
import { getMessageHandlerNames } from './getMessageHandlerNames';
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* Get a list of message types handled by observer
|
|
7
|
-
* @param {object | function} observerInstanceOrClass
|
|
8
|
-
* @returns {string[]}
|
|
9
5
|
*/
|
|
10
|
-
function getHandledMessageTypes(
|
|
6
|
+
export function getHandledMessageTypes(
|
|
7
|
+
observerInstanceOrClass: (object | Function) & { handles?: string[] }
|
|
8
|
+
): string[] {
|
|
11
9
|
if (!observerInstanceOrClass)
|
|
12
10
|
throw new TypeError('observerInstanceOrClass argument required');
|
|
13
11
|
|
|
@@ -20,5 +18,3 @@ function getHandledMessageTypes(observerInstanceOrClass) {
|
|
|
20
18
|
|
|
21
19
|
return getMessageHandlerNames(observerInstanceOrClass);
|
|
22
20
|
}
|
|
23
|
-
|
|
24
|
-
module.exports = getHandledMessageTypes;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
import { IMessageHandler } from "../interfaces";
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Gets a handler for a specific message type, prefers a public (w\o _ prefix) method, if available
|
|
5
|
-
* @param {Object} context
|
|
6
|
-
* @param {String} messageType
|
|
7
|
-
* @return {IMessageHandler}
|
|
8
5
|
*/
|
|
9
|
-
|
|
10
|
-
if (!context || typeof context !== 'object')
|
|
11
|
-
|
|
6
|
+
export function getHandler(context: { [key: string]: any }, messageType: string): IMessageHandler | null {
|
|
7
|
+
if (!context || typeof context !== 'object')
|
|
8
|
+
throw new TypeError('context argument required');
|
|
9
|
+
if (typeof messageType !== 'string' || !messageType.length)
|
|
10
|
+
throw new TypeError('messageType argument must be a non-empty string');
|
|
12
11
|
|
|
13
12
|
if (messageType in context && typeof context[messageType] === 'function')
|
|
14
13
|
return context[messageType].bind(context);
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
1
|
const KNOWN_METHOD_NAMES = new Set([
|
|
4
2
|
'subscribe'
|
|
5
3
|
]);
|
|
6
4
|
|
|
7
|
-
function getInheritedPropertyNames(prototype) {
|
|
5
|
+
function getInheritedPropertyNames(prototype: object): string[] {
|
|
8
6
|
const parentPrototype = prototype && Object.getPrototypeOf(prototype);
|
|
9
7
|
if (!parentPrototype)
|
|
10
8
|
return [];
|
|
@@ -21,11 +19,8 @@ function getInheritedPropertyNames(prototype) {
|
|
|
21
19
|
/**
|
|
22
20
|
* Get message handler names from a command/event handler class.
|
|
23
21
|
* Assumes all private method names start from underscore ("_").
|
|
24
|
-
*
|
|
25
|
-
* @param {any} observerInstanceOrClass Command or event handler class
|
|
26
|
-
* @returns {string[]}
|
|
27
22
|
*/
|
|
28
|
-
function getMessageHandlerNames(observerInstanceOrClass) {
|
|
23
|
+
export function getMessageHandlerNames(observerInstanceOrClass: (object | Function)): string[] {
|
|
29
24
|
if (!observerInstanceOrClass)
|
|
30
25
|
throw new TypeError('observerInstanceOrClass argument required');
|
|
31
26
|
|
|
@@ -47,5 +42,3 @@ function getMessageHandlerNames(observerInstanceOrClass) {
|
|
|
47
42
|
!KNOWN_METHOD_NAMES.has(key) &&
|
|
48
43
|
typeof propDescriptors[key].value === 'function');
|
|
49
44
|
}
|
|
50
|
-
|
|
51
|
-
module.exports = getMessageHandlerNames;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export * from './getClassName';
|
|
2
|
+
export * from './getHandler';
|
|
3
|
+
export * from './validateHandlers';
|
|
4
|
+
export * from './getMessageHandlerNames';
|
|
5
|
+
export * from './getHandledMessageTypes';
|
|
6
|
+
export * from './setupOneTimeEmitterSubscription';
|
|
7
|
+
export * from './subscribe';
|
|
8
|
+
export * from './isClass';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { IEvent, ILogger, IObservable } from "../interfaces";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Create one-time eventEmitter subscription for one or multiple events that match a filter
|
|
5
|
+
*
|
|
6
|
+
* @param {IObservable} emitter
|
|
7
|
+
* @param {string[]} messageTypes Array of event type to subscribe to
|
|
8
|
+
* @param {function(IEvent):any} [handler] Optional handler to execute for a first event received
|
|
9
|
+
* @param {function(IEvent):boolean} [filter] Optional filter to apply before executing a handler
|
|
10
|
+
* @param {ILogger} logger
|
|
11
|
+
* @return {Promise<IEvent>} Resolves to first event that passes filter
|
|
12
|
+
*/
|
|
13
|
+
export function setupOneTimeEmitterSubscription(
|
|
14
|
+
emitter: IObservable,
|
|
15
|
+
messageTypes: string[],
|
|
16
|
+
filter?: (e: IEvent) => boolean,
|
|
17
|
+
handler?: (e: IEvent) => void,
|
|
18
|
+
logger?: ILogger
|
|
19
|
+
): Promise<IEvent> {
|
|
20
|
+
if (typeof emitter !== 'object' || !emitter)
|
|
21
|
+
throw new TypeError('emitter argument must be an Object');
|
|
22
|
+
if (!Array.isArray(messageTypes) || messageTypes.some(m => !m || typeof m !== 'string'))
|
|
23
|
+
throw new TypeError('messageTypes argument must be an Array of non-empty Strings');
|
|
24
|
+
if (handler && typeof handler !== 'function')
|
|
25
|
+
throw new TypeError('handler argument, when specified, must be a Function');
|
|
26
|
+
if (filter && typeof filter !== 'function')
|
|
27
|
+
throw new TypeError('filter argument, when specified, must be a Function');
|
|
28
|
+
|
|
29
|
+
return new Promise(resolve => {
|
|
30
|
+
|
|
31
|
+
// handler will be invoked only once,
|
|
32
|
+
// even if multiple events have been emitted before subscription was destroyed
|
|
33
|
+
// https://nodejs.org/api/events.html#events_emitter_removelistener_eventname_listener
|
|
34
|
+
let handled = false;
|
|
35
|
+
|
|
36
|
+
function filteredHandler(event: IEvent) {
|
|
37
|
+
if (filter && !filter(event)) return;
|
|
38
|
+
if (handled) return;
|
|
39
|
+
handled = true;
|
|
40
|
+
|
|
41
|
+
for (const messageType of messageTypes)
|
|
42
|
+
emitter.off(messageType, filteredHandler);
|
|
43
|
+
|
|
44
|
+
logger?.debug(`'${event.type}' received, one-time subscription to '${messageTypes.join(',')}' removed`);
|
|
45
|
+
|
|
46
|
+
if (handler)
|
|
47
|
+
handler(event);
|
|
48
|
+
|
|
49
|
+
resolve(event);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
for (const messageType of messageTypes)
|
|
53
|
+
emitter.on(messageType, filteredHandler);
|
|
54
|
+
|
|
55
|
+
logger?.debug(`set up one-time ${filter ? 'filtered subscription' : 'subscription'} to '${messageTypes.join(',')}'`);
|
|
56
|
+
});
|
|
57
|
+
}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
import { IMessageHandler, IObservable } from "../interfaces";
|
|
2
|
+
import { getHandler } from './getHandler';
|
|
3
|
+
import { getHandledMessageTypes } from './getHandledMessageTypes';
|
|
2
4
|
|
|
3
|
-
const
|
|
4
|
-
const getHandledMessageTypes = require('./utils/getHandledMessageTypes');
|
|
5
|
-
|
|
6
|
-
const unique = arr => [...new Set(arr)];
|
|
5
|
+
const unique = <T>(arr: T[]): T[] => [...new Set(arr)];
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Subscribe observer to observable
|
|
10
|
-
*
|
|
11
|
-
* @param {IObservable} observable
|
|
12
|
-
* @param {object} observer
|
|
13
|
-
* @param {object} [options]
|
|
14
|
-
* @param {string[]} [options.messageTypes]
|
|
15
|
-
* @param {IMessageHandler} [options.masterHandler]
|
|
16
|
-
* @param {string} [options.queueName]
|
|
17
9
|
*/
|
|
18
|
-
function subscribe(
|
|
10
|
+
export function subscribe(
|
|
11
|
+
observable: IObservable,
|
|
12
|
+
observer: object,
|
|
13
|
+
options: {
|
|
14
|
+
messageTypes?: string[],
|
|
15
|
+
masterHandler?: IMessageHandler,
|
|
16
|
+
queueName?: string
|
|
17
|
+
} = {}
|
|
18
|
+
) {
|
|
19
19
|
if (typeof observable !== 'object' || !observable)
|
|
20
20
|
throw new TypeError('observable argument must be an Object');
|
|
21
21
|
if (typeof observable.on !== 'function')
|
|
@@ -35,14 +35,17 @@ function subscribe(observable, observer, options = {}) {
|
|
|
35
35
|
|
|
36
36
|
for (const messageType of unique(subscribeTo)) {
|
|
37
37
|
const handler = masterHandler || getHandler(observer, messageType);
|
|
38
|
-
|
|
38
|
+
if (!handler)
|
|
39
39
|
throw new Error(`'${messageType}' handler is not defined or not a function`);
|
|
40
40
|
|
|
41
|
-
if (queueName)
|
|
41
|
+
if (queueName) {
|
|
42
|
+
if(!observable.queue)
|
|
43
|
+
throw new TypeError('Observer does not support named queues');
|
|
44
|
+
|
|
42
45
|
observable.queue(queueName).on(messageType, handler);
|
|
43
|
-
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
44
48
|
observable.on(messageType, handler);
|
|
49
|
+
}
|
|
45
50
|
}
|
|
46
51
|
}
|
|
47
|
-
|
|
48
|
-
module.exports = subscribe;
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const getHandler = require('./getHandler');
|
|
1
|
+
import { getHandler } from './getHandler';
|
|
4
2
|
|
|
5
3
|
/**
|
|
6
4
|
* Ensure instance has handlers declared for all handled message types
|
|
7
|
-
*
|
|
8
|
-
* @param {object} instance
|
|
9
5
|
*/
|
|
10
|
-
function validateHandlers(instance, handlesFieldName = 'handles') {
|
|
6
|
+
export function validateHandlers(instance: object, handlesFieldName = 'handles') {
|
|
11
7
|
if (!instance) throw new TypeError('instance argument required');
|
|
12
8
|
|
|
13
9
|
const messageTypes = Object.getPrototypeOf(instance).constructor[handlesFieldName];
|
|
@@ -21,5 +17,3 @@ function validateHandlers(instance, handlesFieldName = 'handles') {
|
|
|
21
17
|
throw new Error(`'${type}' handler is not defined or not a function`);
|
|
22
18
|
}
|
|
23
19
|
}
|
|
24
|
-
|
|
25
|
-
module.exports = validateHandlers;
|
package/index.d.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
export * from "./types/interfaces/IAggregate";
|
|
2
|
-
export * from "./types/interfaces/IAggregateSnapshotStorage";
|
|
3
|
-
export * from "./types/interfaces/ICommandBus";
|
|
4
|
-
export * from "./types/interfaces/ICommandHandler";
|
|
5
|
-
export * from "./types/interfaces/IConcurrentView";
|
|
6
|
-
export * from "./types/interfaces/Identifier";
|
|
7
|
-
export * from "./types/interfaces/IEventReceptor";
|
|
8
|
-
export * from "./types/interfaces/IEventStorage";
|
|
9
|
-
export * from "./types/interfaces/IEventStore";
|
|
10
|
-
export * from "./types/interfaces/IEventStream";
|
|
11
|
-
export * from "./types/interfaces/ILogger";
|
|
12
|
-
export * from "./types/interfaces/IMessageBus";
|
|
13
|
-
export * from "./types/interfaces/IObserver";
|
|
14
|
-
export * from "./types/interfaces/IProjection";
|
|
15
|
-
export * from "./types/interfaces/ISaga";
|
|
16
|
-
export * from "./types/classes/AbstractAggregate";
|
|
17
|
-
export * from "./types/classes/AbstractProjection";
|
|
18
|
-
export * from "./types/classes/AbstractSaga";
|
|
19
|
-
export * from "./types/classes/AggregateCommandHandler";
|
|
20
|
-
export * from "./types/classes/CommandBus";
|
|
21
|
-
export * from "./types/classes/CqrsContainerBuilder";
|
|
22
|
-
export * from "./types/classes/EventStore";
|
|
23
|
-
export * from "./types/classes/EventStream";
|
|
24
|
-
export * from "./types/classes/SagaEventHandler";
|
|
25
|
-
|
|
26
|
-
export var AbstractAggregate: typeof NodeCqrs.AbstractAggregate;
|
|
27
|
-
export var AbstractProjection: typeof NodeCqrs.AbstractProjection;
|
|
28
|
-
export var AbstractSaga: typeof NodeCqrs.AbstractSaga;
|
|
29
|
-
export var AggregateCommandHandler: typeof NodeCqrs.AggregateCommandHandler;
|
|
30
|
-
export var CommandBus: typeof NodeCqrs.CommandBus;
|
|
31
|
-
export var ContainerBuilder: typeof NodeCqrs.CqrsContainerBuilder;
|
|
32
|
-
export var EventStore: typeof NodeCqrs.EventStore;
|
|
33
|
-
export var EventStream: typeof NodeCqrs.EventStream;
|
|
34
|
-
export var InMemoryEventStorage: typeof NodeCqrs.InMemoryEventStorage;
|
|
35
|
-
export var InMemoryMessageBus: typeof NodeCqrs.InMemoryMessageBus;
|
|
36
|
-
export var InMemorySnapshotStorage: typeof NodeCqrs.InMemorySnapshotStorage;
|
|
37
|
-
export var InMemoryView: typeof NodeCqrs.InMemoryView;
|
|
38
|
-
export var SagaEventHandler: typeof NodeCqrs.SagaEventHandler;
|
|
39
|
-
|
|
40
|
-
export {
|
|
41
|
-
getMessageHandlerNames,
|
|
42
|
-
subscribe
|
|
43
|
-
} from "./src";
|
package/index.js
DELETED
package/jsconfig.json
DELETED