@event-driven-io/emmett-esdb 0.43.0-beta.13 → 0.43.0-beta.15

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 CHANGED
@@ -1,1500 +1,406 @@
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;// ../emmett/dist/chunk-AZDDB5SF.js
2
- var isNumber = (val) => typeof val === "number" && val === val;
3
- var isString = (val) => typeof val === "string";
4
- var EmmettError = (_class = class _EmmettError extends Error {
5
- static __initStatic() {this.Codes = {
6
- ValidationError: 400,
7
- IllegalStateError: 403,
8
- NotFoundError: 404,
9
- ConcurrencyError: 412,
10
- InternalServerError: 500
11
- }}
12
-
13
- constructor(options) {
14
- const errorCode = options && typeof options === "object" && "errorCode" in options ? options.errorCode : isNumber(options) ? options : _EmmettError.Codes.InternalServerError;
15
- const message = options && typeof options === "object" && "message" in options ? options.message : isString(options) ? options : `Error with status code '${errorCode}' ocurred during Emmett processing`;
16
- super(message);
17
- this.errorCode = errorCode;
18
- Object.setPrototypeOf(this, _EmmettError.prototype);
19
- }
20
- static mapFrom(error) {
21
- if (_EmmettError.isInstanceOf(error)) {
22
- return error;
23
- }
24
- return new _EmmettError({
25
- errorCode: "errorCode" in error && error.errorCode !== void 0 && error.errorCode !== null ? error.errorCode : _EmmettError.Codes.InternalServerError,
26
- message: _nullishCoalesce(error.message, () => ( "An unknown error occurred"))
27
- });
28
- }
29
- static isInstanceOf(error, errorCode) {
30
- return typeof error === "object" && error !== null && "errorCode" in error && isNumber(error.errorCode) && (errorCode === void 0 || error.errorCode === errorCode);
31
- }
32
- }, _class.__initStatic(), _class);
33
- var ConcurrencyError = class _ConcurrencyError extends EmmettError {
34
- constructor(current, expected, message) {
35
- super({
36
- errorCode: EmmettError.Codes.ConcurrencyError,
37
- message: _nullishCoalesce(message, () => ( `Expected version ${expected.toString()} does not match current ${_optionalChain([current, 'optionalAccess', _ => _.toString, 'call', _2 => _2()])}`))
38
- });
39
- this.current = current;
40
- this.expected = expected;
41
- Object.setPrototypeOf(this, _ConcurrencyError.prototype);
42
- }
43
- };
44
- var ConcurrencyInMemoryDatabaseError = class _ConcurrencyInMemoryDatabaseError extends EmmettError {
45
- constructor(message) {
46
- super({
47
- errorCode: EmmettError.Codes.ConcurrencyError,
48
- message: _nullishCoalesce(message, () => ( `Expected document state does not match current one!`))
49
- });
50
- Object.setPrototypeOf(this, _ConcurrencyInMemoryDatabaseError.prototype);
51
- }
52
- };
53
-
54
- // ../emmett/dist/index.js
55
- var _uuid = require('uuid');
56
-
57
-
58
- var _asyncretry = require('async-retry'); var _asyncretry2 = _interopRequireDefault(_asyncretry);
59
-
60
-
61
-
62
- var emmettPrefix = "emt";
63
- var defaultTag = `${emmettPrefix}:default`;
64
- var unknownTag = `${emmettPrefix}:unknown`;
65
- var STREAM_EXISTS = "STREAM_EXISTS";
66
- var STREAM_DOES_NOT_EXIST = "STREAM_DOES_NOT_EXIST";
67
- var NO_CONCURRENCY_CHECK = "NO_CONCURRENCY_CHECK";
68
- var matchesExpectedVersion = (current, expected, defaultVersion) => {
69
- if (expected === NO_CONCURRENCY_CHECK) return true;
70
- if (expected == STREAM_DOES_NOT_EXIST) return current === defaultVersion;
71
- if (expected == STREAM_EXISTS) return current !== defaultVersion;
72
- return current === expected;
73
- };
74
- var assertExpectedVersionMatchesCurrent = (current, expected, defaultVersion) => {
75
- expected ??= NO_CONCURRENCY_CHECK;
76
- if (!matchesExpectedVersion(current, expected, defaultVersion))
77
- throw new ExpectedVersionConflictError(current, expected);
78
- };
79
- var ExpectedVersionConflictError = class _ExpectedVersionConflictError extends ConcurrencyError {
80
- constructor(current, expected) {
81
- super(_optionalChain([current, 'optionalAccess', _3 => _3.toString, 'call', _4 => _4()]), _optionalChain([expected, 'optionalAccess', _5 => _5.toString, 'call', _6 => _6()]));
82
- Object.setPrototypeOf(this, _ExpectedVersionConflictError.prototype);
83
- }
84
- };
85
- var isPrimitive = (value) => {
86
- const type = typeof value;
87
- return value === null || value === void 0 || type === "boolean" || type === "number" || type === "string" || type === "symbol" || type === "bigint";
88
- };
89
- var compareArrays = (left, right) => {
90
- if (left.length !== right.length) {
91
- return false;
92
- }
93
- for (let i = 0; i < left.length; i++) {
94
- const leftHas = i in left;
95
- const rightHas = i in right;
96
- if (leftHas !== rightHas) return false;
97
- if (leftHas && !deepEquals(left[i], right[i])) return false;
98
- }
99
- return true;
100
- };
101
- var compareDates = (left, right) => {
102
- return left.getTime() === right.getTime();
103
- };
104
- var compareRegExps = (left, right) => {
105
- return left.toString() === right.toString();
106
- };
107
- var compareErrors = (left, right) => {
108
- if (left.message !== right.message || left.name !== right.name) {
109
- return false;
110
- }
111
- const leftKeys = Object.keys(left);
112
- const rightKeys = Object.keys(right);
113
- if (leftKeys.length !== rightKeys.length) return false;
114
- const rightKeySet = new Set(rightKeys);
115
- for (const key of leftKeys) {
116
- if (!rightKeySet.has(key)) return false;
117
- if (!deepEquals(left[key], right[key])) return false;
118
- }
119
- return true;
120
- };
121
- var compareMaps = (left, right) => {
122
- if (left.size !== right.size) return false;
123
- for (const [key, value] of left) {
124
- if (isPrimitive(key)) {
125
- if (!right.has(key) || !deepEquals(value, right.get(key))) {
126
- return false;
127
- }
128
- } else {
129
- let found = false;
130
- for (const [rightKey, rightValue] of right) {
131
- if (deepEquals(key, rightKey) && deepEquals(value, rightValue)) {
132
- found = true;
133
- break;
134
- }
135
- }
136
- if (!found) return false;
137
- }
138
- }
139
- return true;
140
- };
141
- var compareSets = (left, right) => {
142
- if (left.size !== right.size) return false;
143
- for (const leftItem of left) {
144
- if (isPrimitive(leftItem)) {
145
- if (!right.has(leftItem)) return false;
146
- } else {
147
- let found = false;
148
- for (const rightItem of right) {
149
- if (deepEquals(leftItem, rightItem)) {
150
- found = true;
151
- break;
152
- }
153
- }
154
- if (!found) return false;
155
- }
156
- }
157
- return true;
158
- };
159
- var compareArrayBuffers = (left, right) => {
160
- if (left.byteLength !== right.byteLength) return false;
161
- const leftView = new Uint8Array(left);
162
- const rightView = new Uint8Array(right);
163
- for (let i = 0; i < leftView.length; i++) {
164
- if (leftView[i] !== rightView[i]) return false;
165
- }
166
- return true;
167
- };
168
- var compareTypedArrays = (left, right) => {
169
- if (left.constructor !== right.constructor) return false;
170
- if (left.byteLength !== right.byteLength) return false;
171
- const leftArray = new Uint8Array(
172
- left.buffer,
173
- left.byteOffset,
174
- left.byteLength
175
- );
176
- const rightArray = new Uint8Array(
177
- right.buffer,
178
- right.byteOffset,
179
- right.byteLength
180
- );
181
- for (let i = 0; i < leftArray.length; i++) {
182
- if (leftArray[i] !== rightArray[i]) return false;
183
- }
184
- return true;
185
- };
186
- var compareObjects = (left, right) => {
187
- const keys1 = Object.keys(left);
188
- const keys2 = Object.keys(right);
189
- if (keys1.length !== keys2.length) {
190
- return false;
191
- }
192
- for (const key of keys1) {
193
- if (left[key] instanceof Function && right[key] instanceof Function) {
194
- continue;
195
- }
196
- const isEqual = deepEquals(left[key], right[key]);
197
- if (!isEqual) {
198
- return false;
199
- }
200
- }
201
- return true;
202
- };
203
- var getType = (value) => {
204
- if (value === null) return "null";
205
- if (value === void 0) return "undefined";
206
- const primitiveType = typeof value;
207
- if (primitiveType !== "object") return primitiveType;
208
- if (Array.isArray(value)) return "array";
209
- if (value instanceof Boolean) return "boxed-boolean";
210
- if (value instanceof Number) return "boxed-number";
211
- if (value instanceof String) return "boxed-string";
212
- if (value instanceof Date) return "date";
213
- if (value instanceof RegExp) return "regexp";
214
- if (value instanceof Error) return "error";
215
- if (value instanceof Map) return "map";
216
- if (value instanceof Set) return "set";
217
- if (value instanceof ArrayBuffer) return "arraybuffer";
218
- if (value instanceof DataView) return "dataview";
219
- if (value instanceof WeakMap) return "weakmap";
220
- if (value instanceof WeakSet) return "weakset";
221
- if (ArrayBuffer.isView(value)) return "typedarray";
222
- return "object";
223
- };
224
- var deepEquals = (left, right) => {
225
- if (left === right) return true;
226
- if (isEquatable(left)) {
227
- return left.equals(right);
228
- }
229
- const leftType = getType(left);
230
- const rightType = getType(right);
231
- if (leftType !== rightType) return false;
232
- switch (leftType) {
233
- case "null":
234
- case "undefined":
235
- case "boolean":
236
- case "number":
237
- case "bigint":
238
- case "string":
239
- case "symbol":
240
- case "function":
241
- return left === right;
242
- case "array":
243
- return compareArrays(left, right);
244
- case "date":
245
- return compareDates(left, right);
246
- case "regexp":
247
- return compareRegExps(left, right);
248
- case "error":
249
- return compareErrors(left, right);
250
- case "map":
251
- return compareMaps(
252
- left,
253
- right
254
- );
255
- case "set":
256
- return compareSets(left, right);
257
- case "arraybuffer":
258
- return compareArrayBuffers(left, right);
259
- case "dataview":
260
- case "weakmap":
261
- case "weakset":
262
- return false;
263
- case "typedarray":
264
- return compareTypedArrays(
265
- left,
266
- right
267
- );
268
- case "boxed-boolean":
269
- return left.valueOf() === right.valueOf();
270
- case "boxed-number":
271
- return left.valueOf() === right.valueOf();
272
- case "boxed-string":
273
- return left.valueOf() === right.valueOf();
274
- case "object":
275
- return compareObjects(
276
- left,
277
- right
278
- );
279
- default:
280
- return false;
281
- }
282
- };
283
- var isEquatable = (left) => {
284
- return left !== null && left !== void 0 && typeof left === "object" && "equals" in left && typeof left["equals"] === "function";
285
- };
286
- var toNormalizedString = (value) => value.toString().padStart(19, "0");
287
- var bigInt = {
288
- toNormalizedString
289
- };
290
- var bigIntReplacer = (_key, value) => {
291
- return typeof value === "bigint" ? value.toString() : value;
292
- };
293
- var dateReplacer = (_key, value) => {
294
- return value instanceof Date ? value.toISOString() : value;
295
- };
296
- var isFirstLetterNumeric = (str) => {
297
- const c = str.charCodeAt(0);
298
- return c >= 48 && c <= 57;
299
- };
300
- var isFirstLetterNumericOrMinus = (str) => {
301
- const c = str.charCodeAt(0);
302
- return c >= 48 && c <= 57 || c === 45;
303
- };
304
- var bigIntReviver = (_key, value, context) => {
305
- if (typeof value === "number" && Number.isInteger(value) && !Number.isSafeInteger(value)) {
306
- try {
307
- return BigInt(_nullishCoalesce(_optionalChain([context, 'optionalAccess', _7 => _7.source]), () => ( value.toString())));
308
- } catch (e) {
309
- return value;
310
- }
311
- }
312
- if (typeof value === "string" && value.length > 15) {
313
- if (isFirstLetterNumericOrMinus(value)) {
314
- const num = Number(value);
315
- if (Number.isFinite(num) && !Number.isSafeInteger(num)) {
316
- try {
317
- return BigInt(value);
318
- } catch (e2) {
319
- }
320
- }
321
- }
322
- }
323
- return value;
324
- };
325
- var dateReviver = (_key, value) => {
326
- if (typeof value === "string" && value.length === 24 && isFirstLetterNumeric(value) && value[10] === "T" && value[23] === "Z") {
327
- const date = new Date(value);
328
- if (!isNaN(date.getTime())) {
329
- return date;
330
- }
331
- }
332
- return value;
333
- };
334
- var composeJSONReplacers = (...replacers) => {
335
- const filteredReplacers = replacers.filter((r) => r !== void 0);
336
- if (filteredReplacers.length === 0) return void 0;
337
- return (key, value) => (
338
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
339
- filteredReplacers.reduce(
340
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
341
- (accValue, replacer) => replacer(key, accValue),
342
- value
343
- )
344
- );
345
- };
346
- var composeJSONRevivers = (...revivers) => {
347
- const filteredRevivers = revivers.filter((r) => r !== void 0);
348
- if (filteredRevivers.length === 0) return void 0;
349
- return (key, value, context) => (
350
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
351
- filteredRevivers.reduce(
352
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
353
- (accValue, reviver) => reviver(key, accValue, context),
354
- value
355
- )
356
- );
357
- };
358
- var JSONReplacer = (opts) => composeJSONReplacers(
359
- _optionalChain([opts, 'optionalAccess', _8 => _8.replacer]),
360
- _optionalChain([opts, 'optionalAccess', _9 => _9.failOnBigIntSerialization]) !== true ? JSONReplacers.bigInt : void 0,
361
- _optionalChain([opts, 'optionalAccess', _10 => _10.useDefaultDateSerialization]) !== true ? JSONReplacers.date : void 0
362
- );
363
- var JSONReviver = (opts) => composeJSONRevivers(
364
- _optionalChain([opts, 'optionalAccess', _11 => _11.reviver]),
365
- _optionalChain([opts, 'optionalAccess', _12 => _12.parseBigInts]) === true ? JSONRevivers.bigInt : void 0,
366
- _optionalChain([opts, 'optionalAccess', _13 => _13.parseDates]) === true ? JSONRevivers.date : void 0
367
- );
368
- var JSONReplacers = {
369
- bigInt: bigIntReplacer,
370
- date: dateReplacer
371
- };
372
- var JSONRevivers = {
373
- bigInt: bigIntReviver,
374
- date: dateReviver
375
- };
376
- var jsonSerializer = (options) => {
377
- const defaultReplacer = JSONReplacer(options);
378
- const defaultReviver = JSONReviver(options);
379
- return {
380
- serialize: (object, serializerOptions) => JSON.stringify(
381
- object,
382
- serializerOptions ? JSONReplacer(serializerOptions) : defaultReplacer
383
- ),
384
- deserialize: (payload, deserializerOptions) => JSON.parse(
385
- payload,
386
- deserializerOptions ? JSONReviver(deserializerOptions) : defaultReviver
387
- )
388
- };
389
- };
390
- var JSONSerializer = Object.assign(jsonSerializer(), {
391
- from: (options) => _nullishCoalesce(_optionalChain([options, 'optionalAccess', _14 => _14.serialization, 'optionalAccess', _15 => _15.serializer]), () => ( (_optionalChain([options, 'optionalAccess', _16 => _16.serialization, 'optionalAccess', _17 => _17.options]) ? jsonSerializer(_optionalChain([options, 'optionalAccess', _18 => _18.serialization, 'optionalAccess', _19 => _19.options])) : JSONSerializer)))
392
- });
393
- var asyncRetry = async (fn, opts) => {
394
- if (opts === void 0 || opts.retries === 0) return fn();
395
- return _asyncretry2.default.call(void 0,
396
- async (bail) => {
397
- try {
398
- const result = await fn();
399
- if (_optionalChain([opts, 'optionalAccess', _20 => _20.shouldRetryResult]) && opts.shouldRetryResult(result)) {
400
- throw new EmmettError(
401
- `Retrying because of result: ${JSONSerializer.serialize(result)}`
402
- );
403
- }
404
- return result;
405
- } catch (error) {
406
- if (_optionalChain([opts, 'optionalAccess', _21 => _21.shouldRetryError]) && !opts.shouldRetryError(error)) {
407
- bail(error);
408
- return void 0;
409
- }
410
- throw error;
411
- }
412
- },
413
- _nullishCoalesce(opts, () => ( { retries: 0 }))
414
- );
415
- };
416
- var onShutdown = (handler) => {
417
- const signals = ["SIGTERM", "SIGINT"];
418
- if (typeof process !== "undefined" && typeof process.on === "function") {
419
- for (const signal of signals) {
420
- process.on(signal, handler);
421
- }
422
- return () => {
423
- for (const signal of signals) {
424
- process.off(signal, handler);
425
- }
426
- };
427
- }
428
- const deno = globalThis.Deno;
429
- if (deno && typeof deno.addSignalListener === "function") {
430
- for (const signal of signals) {
431
- deno.addSignalListener(signal, handler);
432
- }
433
- return () => {
434
- for (const signal of signals) {
435
- deno.removeSignalListener(signal, handler);
436
- }
437
- };
438
- }
439
- return () => {
440
- };
441
- };
442
- var textEncoder = new TextEncoder();
443
- var isGeneralExpectedDocumentVersion = (version) => {
444
- return version === "DOCUMENT_DOES_NOT_EXIST" || version === "DOCUMENT_EXISTS" || version === "NO_CONCURRENCY_CHECK";
445
- };
446
- var expectedVersionValue = (version) => version === void 0 || isGeneralExpectedDocumentVersion(version) ? null : version;
447
- var operationResult = (result, options) => {
448
- const operationResult2 = {
449
- ...result,
450
- acknowledged: true,
451
- successful: result.successful,
452
- assertSuccessful: (errorMessage) => {
453
- const { successful } = result;
454
- const { operationName, collectionName } = options;
455
- if (!successful)
456
- throw new ConcurrencyInMemoryDatabaseError(
457
- _nullishCoalesce(errorMessage, () => ( `${operationName} on ${collectionName} failed. Expected document state does not match current one! Result: ${JSONSerializer.serialize(result)}!`))
458
- );
459
- }
460
- };
461
- if (_optionalChain([options, 'access', _22 => _22.errors, 'optionalAccess', _23 => _23.throwOnOperationFailures]))
462
- operationResult2.assertSuccessful();
463
- return operationResult2;
464
- };
465
- var getInMemoryDatabase = () => {
466
- const storage = /* @__PURE__ */ new Map();
467
- return {
468
- collection: (collectionName, collectionOptions = {}) => {
469
- const ensureCollectionCreated = () => {
470
- if (!storage.has(collectionName)) storage.set(collectionName, []);
471
- };
472
- const errors = collectionOptions.errors;
473
- const collection = {
474
- collectionName,
475
- insertOne: async (document) => {
476
- ensureCollectionCreated();
477
- const _id = _nullishCoalesce(document._id, () => ( _uuid.v7.call(void 0, )));
478
- const _version = _nullishCoalesce(document._version, () => ( 1n));
479
- const existing = await collection.findOne((c) => c._id === _id);
480
- if (existing) {
481
- return operationResult(
482
- {
483
- successful: false,
484
- insertedId: null,
485
- nextExpectedVersion: _version
486
- },
487
- { operationName: "insertOne", collectionName, errors }
488
- );
489
- }
490
- const documentsInCollection = storage.get(collectionName);
491
- const newDocument = { ...document, _id, _version };
492
- const newCollection = [...documentsInCollection, newDocument];
493
- storage.set(collectionName, newCollection);
494
- return operationResult(
495
- {
496
- successful: true,
497
- insertedId: _id,
498
- nextExpectedVersion: _version
499
- },
500
- { operationName: "insertOne", collectionName, errors }
501
- );
502
- },
503
- findOne: (predicate) => {
504
- ensureCollectionCreated();
505
- const documentsInCollection = storage.get(collectionName);
506
- const filteredDocuments = predicate ? _optionalChain([documentsInCollection, 'optionalAccess', _24 => _24.filter, 'call', _25 => _25((doc) => predicate(doc))]) : documentsInCollection;
507
- const firstOne = _nullishCoalesce(_optionalChain([filteredDocuments, 'optionalAccess', _26 => _26[0]]), () => ( null));
508
- return Promise.resolve(firstOne);
509
- },
510
- find: (predicate) => {
511
- ensureCollectionCreated();
512
- const documentsInCollection = storage.get(collectionName);
513
- const filteredDocuments = predicate ? _optionalChain([documentsInCollection, 'optionalAccess', _27 => _27.filter, 'call', _28 => _28((doc) => predicate(doc))]) : documentsInCollection;
514
- return Promise.resolve(filteredDocuments);
515
- },
516
- deleteOne: (predicate) => {
517
- ensureCollectionCreated();
518
- const documentsInCollection = storage.get(collectionName);
519
- if (predicate) {
520
- const foundIndex = documentsInCollection.findIndex(
521
- (doc) => predicate(doc)
522
- );
523
- if (foundIndex === -1) {
524
- return Promise.resolve(
525
- operationResult(
526
- {
527
- successful: false,
528
- matchedCount: 0,
529
- deletedCount: 0
530
- },
531
- { operationName: "deleteOne", collectionName, errors }
532
- )
533
- );
534
- } else {
535
- const newCollection2 = documentsInCollection.toSpliced(
536
- foundIndex,
537
- 1
538
- );
539
- storage.set(collectionName, newCollection2);
540
- return Promise.resolve(
541
- operationResult(
542
- {
543
- successful: true,
544
- matchedCount: 1,
545
- deletedCount: 1
546
- },
547
- { operationName: "deleteOne", collectionName, errors }
548
- )
549
- );
550
- }
551
- }
552
- const newCollection = documentsInCollection.slice(1);
553
- storage.set(collectionName, newCollection);
554
- return Promise.resolve(
555
- operationResult(
556
- {
557
- successful: true,
558
- matchedCount: 1,
559
- deletedCount: 1
560
- },
561
- { operationName: "deleteOne", collectionName, errors }
562
- )
563
- );
564
- },
565
- replaceOne: (predicate, document, options) => {
566
- ensureCollectionCreated();
567
- const documentsInCollection = storage.get(collectionName);
568
- const firstIndex = documentsInCollection.findIndex(
569
- (doc) => predicate(doc)
570
- );
571
- if (firstIndex === void 0 || firstIndex === -1) {
572
- return Promise.resolve(
573
- operationResult(
574
- {
575
- successful: false,
576
- matchedCount: 0,
577
- modifiedCount: 0,
578
- nextExpectedVersion: 0n
579
- },
580
- { operationName: "replaceOne", collectionName, errors }
581
- )
582
- );
583
- }
584
- const existing = documentsInCollection[firstIndex];
585
- if (typeof _optionalChain([options, 'optionalAccess', _29 => _29.expectedVersion]) === "bigint" && existing._version !== options.expectedVersion) {
586
- return Promise.resolve(
587
- operationResult(
588
- {
589
- successful: false,
590
- matchedCount: 1,
591
- modifiedCount: 0,
592
- nextExpectedVersion: existing._version
593
- },
594
- { operationName: "replaceOne", collectionName, errors }
595
- )
596
- );
597
- }
598
- const newVersion = existing._version + 1n;
599
- const newCollection = documentsInCollection.with(firstIndex, {
600
- _id: existing._id,
601
- ...document,
602
- _version: newVersion
603
- });
604
- storage.set(collectionName, newCollection);
605
- return Promise.resolve(
606
- operationResult(
607
- {
608
- successful: true,
609
- modifiedCount: 1,
610
- matchedCount: firstIndex,
611
- nextExpectedVersion: newVersion
612
- },
613
- { operationName: "replaceOne", collectionName, errors }
614
- )
615
- );
616
- },
617
- handle: async (id, handle, options) => {
618
- const { expectedVersion: version, ...operationOptions } = _nullishCoalesce(options, () => ( {}));
619
- ensureCollectionCreated();
620
- const existing = await collection.findOne(({ _id }) => _id === id);
621
- const expectedVersion = expectedVersionValue(version);
622
- if (existing == null && version === "DOCUMENT_EXISTS" || existing == null && expectedVersion != null || existing != null && version === "DOCUMENT_DOES_NOT_EXIST" || existing != null && expectedVersion !== null && existing._version !== expectedVersion) {
623
- return operationResult(
624
- {
625
- successful: false,
626
- document: existing
627
- },
628
- { operationName: "handle", collectionName, errors }
629
- );
630
- }
631
- const result = handle(existing !== null ? { ...existing } : null);
632
- if (deepEquals(existing, result))
633
- return operationResult(
634
- {
635
- successful: true,
636
- document: existing
637
- },
638
- { operationName: "handle", collectionName, errors }
639
- );
640
- if (!existing && result) {
641
- const newDoc = { ...result, _id: id };
642
- const insertResult = await collection.insertOne({
643
- ...newDoc,
644
- _id: id
645
- });
646
- return {
647
- ...insertResult,
648
- document: {
649
- ...newDoc,
650
- _version: insertResult.nextExpectedVersion
651
- }
652
- };
653
- }
654
- if (existing && !result) {
655
- const deleteResult = await collection.deleteOne(
656
- ({ _id }) => id === _id
657
- );
658
- return { ...deleteResult, document: null };
659
- }
660
- if (existing && result) {
661
- const replaceResult = await collection.replaceOne(
662
- ({ _id }) => id === _id,
663
- result,
664
- {
665
- ...operationOptions,
666
- expectedVersion: _nullishCoalesce(expectedVersion, () => ( "DOCUMENT_EXISTS"))
667
- }
668
- );
669
- return {
670
- ...replaceResult,
671
- document: {
672
- ...result,
673
- _version: replaceResult.nextExpectedVersion
674
- }
675
- };
676
- }
677
- return operationResult(
678
- {
679
- successful: true,
680
- document: existing
681
- },
682
- { operationName: "handle", collectionName, errors }
683
- );
684
- }
685
- };
686
- return collection;
687
- }
688
- };
689
- };
690
- var getCheckpoint = (message2) => {
691
- return message2.metadata.checkpoint;
692
- };
693
- var wasMessageHandled = (message2, checkpoint) => {
694
- const messageCheckpoint = getCheckpoint(message2);
695
- return messageCheckpoint !== null && messageCheckpoint !== void 0 && checkpoint !== null && checkpoint !== void 0 && messageCheckpoint <= checkpoint;
696
- };
697
- var MessageProcessorType = {
698
- PROJECTOR: "projector",
699
- REACTOR: "reactor"
700
- };
701
- var defaultProcessingMessageProcessingScope = (handler, partialContext) => handler(partialContext);
702
- var bigIntProcessorCheckpoint = (value) => bigInt.toNormalizedString(value);
703
- var parseBigIntProcessorCheckpoint = (value) => BigInt(value);
704
- var defaultProcessorVersion = 1;
705
- var defaultProcessorPartition = defaultTag;
706
- var getProcessorInstanceId = (processorId) => `${processorId}:${_uuid.v7.call(void 0, )}`;
707
- var getProjectorId = (options) => `emt:processor:projector:${options.projectionName}`;
708
- var reactor = (options) => {
709
- const {
710
- checkpoints,
711
- processorId,
712
- processorInstanceId: instanceId = getProcessorInstanceId(processorId),
713
- type = MessageProcessorType.REACTOR,
714
- version = defaultProcessorVersion,
715
- partition = defaultProcessorPartition,
716
- hooks = {},
717
- processingScope = defaultProcessingMessageProcessingScope,
718
- startFrom,
719
- canHandle,
720
- stopAfter
721
- } = options;
722
- const isCustomBatch = "eachBatch" in options && !!options.eachBatch;
723
- const eachBatch = isCustomBatch ? options.eachBatch : async (messages, context) => {
724
- let result = void 0;
725
- for (let i = 0; i < messages.length; i++) {
726
- const message2 = messages[i];
727
- const messageProcessingResult = await options.eachMessage(
728
- message2,
729
- context
730
- );
731
- if (messageProcessingResult && messageProcessingResult.type === "STOP") {
732
- result = {
733
- ...messageProcessingResult,
734
- lastSuccessfulMessage: messageProcessingResult.error ? messages[i - 1] : message2
735
- };
736
- break;
737
- }
738
- if (stopAfter && stopAfter(message2)) {
739
- result = {
740
- type: "STOP",
741
- reason: "Stop condition reached",
742
- lastSuccessfulMessage: message2
743
- };
744
- break;
745
- }
746
- if (messageProcessingResult && messageProcessingResult.type === "SKIP") {
747
- result = {
748
- ...messageProcessingResult,
749
- lastSuccessfulMessage: message2
750
- };
751
- continue;
752
- }
753
- }
754
- return result;
755
- };
756
- let isInitiated = false;
757
- let isActive = false;
758
- let lastCheckpoint = null;
759
- let closeSignal = null;
760
- const init = async (initOptions) => {
761
- if (isInitiated) return;
762
- if (hooks.onInit === void 0) {
763
- isInitiated = true;
764
- return;
765
- }
766
- return await processingScope(async (context) => {
767
- await hooks.onInit(context);
768
- isInitiated = true;
769
- }, initOptions);
770
- };
771
- const close = async (closeOptions) => {
772
- isActive = false;
773
- if (closeSignal) {
774
- closeSignal();
775
- closeSignal = null;
776
- }
777
- if (hooks.onClose) {
778
- await processingScope(hooks.onClose, closeOptions);
779
- }
780
- };
781
- return {
782
- // TODO: Consider whether not make it optional or add URN prefix
783
- id: processorId,
784
- instanceId,
785
- type,
786
- canHandle,
787
- init,
788
- start: async (startOptions) => {
789
- if (isActive) return;
790
- await init(startOptions);
791
- isActive = true;
792
- closeSignal = onShutdown(() => close(startOptions));
793
- if (lastCheckpoint !== null) {
794
- return {
795
- lastCheckpoint
796
- };
797
- }
798
- return await processingScope(async (context) => {
799
- if (hooks.onStart) {
800
- await hooks.onStart(context);
801
- }
802
- if (startFrom && startFrom !== "CURRENT") return startFrom;
803
- if (checkpoints) {
804
- const readResult = await _optionalChain([checkpoints, 'optionalAccess', _30 => _30.read, 'call', _31 => _31(
805
- {
806
- processorId,
807
- partition
808
- },
809
- { ...startOptions, ...context }
810
- )]);
811
- lastCheckpoint = readResult.lastCheckpoint;
812
- }
813
- if (lastCheckpoint === null) return "BEGINNING";
814
- return {
815
- lastCheckpoint
816
- };
817
- }, startOptions);
818
- },
819
- close,
820
- get isActive() {
821
- return isActive;
822
- },
823
- handle: async (messages, partialContext) => {
824
- if (!isActive) return Promise.resolve();
825
- return await processingScope(async (context) => {
826
- const messagesAboveCheckpoint = messages.filter(
827
- (message2) => !wasMessageHandled(message2, lastCheckpoint)
828
- );
829
- const upcastedMessages = messagesAboveCheckpoint.map(
830
- (message2) => upcastRecordedMessage(
831
- // TODO: Make it smarter
832
- message2,
833
- _optionalChain([options, 'access', _32 => _32.messageOptions, 'optionalAccess', _33 => _33.schema, 'optionalAccess', _34 => _34.versioning])
834
- )
835
- ).filter(
836
- (upcasted) => !canHandle || canHandle.includes(upcasted.type)
837
- );
838
- const stopMessageIndex = isCustomBatch && stopAfter ? upcastedMessages.findIndex(stopAfter) : -1;
839
- const unhandledMessages = stopMessageIndex !== -1 ? upcastedMessages.slice(0, stopMessageIndex + 1) : upcastedMessages;
840
- const batchResult = await eachBatch(unhandledMessages, context);
841
- const messageProcessingResult = _optionalChain([batchResult, 'optionalAccess', _35 => _35.type]) === "STOP" ? batchResult : stopMessageIndex !== -1 ? {
842
- type: "STOP",
843
- reason: "Stop condition reached",
844
- lastSuccessfulMessage: unhandledMessages[stopMessageIndex]
845
- } : batchResult;
846
- const isStop = messageProcessingResult && messageProcessingResult.type === "STOP";
847
- const checkpointMessage = _optionalChain([messageProcessingResult, 'optionalAccess', _36 => _36.type]) === "STOP" ? messageProcessingResult.lastSuccessfulMessage : messagesAboveCheckpoint[messagesAboveCheckpoint.length - 1];
848
- if (checkpointMessage && checkpoints) {
849
- const storeCheckpointResult = await checkpoints.store(
850
- {
851
- processorId,
852
- version,
853
- message: checkpointMessage,
854
- lastCheckpoint,
855
- partition
856
- },
857
- context
858
- );
859
- if (storeCheckpointResult.success) {
860
- lastCheckpoint = storeCheckpointResult.newCheckpoint;
861
- }
862
- }
863
- if (isStop) {
864
- isActive = false;
865
- return messageProcessingResult;
866
- }
867
- return void 0;
868
- }, partialContext);
869
- }
870
- };
871
- };
872
- var projector = (options) => {
873
- const {
874
- projection: projection2,
875
- processorId = getProjectorId({
876
- projectionName: _nullishCoalesce(projection2.name, () => ( "unknown"))
877
- }),
878
- ...rest
879
- } = options;
880
- return reactor({
881
- ...rest,
882
- type: MessageProcessorType.PROJECTOR,
883
- canHandle: projection2.canHandle,
884
- processorId,
885
- messageOptions: options.projection.eventsOptions,
886
- hooks: {
887
- onInit: _optionalChain([options, 'access', _37 => _37.hooks, 'optionalAccess', _38 => _38.onInit]),
888
- onStart: options.truncateOnStart && options.projection.truncate || _optionalChain([options, 'access', _39 => _39.hooks, 'optionalAccess', _40 => _40.onStart]) ? async (context) => {
889
- if (options.truncateOnStart && options.projection.truncate)
890
- await options.projection.truncate(context);
891
- if (_optionalChain([options, 'access', _41 => _41.hooks, 'optionalAccess', _42 => _42.onStart])) await _optionalChain([options, 'access', _43 => _43.hooks, 'optionalAccess', _44 => _44.onStart, 'call', _45 => _45(context)]);
892
- } : void 0,
893
- onClose: _optionalChain([options, 'access', _46 => _46.hooks, 'optionalAccess', _47 => _47.onClose])
894
- },
895
- eachBatch: async (events, context) => projection2.handle(events, context)
896
- });
897
- };
898
- var inMemoryCheckpointer = () => {
899
- return {
900
- read: async ({ processorId }, { database }) => {
901
- const checkpoint = await database.collection("emt_processor_checkpoints").findOne((d) => d._id === processorId);
902
- return Promise.resolve({
903
- lastCheckpoint: _nullishCoalesce(_optionalChain([checkpoint, 'optionalAccess', _48 => _48.lastCheckpoint]), () => ( null))
904
- });
905
- },
906
- store: async (context, { database }) => {
907
- const { message: message2, processorId, lastCheckpoint } = context;
908
- const checkpoints = database.collection(
909
- "emt_processor_checkpoints"
910
- );
911
- const checkpoint = await checkpoints.findOne(
912
- (d) => d._id === processorId
913
- );
914
- const currentPosition = _nullishCoalesce(_optionalChain([checkpoint, 'optionalAccess', _49 => _49.lastCheckpoint]), () => ( null));
915
- const newCheckpoint = getCheckpoint(message2);
916
- if (currentPosition && (currentPosition === newCheckpoint || currentPosition !== lastCheckpoint)) {
917
- return {
918
- success: false,
919
- reason: currentPosition === newCheckpoint ? "IGNORED" : newCheckpoint !== null && currentPosition > newCheckpoint ? "CURRENT_AHEAD" : "MISMATCH"
920
- };
921
- }
922
- await checkpoints.handle(processorId, (existing) => ({
923
- ..._nullishCoalesce(existing, () => ( {})),
924
- _id: processorId,
925
- lastCheckpoint: newCheckpoint
926
- }));
927
- return { success: true, newCheckpoint };
928
- }
929
- };
930
- };
931
- var inMemoryProcessingScope = (options) => {
932
- const processorDatabase = options.database;
933
- const processingScope = (handler, partialContext) => {
934
- const database = _nullishCoalesce(processorDatabase, () => ( _optionalChain([partialContext, 'optionalAccess', _50 => _50.database])));
935
- if (!database)
936
- throw new EmmettError(
937
- `InMemory processor '${options.processorId}' is missing database. Ensure that you passed it through options`
938
- );
939
- return handler({ ...partialContext, database });
940
- };
941
- return processingScope;
942
- };
943
- var inMemoryProjector = (options) => {
944
- const database = _nullishCoalesce(_optionalChain([options, 'access', _51 => _51.connectionOptions, 'optionalAccess', _52 => _52.database]), () => ( getInMemoryDatabase()));
945
- const hooks = {
946
- onInit: _optionalChain([options, 'access', _53 => _53.hooks, 'optionalAccess', _54 => _54.onInit]),
947
- onStart: _optionalChain([options, 'access', _55 => _55.hooks, 'optionalAccess', _56 => _56.onStart]),
948
- onClose: _optionalChain([options, 'access', _57 => _57.hooks, 'optionalAccess', _58 => _58.onClose]) ? async (context) => {
949
- if (_optionalChain([options, 'access', _59 => _59.hooks, 'optionalAccess', _60 => _60.onClose])) await _optionalChain([options, 'access', _61 => _61.hooks, 'optionalAccess', _62 => _62.onClose, 'call', _63 => _63(context)]);
950
- } : void 0
951
- };
952
- const processor = projector({
953
- ...options,
954
- hooks,
955
- processingScope: inMemoryProcessingScope({
956
- database,
957
- processorId: _nullishCoalesce(options.processorId, () => ( `projection:${options.projection.name}`))
958
- }),
959
- checkpoints: inMemoryCheckpointer()
960
- });
961
- return Object.assign(processor, { database });
962
- };
963
- var inMemoryReactor = (options) => {
964
- const database = _nullishCoalesce(_optionalChain([options, 'access', _64 => _64.connectionOptions, 'optionalAccess', _65 => _65.database]), () => ( getInMemoryDatabase()));
965
- const hooks = {
966
- onInit: _optionalChain([options, 'access', _66 => _66.hooks, 'optionalAccess', _67 => _67.onInit]),
967
- onStart: _optionalChain([options, 'access', _68 => _68.hooks, 'optionalAccess', _69 => _69.onStart]),
968
- onClose: _optionalChain([options, 'access', _70 => _70.hooks, 'optionalAccess', _71 => _71.onClose])
969
- };
970
- const processor = reactor({
971
- ...options,
972
- hooks,
973
- processingScope: inMemoryProcessingScope({
974
- database,
975
- processorId: options.processorId
976
- }),
977
- checkpoints: inMemoryCheckpointer()
978
- });
979
- return Object.assign(processor, { database });
980
- };
981
- var downcastRecordedMessage = (recordedMessage, options) => {
982
- if (!_optionalChain([options, 'optionalAccess', _72 => _72.downcast]))
983
- return recordedMessage;
984
- const downcasted = options.downcast(
985
- recordedMessage
986
- );
987
- return {
988
- ...recordedMessage,
989
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
990
- data: downcasted.data,
991
- ..."metadata" in recordedMessage || "metadata" in downcasted ? {
992
- metadata: {
993
- ..."metadata" in recordedMessage ? recordedMessage.metadata : {},
994
- ..."metadata" in downcasted ? downcasted.metadata : {}
995
- }
996
- } : {}
997
- };
998
- };
999
- var downcastRecordedMessages = (recordedMessages, options) => {
1000
- if (!_optionalChain([options, 'optionalAccess', _73 => _73.downcast]))
1001
- return recordedMessages;
1002
- return recordedMessages.map(
1003
- (recordedMessage) => downcastRecordedMessage(recordedMessage, options)
1004
- );
1005
- };
1006
- var upcastRecordedMessage = (recordedMessage, options) => {
1007
- if (!_optionalChain([options, 'optionalAccess', _74 => _74.upcast]))
1008
- return recordedMessage;
1009
- const upcasted = options.upcast(
1010
- recordedMessage
1011
- );
1012
- return {
1013
- ...recordedMessage,
1014
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
1015
- data: upcasted.data,
1016
- ..."metadata" in recordedMessage || "metadata" in upcasted ? {
1017
- metadata: {
1018
- ..."metadata" in recordedMessage ? recordedMessage.metadata : {},
1019
- ..."metadata" in upcasted ? upcasted.metadata : {}
1020
- }
1021
- } : {}
1022
- };
1023
- };
1024
-
1025
- // src/eventStore/consumers/eventStoreDBEventStoreConsumer.ts
1026
-
1027
-
1028
- var _dbclient = require('@eventstore/db-client');
1029
-
1030
-
1031
- // src/eventStore/consumers/subscriptions/index.ts
1032
-
1033
-
1034
-
1035
-
1036
-
1037
- var _stream = require('stream');
1038
-
1039
- // src/eventStore/eventstoreDBEventStore.ts
1040
-
1041
-
1042
-
1043
-
1044
-
1045
-
1046
-
1047
-
1048
- var toEventStoreDBReadOptions = (options) => {
1049
- return options ? {
1050
- fromRevision: "from" in options ? options.from : void 0,
1051
- maxCount: "maxCount" in options ? options.maxCount : "to" in options ? options.to : void 0
1052
- } : void 0;
1053
- };
1054
- var EventStoreDBEventStoreDefaultStreamVersion = -1n;
1055
- var getEventStoreDBEventStore = (eventStore) => {
1056
- return {
1057
- async aggregateStream(streamName, options) {
1058
- const { evolve, initialState, read } = options;
1059
- const expectedStreamVersion = _optionalChain([read, 'optionalAccess', _75 => _75.expectedStreamVersion]);
1060
- let state = initialState();
1061
- let currentStreamVersion = EventStoreDBEventStoreDefaultStreamVersion;
1062
- let lastEventGlobalPosition = void 0;
1063
- try {
1064
- for await (const resolvedEvent of eventStore.readStream(
1065
- streamName,
1066
- toEventStoreDBReadOptions(options.read)
1067
- )) {
1068
- const { event } = resolvedEvent;
1069
- if (!event) continue;
1070
- state = evolve(
1071
- state,
1072
- upcastRecordedMessage(
1073
- mapFromESDBEvent(resolvedEvent),
1074
- _optionalChain([options, 'optionalAccess', _76 => _76.read, 'optionalAccess', _77 => _77.schema, 'optionalAccess', _78 => _78.versioning])
1075
- )
1076
- );
1077
- currentStreamVersion = event.revision;
1078
- lastEventGlobalPosition = _optionalChain([event, 'access', _79 => _79.position, 'optionalAccess', _80 => _80.commit]);
1079
- }
1080
- assertExpectedVersionMatchesCurrent(
1081
- currentStreamVersion,
1082
- expectedStreamVersion,
1083
- EventStoreDBEventStoreDefaultStreamVersion
1084
- );
1085
- return lastEventGlobalPosition ? {
1086
- currentStreamVersion,
1087
- lastEventGlobalPosition,
1088
- state,
1089
- streamExists: true
1090
- } : {
1091
- currentStreamVersion,
1092
- state,
1093
- streamExists: false
1094
- };
1095
- } catch (error) {
1096
- if (error instanceof _dbclient.StreamNotFoundError) {
1097
- return {
1098
- currentStreamVersion,
1099
- state,
1100
- streamExists: false
1101
- };
1102
- }
1103
- throw error;
1104
- }
1105
- },
1106
- readStream: async (streamName, options) => {
1107
- const events = [];
1108
- let currentStreamVersion = EventStoreDBEventStoreDefaultStreamVersion;
1109
- try {
1110
- for await (const resolvedEvent of eventStore.readStream(
1111
- streamName,
1112
- toEventStoreDBReadOptions(options)
1113
- )) {
1114
- const { event } = resolvedEvent;
1115
- if (!event) continue;
1116
- events.push(
1117
- upcastRecordedMessage(
1118
- mapFromESDBEvent(resolvedEvent),
1119
- _optionalChain([options, 'optionalAccess', _81 => _81.schema, 'optionalAccess', _82 => _82.versioning])
1120
- )
1121
- );
1122
- currentStreamVersion = event.revision;
1123
- }
1124
- return {
1125
- currentStreamVersion,
1126
- events,
1127
- streamExists: true
1128
- };
1129
- } catch (error) {
1130
- if (error instanceof _dbclient.StreamNotFoundError) {
1131
- return {
1132
- currentStreamVersion,
1133
- events: [],
1134
- streamExists: false
1135
- };
1136
- }
1137
- throw error;
1138
- }
1139
- },
1140
- appendToStream: async (streamName, events, options) => {
1141
- try {
1142
- const eventsToStore = downcastRecordedMessages(
1143
- events,
1144
- _optionalChain([options, 'optionalAccess', _83 => _83.schema, 'optionalAccess', _84 => _84.versioning])
1145
- );
1146
- const serializedEvents = eventsToStore.map(_dbclient.jsonEvent);
1147
- const expectedRevision = toExpectedRevision(
1148
- _optionalChain([options, 'optionalAccess', _85 => _85.expectedStreamVersion])
1149
- );
1150
- const appendResult = await eventStore.appendToStream(
1151
- streamName,
1152
- serializedEvents,
1153
- {
1154
- expectedRevision
1155
- }
1156
- );
1157
- return {
1158
- nextExpectedStreamVersion: appendResult.nextExpectedRevision,
1159
- lastEventGlobalPosition: appendResult.position.commit,
1160
- createdNewStream: appendResult.nextExpectedRevision >= BigInt(serializedEvents.length)
1161
- };
1162
- } catch (error) {
1163
- if (error instanceof _dbclient.WrongExpectedVersionError) {
1164
- throw new ExpectedVersionConflictError(
1165
- BigInt(error.actualVersion),
1166
- toExpectedVersion(error.expectedVersion)
1167
- );
1168
- }
1169
- throw error;
1170
- }
1171
- },
1172
- consumer: (options) => eventStoreDBEventStoreConsumer({
1173
- ..._nullishCoalesce(options, () => ( {})),
1174
- client: eventStore
1175
- }),
1176
- streamExists: async (streamName) => {
1177
- try {
1178
- for await (const resolvedEvent of eventStore.readStream(streamName)) {
1179
- const { event } = resolvedEvent;
1180
- if (!event) continue;
1181
- return true;
1182
- }
1183
- return false;
1184
- } catch (error) {
1185
- if (error instanceof _dbclient.StreamNotFoundError) {
1186
- return false;
1187
- }
1188
- throw error;
1189
- }
1190
- }
1191
- //streamEvents: streamEvents(eventStore),
1192
- };
1193
- };
1194
- var getESDBCheckpoint = (resolvedEvent, from) => {
1195
- return !from || _optionalChain([from, 'optionalAccess', _86 => _86.stream]) === $all ? _nullishCoalesce(_optionalChain([resolvedEvent, 'access', _87 => _87.link, 'optionalAccess', _88 => _88.position, 'optionalAccess', _89 => _89.commit]), () => ( _optionalChain([resolvedEvent, 'access', _90 => _90.event, 'optionalAccess', _91 => _91.position, 'optionalAccess', _92 => _92.commit]))) : _nullishCoalesce(_optionalChain([resolvedEvent, 'access', _93 => _93.link, 'optionalAccess', _94 => _94.revision]), () => ( resolvedEvent.event.revision));
1196
- };
1197
- var mapFromESDBEvent = (resolvedEvent, from) => {
1198
- const event = resolvedEvent.event;
1199
- return {
1200
- type: event.type,
1201
- data: event.data,
1202
- metadata: {
1203
- ..._nullishCoalesce(event.metadata, () => ( {})),
1204
- eventId: event.id,
1205
- streamName: event.streamId,
1206
- streamPosition: event.revision,
1207
- globalPosition: event.position.commit,
1208
- checkpoint: bigIntProcessorCheckpoint(
1209
- getESDBCheckpoint(resolvedEvent, from)
1210
- )
1211
- }
1212
- };
1213
- };
1214
- var toExpectedRevision = (expected) => {
1215
- if (expected === void 0) return _dbclient.ANY;
1216
- if (expected === NO_CONCURRENCY_CHECK) return _dbclient.ANY;
1217
- if (expected == STREAM_DOES_NOT_EXIST) return _dbclient.NO_STREAM;
1218
- if (expected == STREAM_EXISTS) return _dbclient.STREAM_EXISTS;
1219
- return expected;
1220
- };
1221
- var toExpectedVersion = (expected) => {
1222
- if (expected === void 0) return NO_CONCURRENCY_CHECK;
1223
- if (expected === _dbclient.ANY) return NO_CONCURRENCY_CHECK;
1224
- if (expected == _dbclient.NO_STREAM) return STREAM_DOES_NOT_EXIST;
1225
- if (expected == _dbclient.STREAM_EXISTS) return STREAM_EXISTS;
1226
- return expected;
1227
- };
1228
-
1229
- // src/eventStore/consumers/subscriptions/index.ts
1230
- var DefaultEventStoreDBEventStoreProcessorBatchSize = 100;
1231
- var DefaultEventStoreDBEventStoreProcessorPullingFrequencyInMs = 50;
1232
- var toGlobalPosition = (startFrom) => startFrom === "BEGINNING" ? _dbclient.START : startFrom === "END" ? _dbclient.END : {
1233
- prepare: parseBigIntProcessorCheckpoint(startFrom.lastCheckpoint),
1234
- commit: parseBigIntProcessorCheckpoint(startFrom.lastCheckpoint)
1235
- };
1236
- var toStreamPosition = (startFrom) => startFrom === "BEGINNING" ? _dbclient.START : startFrom === "END" ? _dbclient.END : parseBigIntProcessorCheckpoint(startFrom.lastCheckpoint);
1237
- var subscribe = (client, from, options) => from == void 0 || from.stream == $all ? client.subscribeToAll({
1238
- ..._nullishCoalesce(_optionalChain([from, 'optionalAccess', _95 => _95.options]), () => ( {})),
1239
- fromPosition: toGlobalPosition(options.startFrom),
1240
- filter: _dbclient.excludeSystemEvents.call(void 0, )
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ let _event_driven_io_emmett = require("@event-driven-io/emmett");
3
+ let _eventstore_db_client = require("@eventstore/db-client");
4
+ let uuid = require("uuid");
5
+ let stream = require("stream");
6
+
7
+ //#region src/eventStore/eventstoreDBEventStore.ts
8
+ const toEventStoreDBReadOptions = (options) => {
9
+ return options ? {
10
+ fromRevision: "from" in options ? options.from : void 0,
11
+ maxCount: "maxCount" in options ? options.maxCount : "to" in options ? options.to : void 0
12
+ } : void 0;
13
+ };
14
+ const EventStoreDBEventStoreDefaultStreamVersion = -1n;
15
+ const getEventStoreDBEventStore = (eventStore) => {
16
+ return {
17
+ async aggregateStream(streamName, options) {
18
+ const { evolve, initialState, read } = options;
19
+ const expectedStreamVersion = read?.expectedStreamVersion;
20
+ let state = initialState();
21
+ let currentStreamVersion = EventStoreDBEventStoreDefaultStreamVersion;
22
+ let lastEventGlobalPosition = void 0;
23
+ try {
24
+ for await (const resolvedEvent of eventStore.readStream(streamName, toEventStoreDBReadOptions(options.read))) {
25
+ const { event } = resolvedEvent;
26
+ if (!event) continue;
27
+ state = evolve(state, (0, _event_driven_io_emmett.upcastRecordedMessage)(mapFromESDBEvent(resolvedEvent), options?.read?.schema?.versioning));
28
+ currentStreamVersion = event.revision;
29
+ lastEventGlobalPosition = event.position?.commit;
30
+ }
31
+ (0, _event_driven_io_emmett.assertExpectedVersionMatchesCurrent)(currentStreamVersion, expectedStreamVersion, EventStoreDBEventStoreDefaultStreamVersion);
32
+ return lastEventGlobalPosition ? {
33
+ currentStreamVersion,
34
+ lastEventGlobalPosition,
35
+ state,
36
+ streamExists: true
37
+ } : {
38
+ currentStreamVersion,
39
+ state,
40
+ streamExists: false
41
+ };
42
+ } catch (error) {
43
+ if (error instanceof _eventstore_db_client.StreamNotFoundError) return {
44
+ currentStreamVersion,
45
+ state,
46
+ streamExists: false
47
+ };
48
+ throw error;
49
+ }
50
+ },
51
+ readStream: async (streamName, options) => {
52
+ const events = [];
53
+ let currentStreamVersion = EventStoreDBEventStoreDefaultStreamVersion;
54
+ try {
55
+ for await (const resolvedEvent of eventStore.readStream(streamName, toEventStoreDBReadOptions(options))) {
56
+ const { event } = resolvedEvent;
57
+ if (!event) continue;
58
+ events.push((0, _event_driven_io_emmett.upcastRecordedMessage)(mapFromESDBEvent(resolvedEvent), options?.schema?.versioning));
59
+ currentStreamVersion = event.revision;
60
+ }
61
+ return {
62
+ currentStreamVersion,
63
+ events,
64
+ streamExists: true
65
+ };
66
+ } catch (error) {
67
+ if (error instanceof _eventstore_db_client.StreamNotFoundError) return {
68
+ currentStreamVersion,
69
+ events: [],
70
+ streamExists: false
71
+ };
72
+ throw error;
73
+ }
74
+ },
75
+ appendToStream: async (streamName, events, options) => {
76
+ try {
77
+ const serializedEvents = (0, _event_driven_io_emmett.downcastRecordedMessages)(events, options?.schema?.versioning).map(_eventstore_db_client.jsonEvent);
78
+ const expectedRevision = toExpectedRevision(options?.expectedStreamVersion);
79
+ const appendResult = await eventStore.appendToStream(streamName, serializedEvents, { expectedRevision });
80
+ return {
81
+ nextExpectedStreamVersion: appendResult.nextExpectedRevision,
82
+ lastEventGlobalPosition: appendResult.position.commit,
83
+ createdNewStream: appendResult.nextExpectedRevision >= BigInt(serializedEvents.length)
84
+ };
85
+ } catch (error) {
86
+ if (error instanceof _eventstore_db_client.WrongExpectedVersionError) throw new _event_driven_io_emmett.ExpectedVersionConflictError(BigInt(error.actualVersion), toExpectedVersion(error.expectedVersion));
87
+ throw error;
88
+ }
89
+ },
90
+ consumer: (options) => eventStoreDBEventStoreConsumer({
91
+ ...options ?? {},
92
+ client: eventStore
93
+ }),
94
+ streamExists: async (streamName) => {
95
+ try {
96
+ for await (const resolvedEvent of eventStore.readStream(streamName)) {
97
+ const { event } = resolvedEvent;
98
+ if (!event) continue;
99
+ return true;
100
+ }
101
+ return false;
102
+ } catch (error) {
103
+ if (error instanceof _eventstore_db_client.StreamNotFoundError) return false;
104
+ throw error;
105
+ }
106
+ }
107
+ };
108
+ };
109
+ const getESDBCheckpoint = (resolvedEvent, from) => {
110
+ return !from || from?.stream === "$all" ? resolvedEvent.link?.position?.commit ?? resolvedEvent.event?.position?.commit : resolvedEvent.link?.revision ?? resolvedEvent.event.revision;
111
+ };
112
+ const mapFromESDBEvent = (resolvedEvent, from) => {
113
+ const event = resolvedEvent.event;
114
+ return {
115
+ type: event.type,
116
+ data: event.data,
117
+ metadata: {
118
+ ...event.metadata ?? {},
119
+ eventId: event.id,
120
+ streamName: event.streamId,
121
+ streamPosition: event.revision,
122
+ globalPosition: event.position.commit,
123
+ checkpoint: (0, _event_driven_io_emmett.bigIntProcessorCheckpoint)(getESDBCheckpoint(resolvedEvent, from))
124
+ }
125
+ };
126
+ };
127
+ const toExpectedRevision = (expected) => {
128
+ if (expected === void 0) return _eventstore_db_client.ANY;
129
+ if (expected === _event_driven_io_emmett.NO_CONCURRENCY_CHECK) return _eventstore_db_client.ANY;
130
+ if (expected == _event_driven_io_emmett.STREAM_DOES_NOT_EXIST) return _eventstore_db_client.NO_STREAM;
131
+ if (expected == _event_driven_io_emmett.STREAM_EXISTS) return _eventstore_db_client.STREAM_EXISTS;
132
+ return expected;
133
+ };
134
+ const toExpectedVersion = (expected) => {
135
+ if (expected === void 0) return _event_driven_io_emmett.NO_CONCURRENCY_CHECK;
136
+ if (expected === _eventstore_db_client.ANY) return _event_driven_io_emmett.NO_CONCURRENCY_CHECK;
137
+ if (expected == _eventstore_db_client.NO_STREAM) return _event_driven_io_emmett.STREAM_DOES_NOT_EXIST;
138
+ if (expected == _eventstore_db_client.STREAM_EXISTS) return _event_driven_io_emmett.STREAM_EXISTS;
139
+ return expected;
140
+ };
141
+
142
+ //#endregion
143
+ //#region src/eventStore/consumers/subscriptions/index.ts
144
+ const DefaultEventStoreDBEventStoreProcessorBatchSize = 100;
145
+ const DefaultEventStoreDBEventStoreProcessorPullingFrequencyInMs = 50;
146
+ const toGlobalPosition = (startFrom) => startFrom === "BEGINNING" ? _eventstore_db_client.START : startFrom === "END" ? _eventstore_db_client.END : {
147
+ prepare: (0, _event_driven_io_emmett.parseBigIntProcessorCheckpoint)(startFrom.lastCheckpoint),
148
+ commit: (0, _event_driven_io_emmett.parseBigIntProcessorCheckpoint)(startFrom.lastCheckpoint)
149
+ };
150
+ const toStreamPosition = (startFrom) => startFrom === "BEGINNING" ? _eventstore_db_client.START : startFrom === "END" ? _eventstore_db_client.END : (0, _event_driven_io_emmett.parseBigIntProcessorCheckpoint)(startFrom.lastCheckpoint);
151
+ const subscribe = (client, from, options) => from == void 0 || from.stream == "$all" ? client.subscribeToAll({
152
+ ...from?.options ?? {},
153
+ fromPosition: toGlobalPosition(options.startFrom),
154
+ filter: (0, _eventstore_db_client.excludeSystemEvents)()
1241
155
  }) : client.subscribeToStream(from.stream, {
1242
- ..._nullishCoalesce(from.options, () => ( {})),
1243
- fromRevision: toStreamPosition(options.startFrom)
156
+ ...from.options ?? {},
157
+ fromRevision: toStreamPosition(options.startFrom)
1244
158
  });
1245
- var isDatabaseUnavailableError = (error) => error instanceof Error && "type" in error && error.type === "unavailable" && "code" in error && error.code === 14;
1246
- var EventStoreDBResubscribeDefaultOptions = {
1247
- forever: true,
1248
- minTimeout: 100,
1249
- factor: 1.5,
1250
- shouldRetryError: (error) => !isDatabaseUnavailableError(error)
1251
- };
1252
- var SubscriptionSequentialHandler = class extends _stream.Transform {
1253
-
1254
-
1255
-
1256
- constructor(options) {
1257
- super({ objectMode: true, ...options });
1258
- this.options = options;
1259
- this.from = options.from;
1260
- this.isRunning = true;
1261
- }
1262
- async _transform(resolvedEvent, _encoding, callback) {
1263
- try {
1264
- if (!this.isRunning || !resolvedEvent.event) {
1265
- callback();
1266
- return;
1267
- }
1268
- const message = mapFromESDBEvent(resolvedEvent, this.from);
1269
- const messageCheckpoint = getCheckpoint(message);
1270
- const result = await this.options.eachBatch([message]);
1271
- if (result && result.type === "STOP") {
1272
- this.isRunning = false;
1273
- if (!result.error) this.push(messageCheckpoint);
1274
- this.push(result);
1275
- this.push(null);
1276
- callback();
1277
- return;
1278
- }
1279
- this.push(messageCheckpoint);
1280
- callback();
1281
- } catch (error) {
1282
- callback(error);
1283
- }
1284
- }
1285
- };
1286
- var eventStoreDBSubscription = ({
1287
- client,
1288
- from,
1289
- batchSize,
1290
- eachBatch,
1291
- resilience
1292
- }) => {
1293
- let isRunning = false;
1294
- let start;
1295
- let processor;
1296
- let subscription;
1297
- const resubscribeOptions = _nullishCoalesce(_optionalChain([resilience, 'optionalAccess', _96 => _96.resubscribeOptions]), () => ( {
1298
- ...EventStoreDBResubscribeDefaultOptions,
1299
- shouldRetryResult: () => isRunning,
1300
- shouldRetryError: (error) => isRunning && EventStoreDBResubscribeDefaultOptions.shouldRetryError(error)
1301
- }));
1302
- const stopSubscription = (callback) => {
1303
- isRunning = false;
1304
- if (processor) processor.isRunning = false;
1305
- return subscription.unsubscribe().then(() => {
1306
- subscription.destroy();
1307
- }).catch((err) => console.error("Error during unsubscribe.%s", err)).finally(_nullishCoalesce(callback, () => ( (() => {
1308
- }))));
1309
- };
1310
- const pipeMessages = (options) => {
1311
- let retry2 = 0;
1312
- return asyncRetry(
1313
- () => new Promise((resolve, reject) => {
1314
- if (!isRunning) {
1315
- resolve();
1316
- return;
1317
- }
1318
- console.info(
1319
- `Starting subscription. ${retry2++} retries. From: ${JSONSerializer.serialize(_nullishCoalesce(from, () => ( "$all")))}, Start from: ${JSONSerializer.serialize(
1320
- options.startFrom
1321
- )}`
1322
- );
1323
- subscription = subscribe(client, from, options);
1324
- processor = new SubscriptionSequentialHandler({
1325
- client,
1326
- from,
1327
- batchSize,
1328
- eachBatch,
1329
- resilience
1330
- });
1331
- const handler = new class extends _stream.Writable {
1332
- async _write(result, _encoding, done) {
1333
- if (!isRunning) return;
1334
- if (isString(result)) {
1335
- options.startFrom = {
1336
- lastCheckpoint: result
1337
- };
1338
- done();
1339
- return;
1340
- }
1341
- if (result && result.type === "STOP" && result.error) {
1342
- console.error(
1343
- `Subscription stopped with error code: ${result.error.errorCode}, message: ${result.error.message}.`
1344
- );
1345
- }
1346
- await stopSubscription();
1347
- done();
1348
- }
1349
- }({ objectMode: true });
1350
- _stream.pipeline.call(void 0,
1351
- subscription,
1352
- processor,
1353
- handler,
1354
- async (error) => {
1355
- console.info(`Stopping subscription.`);
1356
- await stopSubscription(() => {
1357
- if (!error) {
1358
- console.info("Subscription ended successfully.");
1359
- resolve();
1360
- return;
1361
- }
1362
- console.error(
1363
- `Received error: ${JSONSerializer.serialize(error)}.`
1364
- );
1365
- reject(error);
1366
- });
1367
- }
1368
- );
1369
- }),
1370
- resubscribeOptions
1371
- );
1372
- };
1373
- return {
1374
- get isRunning() {
1375
- return isRunning;
1376
- },
1377
- start: (options) => {
1378
- if (isRunning) return start;
1379
- start = (async () => {
1380
- isRunning = true;
1381
- return pipeMessages(options);
1382
- })();
1383
- return start;
1384
- },
1385
- stop: async () => {
1386
- if (!isRunning) return start ? await start : Promise.resolve();
1387
- await stopSubscription();
1388
- await start;
1389
- }
1390
- };
1391
- };
1392
- var zipEventStoreDBEventStoreMessageBatchPullerStartFrom = (options) => {
1393
- if (options.length === 0 || options.some((o) => o === void 0 || o === "BEGINNING"))
1394
- return "BEGINNING";
1395
- if (options.every((o) => o === "END")) return "END";
1396
- return options.filter((o) => o !== void 0 && o !== "BEGINNING" && o !== "END").sort((a, b) => a > b ? 1 : -1)[0];
1397
- };
1398
-
1399
- // src/eventStore/consumers/eventStoreDBEventStoreConsumer.ts
1400
- var $all = "$all";
1401
- var eventStoreDBEventStoreConsumer = (options) => {
1402
- let isRunning = false;
1403
- const { pulling } = options;
1404
- const processors = _nullishCoalesce(options.processors, () => ( []));
1405
- let start;
1406
- let currentSubscription;
1407
- const client = "client" in options && options.client ? options.client : _dbclient.EventStoreDBClient.connectionString(options.connectionString);
1408
- const eachBatch = async (messagesBatch) => {
1409
- const activeProcessors = processors.filter((s) => s.isActive);
1410
- if (activeProcessors.length === 0)
1411
- return {
1412
- type: "STOP",
1413
- reason: "No active processors"
1414
- };
1415
- const result = await Promise.allSettled(
1416
- activeProcessors.map(async (s) => {
1417
- return await s.handle(messagesBatch, { client });
1418
- })
1419
- );
1420
- const error = _optionalChain([result, 'access', _97 => _97.find, 'call', _98 => _98((r) => r.status === "rejected"), 'optionalAccess', _99 => _99.reason]);
1421
- return result.some(
1422
- (r) => r.status === "fulfilled" && _optionalChain([r, 'access', _100 => _100.value, 'optionalAccess', _101 => _101.type]) !== "STOP"
1423
- ) ? void 0 : {
1424
- type: "STOP",
1425
- error: error ? EmmettError.mapFrom(error) : void 0
1426
- };
1427
- };
1428
- const subscription = currentSubscription = eventStoreDBSubscription({
1429
- client,
1430
- from: options.from,
1431
- eachBatch,
1432
- batchSize: _nullishCoalesce(_optionalChain([pulling, 'optionalAccess', _102 => _102.batchSize]), () => ( DefaultEventStoreDBEventStoreProcessorBatchSize)),
1433
- resilience: options.resilience
1434
- });
1435
- const stop = async () => {
1436
- if (!isRunning) return;
1437
- isRunning = false;
1438
- if (currentSubscription) {
1439
- await currentSubscription.stop();
1440
- currentSubscription = void 0;
1441
- }
1442
- await start;
1443
- };
1444
- return {
1445
- consumerId: _nullishCoalesce(options.consumerId, () => ( _uuid.v7.call(void 0, ))),
1446
- get isRunning() {
1447
- return isRunning;
1448
- },
1449
- processors,
1450
- reactor: (options2) => {
1451
- const processor = inMemoryReactor(options2);
1452
- processors.push(
1453
- // TODO: change that
1454
- processor
1455
- );
1456
- return processor;
1457
- },
1458
- projector: (options2) => {
1459
- const processor = inMemoryProjector(options2);
1460
- processors.push(
1461
- // TODO: change that
1462
- processor
1463
- );
1464
- return processor;
1465
- },
1466
- start: () => {
1467
- if (isRunning) return start;
1468
- start = (async () => {
1469
- if (processors.length === 0)
1470
- return Promise.reject(
1471
- new EmmettError(
1472
- "Cannot start consumer without at least a single processor"
1473
- )
1474
- );
1475
- isRunning = true;
1476
- const startFrom = zipEventStoreDBEventStoreMessageBatchPullerStartFrom(
1477
- await Promise.all(processors.map((o) => o.start(client)))
1478
- );
1479
- return subscription.start({ startFrom });
1480
- })();
1481
- return start;
1482
- },
1483
- stop,
1484
- close: stop
1485
- };
1486
- };
1487
-
1488
-
1489
-
1490
-
1491
-
1492
-
1493
-
1494
-
1495
-
1496
-
1497
-
1498
-
1499
- exports.$all = $all; exports.DefaultEventStoreDBEventStoreProcessorBatchSize = DefaultEventStoreDBEventStoreProcessorBatchSize; exports.DefaultEventStoreDBEventStoreProcessorPullingFrequencyInMs = DefaultEventStoreDBEventStoreProcessorPullingFrequencyInMs; exports.EventStoreDBEventStoreDefaultStreamVersion = EventStoreDBEventStoreDefaultStreamVersion; exports.EventStoreDBResubscribeDefaultOptions = EventStoreDBResubscribeDefaultOptions; exports.eventStoreDBEventStoreConsumer = eventStoreDBEventStoreConsumer; exports.eventStoreDBSubscription = eventStoreDBSubscription; exports.getEventStoreDBEventStore = getEventStoreDBEventStore; exports.isDatabaseUnavailableError = isDatabaseUnavailableError; exports.mapFromESDBEvent = mapFromESDBEvent; exports.zipEventStoreDBEventStoreMessageBatchPullerStartFrom = zipEventStoreDBEventStoreMessageBatchPullerStartFrom;
159
+ const isDatabaseUnavailableError = (error) => error instanceof Error && "type" in error && error.type === "unavailable" && "code" in error && error.code === 14;
160
+ const EventStoreDBResubscribeDefaultOptions = {
161
+ forever: true,
162
+ minTimeout: 100,
163
+ factor: 1.5,
164
+ shouldRetryError: (error) => !isDatabaseUnavailableError(error)
165
+ };
166
+ var SubscriptionSequentialHandler = class extends stream.Transform {
167
+ options;
168
+ from;
169
+ isRunning;
170
+ constructor(options) {
171
+ super({
172
+ objectMode: true,
173
+ ...options
174
+ });
175
+ this.options = options;
176
+ this.from = options.from;
177
+ this.isRunning = true;
178
+ }
179
+ async _transform(resolvedEvent, _encoding, callback) {
180
+ try {
181
+ if (!this.isRunning || !resolvedEvent.event) {
182
+ callback();
183
+ return;
184
+ }
185
+ const message = mapFromESDBEvent(resolvedEvent, this.from);
186
+ const messageCheckpoint = (0, _event_driven_io_emmett.getCheckpoint)(message);
187
+ const result = await this.options.eachBatch([message]);
188
+ if (result && result.type === "STOP") {
189
+ this.isRunning = false;
190
+ if (!result.error) this.push(messageCheckpoint);
191
+ this.push(result);
192
+ this.push(null);
193
+ callback();
194
+ return;
195
+ }
196
+ this.push(messageCheckpoint);
197
+ callback();
198
+ } catch (error) {
199
+ callback(error);
200
+ }
201
+ }
202
+ };
203
+ const eventStoreDBSubscription = ({ client, from, batchSize, eachBatch, resilience }) => {
204
+ let isRunning = false;
205
+ let start;
206
+ let processor;
207
+ let subscription;
208
+ const resubscribeOptions = resilience?.resubscribeOptions ?? {
209
+ ...EventStoreDBResubscribeDefaultOptions,
210
+ shouldRetryResult: () => isRunning,
211
+ shouldRetryError: (error) => isRunning && EventStoreDBResubscribeDefaultOptions.shouldRetryError(error)
212
+ };
213
+ const stopSubscription = (callback) => {
214
+ isRunning = false;
215
+ if (processor) processor.isRunning = false;
216
+ return subscription.unsubscribe().then(() => {
217
+ subscription.destroy();
218
+ }).catch((err) => console.error("Error during unsubscribe.%s", err)).finally(callback ?? (() => {}));
219
+ };
220
+ const pipeMessages = (options) => {
221
+ let retry = 0;
222
+ return (0, _event_driven_io_emmett.asyncRetry)(() => new Promise((resolve, reject) => {
223
+ if (!isRunning) {
224
+ resolve();
225
+ return;
226
+ }
227
+ console.info(`Starting subscription. ${retry++} retries. From: ${_event_driven_io_emmett.JSONSerializer.serialize(from ?? "$all")}, Start from: ${_event_driven_io_emmett.JSONSerializer.serialize(options.startFrom)}`);
228
+ subscription = subscribe(client, from, options);
229
+ subscription.once("confirmation", () => options.started?.resolve());
230
+ processor = new SubscriptionSequentialHandler({
231
+ client,
232
+ from,
233
+ batchSize,
234
+ eachBatch,
235
+ resilience
236
+ });
237
+ const handler = new class extends stream.Writable {
238
+ async _write(result, _encoding, done) {
239
+ if (!isRunning) return;
240
+ if ((0, _event_driven_io_emmett.isString)(result)) {
241
+ options.startFrom = { lastCheckpoint: result };
242
+ done();
243
+ return;
244
+ }
245
+ if (result && result.type === "STOP" && result.error) console.error(`Subscription stopped with error code: ${result.error.errorCode}, message: ${result.error.message}.`);
246
+ await stopSubscription();
247
+ done();
248
+ }
249
+ }({ objectMode: true });
250
+ (0, stream.pipeline)(subscription, processor, handler, async (error) => {
251
+ console.info(`Stopping subscription.`);
252
+ await stopSubscription(() => {
253
+ if (!error) {
254
+ console.info("Subscription ended successfully.");
255
+ resolve();
256
+ return;
257
+ }
258
+ console.error(`Received error: ${_event_driven_io_emmett.JSONSerializer.serialize(error)}.`);
259
+ options.started?.reject(error);
260
+ reject(error);
261
+ });
262
+ });
263
+ }), resubscribeOptions);
264
+ };
265
+ return {
266
+ get isRunning() {
267
+ return isRunning;
268
+ },
269
+ start: (options) => {
270
+ if (isRunning) return start;
271
+ start = (async () => {
272
+ isRunning = true;
273
+ return pipeMessages(options);
274
+ })();
275
+ return start;
276
+ },
277
+ stop: async () => {
278
+ if (!isRunning) return start ? await start : Promise.resolve();
279
+ await stopSubscription();
280
+ await start;
281
+ }
282
+ };
283
+ };
284
+ const zipEventStoreDBEventStoreMessageBatchPullerStartFrom = (options) => {
285
+ if (options.length === 0 || options.some((o) => o === void 0 || o === "BEGINNING")) return "BEGINNING";
286
+ if (options.every((o) => o === "END")) return "END";
287
+ return options.filter((o) => o !== void 0 && o !== "BEGINNING" && o !== "END").sort((a, b) => a > b ? 1 : -1)[0];
288
+ };
289
+
290
+ //#endregion
291
+ //#region src/eventStore/consumers/eventStoreDBEventStoreConsumer.ts
292
+ const $all = "$all";
293
+ const eventStoreDBEventStoreConsumer = (options) => {
294
+ let isRunning = false;
295
+ let isInitialized = false;
296
+ const { pulling } = options;
297
+ const processors = options.processors ?? [];
298
+ let abortController = null;
299
+ let start;
300
+ let currentSubscription;
301
+ const startedAwaiter = (0, _event_driven_io_emmett.asyncAwaiter)();
302
+ const client = "client" in options && options.client ? options.client : _eventstore_db_client.EventStoreDBClient.connectionString(options.connectionString);
303
+ const eachBatch = async (messagesBatch) => {
304
+ const activeProcessors = processors.filter((s) => s.isActive);
305
+ if (activeProcessors.length === 0) return {
306
+ type: "STOP",
307
+ reason: "No active processors"
308
+ };
309
+ const result = await Promise.allSettled(activeProcessors.map(async (s) => {
310
+ return await s.handle(messagesBatch, { client });
311
+ }));
312
+ const error = result.find((r) => r.status === "rejected")?.reason;
313
+ return result.some((r) => r.status === "fulfilled" && r.value?.type !== "STOP") ? void 0 : {
314
+ type: "STOP",
315
+ error: error ? _event_driven_io_emmett.EmmettError.mapFrom(error) : void 0
316
+ };
317
+ };
318
+ const subscription = currentSubscription = eventStoreDBSubscription({
319
+ client,
320
+ from: options.from,
321
+ eachBatch,
322
+ batchSize: pulling?.batchSize ?? 100,
323
+ resilience: options.resilience
324
+ });
325
+ const init = async () => {
326
+ if (isInitialized) return;
327
+ for (const processor of processors) await processor.init({});
328
+ isInitialized = true;
329
+ };
330
+ const stopProcessors = () => Promise.all(processors.map((p) => p.close({})));
331
+ const stop = async () => {
332
+ if (!isRunning) return;
333
+ isRunning = false;
334
+ abortController?.abort();
335
+ if (currentSubscription) {
336
+ await currentSubscription.stop();
337
+ currentSubscription = void 0;
338
+ }
339
+ await start;
340
+ abortController = null;
341
+ await stopProcessors();
342
+ };
343
+ return {
344
+ consumerId: options.consumerId ?? (0, uuid.v7)(),
345
+ get isRunning() {
346
+ return isRunning;
347
+ },
348
+ whenStarted: () => startedAwaiter.wait,
349
+ processors,
350
+ reactor: (options) => {
351
+ const processor = (0, _event_driven_io_emmett.inMemoryReactor)(options);
352
+ processors.push(processor);
353
+ return processor;
354
+ },
355
+ projector: (options) => {
356
+ const processor = (0, _event_driven_io_emmett.inMemoryProjector)(options);
357
+ processors.push(processor);
358
+ return processor;
359
+ },
360
+ start: () => {
361
+ if (isRunning) return start;
362
+ startedAwaiter.reset();
363
+ if (processors.length === 0) {
364
+ const error = new _event_driven_io_emmett.EmmettError("Cannot start consumer without at least a single processor");
365
+ startedAwaiter.reject(error);
366
+ return Promise.reject(error);
367
+ }
368
+ isRunning = true;
369
+ abortController = new AbortController();
370
+ start = (async () => {
371
+ if (!isRunning) return;
372
+ try {
373
+ if (!isInitialized) await init();
374
+ const startFrom = zipEventStoreDBEventStoreMessageBatchPullerStartFrom(await Promise.all(processors.map((o) => o.start(client))));
375
+ await subscription.start({
376
+ startFrom,
377
+ started: startedAwaiter
378
+ });
379
+ } catch (error) {
380
+ isRunning = false;
381
+ startedAwaiter.reject(error);
382
+ throw error;
383
+ } finally {
384
+ await stopProcessors();
385
+ }
386
+ })();
387
+ return start;
388
+ },
389
+ stop,
390
+ close: stop
391
+ };
392
+ };
393
+
394
+ //#endregion
395
+ exports.$all = $all;
396
+ exports.DefaultEventStoreDBEventStoreProcessorBatchSize = DefaultEventStoreDBEventStoreProcessorBatchSize;
397
+ exports.DefaultEventStoreDBEventStoreProcessorPullingFrequencyInMs = DefaultEventStoreDBEventStoreProcessorPullingFrequencyInMs;
398
+ exports.EventStoreDBEventStoreDefaultStreamVersion = EventStoreDBEventStoreDefaultStreamVersion;
399
+ exports.EventStoreDBResubscribeDefaultOptions = EventStoreDBResubscribeDefaultOptions;
400
+ exports.eventStoreDBEventStoreConsumer = eventStoreDBEventStoreConsumer;
401
+ exports.eventStoreDBSubscription = eventStoreDBSubscription;
402
+ exports.getEventStoreDBEventStore = getEventStoreDBEventStore;
403
+ exports.isDatabaseUnavailableError = isDatabaseUnavailableError;
404
+ exports.mapFromESDBEvent = mapFromESDBEvent;
405
+ exports.zipEventStoreDBEventStoreMessageBatchPullerStartFrom = zipEventStoreDBEventStoreMessageBatchPullerStartFrom;
1500
406
  //# sourceMappingURL=index.cjs.map