node-cqrs 1.1.0-alpha.0 → 1.1.0-alpha.2

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 (101) hide show
  1. package/CHANGELOG.md +8 -2
  2. package/README.md +100 -88
  3. package/dist/cjs/EventDispatchPipeline.js +12 -2
  4. package/dist/cjs/EventDispatchPipeline.js.map +1 -1
  5. package/dist/cjs/EventDispatcher.js +17 -1
  6. package/dist/cjs/EventDispatcher.js.map +1 -1
  7. package/dist/cjs/EventStore.js +4 -0
  8. package/dist/cjs/EventStore.js.map +1 -1
  9. package/dist/cjs/mongodb/AbstractMongoAccessor.js +51 -0
  10. package/dist/cjs/mongodb/AbstractMongoAccessor.js.map +1 -0
  11. package/dist/cjs/mongodb/AbstractMongoObjectProjection.js +26 -0
  12. package/dist/cjs/mongodb/AbstractMongoObjectProjection.js.map +1 -0
  13. package/dist/cjs/mongodb/AbstractMongoView.js +57 -0
  14. package/dist/cjs/mongodb/AbstractMongoView.js.map +1 -0
  15. package/dist/cjs/mongodb/MongoEventLocker.js +104 -0
  16. package/dist/cjs/mongodb/MongoEventLocker.js.map +1 -0
  17. package/dist/cjs/mongodb/MongoObjectStorage.js +101 -0
  18. package/dist/cjs/mongodb/MongoObjectStorage.js.map +1 -0
  19. package/dist/cjs/mongodb/MongoObjectView.js +41 -0
  20. package/dist/cjs/mongodb/MongoObjectView.js.map +1 -0
  21. package/dist/cjs/mongodb/MongoProjectionDataParams.js +3 -0
  22. package/dist/cjs/mongodb/MongoProjectionDataParams.js.map +1 -0
  23. package/dist/cjs/mongodb/MongoViewLocker.js +136 -0
  24. package/dist/cjs/mongodb/MongoViewLocker.js.map +1 -0
  25. package/dist/cjs/mongodb/index.js +24 -3
  26. package/dist/cjs/mongodb/index.js.map +1 -1
  27. package/dist/cjs/mongodb/utils/getEventId.js +14 -0
  28. package/dist/cjs/mongodb/utils/getEventId.js.map +1 -0
  29. package/dist/cjs/mongodb/utils/index.js +18 -0
  30. package/dist/cjs/mongodb/utils/index.js.map +1 -0
  31. package/dist/cjs/rabbitmq/RabbitMqCommandBus.js +4 -1
  32. package/dist/cjs/rabbitmq/RabbitMqCommandBus.js.map +1 -1
  33. package/dist/cjs/redis/RedisObjectStorage.js +6 -6
  34. package/dist/cjs/redis/RedisObjectStorage.js.map +1 -1
  35. package/dist/cjs/redis/RedisView.js.map +1 -1
  36. package/dist/cjs/sqlite/AbstractSqliteView.js.map +1 -1
  37. package/dist/cjs/sqlite/SqliteObjectStorage.js +6 -6
  38. package/dist/cjs/sqlite/SqliteObjectStorage.js.map +1 -1
  39. package/dist/cjs/sqlite/SqliteObjectView.js.map +1 -1
  40. package/dist/esm/EventDispatchPipeline.js +12 -2
  41. package/dist/esm/EventDispatchPipeline.js.map +1 -1
  42. package/dist/esm/EventDispatcher.js +18 -2
  43. package/dist/esm/EventDispatcher.js.map +1 -1
  44. package/dist/esm/EventStore.js +4 -0
  45. package/dist/esm/EventStore.js.map +1 -1
  46. package/dist/esm/mongodb/AbstractMongoAccessor.js +47 -0
  47. package/dist/esm/mongodb/AbstractMongoAccessor.js.map +1 -0
  48. package/dist/esm/mongodb/AbstractMongoObjectProjection.js +22 -0
  49. package/dist/esm/mongodb/AbstractMongoObjectProjection.js.map +1 -0
  50. package/dist/esm/mongodb/AbstractMongoView.js +53 -0
  51. package/dist/esm/mongodb/AbstractMongoView.js.map +1 -0
  52. package/dist/esm/mongodb/MongoEventLocker.js +100 -0
  53. package/dist/esm/mongodb/MongoEventLocker.js.map +1 -0
  54. package/dist/esm/mongodb/MongoObjectStorage.js +97 -0
  55. package/dist/esm/mongodb/MongoObjectStorage.js.map +1 -0
  56. package/dist/esm/mongodb/MongoObjectView.js +37 -0
  57. package/dist/esm/mongodb/MongoObjectView.js.map +1 -0
  58. package/dist/esm/mongodb/MongoProjectionDataParams.js +2 -0
  59. package/dist/esm/mongodb/MongoProjectionDataParams.js.map +1 -0
  60. package/dist/esm/mongodb/MongoViewLocker.js +132 -0
  61. package/dist/esm/mongodb/MongoViewLocker.js.map +1 -0
  62. package/dist/esm/mongodb/index.js +10 -1
  63. package/dist/esm/mongodb/index.js.map +1 -1
  64. package/dist/esm/mongodb/utils/getEventId.js +10 -0
  65. package/dist/esm/mongodb/utils/getEventId.js.map +1 -0
  66. package/dist/esm/mongodb/utils/index.js +2 -0
  67. package/dist/esm/mongodb/utils/index.js.map +1 -0
  68. package/dist/esm/rabbitmq/RabbitMqCommandBus.js +4 -1
  69. package/dist/esm/rabbitmq/RabbitMqCommandBus.js.map +1 -1
  70. package/dist/esm/redis/RedisObjectStorage.js +7 -7
  71. package/dist/esm/redis/RedisObjectStorage.js.map +1 -1
  72. package/dist/esm/redis/RedisView.js.map +1 -1
  73. package/dist/esm/sqlite/AbstractSqliteView.js.map +1 -1
  74. package/dist/esm/sqlite/SqliteObjectStorage.js +7 -7
  75. package/dist/esm/sqlite/SqliteObjectStorage.js.map +1 -1
  76. package/dist/esm/sqlite/SqliteObjectView.js.map +1 -1
  77. package/dist/types/EventDispatchPipeline.d.ts +3 -1
  78. package/dist/types/EventDispatcher.d.ts +8 -0
  79. package/dist/types/EventStore.d.ts +2 -0
  80. package/dist/types/interfaces/IEventDispatcher.d.ts +3 -0
  81. package/dist/types/mongodb/AbstractMongoAccessor.d.ts +26 -0
  82. package/dist/types/mongodb/AbstractMongoObjectProjection.d.ts +8 -0
  83. package/dist/types/mongodb/AbstractMongoView.d.ts +25 -0
  84. package/dist/types/mongodb/IContainer.d.ts +2 -0
  85. package/dist/types/mongodb/MongoEventLocker.d.ts +47 -0
  86. package/dist/types/mongodb/MongoObjectStorage.d.ts +26 -0
  87. package/dist/types/mongodb/MongoObjectView.d.ts +16 -0
  88. package/dist/types/mongodb/MongoProjectionDataParams.d.ts +14 -0
  89. package/dist/types/mongodb/MongoViewLocker.d.ts +43 -0
  90. package/dist/types/mongodb/index.d.ts +10 -1
  91. package/dist/types/mongodb/utils/getEventId.d.ts +5 -0
  92. package/dist/types/mongodb/utils/index.d.ts +1 -0
  93. package/dist/types/rabbitmq/IContainer.d.ts +2 -2
  94. package/dist/types/rabbitmq/RabbitMqCommandBus.d.ts +1 -0
  95. package/dist/types/redis/RedisObjectStorage.d.ts +6 -6
  96. package/dist/types/redis/RedisView.d.ts +8 -8
  97. package/dist/types/sqlite/AbstractSqliteView.d.ts +2 -2
  98. package/dist/types/sqlite/SqliteObjectStorage.d.ts +7 -7
  99. package/dist/types/sqlite/SqliteObjectView.d.ts +7 -7
  100. package/dist/types/sqlite/utils/getEventId.d.ts +1 -1
  101. package/package.json +4 -3
package/CHANGELOG.md CHANGED
@@ -1,4 +1,4 @@
1
- # [1.1.0-alpha.0](https://github.com/snatalenko/node-cqrs/compare/v1.0.0-beta.1...v1.1.0-alpha.0) (2026-03-21)
1
+ # [1.1.0-alpha.2](https://github.com/snatalenko/node-cqrs/compare/v1.0.0...v1.1.0-alpha.2) (2026-03-24)
2
2
 
3
3
 
4
4
  ### Features
@@ -8,11 +8,15 @@
8
8
  * Redis-backed projection views with distributed locking (experimental) ([8ff0f1e](https://github.com/snatalenko/node-cqrs/commit/8ff0f1e14a6fdcd676d549a9d4c7ad2d2ce7cd4c))
9
9
  * SqliteEventStorage ([ffaf766](https://github.com/snatalenko/node-cqrs/commit/ffaf7669139e797488c50332cac94a234738cc62))
10
10
  * MongoDB-backed event storage ([53fb5e1](https://github.com/snatalenko/node-cqrs/commit/53fb5e1c0d7a027f9afebf88f8d3d516d06c3c48))
11
+ * MongoDb-backed view model (`MongoObjectView`, `AbstractMongoObjectProjection`) ([4995bfe](https://github.com/snatalenko/node-cqrs/commit/4995bfe2daf53372d3e7e36d59ee103219ad6a35))
11
12
 
12
13
  ### Changes
13
14
 
14
15
  * Remove "md5" from peer dependencies ([87600bc](https://github.com/snatalenko/node-cqrs/commit/87600bc5a857b0e251ceed37d99cc5cf66f61ee5))
15
16
  * Expose `restorePromises` on DI container for tracking async projection restoring processes ([ebdaa2c](https://github.com/snatalenko/node-cqrs/commit/ebdaa2ca4ff6d1088deba5d4069d7a027be65107))
17
+ * Use `Identifier` as id type in redis and sqlite views ([dfbe964](https://github.com/snatalenko/node-cqrs/commit/dfbe9648a8ea8e7e5550aa40e0094ca8af1758ef))
18
+ * Add default queueName for RabbitMqCommandBus ([ee4b5a1](https://github.com/snatalenko/node-cqrs/commit/ee4b5a170e44db6227e76d2ffb1695b6dfaef6e4))
19
+ * Add error handling and drain functionality to event publishing process ([d23ea62](https://github.com/snatalenko/node-cqrs/commit/d23ea621c8a71e2cda4baaf091166534c4f5af2e))
16
20
 
17
21
  ### Fixes
18
22
 
@@ -22,9 +26,11 @@
22
26
 
23
27
  * Remove readme code samples in favor of runnable ./examples/ ([73417c3](https://github.com/snatalenko/node-cqrs/commit/73417c3b997f2d838b02dd0b91f05e0a6001e556))
24
28
  * Rearrange examples to use same aggregate and projection implementation ([5325901](https://github.com/snatalenko/node-cqrs/commit/532590143fd29a205b6eb3fd4d6c686b17956835))
29
+ * Add detailed documentation for redis and mongodb modules ([72e66f5](https://github.com/snatalenko/node-cqrs/commit/72e66f5508a6df6c0a4a341e752cfab76830478a))
30
+ * Detailed sqlite and rabbitmq instructions ([dd242fd](https://github.com/snatalenko/node-cqrs/commit/dd242fd73018bcfa0583ab1ddd12518c4f3a4777))
25
31
 
26
32
 
27
- # [1.0.0-beta.1](https://github.com/snatalenko/node-cqrs/compare/v0.17.0...v1.0.0-beta.1) (2026-03-21)
33
+ # [1.0.0](https://github.com/snatalenko/node-cqrs/compare/v0.17.0...v1.0.0) (2026-03-21)
28
34
 
29
35
 
30
36
  ### Features
package/README.md CHANGED
@@ -33,22 +33,20 @@ Built around ES6/TypeScript classes and dependency injection - swap implementati
33
33
  - [Installation](#installation)
34
34
  - [ContainerBuilder](#containerbuilder)
35
35
  - [Commands](#commands)
36
- - [Aggregates (write model)](#aggregates-write-model)
36
+ - [Write Model (Aggregates)](#write-model-aggregates)
37
37
  - [AbstractAggregate](#abstractaggregate)
38
38
  - [Aggregate State](#aggregate-state)
39
39
  - [External Dependencies](#external-dependencies)
40
- - [Projections and Views (read model)](#projections-and-views-read-model)
40
+ - [Read Model (Projections and Views)](#read-model-projections-and-views)
41
41
  - [AbstractProjection](#abstractprojection)
42
42
  - [View restoring on start](#view-restoring-on-start)
43
43
  - [Accessing views](#accessing-views)
44
44
  - [Sagas](#sagas)
45
- - [Infrastructure modules](#infrastructure-modules)
46
- - [In-memory](#in-memory)
47
- - [SQLite](#sqlite)
48
- - [Redis](#redis)
49
- - [RabbitMQ](#rabbitmq)
50
- - [Workers](#workers)
51
- - [MongoDB](#mongodb)
45
+ - [Infrastructure Modules](#infrastructure-modules)
46
+ - [Event Storage](#event-storage)
47
+ - [Read Model](#read-model)
48
+ - [Message Buses](#message-buses)
49
+ - [Other](#other)
52
50
  - [OpenTelemetry](#opentelemetry)
53
51
  - [Examples](#examples)
54
52
 
@@ -75,15 +73,15 @@ interface IMessage<TPayload = any> {
75
73
 
76
74
  Domain logic lives in three building blocks:
77
75
 
78
- - **[Aggregates](#aggregates-write-model)** - handle commands and emit events
79
- - **[Projections](#projections-and-views-read-model)** - consume events and update views
76
+ - **[Aggregates](#write-model-aggregates)** - handle commands and emit events
77
+ - **[Projections](#read-model-projections-and-views)** - consume events and update views
80
78
  - **[Sagas](#sagas)** - manage processes by reacting to events and enqueueing follow-up commands
81
79
 
82
80
  Message delivery is handled by the following components, in order:
83
81
 
84
82
  - **[Command Bus](src/in-memory/InMemoryMessageBus.ts)** - routes commands to handlers
85
83
  - **[Aggregate Command Handler](src/AggregateCommandHandler.ts)** - restores aggregate state and executes commands
86
- - **[Event Store](src/EventStore.ts)** runs the event dispatch pipeline (e.g. encoding, persistence), then publishes events to the event bus for delivery to all subscribers
84
+ - **[Event Store](src/EventStore.ts)** - runs the event dispatch pipeline (e.g. encoding, persistence), then publishes events to the event bus for delivery to all subscribers
87
85
  - **[Saga Event Handler](src/SagaEventHandler.ts)** - restores saga state and applies events
88
86
 
89
87
  > `src/`, `tests/`, and `examples/` are good entry points - the codebase is intentionally small and readable.
@@ -150,10 +148,10 @@ commandBus.send('signupUser', undefined, { payload: { profile, password } });
150
148
  commandBus.send({ type: 'signupUser', payload: { profile, password } });
151
149
  ```
152
150
 
153
- Commands are handled by [Aggregates](#aggregates-write-model) and may also be enqueued by [Sagas](#sagas).
151
+ Commands are handled by [Aggregates](#write-model-aggregates) and may also be enqueued by [Sagas](#sagas).
154
152
 
155
153
 
156
- ## Aggregates (write model)
154
+ ## Write Model (Aggregates)
157
155
 
158
156
  Aggregates handle commands, validate business rules, and emit events.
159
157
  Minimal contract ([IAggregate](src/interfaces/IAggregate.ts)):
@@ -245,7 +243,7 @@ builder.registerAggregate(UserAggregate);
245
243
  ```
246
244
 
247
245
 
248
- ## Projections and Views (read model)
246
+ ## Read Model (Projections and Views)
249
247
 
250
248
  Projections listen to events and update views.
251
249
  Minimal contract ([IProjection](src/interfaces/IProjection.ts)):
@@ -270,14 +268,18 @@ interface IProjection<TView> extends IObserver {
270
268
  Same name-matching rule as AbstractAggregate - `userCreated()` handles the `userCreated` event:
271
269
 
272
270
  ```ts
273
- class UsersProjection extends AbstractProjection<Map<string, { username: string }>> {
271
+ class UsersProjection extends AbstractProjection<Map<string, {
272
+ username: string
273
+ }>> {
274
274
  constructor() {
275
275
  super();
276
276
  this.view = new Map();
277
277
  }
278
278
 
279
279
  userCreated(event: IEvent<UserCreatedEventPayload>) {
280
- this.view.set(event.aggregateId as string, { username: event.payload.username });
280
+ this.view.set(event.aggregateId, {
281
+ username: event.payload.username
282
+ });
281
283
  }
282
284
  }
283
285
  ```
@@ -291,7 +293,8 @@ For persistent views and safe restarts, implement [IViewLocker](src/interfaces/I
291
293
  ### Accessing views
292
294
 
293
295
  ```ts
294
- interface IMyContainer extends IContainer { // optional interface for container typing
296
+ // optional interface for container typing
297
+ interface IMyContainer extends IContainer {
295
298
  usersView: UsersView;
296
299
  }
297
300
 
@@ -317,7 +320,9 @@ Sagas coordinate multi-step processes by reacting to events and enqueueing follo
317
320
  ```ts
318
321
  class WelcomeEmailSaga extends AbstractSaga {
319
322
  userSignedUp(event) {
320
- this.enqueue('sendWelcomeEmail', undefined, { email: event.payload.email });
323
+ this.enqueue('sendWelcomeEmail', undefined, {
324
+ email: event.payload.email
325
+ });
321
326
  }
322
327
  }
323
328
 
@@ -387,95 +392,101 @@ interface ISaga {
387
392
  ```
388
393
 
389
394
 
390
- ## Infrastructure modules
395
+ ## Infrastructure Modules
391
396
 
392
- | Module | Import | Peer dependencies | Use case |
393
- |--------|--------|-------------------|----------|
394
- | In-memory | `node-cqrs` | | Tests and local development |
395
- | SQLite | `node-cqrs/sqlite` | `better-sqlite3` | Persistent views with catch-up |
396
- | Redis | `node-cqrs/redis` | `ioredis` | Distributed persistent views with catch-up |
397
- | RabbitMQ | `node-cqrs/rabbitmq` | `amqplib` | Cross-process event distribution |
398
- | Workers | `node-cqrs/workers` | `comlink` | CPU-heavy projections in worker threads |
399
- | MongoDB | `node-cqrs/mongodb` | `mongodb` | Persistent event storage with concurrency control |
397
+ Swap implementations by registering different classes in the DI container.
398
+ All modules below implement the same interfaces - pick what fits your deployment.
400
399
 
401
- ### In-memory
400
+ ### Event Storage
402
401
 
403
- ```ts
404
- import {
405
- InMemoryEventStorage, // event storage + identifier provider
406
- InMemoryMessageBus, // event/command bus
407
- InMemoryView, // in-memory view with locking support
408
- InMemoryLock, // in-memory lock
409
- InMemorySnapshotStorage // aggregate snapshot storage
410
- } from 'node-cqrs';
411
- ```
402
+ Where aggregate events are persisted and replayed from.
412
403
 
413
- See [examples/user-domain-ts/index.ts](examples/user-domain-ts/index.ts) for a DI-based example and
414
- [examples/user-domain-framework-free/index.ts](examples/user-domain-framework-free/index.ts) for a plain implementation.
404
+ | Implementation | Import | Peer deps | Notes |
405
+ | ---------------------- | ------------------- | ---------------- | --------------------------------------------------------------------------------- |
406
+ | `InMemoryEventStorage` | `node-cqrs` | - | Dev/test only; data lost on restart ([example](examples/user-domain-ts/index.ts)) |
407
+ | `SqliteEventStorage` | `node-cqrs/sqlite` | `better-sqlite3` | Embedded, single-process ([example](examples/sqlite/index.ts)) |
408
+ | `MongoEventStorage` | `node-cqrs/mongodb` | `mongodb` | Distributed, multi-process ([example](examples/mongodb-eventstore/index.ts)) |
415
409
 
416
- ### SQLite
410
+ ### Read Model
417
411
 
418
- ```ts
419
- import {
420
- SqliteEventStorage, // SQLite-backed event storage
421
- AbstractSqliteView, // SQLite view with restore locking and checkpoint tracking
422
- SqliteObjectView // SQLite-backed object view
423
- } from 'node-cqrs/sqlite';
424
- ```
412
+ Where projections store and query their read-side state.
413
+ Each persistent backend provides the same layered set of building blocks:
425
414
 
426
- See [examples/sqlite/index.ts](examples/sqlite/index.ts) for a runnable example.
415
+ | Layer | Purpose |
416
+ | ------------------- | ------------------------------------------------------------------------------------------------ |
417
+ | **Object storage** | Key/value CRUD with optimistic concurrency |
418
+ | **View locker** | Prevents concurrent schema-migration rebuilds - only one process rebuilds at a time; others wait |
419
+ | **Event locker** | Per-event deduplication and last-projected checkpoint |
420
+ | **Composite view** | Combines the above into a single view object |
421
+ | **Base projection** | Wires locking, checkpointing, and error handling automatically |
427
422
 
428
- ### Redis
423
+ #### In-memory
429
424
 
430
- > **Experimental** — the Redis module is new and has not been validated in production. APIs may change in minor versions.
425
+ | Class | Notes |
426
+ | -------------- | -------------------------------------------------------------- |
427
+ | `InMemoryLock` | Simple in-process lock |
428
+ | `InMemoryView` | Simple `Map`-backed view; restores from events on each restart |
431
429
 
432
- ```ts
433
- import {
434
- AbstractRedisProjection, // base class for Redis-backed projections
435
- RedisView, // object view with distributed locking and checkpoint tracking
436
- RedisObjectStorage, // low-level key/value object store
437
- RedisViewLocker, // distributed view lock with auto-prolongation via PEXPIRE
438
- RedisEventLocker // per-event deduplication and last-event checkpoint
439
- } from 'node-cqrs/redis';
440
- ```
430
+ #### SQLite (`node-cqrs/sqlite`, peer dep: `better-sqlite3`)
441
431
 
442
- See [examples/redis/index.ts](examples/redis/index.ts) for a runnable example.
432
+ | Class | Role |
433
+ | -------------------------------- | -------------------------------------------------------------------------------------- |
434
+ | `SqliteObjectStorage` | Key/value object storage with version-based concurrency |
435
+ | `SqliteViewLocker` | Prevents concurrent schema-migration rebuilds via SQLite row lock |
436
+ | `SqliteEventLocker` | Event deduplication and last-event checkpoint |
437
+ | `AbstractSqliteView` | Base class for relational (non-object) SQLite views with view and event locks embedded |
438
+ | `SqliteObjectView` | Composite view combining the above |
439
+ | `AbstractSqliteObjectProjection` | Base projection wired to `SqliteObjectView` |
443
440
 
444
- ### RabbitMQ
441
+ See [src/sqlite](src/sqlite) for additional documentation, and [examples/sqlite](examples/sqlite/index.ts) for runnable project examples
445
442
 
446
- ```ts
447
- import {
448
- RabbitMqGateway, // publish/subscribe gateway with durable and transient queue support
449
- RabbitMqEventBus, // RabbitMQ-backed IEventBus (fanout delivery to all subscribers)
450
- RabbitMqCommandBus // RabbitMQ-backed ICommandBus (point-to-point delivery via durable queue)
451
- } from 'node-cqrs/rabbitmq';
452
- ```
443
+ #### MongoDB (`node-cqrs/mongodb`, peer dep: `mongodb`)
453
444
 
454
- ### Workers
445
+ > **Experimental** - not yet validated in production. APIs may change in minor versions.
455
446
 
456
- ```ts
457
- import {
458
- AbstractWorkerProjection // projections running in worker threads
459
- } from 'node-cqrs/workers';
460
- ```
447
+ | Class | Role |
448
+ | ------------------------------- | --------------------------------------------------------------------------------- |
449
+ | `MongoObjectStorage` | Document storage with version-based optimistic concurrency |
450
+ | `MongoViewLocker` | Prevents concurrent schema-migration rebuilds; auto-prolongs lock via token + TTL |
451
+ | `MongoEventLocker` | Event deduplication and last-event checkpoint |
452
+ | `AbstractMongoView` | Base class combining `MongoViewLocker` + `MongoEventLocker` |
453
+ | `MongoObjectView` | Composite view combining the above |
454
+ | `AbstractMongoObjectProjection` | Base projection wired to `MongoObjectView` |
461
455
 
462
- Define one projection class that runs as a real projection inside a worker thread and a proxy in the main thread. Quickstart:
463
- 1. Extend `AbstractWorkerProjection`.
464
- 2. In the worker module, call `YourProjection.createInstanceInWorkerThread()`.
465
- 3. In the app container, register `YourProjection.workerProxyFactory` like a normal projection.
456
+ See [src/mongodb](src/mongodb) for additional documentation, and [examples/mongodb-views](examples/mongodb-views/index.ts) for runnable projection examples.
466
457
 
467
- See [examples/workers-projection/index.cjs](examples/workers-projection/index.cjs) for a runnable example.
458
+ #### Redis (`node-cqrs/redis`, peer dep: `ioredis`)
468
459
 
469
- ### MongoDB
460
+ > **Experimental** - not yet validated in production. APIs may change in minor versions.
470
461
 
471
- ```ts
472
- import {
473
- MongoEventStorage // event storage, identifier provider, and dispatch pipeline processor
474
- } from 'node-cqrs/mongodb';
475
- ```
462
+ | Class | Role |
463
+ | ------------------------- | ----------------------------------------------------------------------------- |
464
+ | `RedisObjectStorage` | Key/value object storage backed by Redis hashes |
465
+ | `RedisViewLocker` | Prevents concurrent schema-migration rebuilds; auto-prolongs lock via PEXPIRE |
466
+ | `RedisEventLocker` | Event deduplication and last-event checkpoint |
467
+ | `RedisView` | Composite view combining the above |
468
+ | `AbstractRedisProjection` | Base projection wired to `RedisView` |
469
+
470
+ See [src/redis](src/redis) for additional documentation, and [examples/redis](examples/redis/index.ts) for runnable projection examples.
471
+
472
+ ### Message Buses
473
+
474
+ How commands and events move between producers and consumers.
475
+
476
+ | Implementation | Import | Peer deps | Notes |
477
+ | -------------------- | -------------------- | --------- | ------------------------------------------------------------------------------------------------ |
478
+ | `InMemoryMessageBus` | `node-cqrs` | - | Single-process; used as both command and event bus ([example](examples/user-domain-ts/index.ts)) |
479
+ | `RabbitMqEventBus` | `node-cqrs/rabbitmq` | `amqplib` | Fanout delivery to all subscribers ([instructions](src/rabbitmq)) |
480
+ | `RabbitMqCommandBus` | `node-cqrs/rabbitmq` | `amqplib` | Point-to-point via durable queue ([instructions](src/rabbitmq)) |
481
+
482
+ ### Other
476
483
 
477
- See [examples/mongodb/index.ts](examples/mongodb/index.ts) for a full working example.
484
+ | Implementation | Import | Notes |
485
+ | -------------------------- | ------------------- | ------------------------------------------------------------- |
486
+ | `InMemorySnapshotStorage` | `node-cqrs` | Aggregate snapshot cache in memory, resets on process restart |
487
+ | `AbstractWorkerProjection` | `node-cqrs/workers` | Run projections in worker threads ([instructions](src/workers), [example](examples/workers-projection/index.cjs)) |
478
488
 
489
+ > **Experimental** — the Workers module is new and has not been validated in production. APIs may change in minor versions.
479
490
 
480
491
  ## OpenTelemetry
481
492
 
@@ -500,7 +511,8 @@ See [examples/telemetry/index.ts](examples/telemetry/index.ts) for a full workin
500
511
  - [examples/sagas-overlaps](examples/sagas-overlaps/index.ts) - overlapping sagas, multi-step flow
501
512
  - [examples/browser](examples/browser) - browser smoke test
502
513
  - [examples/workers-projection](examples/workers-projection) - worker thread projection
503
- - [examples/mongodb](examples/mongodb/index.ts) - MongoDB event storage with DI container and manual wiring
514
+ - [examples/mongodb-eventstore](examples/mongodb-eventstore/index.ts) - MongoDB event storage with DI container and manual wiring
515
+ - [examples/mongodb-views](examples/mongodb-views/index.ts) - MongoDB-backed projection views with object storage and locking
504
516
  - [examples/telemetry](examples/telemetry/index.ts) - OpenTelemetry tracing with multiple exporters
505
517
 
506
518
  TS examples can be run with NodeJS 24+ without transpiling.
@@ -10,11 +10,14 @@ class EventDispatchPipeline {
10
10
  #processors = [];
11
11
  #pipeline = this.#pipelineInput;
12
12
  #processing = false;
13
+ #pending = new Set();
13
14
  #eventBus;
14
15
  #concurrentLimit;
15
- constructor(eventBus, concurrentLimit) {
16
+ #onError;
17
+ constructor(eventBus, concurrentLimit, onError) {
16
18
  this.#eventBus = eventBus;
17
19
  this.#concurrentLimit = concurrentLimit;
20
+ this.#onError = onError;
18
21
  }
19
22
  addProcessor(preprocessor) {
20
23
  if (!(0, index_ts_1.isDispatchPipelineProcessor)(preprocessor))
@@ -59,7 +62,10 @@ class EventDispatchPipeline {
59
62
  continue;
60
63
  if ((0, index_ts_1.isSnapshotEvent)(event))
61
64
  continue;
62
- void this.#eventBus.publish(event, meta);
65
+ const p = this.#eventBus.publish(event, meta)
66
+ .catch(this.#onError);
67
+ this.#pending.add(p);
68
+ p.finally(() => this.#pending.delete(p));
63
69
  events.push(event);
64
70
  }
65
71
  resolve(events);
@@ -70,6 +76,10 @@ class EventDispatchPipeline {
70
76
  }
71
77
  })();
72
78
  }
79
+ /** Get a promise that resolves when all in-flight fire-and-forget event bus publishes have settled */
80
+ async drain() {
81
+ return Promise.allSettled(this.#pending);
82
+ }
73
83
  async revert(batch) {
74
84
  for (const processor of this.#processors)
75
85
  await processor.revert?.(batch);
@@ -1 +1 @@
1
- {"version":3,"file":"EventDispatchPipeline.js","sourceRoot":"","sources":["../../src/EventDispatchPipeline.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EventDispatchPipeline.js","sourceRoot":"","sources":["../../src/EventDispatchPipeline.ts"],"names":[],"mappings":"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"}
@@ -24,13 +24,25 @@ class EventDispatcher {
24
24
  concurrentLimit;
25
25
  /** Router that selects a pipeline name given events and meta */
26
26
  eventDispatchRouter;
27
+ /**
28
+ * Called when a fire-and-forget event bus publish fails.
29
+ * If not set, publish errors are silently discarded.
30
+ */
31
+ eventPublishErrorHandler;
27
32
  #pipelines = new Map();
28
33
  #tracer;
29
34
  constructor(o) {
35
+ if (o?.eventDispatcherConfig?.concurrentLimit !== undefined)
36
+ (0, index_ts_4.assertNonNegativeInteger)(o.eventDispatcherConfig.concurrentLimit, 'eventDispatcherConfig.concurrentLimit');
37
+ if (o?.eventDispatchRouter !== undefined)
38
+ (0, index_ts_4.assertFunction)(o.eventDispatchRouter, 'eventDispatchRouter');
39
+ if (o?.eventPublishErrorHandler !== undefined)
40
+ (0, index_ts_4.assertFunction)(o.eventPublishErrorHandler, 'eventPublishErrorHandler');
30
41
  this.#tracer = o?.tracerFactory?.(new.target.name);
31
42
  this.eventBus = o?.eventBus ?? new index_ts_3.InMemoryMessageBus();
32
43
  this.concurrentLimit = o?.eventDispatcherConfig?.concurrentLimit ?? EventDispatcher.DEFAULT_CONCURRENT_LIMIT;
33
44
  this.eventDispatchRouter = o?.eventDispatchRouter ?? EventDispatcher.DEFAULT_ROUTER;
45
+ this.eventPublishErrorHandler = o?.eventPublishErrorHandler;
34
46
  if (o?.eventDispatchPipelines) {
35
47
  // Initialize pipelines if provided
36
48
  for (const [name, processors] of Object.entries(o.eventDispatchPipelines))
@@ -63,12 +75,16 @@ class EventDispatcher {
63
75
  (0, index_ts_4.assertDefined)(name, 'pipeline name');
64
76
  if (this.#pipelines.has(name))
65
77
  throw new Error(`pipeline "${name}" already exists`);
66
- const pipeline = new EventDispatchPipeline_ts_1.EventDispatchPipeline(this.eventBus, options?.concurrentLimit ?? this.concurrentLimit);
78
+ const pipeline = new EventDispatchPipeline_ts_1.EventDispatchPipeline(this.eventBus, options?.concurrentLimit ?? this.concurrentLimit, this.eventPublishErrorHandler);
67
79
  for (const p of processors)
68
80
  pipeline.addProcessor(p);
69
81
  this.#pipelines.set(name, pipeline);
70
82
  return pipeline;
71
83
  }
84
+ /** Get a promise that resolves when all in-flight fire-and-forget event bus publishes have settled */
85
+ async drain() {
86
+ return Promise.all([...this.#pipelines.values()].map(p => p.drain()));
87
+ }
72
88
  /** Dispatch events through a routed pipeline and publish to the shared eventBus */
73
89
  async dispatch(events, meta) {
74
90
  if (!(0, index_ts_2.isEventSet)(events) || events.length === 0)
@@ -1 +1 @@
1
- {"version":3,"file":"EventDispatcher.js","sourceRoot":"","sources":["../../src/EventDispatcher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EventDispatcher.js","sourceRoot":"","sources":["../../src/EventDispatcher.ts"],"names":[],"mappings":"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"}
@@ -86,6 +86,10 @@ class EventStore {
86
86
  ...meta
87
87
  });
88
88
  }
89
+ /** Get a promise that resolves when all in-flight fire-and-forget event bus publishes have settled */
90
+ drain() {
91
+ return this.#eventDispatcher.drain();
92
+ }
89
93
  on(messageType, handler) {
90
94
  this.eventBus.on(messageType, handler);
91
95
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EventStore.js","sourceRoot":"","sources":["../../src/EventStore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EventStore.js","sourceRoot":"","sources":["../../src/EventStore.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AbstractMongoAccessor = void 0;
4
+ const index_ts_1 = require("../utils/index.js");
5
+ /**
6
+ * Abstract base class for accessing a MongoDB database.
7
+ *
8
+ * Manages the database connection lifecycle, ensuring initialization via `assertConnection`.
9
+ * Supports providing a Db instance directly or a factory function for lazy initialization.
10
+ *
11
+ * Subclasses must implement the `initialize` method for specific setup tasks
12
+ * (e.g. creating collections or indexes).
13
+ */
14
+ class AbstractMongoAccessor {
15
+ db;
16
+ #dbFactory;
17
+ #initLocker = new index_ts_1.Lock();
18
+ #initialized = false;
19
+ constructor(c) {
20
+ if (!c.viewModelMongoDb && !c.viewModelMongoDbFactory)
21
+ throw new TypeError('either viewModelMongoDb or viewModelMongoDbFactory argument required');
22
+ this.db = c.viewModelMongoDb;
23
+ this.#dbFactory = c.viewModelMongoDbFactory;
24
+ }
25
+ /**
26
+ * Ensures that the MongoDB connection is initialized.
27
+ * Uses a lock to prevent race conditions during concurrent initialization attempts.
28
+ * If the database is not already set, it creates one using the provided factory
29
+ * and then calls the `initialize` method.
30
+ *
31
+ * This method is idempotent and safe to call multiple times.
32
+ */
33
+ async assertConnection() {
34
+ if (this.#initialized)
35
+ return;
36
+ try {
37
+ await this.#initLocker.acquire();
38
+ if (this.#initialized)
39
+ return;
40
+ if (!this.db)
41
+ this.db = await this.#dbFactory();
42
+ await this.initialize(this.db);
43
+ this.#initialized = true;
44
+ }
45
+ finally {
46
+ this.#initLocker.release();
47
+ }
48
+ }
49
+ }
50
+ exports.AbstractMongoAccessor = AbstractMongoAccessor;
51
+ //# sourceMappingURL=AbstractMongoAccessor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AbstractMongoAccessor.js","sourceRoot":"","sources":["../../../src/mongodb/AbstractMongoAccessor.ts"],"names":[],"mappings":";;;AAEA,gDAAyC;AAEzC;;;;;;;;GAQG;AACH,MAAsB,qBAAqB;IAEhC,EAAE,CAAiB;IACpB,UAAU,CAAuC;IACjD,WAAW,GAAG,IAAI,eAAI,EAAE,CAAC;IAClC,YAAY,GAAG,KAAK,CAAC;IAErB,YAAY,CAA4E;QACvF,IAAI,CAAC,CAAC,CAAC,gBAAgB,IAAI,CAAC,CAAC,CAAC,uBAAuB;YACpD,MAAM,IAAI,SAAS,CAAC,sEAAsE,CAAC,CAAC;QAE7F,IAAI,CAAC,EAAE,GAAG,CAAC,CAAC,gBAAgB,CAAC;QAC7B,IAAI,CAAC,UAAU,GAAG,CAAC,CAAC,uBAAuB,CAAC;IAC7C,CAAC;IAID;;;;;;;OAOG;IACH,KAAK,CAAC,gBAAgB;QACrB,IAAI,IAAI,CAAC,YAAY;YACpB,OAAO;QAER,IAAI,CAAC;YACJ,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YACjC,IAAI,IAAI,CAAC,YAAY;gBACpB,OAAO;YAER,IAAI,CAAC,IAAI,CAAC,EAAE;gBACX,IAAI,CAAC,EAAE,GAAG,MAAM,IAAI,CAAC,UAAW,EAAE,CAAC;YAEpC,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAE/B,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;QAC1B,CAAC;gBACO,CAAC;YACR,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;QAC5B,CAAC;IACF,CAAC;CACD;AA7CD,sDA6CC"}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AbstractMongoObjectProjection = void 0;
4
+ const AbstractProjection_ts_1 = require("../AbstractProjection.js");
5
+ const MongoObjectView_ts_1 = require("./MongoObjectView.js");
6
+ class AbstractMongoObjectProjection extends AbstractProjection_ts_1.AbstractProjection {
7
+ static get tableName() {
8
+ throw new Error('tableName is not defined');
9
+ }
10
+ static get schemaVersion() {
11
+ throw new Error('schemaVersion is not defined');
12
+ }
13
+ constructor({ viewModelMongoDb, viewModelMongoDbFactory, logger }) {
14
+ super({ logger });
15
+ this.view = new MongoObjectView_ts_1.MongoObjectView({
16
+ schemaVersion: new.target.schemaVersion,
17
+ projectionName: new.target.name,
18
+ viewModelMongoDb,
19
+ viewModelMongoDbFactory,
20
+ tableNamePrefix: new.target.tableName,
21
+ logger
22
+ });
23
+ }
24
+ }
25
+ exports.AbstractMongoObjectProjection = AbstractMongoObjectProjection;
26
+ //# sourceMappingURL=AbstractMongoObjectProjection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AbstractMongoObjectProjection.js","sourceRoot":"","sources":["../../../src/mongodb/AbstractMongoObjectProjection.ts"],"names":[],"mappings":";;;AACA,oEAA8D;AAC9D,6DAAuD;AAEvD,MAAsB,6BAAiC,SAAQ,0CAAsC;IAEpG,MAAM,KAAK,SAAS;QACnB,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC7C,CAAC;IAED,MAAM,KAAK,aAAa;QACvB,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IACjD,CAAC;IAED,YAAY,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,EACsB;QAEpF,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;QAElB,IAAI,CAAC,IAAI,GAAG,IAAI,oCAAe,CAAC;YAC/B,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,aAAa;YACvC,cAAc,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI;YAC/B,gBAAgB;YAChB,uBAAuB;YACvB,eAAe,EAAE,GAAG,CAAC,MAAM,CAAC,SAAS;YACrC,MAAM;SACN,CAAC,CAAC;IACJ,CAAC;CACD;AAxBD,sEAwBC"}
@@ -0,0 +1,57 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AbstractMongoView = void 0;
4
+ const MongoViewLocker_ts_1 = require("./MongoViewLocker.js");
5
+ const MongoEventLocker_ts_1 = require("./MongoEventLocker.js");
6
+ const AbstractMongoAccessor_ts_1 = require("./AbstractMongoAccessor.js");
7
+ const assert_ts_1 = require("../utils/assert.js");
8
+ /**
9
+ * Base class for MongoDB-backed projection views with restore locking and last-processed-event tracking
10
+ */
11
+ class AbstractMongoView extends AbstractMongoAccessor_ts_1.AbstractMongoAccessor {
12
+ schemaVersion;
13
+ viewLocker;
14
+ eventLocker;
15
+ logger;
16
+ get ready() {
17
+ return this.viewLocker.ready;
18
+ }
19
+ constructor(options) {
20
+ (0, assert_ts_1.assertString)(options.projectionName, 'projectionName');
21
+ (0, assert_ts_1.assertString)(options.schemaVersion, 'schemaVersion');
22
+ super(options);
23
+ this.schemaVersion = options.schemaVersion;
24
+ this.viewLocker = new MongoViewLocker_ts_1.MongoViewLocker(options);
25
+ this.eventLocker = new MongoEventLocker_ts_1.MongoEventLocker(options);
26
+ this.logger = options.logger && 'child' in options.logger ?
27
+ options.logger.child({ serviceName: new.target.name }) :
28
+ options.logger;
29
+ }
30
+ // eslint-disable-next-line class-methods-use-this
31
+ initialize(_db) {
32
+ // Lockers initialize themselves on first use
33
+ }
34
+ async lock() {
35
+ return this.viewLocker.lock();
36
+ }
37
+ async unlock() {
38
+ await this.viewLocker.unlock();
39
+ }
40
+ once(event) {
41
+ return this.viewLocker.once(event);
42
+ }
43
+ getLastEvent() {
44
+ return this.eventLocker.getLastEvent();
45
+ }
46
+ tryMarkAsProjecting(event) {
47
+ return this.eventLocker.tryMarkAsProjecting(event);
48
+ }
49
+ markAsProjected(event) {
50
+ return this.eventLocker.markAsProjected(event);
51
+ }
52
+ markAsLastEvent(event) {
53
+ return this.eventLocker.markAsLastEvent(event);
54
+ }
55
+ }
56
+ exports.AbstractMongoView = AbstractMongoView;
57
+ //# sourceMappingURL=AbstractMongoView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AbstractMongoView.js","sourceRoot":"","sources":["../../../src/mongodb/AbstractMongoView.ts"],"names":[],"mappings":";;;AAGA,6DAAmF;AACnF,+DAAsF;AACtF,yEAAmE;AACnE,kDAAkD;AAElD;;GAEG;AACH,MAAsB,iBAAkB,SAAQ,gDAAqB;IAEjD,aAAa,CAAS;IACtB,UAAU,CAAkB;IAC5B,WAAW,CAAmB;IACvC,MAAM,CAAsB;IAEtC,IAAI,KAAK;QACR,OAAO,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC;IAC9B,CAAC;IAED,YAAY,OAEY;QACvB,IAAA,wBAAY,EAAC,OAAO,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAAC;QACvD,IAAA,wBAAY,EAAC,OAAO,CAAC,aAAa,EAAE,eAAe,CAAC,CAAC;QAErD,KAAK,CAAC,OAAO,CAAC,CAAC;QAEf,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAC3C,IAAI,CAAC,UAAU,GAAG,IAAI,oCAAe,CAAC,OAAO,CAAC,CAAC;QAC/C,IAAI,CAAC,WAAW,GAAG,IAAI,sCAAgB,CAAC,OAAO,CAAC,CAAC;QACjD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;YAC1D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YACxD,OAAO,CAAC,MAAM,CAAC;IACjB,CAAC;IAED,kDAAkD;IACxC,UAAU,CAAC,GAAO;QAC3B,6CAA6C;IAC9C,CAAC;IAED,KAAK,CAAC,IAAI;QACT,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;IAC/B,CAAC;IAED,KAAK,CAAC,MAAM;QACX,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;IAChC,CAAC;IAED,IAAI,CAAC,KAAc;QAClB,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACpC,CAAC;IAED,YAAY;QACX,OAAO,IAAI,CAAC,WAAW,CAAC,YAAY,EAAE,CAAC;IACxC,CAAC;IAED,mBAAmB,CAAC,KAAa;QAChC,OAAO,IAAI,CAAC,WAAW,CAAC,mBAAmB,CAAC,KAAK,CAAC,CAAC;IACpD,CAAC;IAED,eAAe,CAAC,KAAa;QAC5B,OAAO,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IAED,eAAe,CAAC,KAAa;QAC5B,OAAO,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;CACD;AA3DD,8CA2DC"}