event-storage 1.0.0 → 1.2.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/README.md CHANGED
@@ -62,6 +62,8 @@ eventstore.on('ready', () => {
62
62
  | **Optimistic concurrency** | Pass `expectedVersion` to `commit()` to guarantee conflict-free writes. |
63
63
  | **Flexible stream reading** | Range queries, reverse iteration, and a fluent builder API. |
64
64
  | **Derived streams** | Filter or combine events into new read-only streams. |
65
+ | **Multi-value matchers** | Object matchers support array values (OR semantics) and still benefit from O(1) discriminant routing on writes. |
66
+ | **DCB / `typeAccessor`** | Configure `typeAccessor` to have per-type stream indexes maintained automatically, and use `query()` / `Condition` for fine-grained, query-scoped optimistic concurrency (Dynamic Consistency Boundaries). |
65
67
  | **Stream categories** | Name streams `<category>-<id>` and query the whole category at once. |
66
68
  | **Durable consumers** | At-least-once (and exactly-once with `setState`) event delivery with automatic position tracking. |
67
69
  | **Consistency guards** | Build aggregates that enforce business invariants with built-in snapshotting. |
@@ -73,12 +75,34 @@ eventstore.on('ready', () => {
73
75
 
74
76
  ---
75
77
 
78
+ ## HTTP API
79
+
80
+ To expose an event store over HTTP, see the companion package **[event-storage-http](https://github.com/albe/node-event-storage-http)**:
81
+
82
+ ```bash
83
+ npm install event-storage-http
84
+ ```
85
+
86
+ ```javascript
87
+ import EventStore from 'event-storage';
88
+ import { createEventStoreHttpServer } from 'event-storage-http';
89
+
90
+ const eventStore = new EventStore('my-store', { storageDirectory: './data' });
91
+ const server = createEventStoreHttpServer(eventStore);
92
+ server.listen(3000);
93
+ ```
94
+
95
+ The package exposes NDJSON stream endpoints, durable consumer management, and an `HttpEventStream` client helper for consuming event streams over fetch.
96
+
97
+ ---
98
+
76
99
  ## Documentation
77
100
 
78
101
  The full documentation is hosted at **<https://node-event-storage.readthedocs.io/en/latest/>** and covers:
79
102
 
80
103
  - [Getting Started](https://node-event-storage.readthedocs.io/en/latest/getting-started/) — installation, constructor options, basic usage.
81
104
  - [Event Streams](https://node-event-storage.readthedocs.io/en/latest/streams/) — writing, reading, optimistic concurrency, fluent API, joining streams, categories, and event metadata.
105
+ - [Dynamic Consistency Boundaries (DCB)](https://node-event-storage.readthedocs.io/en/latest/dcb/) — `typeAccessor`, multi-value matchers, consistency tokens, and the full DCB workflow.
82
106
  - [Consumers](https://node-event-storage.readthedocs.io/en/latest/consumers/) — at-least-once and exactly-once delivery, consumer state, consistency guards, and read-only mode.
83
107
  - [Advanced Topics](https://node-event-storage.readthedocs.io/en/latest/advanced/) — ACID properties, reliability and crash-safety guarantees, storage configuration, partitioning, custom serialization, compression, security, and access control hooks.
84
108
 
package/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { default as EventStore, default, ExpectedVersion, OptimisticConcurrencyError, LOCK_THROW, LOCK_RECLAIM } from './src/EventStore.js';
1
+ export { default as EventStore, default, ExpectedVersion, OptimisticConcurrencyError, CommitCondition, LOCK_THROW, LOCK_RECLAIM } from './src/EventStore.js';
2
2
  export { default as EventStream } from './src/EventStream.js';
3
3
  export { default as Storage, StorageLockedError } from './src/Storage.js';
4
4
  export { default as Index } from './src/Index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "event-storage",
3
- "version": "1.0.0",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "description": "An optimized embedded event store for node.js",
6
6
  "keywords": [
@@ -43,9 +43,8 @@
43
43
  "src/Partition/*.js",
44
44
  "src/Storage/*.js",
45
45
  "src/WatchesFile.js",
46
- "src/util.js",
47
- "src/metadataUtil.js",
48
- "index.js"
46
+ "index.js",
47
+ "src/utils/*.js"
49
48
  ],
50
49
  "license": "MIT",
51
50
  "maintainers": [
package/src/Consumer.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import stream from 'stream';
2
2
  import fs from 'fs';
3
3
  import path from 'path';
4
- import { assert, ensureDirectory } from './util.js';
4
+ import { assert } from './utils/util.js';
5
+ import { ensureDirectory } from './utils/fsUtil.js';
5
6
  import Storage from './Storage/ReadableStorage.js';
6
7
  const MAX_CATCHUP_BATCH = 10;
7
8
 
@@ -29,8 +30,8 @@ class Consumer extends stream.Readable {
29
30
  * @param {Storage} storage The storage to create the consumer for.
30
31
  * @param {string} indexName The name of the index to consume.
31
32
  * @param {string} identifier The unique name to identify this consumer.
32
- * @param {object} [initialState] The initial state of the consumer.
33
- * @param {number} [startFrom] The revision to start from within the index to consume.
33
+ * @param {object} [initialState={}] The initial state of the consumer.
34
+ * @param {number} [startFrom=0] The revision to start from within the index to consume.
34
35
  */
35
36
  constructor(storage, indexName, identifier, initialState = {}, startFrom = 0) {
36
37
  super({ objectMode: true });
@@ -110,7 +111,7 @@ class Consumer extends stream.Readable {
110
111
  * May only be called from within the document handling callback.
111
112
  *
112
113
  * @param {object|function(object):object} newState
113
- * @param {boolean} [persist] Set to false if this state update should not be persisted yet
114
+ * @param {boolean} [persist=true] Set to false if this state update should not be persisted yet
114
115
  * @api
115
116
  */
116
117
  setState(newState, persist = true) {
@@ -150,6 +151,7 @@ class Consumer extends stream.Readable {
150
151
  if (this.doPersist) {
151
152
  this.persist();
152
153
  }
154
+ this.emit('progress', this.position, this.state);
153
155
  }
154
156
 
155
157
  /**
@@ -243,6 +245,7 @@ class Consumer extends stream.Readable {
243
245
  const maxBatchPosition = Math.min(this.position + MAX_CATCHUP_BATCH + 1, this.index.length);
244
246
  const documents = this.storage.readRange(this.position + 1, maxBatchPosition, this.index);
245
247
  this.consumeDocuments(documents);
248
+ this.emit('progress', this.position, this.state);
246
249
  this.once('persisted', () => catchUpBatch());
247
250
  this.persist();
248
251
  });
@@ -266,8 +269,8 @@ class Consumer extends stream.Readable {
266
269
  /**
267
270
  * Reset this projection to restart processing all documents again.
268
271
  * NOTE: This will overwrite the current state of the projection and hence be destructive.
269
- * @param {object} [initialState] The initial state of the consumer.
270
- * @param {number} [startFrom] The revision to start from within the index to consume.
272
+ * @param {object} [initialState={}] The initial state of the consumer.
273
+ * @param {number} [startFrom=0] The revision to start from within the index to consume.
271
274
  * @api
272
275
  */
273
276
  reset(initialState = {}, startFrom = 0) {