node-cqrs 1.1.0-alpha.7 → 1.1.0-alpha.8

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 CHANGED
@@ -1,3 +1,11 @@
1
+ # [1.1.0-alpha.8](https://github.com/snatalenko/node-cqrs/compare/v1.1.0-alpha.7...v1.1.0-alpha.8) (2026-04-21)
2
+
3
+
4
+ ### Documentation
5
+
6
+ * Minor spec update ([6a2883a](https://github.com/snatalenko/node-cqrs/commit/6a2883adc7b6a7a48bb5f62562c2242826860e89))
7
+
8
+
1
9
  # [1.1.0-alpha.7](https://github.com/snatalenko/node-cqrs/compare/v1.1.0-alpha.6...v1.1.0-alpha.7) (2026-04-06)
2
10
 
3
11
 
package/README.md CHANGED
@@ -11,21 +11,24 @@ node-cqrs
11
11
 
12
12
  Infrastructure-agnostic building blocks for CQRS/ES, inspired by Lokad.CQRS.
13
13
 
14
- CQRS/ES can be simple in a single process - minimal code, no framework:
15
- [examples/user-domain-framework-free](examples/user-domain-framework-free/index.ts).
16
- This library handles the "boring but hard" parts required in distributed environments:
17
-
18
- - safer async command + event handling (per-aggregate FIFO, shared restore, fewer footguns)
19
- - restart-safe projections/views (catch-up with checkpoints, readiness gates, locking)
20
- - snapshots for fast rehydrate (automatic snapshot events + restore)
21
- - pluggable dispatch pipeline (encode/persist/fan-out; order is explicit)
22
- - conflict-safe writes (optimistic concurrency + retry with clean rehydrate)
23
- - routed pipelines with backpressure (named pipelines + concurrency limits)
24
- - competing-consumer delivery (named queues when supported)
25
- - selective restore with correct versioning (filter + tail to keep versions right)
26
- - sagas with built-in correlation (event-id origins + sagaOrigins propagation)
27
-
28
- Built around ES6/TypeScript classes and dependency injection - swap implementations without patching the library.
14
+ ## Features
15
+
16
+ CQRS and Event Sourcing are simple in a single process ([example](examples/user-domain-framework-free/index.ts)), but a minefield in the cloud.
17
+ node-cqrs handles the "boring but hard" distributed plumbing - concurrency, message delivery, projections, and rehydration - so you can focus on your domain logic.
18
+
19
+ - **Reliable Consistency**: Per-aggregate FIFO handling and conflict-safe writes with optimistic concurrency.
20
+ - **Resilient Projections**: Restart-safe views with checkpoints, readiness gates, and locking.
21
+ - **Fast Rehydration**: Automatic snapshotting and selective event restores.
22
+ - **Distributed Sagas**: Built-in event correlation and origin propagation for complex workflows.
23
+ - **Smart Pipelines**: Pluggable dispatching with back-pressure and concurrency limits.
24
+ - **Pluggable by Design**: Thin interfaces on every component - swap any piece, from message buses to event storage, without touching your domain code.
25
+
26
+ The heavy lifting for common stacks is done, so you can mix and match sub-modules to fit your environment:
27
+
28
+ - `node-cqrs/sqlite` Embedded per-process event storage and/or views.
29
+ - `node-cqrs/mongodb` – Distributed event storage and persistent projection views for multi-process deployments.
30
+ - `node-cqrs/rabbitmq` – Robust, distributed command and event bus.
31
+ - `node-cqrs/redis` – Redis-backed persistent projection views for distributed deployments.
29
32
 
30
33
  ## Table of Contents
31
34
 
@@ -55,27 +58,37 @@ Built around ES6/TypeScript classes and dependency injection - swap implementati
55
58
 
56
59
  ![Overview](docs/images/node-cqrs-flow.svg)
57
60
 
61
+ Domain logic lives in three building blocks:
62
+
63
+ - **[Aggregates](#write-model-aggregates)** - handle commands and emit events
64
+ - **[Sagas](#sagas)** - manage processes by reacting to events and enqueueing follow-up commands
65
+ - **[Projections](#read-model-projections-and-views)** - consume events and update views
58
66
 
59
67
  Commands and events are loosely typed objects implementing the [`IMessage`](src/interfaces/IMessage.ts) interface:
60
68
 
61
69
  ```ts
62
- interface IMessage<TPayload = any> {
70
+ interface IMessage<TPayload = unknown> {
71
+
72
+ /** Event or command type */
63
73
  type: string;
64
74
 
65
- aggregateId?: string | number;
75
+ /** Target aggregate identifier for commands, originating aggregate identifier for events */
76
+ aggregateId?: Identifier;
77
+
78
+ /** Aggregate version at the time of the message */
66
79
  aggregateVersion?: number;
80
+
81
+ /** Starter event ids of sagas associated with this message, keyed by saga descriptor */
67
82
  sagaOrigins?: Record<string, string>;
68
83
 
84
+ /** Business data */
69
85
  payload: TPayload;
86
+
87
+ /** Optional metadata/context (e.g. auth info, request id); set on commands, copied to events */
70
88
  context?: any;
71
89
  }
72
90
  ```
73
91
 
74
- Domain logic lives in three building blocks:
75
-
76
- - **[Aggregates](#write-model-aggregates)** - handle commands and emit events
77
- - **[Projections](#read-model-projections-and-views)** - consume events and update views
78
- - **[Sagas](#sagas)** - manage processes by reacting to events and enqueueing follow-up commands
79
92
 
80
93
  Message delivery is handled by the following components, in order:
81
94
 
@@ -486,7 +499,7 @@ How commands and events move between producers and consumers.
486
499
  | `InMemorySnapshotStorage` | `node-cqrs` | Aggregate snapshot cache in memory, resets on process restart |
487
500
  | `AbstractWorkerProjection` | `node-cqrs/workers` | Run projections in worker threads ([instructions](src/workers), [example](examples/workers-projection/index.cjs)) |
488
501
 
489
- > **Experimental** the Workers module is new and has not been validated in production. APIs may change in minor versions.
502
+ > **Experimental** - the Workers module is new and has not been validated in production. APIs may change in minor versions.
490
503
 
491
504
  ## OpenTelemetry
492
505
 
@@ -1 +1 @@
1
- {"version":3,"file":"IMessage.js","sourceRoot":"","sources":["../../../src/interfaces/IMessage.ts"],"names":[],"mappings":";;;AACA,+CAAyC;AA+BlC,MAAM,SAAS,GAAG,CAAC,GAAY,EAAmB,EAAE,CAC1D,IAAA,sBAAQ,EAAC,GAAG,CAAC;OACV,MAAM,IAAI,GAAG;OACb,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;OAC5B,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;AAJX,QAAA,SAAS,aAIE"}
1
+ {"version":3,"file":"IMessage.js","sourceRoot":"","sources":["../../../src/interfaces/IMessage.ts"],"names":[],"mappings":";;;AACA,+CAAyC;AAuBlC,MAAM,SAAS,GAAG,CAAC,GAAY,EAAmB,EAAE,CAC1D,IAAA,sBAAQ,EAAC,GAAG,CAAC;OACV,MAAM,IAAI,GAAG;OACb,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;OAC5B,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;AAJX,QAAA,SAAS,aAIE"}
@@ -1 +1 @@
1
- {"version":3,"file":"IMessage.js","sourceRoot":"","sources":["../../../src/interfaces/IMessage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AA+BzC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAY,EAAmB,EAAE,CAC1D,QAAQ,CAAC,GAAG,CAAC;OACV,MAAM,IAAI,GAAG;OACb,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;OAC5B,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC"}
1
+ {"version":3,"file":"IMessage.js","sourceRoot":"","sources":["../../../src/interfaces/IMessage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAuBzC,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,GAAY,EAAmB,EAAE,CAC1D,QAAQ,CAAC,GAAG,CAAC;OACV,MAAM,IAAI,GAAG;OACb,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;OAC5B,GAAG,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC"}
@@ -1,23 +1,16 @@
1
1
  import type { Identifier } from './Identifier.ts';
2
- export type SagaOriginsMap = Record<string, string>;
3
2
  export interface IMessage<TPayload = unknown> {
4
3
  /** Event or command type */
5
4
  type: string;
6
- /**
7
- * Target aggregate identifier for commands,
8
- * originating aggregate identifier for events
9
- */
5
+ /** Target aggregate identifier for commands, originating aggregate identifier for events */
10
6
  aggregateId?: Identifier;
11
7
  /** Aggregate version at the time of the message */
12
8
  aggregateVersion?: number;
13
9
  /** Starter event ids of sagas associated with this message, keyed by saga descriptor */
14
- sagaOrigins?: SagaOriginsMap;
10
+ sagaOrigins?: Record<string, string>;
15
11
  /** Business data */
16
12
  payload: TPayload;
17
- /**
18
- * Optional metadata/context (e.g. auth info, request id);
19
- * Commonly set on commands, then copied to emitted events
20
- */
13
+ /** Optional metadata/context (e.g. auth info, request id); set on commands, copied to events */
21
14
  context?: any;
22
15
  }
23
16
  export declare const isMessage: (obj: unknown) => obj is IMessage;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-cqrs",
3
- "version": "1.1.0-alpha.7",
3
+ "version": "1.1.0-alpha.8",
4
4
  "description": "TypeScript CQRS/Event Sourcing toolkit for Node.js with DI, sagas, projections, and optional Worker, RabbitMQ, and SQLite adapters",
5
5
  "type": "module",
6
6
  "keywords": [