@event-driven-io/emmett-esdb 0.20.2-alpha.3 → 0.20.2-alpha.4
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/dist/index.cjs +110 -209
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -406
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -1,25 +1,20 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3;// ../emmett/dist/chunk-
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
var
|
|
1
|
+
"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class; var _class2; var _class3;// ../emmett/dist/chunk-3XBWME34.js
|
|
2
|
+
var a = ((n) => (n.NOT_A_NONEMPTY_STRING = "NOT_A_NONEMPTY_STRING", n.NOT_A_POSITIVE_NUMBER = "NOT_A_POSITIVE_NUMBER", n.NOT_AN_UNSIGNED_BIGINT = "NOT_AN_UNSIGNED_BIGINT", n))(a || {});
|
|
3
|
+
var s = (t4) => typeof t4 == "number" && t4 === t4;
|
|
4
|
+
var m = (t4) => typeof t4 == "string";
|
|
5
|
+
var o = class t extends Error {
|
|
5
6
|
|
|
6
|
-
constructor(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
super(message);
|
|
10
|
-
this.errorCode = errorCode;
|
|
11
|
-
Object.setPrototypeOf(this, _EmmettError.prototype);
|
|
7
|
+
constructor(e) {
|
|
8
|
+
let i = e && typeof e == "object" && "errorCode" in e ? e.errorCode : s(e) ? e : 500, n = e && typeof e == "object" && "message" in e ? e.message : m(e) ? e : `Error with status code '${i}' ocurred during Emmett processing`;
|
|
9
|
+
super(n), this.errorCode = i, Object.setPrototypeOf(this, t.prototype);
|
|
12
10
|
}
|
|
13
11
|
};
|
|
14
|
-
var
|
|
15
|
-
constructor(
|
|
16
|
-
super({
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
this.current = current;
|
|
21
|
-
this.expected = expected;
|
|
22
|
-
Object.setPrototypeOf(this, _ConcurrencyError.prototype);
|
|
12
|
+
var g = class t2 extends o {
|
|
13
|
+
constructor(i, n, u) {
|
|
14
|
+
super({ errorCode: 412, message: _nullishCoalesce(u, () => ( `Expected version ${n.toString()} does not match current ${_optionalChain([i, 'optionalAccess', _ => _.toString, 'call', _2 => _2()])}`)) });
|
|
15
|
+
this.current = i;
|
|
16
|
+
this.expected = n;
|
|
17
|
+
Object.setPrototypeOf(this, t2.prototype);
|
|
23
18
|
}
|
|
24
19
|
};
|
|
25
20
|
|
|
@@ -41,41 +36,26 @@ var _asyncretry = require('async-retry'); var _asyncretry2 = _interopRequireDefa
|
|
|
41
36
|
|
|
42
37
|
|
|
43
38
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
var
|
|
47
|
-
var
|
|
48
|
-
var
|
|
49
|
-
|
|
50
|
-
if (expected === NO_CONCURRENCY_CHECK) return true;
|
|
51
|
-
if (expected == STREAM_DOES_NOT_EXIST) return current === defaultVersion;
|
|
52
|
-
if (expected == STREAM_EXISTS) return current !== defaultVersion;
|
|
53
|
-
return current === expected;
|
|
39
|
+
var xe = "STREAM_EXISTS";
|
|
40
|
+
var F = "STREAM_DOES_NOT_EXIST";
|
|
41
|
+
var D = "NO_CONCURRENCY_CHECK";
|
|
42
|
+
var ge = (t4, e, r2) => e === D ? true : e == F ? t4 === r2 : e == xe ? t4 !== r2 : t4 === e;
|
|
43
|
+
var N = (t4, e, r2) => {
|
|
44
|
+
if (e ??= D, !ge(t4, e, r2)) throw new b(t4, e);
|
|
54
45
|
};
|
|
55
|
-
var
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
throw new ExpectedVersionConflictError(current, expected);
|
|
59
|
-
};
|
|
60
|
-
var ExpectedVersionConflictError = class _ExpectedVersionConflictError extends ConcurrencyError {
|
|
61
|
-
constructor(current, expected) {
|
|
62
|
-
super(_optionalChain([current, 'optionalAccess', _3 => _3.toString, 'call', _4 => _4()]), _optionalChain([expected, 'optionalAccess', _5 => _5.toString, 'call', _6 => _6()]));
|
|
63
|
-
Object.setPrototypeOf(this, _ExpectedVersionConflictError.prototype);
|
|
46
|
+
var b = class t3 extends g {
|
|
47
|
+
constructor(e, r2) {
|
|
48
|
+
super(_optionalChain([e, 'optionalAccess', _3 => _3.toString, 'call', _4 => _4()]), _optionalChain([r2, 'optionalAccess', _5 => _5.toString, 'call', _6 => _6()])), Object.setPrototypeOf(this, t3.prototype);
|
|
64
49
|
}
|
|
65
50
|
};
|
|
66
|
-
var
|
|
67
|
-
var
|
|
68
|
-
constructor(
|
|
69
|
-
super({
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
});_class.prototype.__init.call(this);_class.prototype.__init2.call(this);;
|
|
75
|
-
this.onNoActiveReaderCallback = onNoActiveReaderCallback;
|
|
76
|
-
this.streamId = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _7 => _7.streamId]), () => ( _uuid.v4.call(void 0, )));
|
|
77
|
-
this.onNoActiveReaderCallback = onNoActiveReaderCallback;
|
|
78
|
-
this.startChecking(_nullishCoalesce(_optionalChain([options, 'optionalAccess', _8 => _8.intervalCheckInMs]), () => ( 20)));
|
|
51
|
+
var O = (t4, e = {}) => new S(t4, e);
|
|
52
|
+
var S = (_class = class extends _webstreamspolyfill.TransformStream {
|
|
53
|
+
constructor(r2, n = {}) {
|
|
54
|
+
super({ cancel: (o2) => {
|
|
55
|
+
console.log("Stream was canceled. Reason:", o2), this.stopChecking();
|
|
56
|
+
} });_class.prototype.__init.call(this);_class.prototype.__init2.call(this);;
|
|
57
|
+
this.onNoActiveReaderCallback = r2;
|
|
58
|
+
this.streamId = _nullishCoalesce(_optionalChain([n, 'optionalAccess', _7 => _7.streamId]), () => ( _uuid.v4.call(void 0, ))), this.onNoActiveReaderCallback = r2, this.startChecking(_nullishCoalesce(_optionalChain([n, 'optionalAccess', _8 => _8.intervalCheckInMs]), () => ( 20)));
|
|
79
59
|
}
|
|
80
60
|
__init() {this.checkInterval = null}
|
|
81
61
|
|
|
@@ -83,181 +63,102 @@ var NotifyAboutNoActiveReadersStream = (_class = class extends _webstreamspolyfi
|
|
|
83
63
|
get hasActiveSubscribers() {
|
|
84
64
|
return !this._isStopped;
|
|
85
65
|
}
|
|
86
|
-
startChecking(
|
|
66
|
+
startChecking(r2) {
|
|
87
67
|
this.checkInterval = setInterval(() => {
|
|
88
68
|
this.checkNoActiveReader();
|
|
89
|
-
},
|
|
69
|
+
}, r2);
|
|
90
70
|
}
|
|
91
71
|
stopChecking() {
|
|
92
|
-
|
|
93
|
-
clearInterval(this.checkInterval);
|
|
94
|
-
this.checkInterval = null;
|
|
95
|
-
this._isStopped = true;
|
|
96
|
-
this.onNoActiveReaderCallback(this);
|
|
72
|
+
this.checkInterval && (clearInterval(this.checkInterval), this.checkInterval = null, this._isStopped = true, this.onNoActiveReaderCallback(this));
|
|
97
73
|
}
|
|
98
74
|
checkNoActiveReader() {
|
|
99
|
-
|
|
100
|
-
this.stopChecking();
|
|
101
|
-
}
|
|
75
|
+
!this.readable.locked && !this._isStopped && this.stopChecking();
|
|
102
76
|
}
|
|
103
77
|
}, _class);
|
|
104
|
-
var
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
return await fn();
|
|
110
|
-
} catch (error2) {
|
|
111
|
-
if (_optionalChain([opts, 'optionalAccess', _9 => _9.shouldRetryError]) && !opts.shouldRetryError(error2)) {
|
|
112
|
-
bail(error2);
|
|
113
|
-
}
|
|
114
|
-
throw error2;
|
|
115
|
-
}
|
|
116
|
-
},
|
|
117
|
-
_nullishCoalesce(opts, () => ( { retries: 0 }))
|
|
118
|
-
);
|
|
119
|
-
};
|
|
120
|
-
var filter = (filter2) => new (0, _webstreamspolyfill.TransformStream)({
|
|
121
|
-
transform(chunk, controller) {
|
|
122
|
-
if (filter2(chunk)) {
|
|
123
|
-
controller.enqueue(chunk);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
var map = (map22) => new (0, _webstreamspolyfill.TransformStream)({
|
|
128
|
-
transform(chunk, controller) {
|
|
129
|
-
controller.enqueue(map22(chunk));
|
|
78
|
+
var w2 = async (t4, e) => e === void 0 || e.retries === 0 ? t4() : _asyncretry2.default.call(void 0, async (r2) => {
|
|
79
|
+
try {
|
|
80
|
+
return await t4();
|
|
81
|
+
} catch (n) {
|
|
82
|
+
throw _optionalChain([e, 'optionalAccess', _9 => _9.shouldRetryError]) && !e.shouldRetryError(n) && r2(n), n;
|
|
130
83
|
}
|
|
131
|
-
});
|
|
132
|
-
var
|
|
133
|
-
|
|
84
|
+
}, _nullishCoalesce(e, () => ( { retries: 0 })));
|
|
85
|
+
var ae = (t4) => new (0, _webstreamspolyfill.TransformStream)({ transform(e, r2) {
|
|
86
|
+
t4(e) && r2.enqueue(e);
|
|
87
|
+
} });
|
|
88
|
+
var se = (t4) => new (0, _webstreamspolyfill.TransformStream)({ transform(e, r2) {
|
|
89
|
+
r2.enqueue(t4(e));
|
|
90
|
+
} });
|
|
91
|
+
var ie = (t4, e) => new g2(t4, e);
|
|
92
|
+
var g2 = class extends _webstreamspolyfill.TransformStream {
|
|
134
93
|
|
|
135
94
|
|
|
136
|
-
constructor(
|
|
137
|
-
super({
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
controller.enqueue(this.accumulator);
|
|
143
|
-
controller.terminate();
|
|
144
|
-
}
|
|
145
|
-
});
|
|
146
|
-
this.accumulator = initialValue;
|
|
147
|
-
this.reducer = reducer;
|
|
95
|
+
constructor(e, r2) {
|
|
96
|
+
super({ transform: (n) => {
|
|
97
|
+
this.accumulator = this.reducer(this.accumulator, n);
|
|
98
|
+
}, flush: (n) => {
|
|
99
|
+
n.enqueue(this.accumulator), n.terminate();
|
|
100
|
+
} }), this.accumulator = r2, this.reducer = e;
|
|
148
101
|
}
|
|
149
102
|
};
|
|
150
|
-
var
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
});
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
var onRestream = async (createSourceStream, handleChunk2, controller) => {
|
|
161
|
-
const sourceStream = createSourceStream();
|
|
162
|
-
const reader = sourceStream.getReader();
|
|
103
|
+
var me = (t4, e, r2 = { forever: true, minTimeout: 25 }) => new (0, _webstreamspolyfill.TransformStream)({ start(n) {
|
|
104
|
+
w2(() => Ne(t4, e, n), r2).catch((o2) => {
|
|
105
|
+
n.error(o2);
|
|
106
|
+
});
|
|
107
|
+
} });
|
|
108
|
+
var Ne = async (t4, e, r2) => {
|
|
109
|
+
let o2 = t4().getReader();
|
|
163
110
|
try {
|
|
164
|
-
let
|
|
111
|
+
let a2;
|
|
165
112
|
do {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if (done) {
|
|
170
|
-
controller.terminate();
|
|
171
|
-
}
|
|
172
|
-
} while (!done);
|
|
113
|
+
let i = await o2.read();
|
|
114
|
+
a2 = i.done, await e(i, r2), a2 && r2.terminate();
|
|
115
|
+
} while (!a2);
|
|
173
116
|
} finally {
|
|
174
|
-
|
|
117
|
+
o2.releaseLock();
|
|
175
118
|
}
|
|
176
119
|
};
|
|
177
|
-
var
|
|
178
|
-
var
|
|
120
|
+
var de = (t4) => new h(t4);
|
|
121
|
+
var h = (_class2 = class extends _webstreamspolyfill.TransformStream {
|
|
179
122
|
__init3() {this.count = 0}
|
|
180
123
|
|
|
181
|
-
constructor(
|
|
182
|
-
super({
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
if (this.count > this.skip) {
|
|
186
|
-
controller.enqueue(chunk);
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
});_class2.prototype.__init3.call(this);;
|
|
190
|
-
this.skip = skip2;
|
|
124
|
+
constructor(e) {
|
|
125
|
+
super({ transform: (r2, n) => {
|
|
126
|
+
this.count++, this.count > this.skip && n.enqueue(r2);
|
|
127
|
+
} });_class2.prototype.__init3.call(this);, this.skip = e;
|
|
191
128
|
}
|
|
192
129
|
}, _class2);
|
|
193
|
-
var
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
130
|
+
var pe = (t4) => new (0, _webstreamspolyfill.TransformStream)({ transform(e, r2) {
|
|
131
|
+
r2.enqueue(e), t4(e) && r2.terminate();
|
|
132
|
+
} });
|
|
133
|
+
var le = (t4) => new (0, _webstreamspolyfill.TransformStream)({ async transform(e, r2) {
|
|
134
|
+
if (!t4(e)) {
|
|
135
|
+
r2.enqueue(e);
|
|
136
|
+
return;
|
|
199
137
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
controller.enqueue(chunk);
|
|
205
|
-
return;
|
|
206
|
-
}
|
|
207
|
-
await Promise.resolve();
|
|
208
|
-
controller.terminate();
|
|
209
|
-
}
|
|
210
|
-
});
|
|
211
|
-
var take = (limit) => new TakeTransformStream(limit);
|
|
212
|
-
var TakeTransformStream = (_class3 = class extends _webstreamspolyfill.TransformStream {
|
|
138
|
+
await Promise.resolve(), r2.terminate();
|
|
139
|
+
} });
|
|
140
|
+
var ce = (t4) => new C(t4);
|
|
141
|
+
var C = (_class3 = class extends _webstreamspolyfill.TransformStream {
|
|
213
142
|
__init4() {this.count = 0}
|
|
214
143
|
|
|
215
|
-
constructor(
|
|
216
|
-
super({
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
this.count++;
|
|
220
|
-
controller.enqueue(chunk);
|
|
221
|
-
} else {
|
|
222
|
-
controller.terminate();
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
});_class3.prototype.__init4.call(this);;
|
|
226
|
-
this.limit = limit;
|
|
144
|
+
constructor(e) {
|
|
145
|
+
super({ transform: (r2, n) => {
|
|
146
|
+
this.count < this.limit ? (this.count++, n.enqueue(r2)) : n.terminate();
|
|
147
|
+
} });_class3.prototype.__init4.call(this);, this.limit = e;
|
|
227
148
|
}
|
|
228
149
|
}, _class3);
|
|
229
|
-
var
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
controller.enqueue(chunk);
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
var streamTransformations = {
|
|
245
|
-
filter,
|
|
246
|
-
take,
|
|
247
|
-
TakeTransformStream,
|
|
248
|
-
skip,
|
|
249
|
-
SkipTransformStream,
|
|
250
|
-
map,
|
|
251
|
-
notifyAboutNoActiveReadersStream,
|
|
252
|
-
NotifyAboutNoActiveReadersStream,
|
|
253
|
-
reduce,
|
|
254
|
-
ReduceTransformStream,
|
|
255
|
-
retry: retryStream,
|
|
256
|
-
stopAfter,
|
|
257
|
-
stopOn,
|
|
258
|
-
waitAtMost
|
|
259
|
-
};
|
|
260
|
-
var { retry: retry2 } = streamTransformations;
|
|
150
|
+
var ue = (t4) => new (0, _webstreamspolyfill.TransformStream)({ start(e) {
|
|
151
|
+
let r2 = setTimeout(() => {
|
|
152
|
+
e.terminate();
|
|
153
|
+
}, t4), n = e.terminate.bind(e);
|
|
154
|
+
e.terminate = () => {
|
|
155
|
+
clearTimeout(r2), n();
|
|
156
|
+
};
|
|
157
|
+
}, transform(e, r2) {
|
|
158
|
+
r2.enqueue(e);
|
|
159
|
+
} });
|
|
160
|
+
var fe = { filter: ae, take: ce, TakeTransformStream: C, skip: de, SkipTransformStream: h, map: se, notifyAboutNoActiveReadersStream: O, NotifyAboutNoActiveReadersStream: S, reduce: ie, ReduceTransformStream: g2, retry: me, stopAfter: pe, stopOn: le, waitAtMost: ue };
|
|
161
|
+
var { retry: Be } = fe;
|
|
261
162
|
|
|
262
163
|
// src/eventStore/eventstoreDBEventStore.ts
|
|
263
164
|
|
|
@@ -270,7 +171,7 @@ var { retry: retry2 } = streamTransformations;
|
|
|
270
171
|
var _dbclient = require('@eventstore/db-client');
|
|
271
172
|
var _web = require('stream/web');
|
|
272
173
|
var _stream = require('stream');
|
|
273
|
-
var { map
|
|
174
|
+
var { map } = fe;
|
|
274
175
|
var toEventStoreDBReadOptions = (options) => {
|
|
275
176
|
return options ? {
|
|
276
177
|
fromRevision: "from" in options ? options.from : void 0,
|
|
@@ -294,7 +195,7 @@ var getEventStoreDBEventStore = (eventStore) => {
|
|
|
294
195
|
state = evolve(state, mapFromESDBEvent(event));
|
|
295
196
|
currentStreamVersion = event.revision;
|
|
296
197
|
}
|
|
297
|
-
|
|
198
|
+
N(
|
|
298
199
|
currentStreamVersion,
|
|
299
200
|
expectedStreamVersion,
|
|
300
201
|
EventStoreDBEventStoreDefaultStreamVersion
|
|
@@ -362,7 +263,7 @@ var getEventStoreDBEventStore = (eventStore) => {
|
|
|
362
263
|
};
|
|
363
264
|
} catch (error) {
|
|
364
265
|
if (error instanceof _dbclient.WrongExpectedVersionError) {
|
|
365
|
-
throw new
|
|
266
|
+
throw new b(
|
|
366
267
|
error.actualVersion,
|
|
367
268
|
toExpectedVersion(error.expectedVersion)
|
|
368
269
|
);
|
|
@@ -388,16 +289,16 @@ var mapFromESDBEvent = (event) => {
|
|
|
388
289
|
};
|
|
389
290
|
var toExpectedRevision = (expected) => {
|
|
390
291
|
if (expected === void 0) return _dbclient.ANY;
|
|
391
|
-
if (expected ===
|
|
392
|
-
if (expected ==
|
|
393
|
-
if (expected ==
|
|
292
|
+
if (expected === D) return _dbclient.ANY;
|
|
293
|
+
if (expected == F) return _dbclient.NO_STREAM;
|
|
294
|
+
if (expected == xe) return _dbclient.STREAM_EXISTS;
|
|
394
295
|
return expected;
|
|
395
296
|
};
|
|
396
297
|
var toExpectedVersion = (expected) => {
|
|
397
|
-
if (expected === void 0) return
|
|
398
|
-
if (expected === _dbclient.ANY) return
|
|
399
|
-
if (expected == _dbclient.NO_STREAM) return
|
|
400
|
-
if (expected == _dbclient.STREAM_EXISTS) return
|
|
298
|
+
if (expected === void 0) return D;
|
|
299
|
+
if (expected === _dbclient.ANY) return D;
|
|
300
|
+
if (expected == _dbclient.NO_STREAM) return F;
|
|
301
|
+
if (expected == _dbclient.STREAM_EXISTS) return xe;
|
|
401
302
|
return expected;
|
|
402
303
|
};
|
|
403
304
|
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/emmett/emmett/src/packages/emmett-esdb/dist/index.cjs","../../emmett/src/validation/index.ts","../../emmett/src/errors/index.ts","../../emmett/src/eventStore/inMemoryEventStore.ts","../../emmett/src/eventStore/subscriptions/caughtUpTransformStream.ts","../../emmett/src/eventStore/subscriptions/streamingCoordinator.ts","../../emmett/src/streaming/transformations/notifyAboutNoActiveReaders.ts","../../emmett/src/utils/retry.ts","../../emmett/src/streaming/generators/fromArray.ts","../../emmett/src/streaming/restream.ts","../../emmett/src/streaming/transformations/filter.ts","../../emmett/src/streaming/transformations/map.ts","../../emmett/src/streaming/transformations/reduce.ts","../../emmett/src/streaming/transformations/retry.ts","../../emmett/src/streaming/transformations/skip.ts","../../emmett/src/streaming/transformations/stopAfter.ts","../../emmett/src/streaming/transformations/stopOn.ts","../../emmett/src/streaming/transformations/take.ts","../../emmett/src/streaming/transformations/waitAtMost.ts","../../emmett/src/eventStore/expectedVersion.ts","../../emmett/src/streaming/transformations/index.ts","../src/eventStore/eventstoreDBEventStore.ts"],"names":[],"mappings":"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","file":"/home/runner/work/emmett/emmett/src/packages/emmett-esdb/dist/index.cjs","sourcesContent":[null,"import { ValidationError } from '../errors';\n\nexport const enum ValidationErrors {\n NOT_A_NONEMPTY_STRING = 'NOT_A_NONEMPTY_STRING',\n NOT_A_POSITIVE_NUMBER = 'NOT_A_POSITIVE_NUMBER',\n NOT_AN_UNSIGNED_BIGINT = 'NOT_AN_UNSIGNED_BIGINT',\n}\n\nexport const isNumber = (val: unknown): val is number =>\n typeof val === 'number' && val === val;\n\nexport const isString = (val: unknown): val is string =>\n typeof val === 'string';\n\nexport const assertNotEmptyString = (value: unknown): string => {\n if (!isString(value) || value.length === 0) {\n throw new ValidationError(ValidationErrors.NOT_A_NONEMPTY_STRING);\n }\n return value;\n};\n\nexport const assertPositiveNumber = (value: unknown): number => {\n if (!isNumber(value) || value <= 0) {\n throw new ValidationError(ValidationErrors.NOT_A_POSITIVE_NUMBER);\n }\n return value;\n};\n\nexport const assertUnsignedBigInt = (value: string): bigint => {\n const number = BigInt(value);\n if (number < 0) {\n throw new ValidationError(ValidationErrors.NOT_AN_UNSIGNED_BIGINT);\n }\n return number;\n};\n\nexport * from './dates';\n","import { isNumber, isString } from '../validation';\n\nexport type ErrorConstructor<ErrorType extends Error> = new (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ...args: any[]\n) => ErrorType;\n\nexport const isErrorConstructor = <ErrorType extends Error>(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n expect: Function,\n): expect is ErrorConstructor<ErrorType> => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return (\n typeof expect === 'function' &&\n expect.prototype &&\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect.prototype.constructor === expect\n );\n};\n\nexport class EmmettError extends Error {\n public errorCode: number;\n\n constructor(\n options?: { errorCode: number; message?: string } | string | number,\n ) {\n const errorCode =\n options && typeof options === 'object' && 'errorCode' in options\n ? options.errorCode\n : isNumber(options)\n ? options\n : 500;\n const message =\n options && typeof options === 'object' && 'message' in options\n ? options.message\n : isString(options)\n ? options\n : `Error with status code '${errorCode}' ocurred during Emmett processing`;\n\n super(message);\n this.errorCode = errorCode;\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, EmmettError.prototype);\n }\n}\n\nexport class ConcurrencyError extends EmmettError {\n constructor(\n public current: string | undefined,\n public expected: string,\n message?: string,\n ) {\n super({\n errorCode: 412,\n message:\n message ??\n `Expected version ${expected.toString()} does not match current ${current?.toString()}`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ConcurrencyError.prototype);\n }\n}\n\nexport class ValidationError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: 400,\n message: message ?? `Validation Error ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\nexport class IllegalStateError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: 403,\n message: message ?? `Illegal State ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, IllegalStateError.prototype);\n }\n}\n\nexport class NotFoundError extends EmmettError {\n constructor(options?: { id: string; type: string; message?: string }) {\n super({\n errorCode: 404,\n message:\n options?.message ??\n (options?.id\n ? options.type\n ? `${options.type} with ${options.id} was not found during Emmett processing`\n : `State with ${options.id} was not found during Emmett processing`\n : options?.type\n ? `${options.type} was not found during Emmett processing`\n : 'State was not found during Emmett processing'),\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, NotFoundError.prototype);\n }\n}\n","import { v4 as uuid } from 'uuid';\nimport type {\n Event,\n ReadEvent,\n ReadEventMetadataWithGlobalPosition,\n} from '../typing';\nimport {\n type AggregateStreamOptions,\n type AggregateStreamResult,\n type AppendToStreamOptions,\n type AppendToStreamResult,\n type DefaultStreamVersionType,\n type EventStore,\n type ReadStreamOptions,\n type ReadStreamResult,\n} from './eventStore';\nimport { assertExpectedVersionMatchesCurrent } from './expectedVersion';\nimport { StreamingCoordinator } from './subscriptions';\n\nexport type EventHandler<E extends Event = Event> = (\n eventEnvelope: ReadEvent<E>,\n) => void;\n\nexport const InMemoryEventStoreDefaultStreamVersion = 0n;\n\nexport const getInMemoryEventStore = (): EventStore<\n DefaultStreamVersionType,\n ReadEventMetadataWithGlobalPosition\n> => {\n const streams = new Map<\n string,\n ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[]\n >();\n const streamingCoordinator = StreamingCoordinator();\n\n const getAllEventsCount = () => {\n return Array.from<ReadEvent[]>(streams.values())\n .map((s) => s.length)\n .reduce((p, c) => p + c, 0);\n };\n\n return {\n async aggregateStream<State, EventType extends Event>(\n streamName: string,\n options: AggregateStreamOptions<State, EventType>,\n ): Promise<AggregateStreamResult<State>> {\n const { evolve, initialState, read } = options;\n\n const result = await this.readStream<EventType>(streamName, read);\n\n const events = result?.events ?? [];\n\n return {\n currentStreamVersion: BigInt(events.length),\n state: events.reduce(evolve, initialState()),\n streamExists: result.streamExists,\n };\n },\n\n readStream: <EventType extends Event>(\n streamName: string,\n options?: ReadStreamOptions,\n ): Promise<\n ReadStreamResult<\n EventType,\n DefaultStreamVersionType,\n ReadEventMetadataWithGlobalPosition\n >\n > => {\n const events = streams.get(streamName);\n const currentStreamVersion = events\n ? BigInt(events.length)\n : InMemoryEventStoreDefaultStreamVersion;\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n options?.expectedStreamVersion,\n InMemoryEventStoreDefaultStreamVersion,\n );\n\n const from = Number(options && 'from' in options ? options.from : 0);\n const to = Number(\n options && 'to' in options\n ? options.to\n : options && 'maxCount' in options && options.maxCount\n ? options.from + options.maxCount\n : (events?.length ?? 1),\n );\n\n const resultEvents =\n events !== undefined && events.length > 0\n ? events\n .map(\n (e) =>\n e as ReadEvent<\n EventType,\n ReadEventMetadataWithGlobalPosition\n >,\n )\n .slice(from, to)\n : [];\n\n const result: ReadStreamResult<\n EventType,\n DefaultStreamVersionType,\n ReadEventMetadataWithGlobalPosition\n > = {\n currentStreamVersion,\n events: resultEvents,\n streamExists: events !== undefined && events.length > 0,\n };\n\n return Promise.resolve(result);\n },\n\n appendToStream: async <EventType extends Event>(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions,\n ): Promise<AppendToStreamResult> => {\n const currentEvents = streams.get(streamName) ?? [];\n const currentStreamVersion =\n currentEvents.length > 0\n ? BigInt(currentEvents.length)\n : InMemoryEventStoreDefaultStreamVersion;\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n options?.expectedStreamVersion,\n InMemoryEventStoreDefaultStreamVersion,\n );\n\n const newEvents: ReadEvent<\n EventType,\n ReadEventMetadataWithGlobalPosition\n >[] = events.map((event, index) => {\n return {\n ...event,\n metadata: {\n ...(event.metadata ?? {}),\n streamName,\n eventId: uuid(),\n streamPosition: BigInt(currentEvents.length + index + 1),\n globalPosition: BigInt(getAllEventsCount() + index + 1),\n },\n };\n });\n\n const positionOfLastEventInTheStream = BigInt(\n newEvents.slice(-1)[0]!.metadata.streamPosition,\n );\n\n streams.set(streamName, [...currentEvents, ...newEvents]);\n await streamingCoordinator.notify(newEvents);\n\n const result: AppendToStreamResult = {\n nextExpectedStreamVersion: positionOfLastEventInTheStream,\n createdNewStream:\n currentStreamVersion === InMemoryEventStoreDefaultStreamVersion,\n };\n\n return result;\n },\n\n //streamEvents: streamingCoordinator.stream,\n };\n};\n","import { TransformStream } from 'web-streams-polyfill';\nimport type {\n Event,\n ReadEvent,\n ReadEventMetadataWithGlobalPosition,\n} from '../../typing';\nimport { globalStreamCaughtUp, type GlobalSubscriptionEvent } from '../events';\n\nexport const streamTrackingGlobalPosition = (\n currentEvents: ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[],\n) => new CaughtUpTransformStream(currentEvents);\n\nexport class CaughtUpTransformStream extends TransformStream<\n ReadEvent<Event, ReadEventMetadataWithGlobalPosition>,\n | ReadEvent<Event, ReadEventMetadataWithGlobalPosition>\n | GlobalSubscriptionEvent\n> {\n private _currentPosition: bigint;\n private _logPosition: bigint;\n\n constructor(events: ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[]) {\n super({\n start: (controller) => {\n let globalPosition = 0n;\n for (const event of events) {\n controller.enqueue(event);\n globalPosition = event.metadata.globalPosition;\n }\n controller.enqueue(globalStreamCaughtUp({ globalPosition }));\n },\n transform: (event, controller) => {\n this._currentPosition = event.metadata.globalPosition;\n controller.enqueue(event);\n\n if (this._currentPosition < this._logPosition) return;\n\n controller.enqueue(\n globalStreamCaughtUp({ globalPosition: this._currentPosition }),\n );\n },\n });\n\n this._currentPosition = this._logPosition =\n events.length > 0\n ? events[events.length - 1]!.metadata.globalPosition\n : 0n;\n }\n\n public set logPosition(value: bigint) {\n this._logPosition = value;\n }\n}\n","import { v4 as uuid } from 'uuid';\nimport { notifyAboutNoActiveReadersStream } from '../../streaming/transformations/notifyAboutNoActiveReaders';\nimport { writeToStream } from '../../streaming/writers';\nimport type {\n Event,\n ReadEvent,\n ReadEventMetadataWithGlobalPosition,\n} from '../../typing';\nimport {\n CaughtUpTransformStream,\n streamTrackingGlobalPosition,\n} from './caughtUpTransformStream';\n\nexport const StreamingCoordinator = () => {\n const allEvents: ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[] = [];\n const listeners = new Map<string, CaughtUpTransformStream>();\n\n return {\n notify: async (\n events: ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[],\n ) => {\n if (events.length === 0) return;\n\n allEvents.push(...events);\n\n for (const listener of listeners.values()) {\n listener.logPosition =\n events[events.length - 1]!.metadata.globalPosition;\n\n await writeToStream(listener, events);\n }\n },\n\n stream: () => {\n const streamId = uuid();\n const transformStream = streamTrackingGlobalPosition(allEvents);\n\n listeners.set(streamId, transformStream);\n return transformStream.readable.pipeThrough(\n notifyAboutNoActiveReadersStream(\n (stream) => {\n if (listeners.has(stream.streamId))\n listeners.delete(stream.streamId);\n },\n { streamId },\n ),\n );\n },\n };\n};\n","import { v4 as uuid } from 'uuid';\nimport { TransformStream } from 'web-streams-polyfill';\n\nexport const notifyAboutNoActiveReadersStream = <Item>(\n onNoActiveReaderCallback: (\n stream: NotifyAboutNoActiveReadersStream<Item>,\n ) => void,\n options: { streamId?: string; intervalCheckInMs?: number } = {},\n) => new NotifyAboutNoActiveReadersStream(onNoActiveReaderCallback, options);\n\nexport class NotifyAboutNoActiveReadersStream<Item> extends TransformStream<\n Item,\n Item\n> {\n private checkInterval: NodeJS.Timeout | null = null;\n public readonly streamId: string;\n private _isStopped: boolean = false;\n public get hasActiveSubscribers() {\n return !this._isStopped;\n }\n\n constructor(\n private onNoActiveReaderCallback: (\n stream: NotifyAboutNoActiveReadersStream<Item>,\n ) => void,\n options: { streamId?: string; intervalCheckInMs?: number } = {},\n ) {\n super({\n cancel: (reason) => {\n console.log('Stream was canceled. Reason:', reason);\n this.stopChecking();\n },\n });\n this.streamId = options?.streamId ?? uuid();\n\n this.onNoActiveReaderCallback = onNoActiveReaderCallback;\n\n this.startChecking(options?.intervalCheckInMs ?? 20);\n }\n\n private startChecking(interval: number) {\n this.checkInterval = setInterval(() => {\n this.checkNoActiveReader();\n }, interval);\n }\n\n private stopChecking() {\n if (!this.checkInterval) return;\n\n clearInterval(this.checkInterval);\n this.checkInterval = null;\n this._isStopped = true;\n this.onNoActiveReaderCallback(this);\n }\n\n private checkNoActiveReader() {\n if (!this.readable.locked && !this._isStopped) {\n this.stopChecking();\n }\n }\n}\n","import retry from 'async-retry';\n\nexport type AsyncRetryOptions = retry.Options & {\n shouldRetryError?: (error: unknown) => boolean;\n};\n\nexport const NoRetries: AsyncRetryOptions = { retries: 0 };\n\nexport const asyncRetry = async <T>(\n fn: () => Promise<T>,\n opts?: AsyncRetryOptions,\n): Promise<T> => {\n if (opts === undefined || opts.retries === 0) return fn();\n\n return retry(\n async (bail) => {\n try {\n return await fn();\n } catch (error) {\n if (opts?.shouldRetryError && !opts.shouldRetryError(error)) {\n bail(error as Error);\n }\n throw error;\n }\n },\n opts ?? { retries: 0 },\n );\n};\n","import { ReadableStream } from 'web-streams-polyfill';\n\nexport const fromArray = <T>(chunks: T[]) =>\n new ReadableStream<T>({\n start(controller) {\n for (const chunk of chunks) controller.enqueue(chunk);\n controller.close();\n },\n });\n","import {\n type ReadableStream,\n type ReadableStreamDefaultReadResult,\n type TransformStreamDefaultController,\n} from 'web-streams-polyfill';\nimport type { AsyncRetryOptions } from '../utils';\nimport type { Decoder } from './decoders';\nimport { DefaultDecoder } from './decoders/composite';\nimport { streamTransformations } from './transformations';\n\nconst { retry } = streamTransformations;\n\nexport const restream = <\n Source = unknown,\n Transformed = Source,\n StreamType = Source,\n>(\n createSourceStream: () => ReadableStream<StreamType>,\n transform: (input: Source) => Transformed = (source) =>\n source as unknown as Transformed,\n retryOptions: AsyncRetryOptions = { forever: true, minTimeout: 25 },\n decoder: Decoder<StreamType, Source> = new DefaultDecoder<Source>(),\n): ReadableStream<Transformed> =>\n retry(createSourceStream, handleChunk(transform, decoder), retryOptions)\n .readable;\n\nconst handleChunk =\n <Source = unknown, Transformed = Source, StreamType = Source>(\n transform: (input: Source) => Transformed = (source) =>\n source as unknown as Transformed,\n decoder: Decoder<StreamType, Source> = new DefaultDecoder<Source>(),\n ) =>\n (\n readResult: ReadableStreamDefaultReadResult<StreamType>,\n controller: TransformStreamDefaultController<Transformed>,\n ): void => {\n const { done: isDone, value } = readResult;\n\n if (value) decoder.addToBuffer(value);\n\n if (!isDone && !decoder.hasCompleteMessage()) return;\n\n decodeAndTransform(decoder, transform, controller);\n };\n\nconst decodeAndTransform = <StreamType, Source, Transformed = Source>(\n decoder: Decoder<StreamType, Source>,\n transform: (input: Source) => Transformed,\n controller: TransformStreamDefaultController<Transformed>,\n) => {\n try {\n const decoded = decoder.decode();\n if (!decoded) return; // TODO: Add a proper handling of decode errors\n\n const transformed = transform(decoded);\n controller.enqueue(transformed);\n } catch (error) {\n controller.error(new Error(`Decoding error: ${error?.toString()}`));\n }\n};\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const filter = <Item>(filter: (item: Item) => boolean) =>\n new TransformStream<Item, Item>({\n transform(chunk, controller) {\n if (filter(chunk)) {\n controller.enqueue(chunk);\n }\n },\n });\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const map = <From, To>(map: (item: From) => To) =>\n new TransformStream<From, To>({\n transform(chunk, controller) {\n controller.enqueue(map(chunk));\n },\n });\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const reduce = <I, O>(\n reducer: (accumulator: O, chunk: I) => O,\n initialValue: O,\n) => new ReduceTransformStream<I, O>(reducer, initialValue);\n\nexport class ReduceTransformStream<I, O> extends TransformStream<I, O> {\n private accumulator: O;\n private reducer: (accumulator: O, chunk: I) => O;\n\n constructor(reducer: (accumulator: O, chunk: I) => O, initialValue: O) {\n super({\n transform: (chunk) => {\n this.accumulator = this.reducer(this.accumulator, chunk);\n },\n flush: (controller) => {\n controller.enqueue(this.accumulator);\n controller.terminate();\n },\n });\n\n this.accumulator = initialValue;\n this.reducer = reducer;\n }\n}\n","import {\n type ReadableStream,\n type ReadableStreamDefaultReadResult,\n TransformStream,\n type TransformStreamDefaultController,\n} from 'web-streams-polyfill';\nimport { type AsyncRetryOptions, asyncRetry } from '../../utils';\n\nexport const retryStream = <\n Source = unknown,\n Transformed = Source,\n StreamType = Source,\n>(\n createSourceStream: () => ReadableStream<StreamType>,\n handleChunk: (\n readResult: ReadableStreamDefaultReadResult<StreamType>,\n controller: TransformStreamDefaultController<Transformed>,\n ) => Promise<void> | void,\n retryOptions: AsyncRetryOptions = { forever: true, minTimeout: 25 },\n): TransformStream<Source, Transformed> =>\n new TransformStream<Source, Transformed>({\n start(controller) {\n asyncRetry(\n () => onRestream(createSourceStream, handleChunk, controller),\n retryOptions,\n ).catch((error) => {\n controller.error(error);\n });\n },\n });\n\nconst onRestream = async <StreamType, Source, Transformed = Source>(\n createSourceStream: () => ReadableStream<StreamType>,\n handleChunk: (\n readResult: ReadableStreamDefaultReadResult<StreamType>,\n controller: TransformStreamDefaultController<Transformed>,\n ) => Promise<void> | void,\n controller: TransformStreamDefaultController<Transformed>,\n): Promise<void> => {\n const sourceStream = createSourceStream();\n const reader = sourceStream.getReader();\n\n try {\n let done: boolean;\n\n do {\n const result = await reader.read();\n done = result.done;\n\n await handleChunk(result, controller);\n\n if (done) {\n controller.terminate();\n }\n } while (!done);\n } finally {\n reader.releaseLock();\n }\n};\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const skip = <T>(limit: number) => new SkipTransformStream<T>(limit);\n\nexport class SkipTransformStream<T> extends TransformStream<T, T> {\n private count = 0;\n private skip: number;\n\n constructor(skip: number) {\n super({\n transform: (chunk, controller) => {\n this.count++;\n if (this.count > this.skip) {\n controller.enqueue(chunk);\n }\n },\n });\n\n this.skip = skip;\n }\n}\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const stopAfter = <Item>(stopCondition: (item: Item) => boolean) =>\n new TransformStream<Item, Item>({\n transform(chunk, controller) {\n controller.enqueue(chunk);\n\n if (stopCondition(chunk)) {\n controller.terminate();\n }\n },\n });\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const stopOn = <Item>(stopCondition: (item: Item) => boolean) =>\n new TransformStream<Item, Item>({\n async transform(chunk, controller) {\n if (!stopCondition(chunk)) {\n controller.enqueue(chunk);\n return;\n }\n await Promise.resolve();\n controller.terminate();\n },\n });\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const take = <T>(limit: number) => new TakeTransformStream<T>(limit);\n\nexport class TakeTransformStream<T> extends TransformStream<T, T> {\n private count = 0;\n private limit: number;\n\n constructor(limit: number) {\n super({\n transform: (chunk, controller) => {\n if (this.count < this.limit) {\n this.count++;\n controller.enqueue(chunk);\n } else {\n controller.terminate();\n }\n },\n });\n\n this.limit = limit;\n }\n}\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const waitAtMost = <Item>(waitTimeInMs: number) =>\n new TransformStream<Item, Item>({\n start(controller) {\n const timeoutId = setTimeout(() => {\n controller.terminate();\n }, waitTimeInMs);\n\n const originalTerminate = controller.terminate.bind(controller);\n\n // Clear the timeout if the stream is terminated early\n controller.terminate = () => {\n clearTimeout(timeoutId);\n originalTerminate();\n };\n },\n transform(chunk, controller) {\n controller.enqueue(chunk);\n },\n });\n","import { ConcurrencyError } from '../errors';\nimport type { Flavour } from '../typing';\nimport type { DefaultStreamVersionType } from './eventStore';\n\nexport type ExpectedStreamVersion<VersionType = DefaultStreamVersionType> =\n | ExpectedStreamVersionWithValue<VersionType>\n | ExpectedStreamVersionGeneral;\n\nexport type ExpectedStreamVersionWithValue<\n VersionType = DefaultStreamVersionType,\n> = Flavour<VersionType, 'StreamVersion'>;\n\nexport type ExpectedStreamVersionGeneral = Flavour<\n 'STREAM_EXISTS' | 'STREAM_DOES_NOT_EXIST' | 'NO_CONCURRENCY_CHECK',\n 'StreamVersion'\n>;\n\nexport const STREAM_EXISTS = 'STREAM_EXISTS' as ExpectedStreamVersionGeneral;\nexport const STREAM_DOES_NOT_EXIST =\n 'STREAM_DOES_NOT_EXIST' as ExpectedStreamVersionGeneral;\nexport const NO_CONCURRENCY_CHECK =\n 'NO_CONCURRENCY_CHECK' as ExpectedStreamVersionGeneral;\n\nexport const matchesExpectedVersion = <\n StreamVersion = DefaultStreamVersionType,\n>(\n current: StreamVersion | undefined,\n expected: ExpectedStreamVersion<StreamVersion>,\n defaultVersion: StreamVersion,\n): boolean => {\n if (expected === NO_CONCURRENCY_CHECK) return true;\n\n if (expected == STREAM_DOES_NOT_EXIST) return current === defaultVersion;\n\n if (expected == STREAM_EXISTS) return current !== defaultVersion;\n\n return current === expected;\n};\n\nexport const assertExpectedVersionMatchesCurrent = <\n StreamVersion = DefaultStreamVersionType,\n>(\n current: StreamVersion,\n expected: ExpectedStreamVersion<StreamVersion> | undefined,\n defaultVersion: StreamVersion,\n): void => {\n expected ??= NO_CONCURRENCY_CHECK;\n\n if (!matchesExpectedVersion(current, expected, defaultVersion))\n throw new ExpectedVersionConflictError(current, expected);\n};\n\nexport class ExpectedVersionConflictError<\n VersionType = DefaultStreamVersionType,\n> extends ConcurrencyError {\n constructor(\n current: VersionType,\n expected: ExpectedStreamVersion<VersionType>,\n ) {\n super(current?.toString(), expected?.toString());\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ExpectedVersionConflictError.prototype);\n }\n}\n\nexport const isExpectedVersionConflictError = (\n error: unknown,\n): error is ExpectedVersionConflictError =>\n error instanceof ExpectedVersionConflictError;\n","import { filter } from './filter';\nimport { map } from './map';\nimport {\n notifyAboutNoActiveReadersStream,\n NotifyAboutNoActiveReadersStream,\n} from './notifyAboutNoActiveReaders';\nimport { reduce, ReduceTransformStream } from './reduce';\nimport { retryStream } from './retry';\nimport { skip, SkipTransformStream } from './skip';\nimport { stopAfter } from './stopAfter';\nimport { stopOn } from './stopOn';\nimport { take, TakeTransformStream } from './take';\nimport { waitAtMost } from './waitAtMost';\n\nexport const streamTransformations = {\n filter,\n take,\n TakeTransformStream,\n skip,\n SkipTransformStream,\n map,\n notifyAboutNoActiveReadersStream,\n NotifyAboutNoActiveReadersStream,\n reduce,\n ReduceTransformStream,\n retry: retryStream,\n stopAfter,\n stopOn,\n waitAtMost,\n};\n","import {\n ExpectedVersionConflictError,\n NO_CONCURRENCY_CHECK,\n STREAM_DOES_NOT_EXIST,\n STREAM_EXISTS,\n assertExpectedVersionMatchesCurrent,\n globalStreamCaughtUp,\n streamTransformations,\n type AggregateStreamOptions,\n type AggregateStreamResult,\n type AppendToStreamOptions,\n type AppendToStreamResult,\n type DefaultStreamVersionType,\n type Event,\n type EventStore,\n type ExpectedStreamVersion,\n type GlobalStreamCaughtUp,\n type ReadEvent,\n type ReadEventMetadataWithGlobalPosition,\n type ReadStreamOptions,\n type ReadStreamResult,\n} from '@event-driven-io/emmett';\nimport {\n ANY,\n STREAM_EXISTS as ESDB_STREAM_EXISTS,\n EventStoreDBClient,\n NO_STREAM,\n StreamNotFoundError,\n WrongExpectedVersionError,\n jsonEvent,\n type AllStreamResolvedEvent,\n type AllStreamSubscription,\n type AppendExpectedRevision,\n type ReadStreamOptions as ESDBReadStreamOptions,\n type JSONRecordedEvent,\n} from '@eventstore/db-client';\nimport { WritableStream, type ReadableStream } from 'node:stream/web';\nimport { Readable } from 'stream';\n\nconst { map } = streamTransformations;\n\nconst toEventStoreDBReadOptions = (\n options: ReadStreamOptions | undefined,\n): ESDBReadStreamOptions | undefined => {\n return options\n ? {\n fromRevision: 'from' in options ? options.from : undefined,\n maxCount:\n 'maxCount' in options\n ? options.maxCount\n : 'to' in options\n ? options.to\n : undefined,\n }\n : undefined;\n};\n\nexport const EventStoreDBEventStoreDefaultStreamVersion = -1n;\n\nexport const getEventStoreDBEventStore = (\n eventStore: EventStoreDBClient,\n): EventStore<\n DefaultStreamVersionType,\n ReadEventMetadataWithGlobalPosition\n> => {\n return {\n async aggregateStream<State, EventType extends Event>(\n streamName: string,\n options: AggregateStreamOptions<State, EventType>,\n ): Promise<AggregateStreamResult<State>> {\n const { evolve, initialState, read } = options;\n\n const expectedStreamVersion = read?.expectedStreamVersion;\n\n let state = initialState();\n let currentStreamVersion: bigint =\n EventStoreDBEventStoreDefaultStreamVersion;\n\n try {\n for await (const { event } of eventStore.readStream<EventType>(\n streamName,\n toEventStoreDBReadOptions(options.read),\n )) {\n if (!event) continue;\n\n state = evolve(state, mapFromESDBEvent<EventType>(event));\n currentStreamVersion = event.revision;\n }\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n expectedStreamVersion,\n EventStoreDBEventStoreDefaultStreamVersion,\n );\n\n return {\n currentStreamVersion,\n state,\n streamExists: true,\n };\n } catch (error) {\n if (error instanceof StreamNotFoundError) {\n return {\n currentStreamVersion,\n state,\n streamExists: false,\n };\n }\n\n throw error;\n }\n },\n\n readStream: async <EventType extends Event>(\n streamName: string,\n options?: ReadStreamOptions,\n ): Promise<\n ReadStreamResult<\n EventType,\n DefaultStreamVersionType,\n ReadEventMetadataWithGlobalPosition\n >\n > => {\n const events: ReadEvent<\n EventType,\n ReadEventMetadataWithGlobalPosition\n >[] = [];\n\n let currentStreamVersion: bigint =\n EventStoreDBEventStoreDefaultStreamVersion;\n\n try {\n for await (const { event } of eventStore.readStream<EventType>(\n streamName,\n toEventStoreDBReadOptions(options),\n )) {\n if (!event) continue;\n events.push(mapFromESDBEvent(event));\n currentStreamVersion = event.revision;\n }\n return {\n currentStreamVersion,\n events,\n streamExists: true,\n };\n } catch (error) {\n if (error instanceof StreamNotFoundError) {\n return {\n currentStreamVersion,\n events: [],\n streamExists: false,\n };\n }\n\n throw error;\n }\n },\n\n appendToStream: async <EventType extends Event>(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions,\n ): Promise<AppendToStreamResult> => {\n try {\n const serializedEvents = events.map(jsonEvent);\n\n const expectedRevision = toExpectedRevision(\n options?.expectedStreamVersion,\n );\n\n const appendResult = await eventStore.appendToStream(\n streamName,\n serializedEvents,\n {\n expectedRevision,\n },\n );\n\n return {\n nextExpectedStreamVersion: appendResult.nextExpectedRevision,\n createdNewStream:\n appendResult.nextExpectedRevision >=\n BigInt(serializedEvents.length),\n };\n } catch (error) {\n if (error instanceof WrongExpectedVersionError) {\n throw new ExpectedVersionConflictError(\n error.actualVersion,\n toExpectedVersion(error.expectedVersion),\n );\n }\n\n throw error;\n }\n },\n\n //streamEvents: streamEvents(eventStore),\n };\n};\n\nconst mapFromESDBEvent = <EventType extends Event = Event>(\n event: JSONRecordedEvent<EventType>,\n): ReadEvent<EventType, ReadEventMetadataWithGlobalPosition> => {\n return <ReadEvent<EventType, ReadEventMetadataWithGlobalPosition>>{\n type: event.type,\n data: event.data,\n metadata: {\n ...((event.metadata as ReadEventMetadataWithGlobalPosition) ??\n ({} as ReadEventMetadataWithGlobalPosition)),\n eventId: event.id,\n streamName: event.streamId,\n streamPosition: event.revision,\n globalPosition: event.position!.commit,\n },\n };\n};\n\nconst toExpectedRevision = (\n expected: ExpectedStreamVersion | undefined,\n): AppendExpectedRevision => {\n if (expected === undefined) return ANY;\n\n if (expected === NO_CONCURRENCY_CHECK) return ANY;\n\n if (expected == STREAM_DOES_NOT_EXIST) return NO_STREAM;\n\n if (expected == STREAM_EXISTS) return ESDB_STREAM_EXISTS;\n\n return expected as bigint;\n};\n\nconst toExpectedVersion = (\n expected: AppendExpectedRevision | undefined,\n): ExpectedStreamVersion => {\n if (expected === undefined) return NO_CONCURRENCY_CHECK;\n\n if (expected === ANY) return NO_CONCURRENCY_CHECK;\n\n if (expected == NO_STREAM) return STREAM_DOES_NOT_EXIST;\n\n if (expected == ESDB_STREAM_EXISTS) return STREAM_EXISTS;\n\n return expected;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst convertToWebReadableStream = (\n allStreamSubscription: AllStreamSubscription,\n): ReadableStream<AllStreamResolvedEvent | GlobalStreamCaughtUp> => {\n // Validate the input type\n if (!(allStreamSubscription instanceof Readable)) {\n throw new Error('Provided stream is not a Node.js Readable stream.');\n }\n\n let globalPosition = 0n;\n\n const stream = Readable.toWeb(\n allStreamSubscription,\n ) as ReadableStream<AllStreamResolvedEvent>;\n\n const writable = new WritableStream<\n AllStreamResolvedEvent | GlobalStreamCaughtUp\n >();\n\n allStreamSubscription.on('caughtUp', async () => {\n console.log(globalPosition);\n await writable.getWriter().write(globalStreamCaughtUp({ globalPosition }));\n });\n\n const transform = map<\n AllStreamResolvedEvent,\n AllStreamResolvedEvent | GlobalStreamCaughtUp\n >((event) => {\n if (event?.event?.position.commit)\n globalPosition = event.event?.position.commit;\n\n return event;\n });\n\n return stream.pipeThrough<AllStreamResolvedEvent | GlobalStreamCaughtUp>(\n transform,\n );\n};\n\n// const streamEvents = (eventStore: EventStoreDBClient) => () => {\n// return restream<\n// AllStreamResolvedEvent | GlobalSubscriptionEvent,\n// | ReadEvent<Event, ReadEventMetadataWithGlobalPosition>\n// | GlobalSubscriptionEvent\n// >(\n// (): ReadableStream<AllStreamResolvedEvent | GlobalSubscriptionEvent> =>\n// convertToWebReadableStream(\n// eventStore.subscribeToAll({\n// fromPosition: START,\n// filter: excludeSystemEvents(),\n// }),\n// ),\n// (\n// resolvedEvent: AllStreamResolvedEvent | GlobalSubscriptionEvent,\n// ): ReadEvent<Event, ReadEventMetadataWithGlobalPosition> =>\n// mapFromESDBEvent(resolvedEvent.event as JSONRecordedEvent<Event>),\n// );\n// };\n"]}
|
|
1
|
+
{"version":3,"sources":["/home/runner/work/emmett/emmett/src/packages/emmett-esdb/dist/index.cjs","../../emmett/src/validation/index.ts","../../emmett/src/errors/index.ts","../../emmett/src/eventStore/inMemoryEventStore.ts","../../emmett/src/eventStore/subscriptions/caughtUpTransformStream.ts","../../emmett/src/eventStore/subscriptions/streamingCoordinator.ts","../../emmett/src/streaming/transformations/notifyAboutNoActiveReaders.ts","../../emmett/src/utils/retry.ts","../../emmett/src/streaming/generators/fromArray.ts","../../emmett/src/streaming/restream.ts","../../emmett/src/streaming/transformations/filter.ts","../../emmett/src/streaming/transformations/map.ts","../../emmett/src/streaming/transformations/reduce.ts","../../emmett/src/streaming/transformations/retry.ts","../../emmett/src/streaming/transformations/skip.ts","../../emmett/src/streaming/transformations/stopAfter.ts","../../emmett/src/streaming/transformations/stopOn.ts","../../emmett/src/streaming/transformations/take.ts","../../emmett/src/streaming/transformations/waitAtMost.ts","../../emmett/src/eventStore/expectedVersion.ts","../../emmett/src/streaming/transformations/index.ts","../src/eventStore/eventstoreDBEventStore.ts"],"names":["ValidationErrors","isNumber","val","isString","EmmettError","_EmmettError","options","errorCode","message","ConcurrencyError","_ConcurrencyError","current","expected","onNoActiveReaderCallback","error","reducer","done","skip","limit","streamTransformations"],"mappings":"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","file":"/home/runner/work/emmett/emmett/src/packages/emmett-esdb/dist/index.cjs","sourcesContent":[null,"import { ValidationError } from '../errors';\n\nexport const enum ValidationErrors {\n NOT_A_NONEMPTY_STRING = 'NOT_A_NONEMPTY_STRING',\n NOT_A_POSITIVE_NUMBER = 'NOT_A_POSITIVE_NUMBER',\n NOT_AN_UNSIGNED_BIGINT = 'NOT_AN_UNSIGNED_BIGINT',\n}\n\nexport const isNumber = (val: unknown): val is number =>\n typeof val === 'number' && val === val;\n\nexport const isString = (val: unknown): val is string =>\n typeof val === 'string';\n\nexport const assertNotEmptyString = (value: unknown): string => {\n if (!isString(value) || value.length === 0) {\n throw new ValidationError(ValidationErrors.NOT_A_NONEMPTY_STRING);\n }\n return value;\n};\n\nexport const assertPositiveNumber = (value: unknown): number => {\n if (!isNumber(value) || value <= 0) {\n throw new ValidationError(ValidationErrors.NOT_A_POSITIVE_NUMBER);\n }\n return value;\n};\n\nexport const assertUnsignedBigInt = (value: string): bigint => {\n const number = BigInt(value);\n if (number < 0) {\n throw new ValidationError(ValidationErrors.NOT_AN_UNSIGNED_BIGINT);\n }\n return number;\n};\n\nexport * from './dates';\n","import { isNumber, isString } from '../validation';\n\nexport type ErrorConstructor<ErrorType extends Error> = new (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ...args: any[]\n) => ErrorType;\n\nexport const isErrorConstructor = <ErrorType extends Error>(\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n expect: Function,\n): expect is ErrorConstructor<ErrorType> => {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return\n return (\n typeof expect === 'function' &&\n expect.prototype &&\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n expect.prototype.constructor === expect\n );\n};\n\nexport class EmmettError extends Error {\n public errorCode: number;\n\n constructor(\n options?: { errorCode: number; message?: string } | string | number,\n ) {\n const errorCode =\n options && typeof options === 'object' && 'errorCode' in options\n ? options.errorCode\n : isNumber(options)\n ? options\n : 500;\n const message =\n options && typeof options === 'object' && 'message' in options\n ? options.message\n : isString(options)\n ? options\n : `Error with status code '${errorCode}' ocurred during Emmett processing`;\n\n super(message);\n this.errorCode = errorCode;\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, EmmettError.prototype);\n }\n}\n\nexport class ConcurrencyError extends EmmettError {\n constructor(\n public current: string | undefined,\n public expected: string,\n message?: string,\n ) {\n super({\n errorCode: 412,\n message:\n message ??\n `Expected version ${expected.toString()} does not match current ${current?.toString()}`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ConcurrencyError.prototype);\n }\n}\n\nexport class ValidationError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: 400,\n message: message ?? `Validation Error ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ValidationError.prototype);\n }\n}\n\nexport class IllegalStateError extends EmmettError {\n constructor(message?: string) {\n super({\n errorCode: 403,\n message: message ?? `Illegal State ocurred during Emmett processing`,\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, IllegalStateError.prototype);\n }\n}\n\nexport class NotFoundError extends EmmettError {\n constructor(options?: { id: string; type: string; message?: string }) {\n super({\n errorCode: 404,\n message:\n options?.message ??\n (options?.id\n ? options.type\n ? `${options.type} with ${options.id} was not found during Emmett processing`\n : `State with ${options.id} was not found during Emmett processing`\n : options?.type\n ? `${options.type} was not found during Emmett processing`\n : 'State was not found during Emmett processing'),\n });\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, NotFoundError.prototype);\n }\n}\n","import { v4 as uuid } from 'uuid';\nimport type {\n Event,\n ReadEvent,\n ReadEventMetadataWithGlobalPosition,\n} from '../typing';\nimport {\n type AggregateStreamOptions,\n type AggregateStreamResult,\n type AppendToStreamOptions,\n type AppendToStreamResult,\n type DefaultStreamVersionType,\n type EventStore,\n type ReadStreamOptions,\n type ReadStreamResult,\n} from './eventStore';\nimport { assertExpectedVersionMatchesCurrent } from './expectedVersion';\nimport { StreamingCoordinator } from './subscriptions';\n\nexport type EventHandler<E extends Event = Event> = (\n eventEnvelope: ReadEvent<E>,\n) => void;\n\nexport const InMemoryEventStoreDefaultStreamVersion = 0n;\n\nexport const getInMemoryEventStore = (): EventStore<\n DefaultStreamVersionType,\n ReadEventMetadataWithGlobalPosition\n> => {\n const streams = new Map<\n string,\n ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[]\n >();\n const streamingCoordinator = StreamingCoordinator();\n\n const getAllEventsCount = () => {\n return Array.from<ReadEvent[]>(streams.values())\n .map((s) => s.length)\n .reduce((p, c) => p + c, 0);\n };\n\n return {\n async aggregateStream<State, EventType extends Event>(\n streamName: string,\n options: AggregateStreamOptions<State, EventType>,\n ): Promise<AggregateStreamResult<State>> {\n const { evolve, initialState, read } = options;\n\n const result = await this.readStream<EventType>(streamName, read);\n\n const events = result?.events ?? [];\n\n return {\n currentStreamVersion: BigInt(events.length),\n state: events.reduce(evolve, initialState()),\n streamExists: result.streamExists,\n };\n },\n\n readStream: <EventType extends Event>(\n streamName: string,\n options?: ReadStreamOptions,\n ): Promise<\n ReadStreamResult<\n EventType,\n DefaultStreamVersionType,\n ReadEventMetadataWithGlobalPosition\n >\n > => {\n const events = streams.get(streamName);\n const currentStreamVersion = events\n ? BigInt(events.length)\n : InMemoryEventStoreDefaultStreamVersion;\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n options?.expectedStreamVersion,\n InMemoryEventStoreDefaultStreamVersion,\n );\n\n const from = Number(options && 'from' in options ? options.from : 0);\n const to = Number(\n options && 'to' in options\n ? options.to\n : options && 'maxCount' in options && options.maxCount\n ? options.from + options.maxCount\n : (events?.length ?? 1),\n );\n\n const resultEvents =\n events !== undefined && events.length > 0\n ? events\n .map(\n (e) =>\n e as ReadEvent<\n EventType,\n ReadEventMetadataWithGlobalPosition\n >,\n )\n .slice(from, to)\n : [];\n\n const result: ReadStreamResult<\n EventType,\n DefaultStreamVersionType,\n ReadEventMetadataWithGlobalPosition\n > = {\n currentStreamVersion,\n events: resultEvents,\n streamExists: events !== undefined && events.length > 0,\n };\n\n return Promise.resolve(result);\n },\n\n appendToStream: async <EventType extends Event>(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions,\n ): Promise<AppendToStreamResult> => {\n const currentEvents = streams.get(streamName) ?? [];\n const currentStreamVersion =\n currentEvents.length > 0\n ? BigInt(currentEvents.length)\n : InMemoryEventStoreDefaultStreamVersion;\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n options?.expectedStreamVersion,\n InMemoryEventStoreDefaultStreamVersion,\n );\n\n const newEvents: ReadEvent<\n EventType,\n ReadEventMetadataWithGlobalPosition\n >[] = events.map((event, index) => {\n return {\n ...event,\n metadata: {\n ...(event.metadata ?? {}),\n streamName,\n eventId: uuid(),\n streamPosition: BigInt(currentEvents.length + index + 1),\n globalPosition: BigInt(getAllEventsCount() + index + 1),\n },\n };\n });\n\n const positionOfLastEventInTheStream = BigInt(\n newEvents.slice(-1)[0]!.metadata.streamPosition,\n );\n\n streams.set(streamName, [...currentEvents, ...newEvents]);\n await streamingCoordinator.notify(newEvents);\n\n const result: AppendToStreamResult = {\n nextExpectedStreamVersion: positionOfLastEventInTheStream,\n createdNewStream:\n currentStreamVersion === InMemoryEventStoreDefaultStreamVersion,\n };\n\n return result;\n },\n\n //streamEvents: streamingCoordinator.stream,\n };\n};\n","import { TransformStream } from 'web-streams-polyfill';\nimport type {\n Event,\n ReadEvent,\n ReadEventMetadataWithGlobalPosition,\n} from '../../typing';\nimport { globalStreamCaughtUp, type GlobalSubscriptionEvent } from '../events';\n\nexport const streamTrackingGlobalPosition = (\n currentEvents: ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[],\n) => new CaughtUpTransformStream(currentEvents);\n\nexport class CaughtUpTransformStream extends TransformStream<\n ReadEvent<Event, ReadEventMetadataWithGlobalPosition>,\n | ReadEvent<Event, ReadEventMetadataWithGlobalPosition>\n | GlobalSubscriptionEvent\n> {\n private _currentPosition: bigint;\n private _logPosition: bigint;\n\n constructor(events: ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[]) {\n super({\n start: (controller) => {\n let globalPosition = 0n;\n for (const event of events) {\n controller.enqueue(event);\n globalPosition = event.metadata.globalPosition;\n }\n controller.enqueue(globalStreamCaughtUp({ globalPosition }));\n },\n transform: (event, controller) => {\n this._currentPosition = event.metadata.globalPosition;\n controller.enqueue(event);\n\n if (this._currentPosition < this._logPosition) return;\n\n controller.enqueue(\n globalStreamCaughtUp({ globalPosition: this._currentPosition }),\n );\n },\n });\n\n this._currentPosition = this._logPosition =\n events.length > 0\n ? events[events.length - 1]!.metadata.globalPosition\n : 0n;\n }\n\n public set logPosition(value: bigint) {\n this._logPosition = value;\n }\n}\n","import { v4 as uuid } from 'uuid';\nimport { notifyAboutNoActiveReadersStream } from '../../streaming/transformations/notifyAboutNoActiveReaders';\nimport { writeToStream } from '../../streaming/writers';\nimport type {\n Event,\n ReadEvent,\n ReadEventMetadataWithGlobalPosition,\n} from '../../typing';\nimport {\n CaughtUpTransformStream,\n streamTrackingGlobalPosition,\n} from './caughtUpTransformStream';\n\nexport const StreamingCoordinator = () => {\n const allEvents: ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[] = [];\n const listeners = new Map<string, CaughtUpTransformStream>();\n\n return {\n notify: async (\n events: ReadEvent<Event, ReadEventMetadataWithGlobalPosition>[],\n ) => {\n if (events.length === 0) return;\n\n allEvents.push(...events);\n\n for (const listener of listeners.values()) {\n listener.logPosition =\n events[events.length - 1]!.metadata.globalPosition;\n\n await writeToStream(listener, events);\n }\n },\n\n stream: () => {\n const streamId = uuid();\n const transformStream = streamTrackingGlobalPosition(allEvents);\n\n listeners.set(streamId, transformStream);\n return transformStream.readable.pipeThrough(\n notifyAboutNoActiveReadersStream(\n (stream) => {\n if (listeners.has(stream.streamId))\n listeners.delete(stream.streamId);\n },\n { streamId },\n ),\n );\n },\n };\n};\n","import { v4 as uuid } from 'uuid';\nimport { TransformStream } from 'web-streams-polyfill';\n\nexport const notifyAboutNoActiveReadersStream = <Item>(\n onNoActiveReaderCallback: (\n stream: NotifyAboutNoActiveReadersStream<Item>,\n ) => void,\n options: { streamId?: string; intervalCheckInMs?: number } = {},\n) => new NotifyAboutNoActiveReadersStream(onNoActiveReaderCallback, options);\n\nexport class NotifyAboutNoActiveReadersStream<Item> extends TransformStream<\n Item,\n Item\n> {\n private checkInterval: NodeJS.Timeout | null = null;\n public readonly streamId: string;\n private _isStopped: boolean = false;\n public get hasActiveSubscribers() {\n return !this._isStopped;\n }\n\n constructor(\n private onNoActiveReaderCallback: (\n stream: NotifyAboutNoActiveReadersStream<Item>,\n ) => void,\n options: { streamId?: string; intervalCheckInMs?: number } = {},\n ) {\n super({\n cancel: (reason) => {\n console.log('Stream was canceled. Reason:', reason);\n this.stopChecking();\n },\n });\n this.streamId = options?.streamId ?? uuid();\n\n this.onNoActiveReaderCallback = onNoActiveReaderCallback;\n\n this.startChecking(options?.intervalCheckInMs ?? 20);\n }\n\n private startChecking(interval: number) {\n this.checkInterval = setInterval(() => {\n this.checkNoActiveReader();\n }, interval);\n }\n\n private stopChecking() {\n if (!this.checkInterval) return;\n\n clearInterval(this.checkInterval);\n this.checkInterval = null;\n this._isStopped = true;\n this.onNoActiveReaderCallback(this);\n }\n\n private checkNoActiveReader() {\n if (!this.readable.locked && !this._isStopped) {\n this.stopChecking();\n }\n }\n}\n","import retry from 'async-retry';\n\nexport type AsyncRetryOptions = retry.Options & {\n shouldRetryError?: (error: unknown) => boolean;\n};\n\nexport const NoRetries: AsyncRetryOptions = { retries: 0 };\n\nexport const asyncRetry = async <T>(\n fn: () => Promise<T>,\n opts?: AsyncRetryOptions,\n): Promise<T> => {\n if (opts === undefined || opts.retries === 0) return fn();\n\n return retry(\n async (bail) => {\n try {\n return await fn();\n } catch (error) {\n if (opts?.shouldRetryError && !opts.shouldRetryError(error)) {\n bail(error as Error);\n }\n throw error;\n }\n },\n opts ?? { retries: 0 },\n );\n};\n","import { ReadableStream } from 'web-streams-polyfill';\n\nexport const fromArray = <T>(chunks: T[]) =>\n new ReadableStream<T>({\n start(controller) {\n for (const chunk of chunks) controller.enqueue(chunk);\n controller.close();\n },\n });\n","import {\n type ReadableStream,\n type ReadableStreamDefaultReadResult,\n type TransformStreamDefaultController,\n} from 'web-streams-polyfill';\nimport type { AsyncRetryOptions } from '../utils';\nimport type { Decoder } from './decoders';\nimport { DefaultDecoder } from './decoders/composite';\nimport { streamTransformations } from './transformations';\n\nconst { retry } = streamTransformations;\n\nexport const restream = <\n Source = unknown,\n Transformed = Source,\n StreamType = Source,\n>(\n createSourceStream: () => ReadableStream<StreamType>,\n transform: (input: Source) => Transformed = (source) =>\n source as unknown as Transformed,\n retryOptions: AsyncRetryOptions = { forever: true, minTimeout: 25 },\n decoder: Decoder<StreamType, Source> = new DefaultDecoder<Source>(),\n): ReadableStream<Transformed> =>\n retry(createSourceStream, handleChunk(transform, decoder), retryOptions)\n .readable;\n\nconst handleChunk =\n <Source = unknown, Transformed = Source, StreamType = Source>(\n transform: (input: Source) => Transformed = (source) =>\n source as unknown as Transformed,\n decoder: Decoder<StreamType, Source> = new DefaultDecoder<Source>(),\n ) =>\n (\n readResult: ReadableStreamDefaultReadResult<StreamType>,\n controller: TransformStreamDefaultController<Transformed>,\n ): void => {\n const { done: isDone, value } = readResult;\n\n if (value) decoder.addToBuffer(value);\n\n if (!isDone && !decoder.hasCompleteMessage()) return;\n\n decodeAndTransform(decoder, transform, controller);\n };\n\nconst decodeAndTransform = <StreamType, Source, Transformed = Source>(\n decoder: Decoder<StreamType, Source>,\n transform: (input: Source) => Transformed,\n controller: TransformStreamDefaultController<Transformed>,\n) => {\n try {\n const decoded = decoder.decode();\n if (!decoded) return; // TODO: Add a proper handling of decode errors\n\n const transformed = transform(decoded);\n controller.enqueue(transformed);\n } catch (error) {\n controller.error(new Error(`Decoding error: ${error?.toString()}`));\n }\n};\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const filter = <Item>(filter: (item: Item) => boolean) =>\n new TransformStream<Item, Item>({\n transform(chunk, controller) {\n if (filter(chunk)) {\n controller.enqueue(chunk);\n }\n },\n });\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const map = <From, To>(map: (item: From) => To) =>\n new TransformStream<From, To>({\n transform(chunk, controller) {\n controller.enqueue(map(chunk));\n },\n });\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const reduce = <I, O>(\n reducer: (accumulator: O, chunk: I) => O,\n initialValue: O,\n) => new ReduceTransformStream<I, O>(reducer, initialValue);\n\nexport class ReduceTransformStream<I, O> extends TransformStream<I, O> {\n private accumulator: O;\n private reducer: (accumulator: O, chunk: I) => O;\n\n constructor(reducer: (accumulator: O, chunk: I) => O, initialValue: O) {\n super({\n transform: (chunk) => {\n this.accumulator = this.reducer(this.accumulator, chunk);\n },\n flush: (controller) => {\n controller.enqueue(this.accumulator);\n controller.terminate();\n },\n });\n\n this.accumulator = initialValue;\n this.reducer = reducer;\n }\n}\n","import {\n type ReadableStream,\n type ReadableStreamDefaultReadResult,\n TransformStream,\n type TransformStreamDefaultController,\n} from 'web-streams-polyfill';\nimport { type AsyncRetryOptions, asyncRetry } from '../../utils';\n\nexport const retryStream = <\n Source = unknown,\n Transformed = Source,\n StreamType = Source,\n>(\n createSourceStream: () => ReadableStream<StreamType>,\n handleChunk: (\n readResult: ReadableStreamDefaultReadResult<StreamType>,\n controller: TransformStreamDefaultController<Transformed>,\n ) => Promise<void> | void,\n retryOptions: AsyncRetryOptions = { forever: true, minTimeout: 25 },\n): TransformStream<Source, Transformed> =>\n new TransformStream<Source, Transformed>({\n start(controller) {\n asyncRetry(\n () => onRestream(createSourceStream, handleChunk, controller),\n retryOptions,\n ).catch((error) => {\n controller.error(error);\n });\n },\n });\n\nconst onRestream = async <StreamType, Source, Transformed = Source>(\n createSourceStream: () => ReadableStream<StreamType>,\n handleChunk: (\n readResult: ReadableStreamDefaultReadResult<StreamType>,\n controller: TransformStreamDefaultController<Transformed>,\n ) => Promise<void> | void,\n controller: TransformStreamDefaultController<Transformed>,\n): Promise<void> => {\n const sourceStream = createSourceStream();\n const reader = sourceStream.getReader();\n\n try {\n let done: boolean;\n\n do {\n const result = await reader.read();\n done = result.done;\n\n await handleChunk(result, controller);\n\n if (done) {\n controller.terminate();\n }\n } while (!done);\n } finally {\n reader.releaseLock();\n }\n};\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const skip = <T>(limit: number) => new SkipTransformStream<T>(limit);\n\nexport class SkipTransformStream<T> extends TransformStream<T, T> {\n private count = 0;\n private skip: number;\n\n constructor(skip: number) {\n super({\n transform: (chunk, controller) => {\n this.count++;\n if (this.count > this.skip) {\n controller.enqueue(chunk);\n }\n },\n });\n\n this.skip = skip;\n }\n}\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const stopAfter = <Item>(stopCondition: (item: Item) => boolean) =>\n new TransformStream<Item, Item>({\n transform(chunk, controller) {\n controller.enqueue(chunk);\n\n if (stopCondition(chunk)) {\n controller.terminate();\n }\n },\n });\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const stopOn = <Item>(stopCondition: (item: Item) => boolean) =>\n new TransformStream<Item, Item>({\n async transform(chunk, controller) {\n if (!stopCondition(chunk)) {\n controller.enqueue(chunk);\n return;\n }\n await Promise.resolve();\n controller.terminate();\n },\n });\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const take = <T>(limit: number) => new TakeTransformStream<T>(limit);\n\nexport class TakeTransformStream<T> extends TransformStream<T, T> {\n private count = 0;\n private limit: number;\n\n constructor(limit: number) {\n super({\n transform: (chunk, controller) => {\n if (this.count < this.limit) {\n this.count++;\n controller.enqueue(chunk);\n } else {\n controller.terminate();\n }\n },\n });\n\n this.limit = limit;\n }\n}\n","import { TransformStream } from 'web-streams-polyfill';\n\nexport const waitAtMost = <Item>(waitTimeInMs: number) =>\n new TransformStream<Item, Item>({\n start(controller) {\n const timeoutId = setTimeout(() => {\n controller.terminate();\n }, waitTimeInMs);\n\n const originalTerminate = controller.terminate.bind(controller);\n\n // Clear the timeout if the stream is terminated early\n controller.terminate = () => {\n clearTimeout(timeoutId);\n originalTerminate();\n };\n },\n transform(chunk, controller) {\n controller.enqueue(chunk);\n },\n });\n","import { ConcurrencyError } from '../errors';\nimport type { Flavour } from '../typing';\nimport type { DefaultStreamVersionType } from './eventStore';\n\nexport type ExpectedStreamVersion<VersionType = DefaultStreamVersionType> =\n | ExpectedStreamVersionWithValue<VersionType>\n | ExpectedStreamVersionGeneral;\n\nexport type ExpectedStreamVersionWithValue<\n VersionType = DefaultStreamVersionType,\n> = Flavour<VersionType, 'StreamVersion'>;\n\nexport type ExpectedStreamVersionGeneral = Flavour<\n 'STREAM_EXISTS' | 'STREAM_DOES_NOT_EXIST' | 'NO_CONCURRENCY_CHECK',\n 'StreamVersion'\n>;\n\nexport const STREAM_EXISTS = 'STREAM_EXISTS' as ExpectedStreamVersionGeneral;\nexport const STREAM_DOES_NOT_EXIST =\n 'STREAM_DOES_NOT_EXIST' as ExpectedStreamVersionGeneral;\nexport const NO_CONCURRENCY_CHECK =\n 'NO_CONCURRENCY_CHECK' as ExpectedStreamVersionGeneral;\n\nexport const matchesExpectedVersion = <\n StreamVersion = DefaultStreamVersionType,\n>(\n current: StreamVersion | undefined,\n expected: ExpectedStreamVersion<StreamVersion>,\n defaultVersion: StreamVersion,\n): boolean => {\n if (expected === NO_CONCURRENCY_CHECK) return true;\n\n if (expected == STREAM_DOES_NOT_EXIST) return current === defaultVersion;\n\n if (expected == STREAM_EXISTS) return current !== defaultVersion;\n\n return current === expected;\n};\n\nexport const assertExpectedVersionMatchesCurrent = <\n StreamVersion = DefaultStreamVersionType,\n>(\n current: StreamVersion,\n expected: ExpectedStreamVersion<StreamVersion> | undefined,\n defaultVersion: StreamVersion,\n): void => {\n expected ??= NO_CONCURRENCY_CHECK;\n\n if (!matchesExpectedVersion(current, expected, defaultVersion))\n throw new ExpectedVersionConflictError(current, expected);\n};\n\nexport class ExpectedVersionConflictError<\n VersionType = DefaultStreamVersionType,\n> extends ConcurrencyError {\n constructor(\n current: VersionType,\n expected: ExpectedStreamVersion<VersionType>,\n ) {\n super(current?.toString(), expected?.toString());\n\n // 👇️ because we are extending a built-in class\n Object.setPrototypeOf(this, ExpectedVersionConflictError.prototype);\n }\n}\n\nexport const isExpectedVersionConflictError = (\n error: unknown,\n): error is ExpectedVersionConflictError =>\n error instanceof ExpectedVersionConflictError;\n","import { filter } from './filter';\nimport { map } from './map';\nimport {\n notifyAboutNoActiveReadersStream,\n NotifyAboutNoActiveReadersStream,\n} from './notifyAboutNoActiveReaders';\nimport { reduce, ReduceTransformStream } from './reduce';\nimport { retryStream } from './retry';\nimport { skip, SkipTransformStream } from './skip';\nimport { stopAfter } from './stopAfter';\nimport { stopOn } from './stopOn';\nimport { take, TakeTransformStream } from './take';\nimport { waitAtMost } from './waitAtMost';\n\nexport const streamTransformations = {\n filter,\n take,\n TakeTransformStream,\n skip,\n SkipTransformStream,\n map,\n notifyAboutNoActiveReadersStream,\n NotifyAboutNoActiveReadersStream,\n reduce,\n ReduceTransformStream,\n retry: retryStream,\n stopAfter,\n stopOn,\n waitAtMost,\n};\n","import {\n ExpectedVersionConflictError,\n NO_CONCURRENCY_CHECK,\n STREAM_DOES_NOT_EXIST,\n STREAM_EXISTS,\n assertExpectedVersionMatchesCurrent,\n globalStreamCaughtUp,\n streamTransformations,\n type AggregateStreamOptions,\n type AggregateStreamResult,\n type AppendToStreamOptions,\n type AppendToStreamResult,\n type DefaultStreamVersionType,\n type Event,\n type EventStore,\n type ExpectedStreamVersion,\n type GlobalStreamCaughtUp,\n type ReadEvent,\n type ReadEventMetadataWithGlobalPosition,\n type ReadStreamOptions,\n type ReadStreamResult,\n} from '@event-driven-io/emmett';\nimport {\n ANY,\n STREAM_EXISTS as ESDB_STREAM_EXISTS,\n EventStoreDBClient,\n NO_STREAM,\n StreamNotFoundError,\n WrongExpectedVersionError,\n jsonEvent,\n type AllStreamResolvedEvent,\n type AllStreamSubscription,\n type AppendExpectedRevision,\n type ReadStreamOptions as ESDBReadStreamOptions,\n type JSONRecordedEvent,\n} from '@eventstore/db-client';\nimport { WritableStream, type ReadableStream } from 'node:stream/web';\nimport { Readable } from 'stream';\n\nconst { map } = streamTransformations;\n\nconst toEventStoreDBReadOptions = (\n options: ReadStreamOptions | undefined,\n): ESDBReadStreamOptions | undefined => {\n return options\n ? {\n fromRevision: 'from' in options ? options.from : undefined,\n maxCount:\n 'maxCount' in options\n ? options.maxCount\n : 'to' in options\n ? options.to\n : undefined,\n }\n : undefined;\n};\n\nexport const EventStoreDBEventStoreDefaultStreamVersion = -1n;\n\nexport const getEventStoreDBEventStore = (\n eventStore: EventStoreDBClient,\n): EventStore<\n DefaultStreamVersionType,\n ReadEventMetadataWithGlobalPosition\n> => {\n return {\n async aggregateStream<State, EventType extends Event>(\n streamName: string,\n options: AggregateStreamOptions<State, EventType>,\n ): Promise<AggregateStreamResult<State>> {\n const { evolve, initialState, read } = options;\n\n const expectedStreamVersion = read?.expectedStreamVersion;\n\n let state = initialState();\n let currentStreamVersion: bigint =\n EventStoreDBEventStoreDefaultStreamVersion;\n\n try {\n for await (const { event } of eventStore.readStream<EventType>(\n streamName,\n toEventStoreDBReadOptions(options.read),\n )) {\n if (!event) continue;\n\n state = evolve(state, mapFromESDBEvent<EventType>(event));\n currentStreamVersion = event.revision;\n }\n\n assertExpectedVersionMatchesCurrent(\n currentStreamVersion,\n expectedStreamVersion,\n EventStoreDBEventStoreDefaultStreamVersion,\n );\n\n return {\n currentStreamVersion,\n state,\n streamExists: true,\n };\n } catch (error) {\n if (error instanceof StreamNotFoundError) {\n return {\n currentStreamVersion,\n state,\n streamExists: false,\n };\n }\n\n throw error;\n }\n },\n\n readStream: async <EventType extends Event>(\n streamName: string,\n options?: ReadStreamOptions,\n ): Promise<\n ReadStreamResult<\n EventType,\n DefaultStreamVersionType,\n ReadEventMetadataWithGlobalPosition\n >\n > => {\n const events: ReadEvent<\n EventType,\n ReadEventMetadataWithGlobalPosition\n >[] = [];\n\n let currentStreamVersion: bigint =\n EventStoreDBEventStoreDefaultStreamVersion;\n\n try {\n for await (const { event } of eventStore.readStream<EventType>(\n streamName,\n toEventStoreDBReadOptions(options),\n )) {\n if (!event) continue;\n events.push(mapFromESDBEvent(event));\n currentStreamVersion = event.revision;\n }\n return {\n currentStreamVersion,\n events,\n streamExists: true,\n };\n } catch (error) {\n if (error instanceof StreamNotFoundError) {\n return {\n currentStreamVersion,\n events: [],\n streamExists: false,\n };\n }\n\n throw error;\n }\n },\n\n appendToStream: async <EventType extends Event>(\n streamName: string,\n events: EventType[],\n options?: AppendToStreamOptions,\n ): Promise<AppendToStreamResult> => {\n try {\n const serializedEvents = events.map(jsonEvent);\n\n const expectedRevision = toExpectedRevision(\n options?.expectedStreamVersion,\n );\n\n const appendResult = await eventStore.appendToStream(\n streamName,\n serializedEvents,\n {\n expectedRevision,\n },\n );\n\n return {\n nextExpectedStreamVersion: appendResult.nextExpectedRevision,\n createdNewStream:\n appendResult.nextExpectedRevision >=\n BigInt(serializedEvents.length),\n };\n } catch (error) {\n if (error instanceof WrongExpectedVersionError) {\n throw new ExpectedVersionConflictError(\n error.actualVersion,\n toExpectedVersion(error.expectedVersion),\n );\n }\n\n throw error;\n }\n },\n\n //streamEvents: streamEvents(eventStore),\n };\n};\n\nconst mapFromESDBEvent = <EventType extends Event = Event>(\n event: JSONRecordedEvent<EventType>,\n): ReadEvent<EventType, ReadEventMetadataWithGlobalPosition> => {\n return <ReadEvent<EventType, ReadEventMetadataWithGlobalPosition>>{\n type: event.type,\n data: event.data,\n metadata: {\n ...((event.metadata as ReadEventMetadataWithGlobalPosition) ??\n ({} as ReadEventMetadataWithGlobalPosition)),\n eventId: event.id,\n streamName: event.streamId,\n streamPosition: event.revision,\n globalPosition: event.position!.commit,\n },\n };\n};\n\nconst toExpectedRevision = (\n expected: ExpectedStreamVersion | undefined,\n): AppendExpectedRevision => {\n if (expected === undefined) return ANY;\n\n if (expected === NO_CONCURRENCY_CHECK) return ANY;\n\n if (expected == STREAM_DOES_NOT_EXIST) return NO_STREAM;\n\n if (expected == STREAM_EXISTS) return ESDB_STREAM_EXISTS;\n\n return expected as bigint;\n};\n\nconst toExpectedVersion = (\n expected: AppendExpectedRevision | undefined,\n): ExpectedStreamVersion => {\n if (expected === undefined) return NO_CONCURRENCY_CHECK;\n\n if (expected === ANY) return NO_CONCURRENCY_CHECK;\n\n if (expected == NO_STREAM) return STREAM_DOES_NOT_EXIST;\n\n if (expected == ESDB_STREAM_EXISTS) return STREAM_EXISTS;\n\n return expected;\n};\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nconst convertToWebReadableStream = (\n allStreamSubscription: AllStreamSubscription,\n): ReadableStream<AllStreamResolvedEvent | GlobalStreamCaughtUp> => {\n // Validate the input type\n if (!(allStreamSubscription instanceof Readable)) {\n throw new Error('Provided stream is not a Node.js Readable stream.');\n }\n\n let globalPosition = 0n;\n\n const stream = Readable.toWeb(\n allStreamSubscription,\n ) as ReadableStream<AllStreamResolvedEvent>;\n\n const writable = new WritableStream<\n AllStreamResolvedEvent | GlobalStreamCaughtUp\n >();\n\n allStreamSubscription.on('caughtUp', async () => {\n console.log(globalPosition);\n await writable.getWriter().write(globalStreamCaughtUp({ globalPosition }));\n });\n\n const transform = map<\n AllStreamResolvedEvent,\n AllStreamResolvedEvent | GlobalStreamCaughtUp\n >((event) => {\n if (event?.event?.position.commit)\n globalPosition = event.event?.position.commit;\n\n return event;\n });\n\n return stream.pipeThrough<AllStreamResolvedEvent | GlobalStreamCaughtUp>(\n transform,\n );\n};\n\n// const streamEvents = (eventStore: EventStoreDBClient) => () => {\n// return restream<\n// AllStreamResolvedEvent | GlobalSubscriptionEvent,\n// | ReadEvent<Event, ReadEventMetadataWithGlobalPosition>\n// | GlobalSubscriptionEvent\n// >(\n// (): ReadableStream<AllStreamResolvedEvent | GlobalSubscriptionEvent> =>\n// convertToWebReadableStream(\n// eventStore.subscribeToAll({\n// fromPosition: START,\n// filter: excludeSystemEvents(),\n// }),\n// ),\n// (\n// resolvedEvent: AllStreamResolvedEvent | GlobalSubscriptionEvent,\n// ): ReadEvent<Event, ReadEventMetadataWithGlobalPosition> =>\n// mapFromESDBEvent(resolvedEvent.event as JSONRecordedEvent<Event>),\n// );\n// };\n"]}
|