@event-driven-io/emmett-sqlite 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,1763 +1,471 @@
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(); } } async function _asyncNullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return await 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 isErrorConstructor = (expect) => {
5
- return typeof expect === "function" && expect.prototype && // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
6
- expect.prototype.constructor === expect;
7
- };
8
- var EmmettError = (_class = class _EmmettError extends Error {
9
- static __initStatic() {this.Codes = {
10
- ValidationError: 400,
11
- IllegalStateError: 403,
12
- NotFoundError: 404,
13
- ConcurrencyError: 412,
14
- InternalServerError: 500
15
- }}
16
-
17
- constructor(options) {
18
- const errorCode = options && typeof options === "object" && "errorCode" in options ? options.errorCode : isNumber(options) ? options : _EmmettError.Codes.InternalServerError;
19
- const message = options && typeof options === "object" && "message" in options ? options.message : isString(options) ? options : `Error with status code '${errorCode}' ocurred during Emmett processing`;
20
- super(message);
21
- this.errorCode = errorCode;
22
- Object.setPrototypeOf(this, _EmmettError.prototype);
23
- }
24
- static mapFrom(error) {
25
- if (_EmmettError.isInstanceOf(error)) {
26
- return error;
27
- }
28
- return new _EmmettError({
29
- errorCode: "errorCode" in error && error.errorCode !== void 0 && error.errorCode !== null ? error.errorCode : _EmmettError.Codes.InternalServerError,
30
- message: _nullishCoalesce(error.message, () => ( "An unknown error occurred"))
31
- });
32
- }
33
- static isInstanceOf(error, errorCode) {
34
- return typeof error === "object" && error !== null && "errorCode" in error && isNumber(error.errorCode) && (errorCode === void 0 || error.errorCode === errorCode);
35
- }
36
- }, _class.__initStatic(), _class);
37
- var ConcurrencyError = class _ConcurrencyError extends EmmettError {
38
- constructor(current, expected, message) {
39
- super({
40
- errorCode: EmmettError.Codes.ConcurrencyError,
41
- message: _nullishCoalesce(message, () => ( `Expected version ${expected.toString()} does not match current ${_optionalChain([current, 'optionalAccess', _ => _.toString, 'call', _2 => _2()])}`))
42
- });
43
- this.current = current;
44
- this.expected = expected;
45
- Object.setPrototypeOf(this, _ConcurrencyError.prototype);
46
- }
47
- };
48
-
49
- // ../emmett/dist/index.js
50
- var _uuid = require('uuid');
51
-
52
-
53
- var _asyncretry = require('async-retry'); var _asyncretry2 = _interopRequireDefault(_asyncretry);
54
-
55
-
56
-
57
- var emmettPrefix = "emt";
58
- var defaultTag = `${emmettPrefix}:default`;
59
- var unknownTag = `${emmettPrefix}:unknown`;
60
- var canCreateEventStoreSession = (eventStore) => "withSession" in eventStore;
61
- var nulloSessionFactory = (eventStore) => ({
62
- withSession: (callback) => {
63
- const nulloSession = {
64
- eventStore,
65
- close: () => Promise.resolve()
66
- };
67
- return callback(nulloSession);
68
- }
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+ let _event_driven_io_emmett = require("@event-driven-io/emmett");
3
+ let _event_driven_io_pongo = require("@event-driven-io/pongo");
4
+ let _event_driven_io_dumbo = require("@event-driven-io/dumbo");
5
+ let uuid = require("uuid");
6
+
7
+ //#region src/eventStore/projections/pongo/pongoProjections.ts
8
+ const pongoProjection = ({ name, kind, version, truncate, handle, canHandle, eventsOptions }) => sqliteProjection({
9
+ name,
10
+ version,
11
+ kind: kind ?? "emt:projections:postgresql:pongo:generic",
12
+ canHandle,
13
+ eventsOptions,
14
+ handle: async (events, context) => {
15
+ const { connection } = context;
16
+ const pongo = (0, _event_driven_io_pongo.pongoClient)({
17
+ driver: await pongoDriverRegistry.tryResolve(context.driverType),
18
+ connectionOptions: { connection }
19
+ });
20
+ try {
21
+ await handle(events, {
22
+ ...context,
23
+ pongo
24
+ });
25
+ } finally {
26
+ await pongo.close();
27
+ }
28
+ },
29
+ truncate: truncate ? async (context) => {
30
+ const { connection } = context;
31
+ const pongo = (0, _event_driven_io_pongo.pongoClient)({
32
+ driver: await pongoDriverRegistry.tryResolve(context.driverType),
33
+ connectionOptions: { connection }
34
+ });
35
+ try {
36
+ await truncate({
37
+ ...context,
38
+ pongo
39
+ });
40
+ } finally {
41
+ await pongo.close();
42
+ }
43
+ } : void 0
69
44
  });
70
- var STREAM_EXISTS = "STREAM_EXISTS";
71
- var STREAM_DOES_NOT_EXIST = "STREAM_DOES_NOT_EXIST";
72
- var NO_CONCURRENCY_CHECK = "NO_CONCURRENCY_CHECK";
73
- var matchesExpectedVersion = (current, expected, defaultVersion) => {
74
- if (expected === NO_CONCURRENCY_CHECK) return true;
75
- if (expected == STREAM_DOES_NOT_EXIST) return current === defaultVersion;
76
- if (expected == STREAM_EXISTS) return current !== defaultVersion;
77
- return current === expected;
78
- };
79
- var assertExpectedVersionMatchesCurrent = (current, expected, defaultVersion) => {
80
- expected ??= NO_CONCURRENCY_CHECK;
81
- if (!matchesExpectedVersion(current, expected, defaultVersion))
82
- throw new ExpectedVersionConflictError(current, expected);
83
- };
84
- var ExpectedVersionConflictError = class _ExpectedVersionConflictError extends ConcurrencyError {
85
- constructor(current, expected) {
86
- super(_optionalChain([current, 'optionalAccess', _3 => _3.toString, 'call', _4 => _4()]), _optionalChain([expected, 'optionalAccess', _5 => _5.toString, 'call', _6 => _6()]));
87
- Object.setPrototypeOf(this, _ExpectedVersionConflictError.prototype);
88
- }
89
- };
90
- var isExpectedVersionConflictError = (error) => error instanceof ExpectedVersionConflictError || EmmettError.isInstanceOf(
91
- error,
92
- ExpectedVersionConflictError.Codes.ConcurrencyError
93
- );
94
- async function reduceAsync(items, fn, initial) {
95
- let accumulator = initial;
96
- for (let i = 0; i < items.length; i++) {
97
- accumulator = await fn(accumulator, items[i], i);
98
- }
99
- return accumulator;
100
- }
101
- var isPrimitive = (value) => {
102
- const type = typeof value;
103
- return value === null || value === void 0 || type === "boolean" || type === "number" || type === "string" || type === "symbol" || type === "bigint";
104
- };
105
- var compareArrays = (left, right) => {
106
- if (left.length !== right.length) {
107
- return false;
108
- }
109
- for (let i = 0; i < left.length; i++) {
110
- const leftHas = i in left;
111
- const rightHas = i in right;
112
- if (leftHas !== rightHas) return false;
113
- if (leftHas && !deepEquals(left[i], right[i])) return false;
114
- }
115
- return true;
116
- };
117
- var compareDates = (left, right) => {
118
- return left.getTime() === right.getTime();
119
- };
120
- var compareRegExps = (left, right) => {
121
- return left.toString() === right.toString();
122
- };
123
- var compareErrors = (left, right) => {
124
- if (left.message !== right.message || left.name !== right.name) {
125
- return false;
126
- }
127
- const leftKeys = Object.keys(left);
128
- const rightKeys = Object.keys(right);
129
- if (leftKeys.length !== rightKeys.length) return false;
130
- const rightKeySet = new Set(rightKeys);
131
- for (const key of leftKeys) {
132
- if (!rightKeySet.has(key)) return false;
133
- if (!deepEquals(left[key], right[key])) return false;
134
- }
135
- return true;
136
- };
137
- var compareMaps = (left, right) => {
138
- if (left.size !== right.size) return false;
139
- for (const [key, value] of left) {
140
- if (isPrimitive(key)) {
141
- if (!right.has(key) || !deepEquals(value, right.get(key))) {
142
- return false;
143
- }
144
- } else {
145
- let found = false;
146
- for (const [rightKey, rightValue] of right) {
147
- if (deepEquals(key, rightKey) && deepEquals(value, rightValue)) {
148
- found = true;
149
- break;
150
- }
151
- }
152
- if (!found) return false;
153
- }
154
- }
155
- return true;
156
- };
157
- var compareSets = (left, right) => {
158
- if (left.size !== right.size) return false;
159
- for (const leftItem of left) {
160
- if (isPrimitive(leftItem)) {
161
- if (!right.has(leftItem)) return false;
162
- } else {
163
- let found = false;
164
- for (const rightItem of right) {
165
- if (deepEquals(leftItem, rightItem)) {
166
- found = true;
167
- break;
168
- }
169
- }
170
- if (!found) return false;
171
- }
172
- }
173
- return true;
174
- };
175
- var compareArrayBuffers = (left, right) => {
176
- if (left.byteLength !== right.byteLength) return false;
177
- const leftView = new Uint8Array(left);
178
- const rightView = new Uint8Array(right);
179
- for (let i = 0; i < leftView.length; i++) {
180
- if (leftView[i] !== rightView[i]) return false;
181
- }
182
- return true;
183
- };
184
- var compareTypedArrays = (left, right) => {
185
- if (left.constructor !== right.constructor) return false;
186
- if (left.byteLength !== right.byteLength) return false;
187
- const leftArray = new Uint8Array(
188
- left.buffer,
189
- left.byteOffset,
190
- left.byteLength
191
- );
192
- const rightArray = new Uint8Array(
193
- right.buffer,
194
- right.byteOffset,
195
- right.byteLength
196
- );
197
- for (let i = 0; i < leftArray.length; i++) {
198
- if (leftArray[i] !== rightArray[i]) return false;
199
- }
200
- return true;
201
- };
202
- var compareObjects = (left, right) => {
203
- const keys1 = Object.keys(left);
204
- const keys2 = Object.keys(right);
205
- if (keys1.length !== keys2.length) {
206
- return false;
207
- }
208
- for (const key of keys1) {
209
- if (left[key] instanceof Function && right[key] instanceof Function) {
210
- continue;
211
- }
212
- const isEqual = deepEquals(left[key], right[key]);
213
- if (!isEqual) {
214
- return false;
215
- }
216
- }
217
- return true;
218
- };
219
- var getType = (value) => {
220
- if (value === null) return "null";
221
- if (value === void 0) return "undefined";
222
- const primitiveType = typeof value;
223
- if (primitiveType !== "object") return primitiveType;
224
- if (Array.isArray(value)) return "array";
225
- if (value instanceof Boolean) return "boxed-boolean";
226
- if (value instanceof Number) return "boxed-number";
227
- if (value instanceof String) return "boxed-string";
228
- if (value instanceof Date) return "date";
229
- if (value instanceof RegExp) return "regexp";
230
- if (value instanceof Error) return "error";
231
- if (value instanceof Map) return "map";
232
- if (value instanceof Set) return "set";
233
- if (value instanceof ArrayBuffer) return "arraybuffer";
234
- if (value instanceof DataView) return "dataview";
235
- if (value instanceof WeakMap) return "weakmap";
236
- if (value instanceof WeakSet) return "weakset";
237
- if (ArrayBuffer.isView(value)) return "typedarray";
238
- return "object";
239
- };
240
- var deepEquals = (left, right) => {
241
- if (left === right) return true;
242
- if (isEquatable(left)) {
243
- return left.equals(right);
244
- }
245
- const leftType = getType(left);
246
- const rightType = getType(right);
247
- if (leftType !== rightType) return false;
248
- switch (leftType) {
249
- case "null":
250
- case "undefined":
251
- case "boolean":
252
- case "number":
253
- case "bigint":
254
- case "string":
255
- case "symbol":
256
- case "function":
257
- return left === right;
258
- case "array":
259
- return compareArrays(left, right);
260
- case "date":
261
- return compareDates(left, right);
262
- case "regexp":
263
- return compareRegExps(left, right);
264
- case "error":
265
- return compareErrors(left, right);
266
- case "map":
267
- return compareMaps(
268
- left,
269
- right
270
- );
271
- case "set":
272
- return compareSets(left, right);
273
- case "arraybuffer":
274
- return compareArrayBuffers(left, right);
275
- case "dataview":
276
- case "weakmap":
277
- case "weakset":
278
- return false;
279
- case "typedarray":
280
- return compareTypedArrays(
281
- left,
282
- right
283
- );
284
- case "boxed-boolean":
285
- return left.valueOf() === right.valueOf();
286
- case "boxed-number":
287
- return left.valueOf() === right.valueOf();
288
- case "boxed-string":
289
- return left.valueOf() === right.valueOf();
290
- case "object":
291
- return compareObjects(
292
- left,
293
- right
294
- );
295
- default:
296
- return false;
297
- }
298
- };
299
- var isEquatable = (left) => {
300
- return left !== null && left !== void 0 && typeof left === "object" && "equals" in left && typeof left["equals"] === "function";
301
- };
302
- var toNormalizedString = (value) => value.toString().padStart(19, "0");
303
- var bigInt = {
304
- toNormalizedString
305
- };
306
- var bigIntReplacer = (_key, value) => {
307
- return typeof value === "bigint" ? value.toString() : value;
308
- };
309
- var dateReplacer = (_key, value) => {
310
- return value instanceof Date ? value.toISOString() : value;
311
- };
312
- var isFirstLetterNumeric = (str) => {
313
- const c = str.charCodeAt(0);
314
- return c >= 48 && c <= 57;
315
- };
316
- var isFirstLetterNumericOrMinus = (str) => {
317
- const c = str.charCodeAt(0);
318
- return c >= 48 && c <= 57 || c === 45;
319
- };
320
- var bigIntReviver = (_key, value, context) => {
321
- if (typeof value === "number" && Number.isInteger(value) && !Number.isSafeInteger(value)) {
322
- try {
323
- return BigInt(_nullishCoalesce(_optionalChain([context, 'optionalAccess', _7 => _7.source]), () => ( value.toString())));
324
- } catch (e2) {
325
- return value;
326
- }
327
- }
328
- if (typeof value === "string" && value.length > 15) {
329
- if (isFirstLetterNumericOrMinus(value)) {
330
- const num = Number(value);
331
- if (Number.isFinite(num) && !Number.isSafeInteger(num)) {
332
- try {
333
- return BigInt(value);
334
- } catch (e3) {
335
- }
336
- }
337
- }
338
- }
339
- return value;
340
- };
341
- var dateReviver = (_key, value) => {
342
- if (typeof value === "string" && value.length === 24 && isFirstLetterNumeric(value) && value[10] === "T" && value[23] === "Z") {
343
- const date = new Date(value);
344
- if (!isNaN(date.getTime())) {
345
- return date;
346
- }
347
- }
348
- return value;
349
- };
350
- var composeJSONReplacers = (...replacers) => {
351
- const filteredReplacers = replacers.filter((r) => r !== void 0);
352
- if (filteredReplacers.length === 0) return void 0;
353
- return (key, value) => (
354
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
355
- filteredReplacers.reduce(
356
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
357
- (accValue, replacer) => replacer(key, accValue),
358
- value
359
- )
360
- );
361
- };
362
- var composeJSONRevivers = (...revivers) => {
363
- const filteredRevivers = revivers.filter((r) => r !== void 0);
364
- if (filteredRevivers.length === 0) return void 0;
365
- return (key, value, context) => (
366
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
367
- filteredRevivers.reduce(
368
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
369
- (accValue, reviver) => reviver(key, accValue, context),
370
- value
371
- )
372
- );
373
- };
374
- var JSONReplacer = (opts) => composeJSONReplacers(
375
- _optionalChain([opts, 'optionalAccess', _8 => _8.replacer]),
376
- _optionalChain([opts, 'optionalAccess', _9 => _9.failOnBigIntSerialization]) !== true ? JSONReplacers.bigInt : void 0,
377
- _optionalChain([opts, 'optionalAccess', _10 => _10.useDefaultDateSerialization]) !== true ? JSONReplacers.date : void 0
378
- );
379
- var JSONReviver = (opts) => composeJSONRevivers(
380
- _optionalChain([opts, 'optionalAccess', _11 => _11.reviver]),
381
- _optionalChain([opts, 'optionalAccess', _12 => _12.parseBigInts]) === true ? JSONRevivers.bigInt : void 0,
382
- _optionalChain([opts, 'optionalAccess', _13 => _13.parseDates]) === true ? JSONRevivers.date : void 0
383
- );
384
- var JSONReplacers = {
385
- bigInt: bigIntReplacer,
386
- date: dateReplacer
387
- };
388
- var JSONRevivers = {
389
- bigInt: bigIntReviver,
390
- date: dateReviver
391
- };
392
- var jsonSerializer = (options) => {
393
- const defaultReplacer = JSONReplacer(options);
394
- const defaultReviver = JSONReviver(options);
395
- return {
396
- serialize: (object, serializerOptions) => JSON.stringify(
397
- object,
398
- serializerOptions ? JSONReplacer(serializerOptions) : defaultReplacer
399
- ),
400
- deserialize: (payload, deserializerOptions) => JSON.parse(
401
- payload,
402
- deserializerOptions ? JSONReviver(deserializerOptions) : defaultReviver
403
- )
404
- };
405
- };
406
- var JSONSerializer = Object.assign(jsonSerializer(), {
407
- 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)))
45
+ const pongoMultiStreamProjection = (options) => {
46
+ const { collectionName, getDocumentId, canHandle } = options;
47
+ const collectionNameWithVersion = options.version && options.version > 0 ? `${collectionName}_v${options.version}` : collectionName;
48
+ return pongoProjection({
49
+ name: collectionNameWithVersion,
50
+ version: options.version,
51
+ kind: options.kind ?? "emt:projections:postgresql:pongo:multi_stream",
52
+ eventsOptions: options.eventsOptions,
53
+ handle: async (events, { pongo }) => {
54
+ const collection = pongo.db().collection(collectionNameWithVersion, options.collectionOptions);
55
+ const eventsByDocumentId = events.map((event) => {
56
+ return {
57
+ documentId: getDocumentId(event),
58
+ event
59
+ };
60
+ }).reduce((acc, { documentId, event }) => {
61
+ if (!acc.has(documentId)) acc.set(documentId, []);
62
+ acc.get(documentId).push(event);
63
+ return acc;
64
+ }, /* @__PURE__ */ new Map());
65
+ await collection.handle([...eventsByDocumentId.keys()], (document, id) => {
66
+ return (0, _event_driven_io_emmett.reduceAsync)(eventsByDocumentId.get(id), async (acc, event) => await options.evolve(acc, event), document ?? ("initialState" in options ? options.initialState() : null));
67
+ });
68
+ },
69
+ canHandle,
70
+ truncate: async (context) => {
71
+ const { connection } = context;
72
+ const pongo = (0, _event_driven_io_pongo.pongoClient)({
73
+ driver: await pongoDriverRegistry.tryResolve(context.driverType),
74
+ connectionOptions: { connection }
75
+ });
76
+ try {
77
+ await pongo.db().collection(collectionNameWithVersion, options.collectionOptions).deleteMany();
78
+ } finally {
79
+ await pongo.close();
80
+ }
81
+ },
82
+ init: async (context) => {
83
+ const { connection } = context;
84
+ const driver = await pongoDriverRegistry.tryResolve(context.driverType);
85
+ const pongo = (0, _event_driven_io_pongo.pongoClient)({
86
+ connectionOptions: { connection },
87
+ driver
88
+ });
89
+ try {
90
+ await pongo.db().collection(collectionNameWithVersion, options.collectionOptions).schema.migrate();
91
+ } finally {
92
+ await pongo.close();
93
+ }
94
+ }
95
+ });
96
+ };
97
+ const pongoSingleStreamProjection = (options) => {
98
+ return pongoMultiStreamProjection({
99
+ ...options,
100
+ kind: "emt:projections:postgresql:pongo:single_stream",
101
+ getDocumentId: options.getDocumentId ?? ((event) => event.metadata.streamName)
102
+ });
103
+ };
104
+
105
+ //#endregion
106
+ //#region src/eventStore/projections/pongo/pongoProjectionSpec.ts
107
+ const withCollection = async (handle, options) => {
108
+ const { connection, inDatabase, inCollection } = options;
109
+ const driver = await pongoDriverRegistry.tryResolve(connection.driverType);
110
+ const pongo = (0, _event_driven_io_pongo.pongoClient)({
111
+ connectionOptions: { connection },
112
+ driver
113
+ });
114
+ try {
115
+ return handle(pongo.db(inDatabase).collection(inCollection));
116
+ } finally {
117
+ await pongo.close();
118
+ }
119
+ };
120
+ const withoutIdAndVersion = (doc) => {
121
+ const { _id, _version, ...without } = doc;
122
+ return without;
123
+ };
124
+ const assertDocumentsEqual = (actual, expected) => {
125
+ if ("_id" in expected) (0, _event_driven_io_emmett.assertEqual)(expected._id, actual._id, `Document ids are not matching! Expected: ${expected._id}, Actual: ${actual._id}`);
126
+ return (0, _event_driven_io_emmett.assertDeepEqual)(withoutIdAndVersion(actual), withoutIdAndVersion(expected));
127
+ };
128
+ const documentExists = (document, options) => (assertOptions) => withCollection(async (collection) => {
129
+ const result = await collection.findOne("withId" in options ? { _id: options.withId } : options.matchingFilter);
130
+ (0, _event_driven_io_emmett.assertIsNotNull)(result);
131
+ assertDocumentsEqual(result, document);
132
+ }, {
133
+ ...options,
134
+ ...assertOptions
408
135
  });
409
- var NoRetries = { retries: 0 };
410
- var asyncRetry = async (fn, opts) => {
411
- if (opts === void 0 || opts.retries === 0) return fn();
412
- return _asyncretry2.default.call(void 0,
413
- async (bail) => {
414
- try {
415
- const result = await fn();
416
- if (_optionalChain([opts, 'optionalAccess', _20 => _20.shouldRetryResult]) && opts.shouldRetryResult(result)) {
417
- throw new EmmettError(
418
- `Retrying because of result: ${JSONSerializer.serialize(result)}`
419
- );
420
- }
421
- return result;
422
- } catch (error) {
423
- if (_optionalChain([opts, 'optionalAccess', _21 => _21.shouldRetryError]) && !opts.shouldRetryError(error)) {
424
- bail(error);
425
- return void 0;
426
- }
427
- throw error;
428
- }
429
- },
430
- _nullishCoalesce(opts, () => ( { retries: 0 }))
431
- );
432
- };
433
- var onShutdown = (handler) => {
434
- const signals = ["SIGTERM", "SIGINT"];
435
- if (typeof process !== "undefined" && typeof process.on === "function") {
436
- for (const signal of signals) {
437
- process.on(signal, handler);
438
- }
439
- return () => {
440
- for (const signal of signals) {
441
- process.off(signal, handler);
442
- }
443
- };
444
- }
445
- const deno = globalThis.Deno;
446
- if (deno && typeof deno.addSignalListener === "function") {
447
- for (const signal of signals) {
448
- deno.addSignalListener(signal, handler);
449
- }
450
- return () => {
451
- for (const signal of signals) {
452
- deno.removeSignalListener(signal, handler);
453
- }
454
- };
455
- }
456
- return () => {
457
- };
458
- };
459
- var textEncoder = new TextEncoder();
460
- var getCheckpoint = (message2) => {
461
- return message2.metadata.checkpoint;
462
- };
463
- var wasMessageHandled = (message2, checkpoint) => {
464
- const messageCheckpoint = getCheckpoint(message2);
465
- return messageCheckpoint !== null && messageCheckpoint !== void 0 && checkpoint !== null && checkpoint !== void 0 && messageCheckpoint <= checkpoint;
466
- };
467
- var MessageProcessorType = {
468
- PROJECTOR: "projector",
469
- REACTOR: "reactor"
470
- };
471
- var defaultProcessingMessageProcessingScope = (handler, partialContext) => handler(partialContext);
472
- var bigIntProcessorCheckpoint = (value) => bigInt.toNormalizedString(value);
473
- var parseBigIntProcessorCheckpoint = (value) => BigInt(value);
474
- var defaultProcessorVersion = 1;
475
- var defaultProcessorPartition = defaultTag;
476
- var getProcessorInstanceId = (processorId) => `${processorId}:${_uuid.v7.call(void 0, )}`;
477
- var getProjectorId = (options) => `emt:processor:projector:${options.projectionName}`;
478
- var reactor = (options) => {
479
- const {
480
- checkpoints,
481
- processorId,
482
- processorInstanceId: instanceId = getProcessorInstanceId(processorId),
483
- type = MessageProcessorType.REACTOR,
484
- version = defaultProcessorVersion,
485
- partition = defaultProcessorPartition,
486
- hooks = {},
487
- processingScope = defaultProcessingMessageProcessingScope,
488
- startFrom,
489
- canHandle,
490
- stopAfter
491
- } = options;
492
- const isCustomBatch = "eachBatch" in options && !!options.eachBatch;
493
- const eachBatch = isCustomBatch ? options.eachBatch : async (messages, context) => {
494
- let result = void 0;
495
- for (let i = 0; i < messages.length; i++) {
496
- const message2 = messages[i];
497
- const messageProcessingResult = await options.eachMessage(
498
- message2,
499
- context
500
- );
501
- if (messageProcessingResult && messageProcessingResult.type === "STOP") {
502
- result = {
503
- ...messageProcessingResult,
504
- lastSuccessfulMessage: messageProcessingResult.error ? messages[i - 1] : message2
505
- };
506
- break;
507
- }
508
- if (stopAfter && stopAfter(message2)) {
509
- result = {
510
- type: "STOP",
511
- reason: "Stop condition reached",
512
- lastSuccessfulMessage: message2
513
- };
514
- break;
515
- }
516
- if (messageProcessingResult && messageProcessingResult.type === "SKIP") {
517
- result = {
518
- ...messageProcessingResult,
519
- lastSuccessfulMessage: message2
520
- };
521
- continue;
522
- }
523
- }
524
- return result;
525
- };
526
- let isInitiated = false;
527
- let isActive = false;
528
- let lastCheckpoint = null;
529
- let closeSignal = null;
530
- const init = async (initOptions) => {
531
- if (isInitiated) return;
532
- if (hooks.onInit === void 0) {
533
- isInitiated = true;
534
- return;
535
- }
536
- return await processingScope(async (context) => {
537
- await hooks.onInit(context);
538
- isInitiated = true;
539
- }, initOptions);
540
- };
541
- const close = async (closeOptions) => {
542
- isActive = false;
543
- if (closeSignal) {
544
- closeSignal();
545
- closeSignal = null;
546
- }
547
- if (hooks.onClose) {
548
- await processingScope(hooks.onClose, closeOptions);
549
- }
550
- };
551
- return {
552
- // TODO: Consider whether not make it optional or add URN prefix
553
- id: processorId,
554
- instanceId,
555
- type,
556
- canHandle,
557
- init,
558
- start: async (startOptions) => {
559
- if (isActive) return;
560
- await init(startOptions);
561
- isActive = true;
562
- closeSignal = onShutdown(() => close(startOptions));
563
- if (lastCheckpoint !== null) {
564
- return {
565
- lastCheckpoint
566
- };
567
- }
568
- return await processingScope(async (context) => {
569
- if (hooks.onStart) {
570
- await hooks.onStart(context);
571
- }
572
- if (startFrom && startFrom !== "CURRENT") return startFrom;
573
- if (checkpoints) {
574
- const readResult = await _optionalChain([checkpoints, 'optionalAccess', _22 => _22.read, 'call', _23 => _23(
575
- {
576
- processorId,
577
- partition
578
- },
579
- { ...startOptions, ...context }
580
- )]);
581
- lastCheckpoint = readResult.lastCheckpoint;
582
- }
583
- if (lastCheckpoint === null) return "BEGINNING";
584
- return {
585
- lastCheckpoint
586
- };
587
- }, startOptions);
588
- },
589
- close,
590
- get isActive() {
591
- return isActive;
592
- },
593
- handle: async (messages, partialContext) => {
594
- if (!isActive) return Promise.resolve();
595
- return await processingScope(async (context) => {
596
- const messagesAboveCheckpoint = messages.filter(
597
- (message2) => !wasMessageHandled(message2, lastCheckpoint)
598
- );
599
- const upcastedMessages = messagesAboveCheckpoint.map(
600
- (message2) => upcastRecordedMessage(
601
- // TODO: Make it smarter
602
- message2,
603
- _optionalChain([options, 'access', _24 => _24.messageOptions, 'optionalAccess', _25 => _25.schema, 'optionalAccess', _26 => _26.versioning])
604
- )
605
- ).filter(
606
- (upcasted) => !canHandle || canHandle.includes(upcasted.type)
607
- );
608
- const stopMessageIndex = isCustomBatch && stopAfter ? upcastedMessages.findIndex(stopAfter) : -1;
609
- const unhandledMessages = stopMessageIndex !== -1 ? upcastedMessages.slice(0, stopMessageIndex + 1) : upcastedMessages;
610
- const batchResult = await eachBatch(unhandledMessages, context);
611
- const messageProcessingResult = _optionalChain([batchResult, 'optionalAccess', _27 => _27.type]) === "STOP" ? batchResult : stopMessageIndex !== -1 ? {
612
- type: "STOP",
613
- reason: "Stop condition reached",
614
- lastSuccessfulMessage: unhandledMessages[stopMessageIndex]
615
- } : batchResult;
616
- const isStop = messageProcessingResult && messageProcessingResult.type === "STOP";
617
- const checkpointMessage = _optionalChain([messageProcessingResult, 'optionalAccess', _28 => _28.type]) === "STOP" ? messageProcessingResult.lastSuccessfulMessage : messagesAboveCheckpoint[messagesAboveCheckpoint.length - 1];
618
- if (checkpointMessage && checkpoints) {
619
- const storeCheckpointResult = await checkpoints.store(
620
- {
621
- processorId,
622
- version,
623
- message: checkpointMessage,
624
- lastCheckpoint,
625
- partition
626
- },
627
- context
628
- );
629
- if (storeCheckpointResult.success) {
630
- lastCheckpoint = storeCheckpointResult.newCheckpoint;
631
- }
632
- }
633
- if (isStop) {
634
- isActive = false;
635
- return messageProcessingResult;
636
- }
637
- return void 0;
638
- }, partialContext);
639
- }
640
- };
641
- };
642
- var projector = (options) => {
643
- const {
644
- projection: projection2,
645
- processorId = getProjectorId({
646
- projectionName: _nullishCoalesce(projection2.name, () => ( "unknown"))
647
- }),
648
- ...rest
649
- } = options;
650
- return reactor({
651
- ...rest,
652
- type: MessageProcessorType.PROJECTOR,
653
- canHandle: projection2.canHandle,
654
- processorId,
655
- messageOptions: options.projection.eventsOptions,
656
- hooks: {
657
- onInit: _optionalChain([options, 'access', _29 => _29.hooks, 'optionalAccess', _30 => _30.onInit]),
658
- onStart: options.truncateOnStart && options.projection.truncate || _optionalChain([options, 'access', _31 => _31.hooks, 'optionalAccess', _32 => _32.onStart]) ? async (context) => {
659
- if (options.truncateOnStart && options.projection.truncate)
660
- await options.projection.truncate(context);
661
- if (_optionalChain([options, 'access', _33 => _33.hooks, 'optionalAccess', _34 => _34.onStart])) await _optionalChain([options, 'access', _35 => _35.hooks, 'optionalAccess', _36 => _36.onStart, 'call', _37 => _37(context)]);
662
- } : void 0,
663
- onClose: _optionalChain([options, 'access', _38 => _38.hooks, 'optionalAccess', _39 => _39.onClose])
664
- },
665
- eachBatch: async (events, context) => projection2.handle(events, context)
666
- });
667
- };
668
- var AssertionError = class extends Error {
669
- constructor(message2) {
670
- super(message2);
671
- }
672
- };
673
- var isSubset = (superObj, subObj) => {
674
- const sup = superObj;
675
- const sub = subObj;
676
- assertOk(sup);
677
- assertOk(sub);
678
- return Object.keys(sub).every((ele) => {
679
- if (sub[ele] !== null && typeof sub[ele] == "object") {
680
- return isSubset(sup[ele], sub[ele]);
681
- }
682
- return sub[ele] === sup[ele];
683
- });
684
- };
685
- var assertFails = (message2) => {
686
- throw new AssertionError(_nullishCoalesce(message2, () => ( "That should not ever happened, right?")));
687
- };
688
- var assertDeepEqual = (actual, expected, message2) => {
689
- if (!deepEquals(actual, expected))
690
- throw new AssertionError(
691
- _nullishCoalesce(message2, () => ( `subObj:
692
- ${JSONSerializer.serialize(expected)}
693
- is not equal to
694
- ${JSONSerializer.serialize(actual)}`))
695
- );
696
- };
697
- function assertTrue(condition, message2) {
698
- if (condition !== true)
699
- throw new AssertionError(_nullishCoalesce(message2, () => ( `Condition is false`)));
700
- }
701
- function assertOk(obj, message2) {
702
- if (!obj) throw new AssertionError(_nullishCoalesce(message2, () => ( `Condition is not truthy`)));
703
- }
704
- function assertEqual(expected, actual, message2) {
705
- if (expected !== actual)
706
- throw new AssertionError(
707
- `${_nullishCoalesce(message2, () => ( "Objects are not equal"))}:
708
- Expected: ${JSONSerializer.serialize(expected)}
709
- Actual: ${JSONSerializer.serialize(actual)}`
710
- );
711
- }
712
- function assertNotEqual(obj, other, message2) {
713
- if (obj === other)
714
- throw new AssertionError(
715
- _nullishCoalesce(message2, () => ( `Objects are equal: ${JSONSerializer.serialize(obj)}`))
716
- );
717
- }
718
- function assertIsNotNull(result) {
719
- assertNotEqual(result, null);
720
- assertOk(result);
721
- }
722
- function assertIsNull(result) {
723
- assertEqual(result, null);
724
- }
725
- var assertThatArray = (array) => {
726
- return {
727
- isEmpty: () => assertEqual(
728
- array.length,
729
- 0,
730
- `Array is not empty ${JSONSerializer.serialize(array)}`
731
- ),
732
- isNotEmpty: () => assertNotEqual(array.length, 0, `Array is empty`),
733
- hasSize: (length) => assertEqual(array.length, length),
734
- containsElements: (other) => {
735
- assertTrue(other.every((ts) => array.some((o) => deepEquals(ts, o))));
736
- },
737
- containsElementsMatching: (other) => {
738
- assertTrue(other.every((ts) => array.some((o) => isSubset(o, ts))));
739
- },
740
- containsOnlyElementsMatching: (other) => {
741
- assertEqual(array.length, other.length, `Arrays lengths don't match`);
742
- assertTrue(other.every((ts) => array.some((o) => isSubset(o, ts))));
743
- },
744
- containsExactlyInAnyOrder: (other) => {
745
- assertEqual(array.length, other.length);
746
- assertTrue(array.every((ts) => other.some((o) => deepEquals(ts, o))));
747
- },
748
- containsExactlyInAnyOrderElementsOf: (other) => {
749
- assertEqual(array.length, other.length);
750
- assertTrue(array.every((ts) => other.some((o) => deepEquals(ts, o))));
751
- },
752
- containsExactlyElementsOf: (other) => {
753
- assertEqual(array.length, other.length);
754
- for (let i = 0; i < array.length; i++) {
755
- assertTrue(deepEquals(array[i], other[i]));
756
- }
757
- },
758
- containsExactly: (elem) => {
759
- assertEqual(array.length, 1);
760
- assertTrue(deepEquals(array[0], elem));
761
- },
762
- contains: (elem) => {
763
- assertTrue(array.some((a) => deepEquals(a, elem)));
764
- },
765
- containsOnlyOnceElementsOf: (other) => {
766
- assertTrue(
767
- other.map((o) => array.filter((a) => deepEquals(a, o)).length).filter((a) => a === 1).length === other.length
768
- );
769
- },
770
- containsAnyOf: (other) => {
771
- assertTrue(array.some((a) => other.some((o) => deepEquals(a, o))));
772
- },
773
- allMatch: (matches) => {
774
- assertTrue(array.every(matches));
775
- },
776
- anyMatches: (matches) => {
777
- assertTrue(array.some(matches));
778
- },
779
- allMatchAsync: async (matches) => {
780
- for (const item of array) {
781
- assertTrue(await matches(item));
782
- }
783
- }
784
- };
785
- };
786
- var downcastRecordedMessage = (recordedMessage, options) => {
787
- if (!_optionalChain([options, 'optionalAccess', _40 => _40.downcast]))
788
- return recordedMessage;
789
- const downcasted = options.downcast(
790
- recordedMessage
791
- );
792
- return {
793
- ...recordedMessage,
794
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
795
- data: downcasted.data,
796
- ..."metadata" in recordedMessage || "metadata" in downcasted ? {
797
- metadata: {
798
- ..."metadata" in recordedMessage ? recordedMessage.metadata : {},
799
- ..."metadata" in downcasted ? downcasted.metadata : {}
800
- }
801
- } : {}
802
- };
803
- };
804
- var downcastRecordedMessages = (recordedMessages, options) => {
805
- if (!_optionalChain([options, 'optionalAccess', _41 => _41.downcast]))
806
- return recordedMessages;
807
- return recordedMessages.map(
808
- (recordedMessage) => downcastRecordedMessage(recordedMessage, options)
809
- );
810
- };
811
- var upcastRecordedMessage = (recordedMessage, options) => {
812
- if (!_optionalChain([options, 'optionalAccess', _42 => _42.upcast]))
813
- return recordedMessage;
814
- const upcasted = options.upcast(
815
- recordedMessage
816
- );
817
- return {
818
- ...recordedMessage,
819
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
820
- data: upcasted.data,
821
- ..."metadata" in recordedMessage || "metadata" in upcasted ? {
822
- metadata: {
823
- ..."metadata" in recordedMessage ? recordedMessage.metadata : {},
824
- ..."metadata" in upcasted ? upcasted.metadata : {}
825
- }
826
- } : {}
827
- };
828
- };
829
- var projection = (definition) => definition;
830
- var WorkflowHandlerStreamVersionConflictRetryOptions = {
831
- retries: 3,
832
- minTimeout: 100,
833
- factor: 1.5,
834
- shouldRetryError: isExpectedVersionConflictError
835
- };
836
- var fromWorkflowHandlerRetryOptions = (retryOptions) => {
837
- if (retryOptions === void 0) return NoRetries;
838
- if ("onVersionConflict" in retryOptions) {
839
- if (typeof retryOptions.onVersionConflict === "boolean")
840
- return WorkflowHandlerStreamVersionConflictRetryOptions;
841
- else if (typeof retryOptions.onVersionConflict === "number")
842
- return {
843
- ...WorkflowHandlerStreamVersionConflictRetryOptions,
844
- retries: retryOptions.onVersionConflict
845
- };
846
- else return retryOptions.onVersionConflict;
847
- }
848
- return retryOptions;
849
- };
850
- var emptyHandlerResult = (nextExpectedStreamVersion = 0n) => ({
851
- newMessages: [],
852
- createdNewStream: false,
853
- nextExpectedStreamVersion
136
+ const documentsAreTheSame = (documents, options) => (assertOptions) => withCollection(async (collection) => {
137
+ const result = await collection.find("withId" in options ? { _id: options.withId } : options.matchingFilter);
138
+ (0, _event_driven_io_emmett.assertEqual)(documents.length, result.length, "Different Documents Count than expected");
139
+ for (let i = 0; i < documents.length; i++) (0, _event_driven_io_emmett.assertThatArray)(result).contains(documents[i]);
140
+ }, {
141
+ ...options,
142
+ ...assertOptions
854
143
  });
855
- var createInputMetadata = (originalMessageId, action) => ({
856
- originalMessageId,
857
- input: true,
858
- action
144
+ const documentsMatchingHaveCount = (expectedCount, options) => (assertOptions) => withCollection(async (collection) => {
145
+ (0, _event_driven_io_emmett.assertEqual)(expectedCount, (await collection.find("withId" in options ? { _id: options.withId } : options.matchingFilter)).length, "Different Documents Count than expected");
146
+ }, {
147
+ ...options,
148
+ ...assertOptions
859
149
  });
860
- var tagOutputMessage = (msg, action) => {
861
- const existingMetadata = "metadata" in msg && msg.metadata ? msg.metadata : {};
862
- return {
863
- ...msg,
864
- metadata: {
865
- ...existingMetadata,
866
- action
867
- }
868
- };
869
- };
870
- var createWrappedInitialState = (initialState) => {
871
- return () => ({
872
- userState: initialState(),
873
- processedInputIds: /* @__PURE__ */ new Set()
874
- });
875
- };
876
- var createWrappedEvolve = (evolve, workflowName, separateInputInboxFromProcessing) => {
877
- return (state, event2) => {
878
- const metadata = event2.metadata;
879
- let processedInputIds = state.processedInputIds;
880
- if (_optionalChain([metadata, 'optionalAccess', _43 => _43.input]) === true && typeof _optionalChain([metadata, 'optionalAccess', _44 => _44.originalMessageId]) === "string") {
881
- processedInputIds = new Set(state.processedInputIds);
882
- processedInputIds.add(metadata.originalMessageId);
883
- }
884
- if (separateInputInboxFromProcessing && _optionalChain([metadata, 'optionalAccess', _45 => _45.input]) === true) {
885
- return {
886
- userState: state.userState,
887
- processedInputIds
888
- };
889
- }
890
- const eventType = event2.type;
891
- const eventForEvolve = eventType.startsWith(`${workflowName}:`) ? {
892
- ...event2,
893
- type: eventType.replace(`${workflowName}:`, "")
894
- } : event2;
895
- return {
896
- userState: evolve(state.userState, eventForEvolve),
897
- processedInputIds
898
- };
899
- };
900
- };
901
- var workflowStreamName = ({
902
- workflowName,
903
- workflowId
904
- }) => `emt:workflow:${workflowName}:${workflowId}`;
905
- var WorkflowHandler = (options) => async (store, message2, handleOptions) => asyncRetry(
906
- async () => {
907
- const result = await withSession2(store, async ({ eventStore }) => {
908
- const {
909
- workflow: { evolve, initialState, decide, name: workflowName },
910
- getWorkflowId: getWorkflowId2
911
- } = options;
912
- const inputMessageId = (
913
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
914
- _nullishCoalesce(("metadata" in message2 && _optionalChain([message2, 'access', _46 => _46.metadata, 'optionalAccess', _47 => _47.messageId]) ? (
915
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
916
- message2.metadata.messageId
917
- ) : void 0), () => ( _uuid.v7.call(void 0, )))
918
- );
919
- const messageWithMetadata = {
920
- ...message2,
921
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
922
- metadata: {
923
- messageId: inputMessageId,
924
- ...message2.metadata
925
- }
926
- };
927
- const workflowId = getWorkflowId2(messageWithMetadata);
928
- if (!workflowId) {
929
- return emptyHandlerResult();
930
- }
931
- const streamName = options.mapWorkflowId ? options.mapWorkflowId(workflowId) : workflowStreamName({ workflowName, workflowId });
932
- const messageType = messageWithMetadata.type;
933
- const hasWorkflowPrefix = messageType.startsWith(`${workflowName}:`);
934
- if (options.separateInputInboxFromProcessing && !hasWorkflowPrefix) {
935
- const inputMetadata2 = createInputMetadata(
936
- inputMessageId,
937
- "InitiatedBy"
938
- );
939
- const inputToStore2 = {
940
- type: `${workflowName}:${messageWithMetadata.type}`,
941
- data: messageWithMetadata.data,
942
- kind: messageWithMetadata.kind,
943
- metadata: inputMetadata2
944
- };
945
- const appendResult2 = await eventStore.appendToStream(
946
- streamName,
947
- [inputToStore2],
948
- {
949
- ...handleOptions,
950
- expectedStreamVersion: _nullishCoalesce(_optionalChain([handleOptions, 'optionalAccess', _48 => _48.expectedStreamVersion]), () => ( NO_CONCURRENCY_CHECK))
951
- }
952
- );
953
- return {
954
- ...appendResult2,
955
- newMessages: []
956
- };
957
- }
958
- const wrappedInitialState = createWrappedInitialState(initialState);
959
- const wrappedEvolve = createWrappedEvolve(
960
- evolve,
961
- workflowName,
962
- _nullishCoalesce(options.separateInputInboxFromProcessing, () => ( false))
963
- );
964
- const aggregationResult = await eventStore.aggregateStream(streamName, {
965
- evolve: wrappedEvolve,
966
- initialState: wrappedInitialState,
967
- read: {
968
- ...handleOptions,
969
- // expected stream version is passed to fail fast
970
- // if stream is in the wrong state
971
- expectedStreamVersion: _nullishCoalesce(_optionalChain([handleOptions, 'optionalAccess', _49 => _49.expectedStreamVersion]), () => ( NO_CONCURRENCY_CHECK))
972
- }
973
- });
974
- const { currentStreamVersion } = aggregationResult;
975
- const { userState: state, processedInputIds } = aggregationResult.state;
976
- if (processedInputIds.has(inputMessageId)) {
977
- return emptyHandlerResult(currentStreamVersion);
978
- }
979
- const messageForDecide = hasWorkflowPrefix ? {
980
- ...messageWithMetadata,
981
- type: messageType.replace(`${workflowName}:`, "")
982
- } : messageWithMetadata;
983
- const result2 = decide(messageForDecide, state);
984
- const inputMetadata = createInputMetadata(
985
- inputMessageId,
986
- aggregationResult.streamExists ? "Received" : "InitiatedBy"
987
- );
988
- const inputToStore = {
989
- type: `${workflowName}:${messageWithMetadata.type}`,
990
- data: messageWithMetadata.data,
991
- kind: messageWithMetadata.kind,
992
- metadata: inputMetadata
993
- };
994
- const outputMessages = (Array.isArray(result2) ? result2 : [result2]).filter((msg) => msg !== void 0 && msg !== null);
995
- const outputCommandTypes = _nullishCoalesce(_optionalChain([options, 'access', _50 => _50.outputs, 'optionalAccess', _51 => _51.commands]), () => ( []));
996
- const taggedOutputMessages = outputMessages.map((msg) => {
997
- const action = outputCommandTypes.includes(
998
- msg.type
999
- ) ? "Sent" : "Published";
1000
- return tagOutputMessage(msg, action);
1001
- });
1002
- const messagesToAppend = options.separateInputInboxFromProcessing && hasWorkflowPrefix ? [...taggedOutputMessages] : [inputToStore, ...taggedOutputMessages];
1003
- if (messagesToAppend.length === 0) {
1004
- return emptyHandlerResult(currentStreamVersion);
1005
- }
1006
- const expectedStreamVersion = _nullishCoalesce(_optionalChain([handleOptions, 'optionalAccess', _52 => _52.expectedStreamVersion]), () => ( (aggregationResult.streamExists ? currentStreamVersion : STREAM_DOES_NOT_EXIST)));
1007
- const appendResult = await eventStore.appendToStream(
1008
- streamName,
1009
- // TODO: Fix this cast
1010
- messagesToAppend,
1011
- {
1012
- ...handleOptions,
1013
- expectedStreamVersion
1014
- }
1015
- );
1016
- return {
1017
- ...appendResult,
1018
- newMessages: outputMessages
1019
- };
1020
- });
1021
- return result;
1022
- },
1023
- fromWorkflowHandlerRetryOptions(
1024
- handleOptions && "retry" in handleOptions ? handleOptions.retry : options.retry
1025
- )
1026
- );
1027
- var withSession2 = (eventStore, callback) => {
1028
- const sessionFactory = canCreateEventStoreSession(eventStore) ? eventStore : nulloSessionFactory(eventStore);
1029
- return sessionFactory.withSession(callback);
1030
- };
1031
- var getWorkflowId = (options) => `emt:processor:workflow:${options.workflowName}`;
1032
- var workflowProcessor = (options) => {
1033
- const { workflow, ...rest } = options;
1034
- const inputs = [...options.inputs.commands, ...options.inputs.events];
1035
- let canHandle = inputs;
1036
- if (options.separateInputInboxFromProcessing)
1037
- canHandle = [
1038
- ...canHandle,
1039
- ...options.inputs.commands.map((t) => `${workflow.name}:${t}`),
1040
- ...options.inputs.events.map((t) => `${workflow.name}:${t}`)
1041
- ];
1042
- if (options.outputHandler)
1043
- canHandle = [...canHandle, ...options.outputHandler.canHandle];
1044
- const handle = WorkflowHandler(options);
1045
- return reactor({
1046
- ...rest,
1047
- processorId: _nullishCoalesce(options.processorId, () => ( getWorkflowId({ workflowName: workflow.name }))),
1048
- canHandle,
1049
- type: MessageProcessorType.PROJECTOR,
1050
- eachMessage: async (message2, context) => {
1051
- const messageType = message2.type;
1052
- const metadata = message2.metadata;
1053
- const isInput = _optionalChain([metadata, 'optionalAccess', _53 => _53.input]) === true;
1054
- if (isInput || inputs.includes(messageType)) {
1055
- const result = await handle(
1056
- context.connection.messageStore,
1057
- message2,
1058
- context
1059
- );
1060
- if (options.stopAfter && result.newMessages.length > 0) {
1061
- for (const outputMessage of result.newMessages) {
1062
- if (options.stopAfter(
1063
- outputMessage
1064
- )) {
1065
- return { type: "STOP", reason: "Stop condition reached" };
1066
- }
1067
- }
1068
- }
1069
- return;
1070
- }
1071
- if (_optionalChain([options, 'access', _54 => _54.outputHandler, 'optionalAccess', _55 => _55.canHandle, 'access', _56 => _56.includes, 'call', _57 => _57(messageType)]) === true) {
1072
- const recordedMessage = message2;
1073
- const handledOutputMessages = options.outputHandler.eachBatch ? await options.outputHandler.eachBatch([recordedMessage], context) : await options.outputHandler.eachMessage(recordedMessage, context);
1074
- if (handledOutputMessages instanceof EmmettError) {
1075
- return {
1076
- type: "STOP",
1077
- reason: "Routing error",
1078
- error: handledOutputMessages
1079
- };
1080
- }
1081
- const messagesToAppend = Array.isArray(handledOutputMessages) ? handledOutputMessages : handledOutputMessages ? [handledOutputMessages] : [];
1082
- if (messagesToAppend.length === 0) {
1083
- return;
1084
- }
1085
- const workflowId = options.getWorkflowId(
1086
- message2
1087
- );
1088
- if (!workflowId) return;
1089
- const streamName = options.mapWorkflowId ? options.mapWorkflowId(workflowId) : workflowStreamName({
1090
- workflowName: workflow.name,
1091
- workflowId
1092
- });
1093
- await context.connection.messageStore.appendToStream(
1094
- streamName,
1095
- messagesToAppend
1096
- );
1097
- return;
1098
- }
1099
- return;
1100
- }
1101
- });
1102
- };
1103
-
1104
- // src/eventStore/projections/pongo/pongoProjections.ts
1105
-
1106
-
1107
- var _pongo = require('@event-driven-io/pongo');
1108
- var pongoProjection = ({
1109
- name,
1110
- kind,
1111
- version,
1112
- truncate,
1113
- handle,
1114
- canHandle,
1115
- eventsOptions
1116
- }) => sqliteProjection({
1117
- name,
1118
- version,
1119
- kind: _nullishCoalesce(kind, () => ( "emt:projections:postgresql:pongo:generic")),
1120
- canHandle,
1121
- eventsOptions,
1122
- handle: async (events, context) => {
1123
- const { connection } = context;
1124
- const driver = await pongoDriverRegistry.tryResolve(
1125
- context.driverType
1126
- );
1127
- const pongo = _pongo.pongoClient.call(void 0, {
1128
- driver,
1129
- connectionOptions: { connection }
1130
- });
1131
- try {
1132
- await handle(events, {
1133
- ...context,
1134
- pongo
1135
- });
1136
- } finally {
1137
- await pongo.close();
1138
- }
1139
- },
1140
- truncate: truncate ? async (context) => {
1141
- const { connection } = context;
1142
- const driver = await pongoDriverRegistry.tryResolve(
1143
- context.driverType
1144
- );
1145
- const pongo = _pongo.pongoClient.call(void 0, {
1146
- driver,
1147
- connectionOptions: { connection }
1148
- });
1149
- try {
1150
- await truncate({
1151
- ...context,
1152
- pongo
1153
- });
1154
- } finally {
1155
- await pongo.close();
1156
- }
1157
- } : void 0
150
+ const documentMatchingExists = (options) => (assertOptions) => withCollection(async (collection) => {
151
+ (0, _event_driven_io_emmett.assertThatArray)(await collection.find("withId" in options ? { _id: options.withId } : options.matchingFilter)).isNotEmpty();
152
+ }, {
153
+ ...options,
154
+ ...assertOptions
1158
155
  });
1159
- var pongoMultiStreamProjection = (options) => {
1160
- const { collectionName, getDocumentId, canHandle } = options;
1161
- const collectionNameWithVersion = options.version && options.version > 0 ? `${collectionName}_v${options.version}` : collectionName;
1162
- return pongoProjection({
1163
- name: collectionNameWithVersion,
1164
- version: options.version,
1165
- kind: _nullishCoalesce(options.kind, () => ( "emt:projections:postgresql:pongo:multi_stream")),
1166
- eventsOptions: options.eventsOptions,
1167
- handle: async (events, { pongo }) => {
1168
- const collection = pongo.db().collection(
1169
- collectionNameWithVersion,
1170
- options.collectionOptions
1171
- );
1172
- const eventsByDocumentId = events.map((event) => {
1173
- const documentId = getDocumentId(event);
1174
- return {
1175
- documentId,
1176
- event
1177
- };
1178
- }).reduce((acc, { documentId, event }) => {
1179
- if (!acc.has(documentId)) {
1180
- acc.set(documentId, []);
1181
- }
1182
- acc.get(documentId).push(event);
1183
- return acc;
1184
- }, /* @__PURE__ */ new Map());
1185
- await collection.handle(
1186
- [...eventsByDocumentId.keys()],
1187
- (document, id) => {
1188
- const events2 = eventsByDocumentId.get(id);
1189
- return reduceAsync(
1190
- events2,
1191
- async (acc, event) => await options.evolve(acc, event),
1192
- _nullishCoalesce(document, () => ( ("initialState" in options ? options.initialState() : null)))
1193
- );
1194
- }
1195
- );
1196
- },
1197
- canHandle,
1198
- truncate: async (context) => {
1199
- const { connection } = context;
1200
- const driver = await pongoDriverRegistry.tryResolve(
1201
- context.driverType
1202
- );
1203
- const pongo = _pongo.pongoClient.call(void 0, {
1204
- driver,
1205
- connectionOptions: { connection }
1206
- });
1207
- try {
1208
- await pongo.db().collection(
1209
- collectionNameWithVersion,
1210
- options.collectionOptions
1211
- ).deleteMany();
1212
- } finally {
1213
- await pongo.close();
1214
- }
1215
- },
1216
- init: async (context) => {
1217
- const { connection } = context;
1218
- const driver = await pongoDriverRegistry.tryResolve(
1219
- context.driverType
1220
- );
1221
- const pongo = _pongo.pongoClient.call(void 0, {
1222
- connectionOptions: { connection },
1223
- driver
1224
- });
1225
- try {
1226
- await pongo.db().collection(
1227
- collectionNameWithVersion,
1228
- options.collectionOptions
1229
- ).schema.migrate();
1230
- } finally {
1231
- await pongo.close();
1232
- }
1233
- }
1234
- });
1235
- };
1236
- var pongoSingleStreamProjection = (options) => {
1237
- return pongoMultiStreamProjection({
1238
- ...options,
1239
- kind: "emt:projections:postgresql:pongo:single_stream",
1240
- getDocumentId: _nullishCoalesce(options.getDocumentId, () => ( ((event) => event.metadata.streamName)))
1241
- });
1242
- };
1243
-
1244
- // src/eventStore/projections/pongo/pongoProjectionSpec.ts
1245
-
1246
-
1247
-
1248
- var withCollection = async (handle, options) => {
1249
- const { connection, inDatabase, inCollection } = options;
1250
- const driver = await pongoDriverRegistry.tryResolve(
1251
- connection.driverType
1252
- );
1253
- const pongo = _pongo.pongoClient.call(void 0, {
1254
- connectionOptions: { connection },
1255
- driver
1256
- });
1257
- try {
1258
- const collection = pongo.db(inDatabase).collection(inCollection);
1259
- return handle(collection);
1260
- } finally {
1261
- await pongo.close();
1262
- }
1263
- };
1264
- var withoutIdAndVersion = (doc) => {
1265
- const { _id, _version, ...without } = doc;
1266
- return without;
1267
- };
1268
- var assertDocumentsEqual = (actual, expected) => {
1269
- if ("_id" in expected)
1270
- assertEqual(
1271
- expected._id,
1272
- actual._id,
1273
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
1274
- `Document ids are not matching! Expected: ${expected._id}, Actual: ${actual._id}`
1275
- );
1276
- return assertDeepEqual(
1277
- withoutIdAndVersion(actual),
1278
- withoutIdAndVersion(expected)
1279
- );
1280
- };
1281
- var documentExists = (document, options) => (assertOptions) => withCollection(
1282
- async (collection) => {
1283
- const result = await collection.findOne(
1284
- "withId" in options ? { _id: options.withId } : options.matchingFilter
1285
- );
1286
- assertIsNotNull(result);
1287
- assertDocumentsEqual(result, document);
1288
- },
1289
- { ...options, ...assertOptions }
1290
- );
1291
- var documentsAreTheSame = (documents, options) => (assertOptions) => withCollection(
1292
- async (collection) => {
1293
- const result = await collection.find(
1294
- "withId" in options ? { _id: options.withId } : options.matchingFilter
1295
- );
1296
- assertEqual(
1297
- documents.length,
1298
- result.length,
1299
- "Different Documents Count than expected"
1300
- );
1301
- for (let i = 0; i < documents.length; i++) {
1302
- assertThatArray(result).contains(documents[i]);
1303
- }
1304
- },
1305
- { ...options, ...assertOptions }
1306
- );
1307
- var documentsMatchingHaveCount = (expectedCount, options) => (assertOptions) => withCollection(
1308
- async (collection) => {
1309
- const result = await collection.find(
1310
- "withId" in options ? { _id: options.withId } : options.matchingFilter
1311
- );
1312
- assertEqual(
1313
- expectedCount,
1314
- result.length,
1315
- "Different Documents Count than expected"
1316
- );
1317
- },
1318
- { ...options, ...assertOptions }
1319
- );
1320
- var documentMatchingExists = (options) => (assertOptions) => withCollection(
1321
- async (collection) => {
1322
- const result = await collection.find(
1323
- "withId" in options ? { _id: options.withId } : options.matchingFilter
1324
- );
1325
- assertThatArray(result).isNotEmpty();
1326
- },
1327
- { ...options, ...assertOptions }
1328
- );
1329
- var documentDoesNotExist = (options) => (assertOptions) => withCollection(
1330
- async (collection) => {
1331
- const result = await collection.findOne(
1332
- "withId" in options ? { _id: options.withId } : options.matchingFilter
1333
- );
1334
- assertIsNull(result);
1335
- },
1336
- { ...options, ...assertOptions }
1337
- );
1338
- var expectPongoDocuments = {
1339
- fromCollection: (collectionName) => {
1340
- return {
1341
- withId: (id) => {
1342
- return {
1343
- toBeEqual: (document) => documentExists(document, {
1344
- withId: id,
1345
- inCollection: collectionName
1346
- }),
1347
- toExist: () => documentMatchingExists({
1348
- withId: id,
1349
- inCollection: collectionName
1350
- }),
1351
- notToExist: () => documentDoesNotExist({
1352
- withId: id,
1353
- inCollection: collectionName
1354
- })
1355
- };
1356
- },
1357
- matching: (filter) => {
1358
- return {
1359
- toBeTheSame: (documents) => documentsAreTheSame(documents, {
1360
- matchingFilter: filter,
1361
- inCollection: collectionName
1362
- }),
1363
- toHaveCount: (expectedCount) => documentsMatchingHaveCount(expectedCount, {
1364
- matchingFilter: filter,
1365
- inCollection: collectionName
1366
- }),
1367
- toExist: () => documentMatchingExists({
1368
- matchingFilter: filter,
1369
- inCollection: collectionName
1370
- }),
1371
- notToExist: () => documentDoesNotExist({
1372
- matchingFilter: filter,
1373
- inCollection: collectionName
1374
- })
1375
- };
1376
- }
1377
- };
1378
- }
1379
- };
1380
-
1381
- // src/eventStore/projections/sqliteProjection.ts
1382
- var handleProjections = async (options) => {
1383
- const {
1384
- projections: allProjections,
1385
- events,
1386
- connection,
1387
- execute,
1388
- driverType
1389
- } = options;
1390
- const eventTypes = events.map((e) => e.type);
1391
- for (const projection2 of allProjections) {
1392
- if (!projection2.canHandle.some((type) => eventTypes.includes(type))) {
1393
- continue;
1394
- }
1395
- await projection2.handle(events, {
1396
- connection,
1397
- execute,
1398
- driverType
1399
- });
1400
- }
1401
- };
1402
- var sqliteProjection = (definition) => projection(definition);
1403
- var sqliteRawBatchSQLProjection = (options) => sqliteProjection({
1404
- name: options.name,
1405
- kind: _nullishCoalesce(options.kind, () => ( "emt:projections:sqlite:raw_sql:batch")),
1406
- version: options.version,
1407
- canHandle: options.canHandle,
1408
- eventsOptions: options.eventsOptions,
1409
- handle: async (events, context) => {
1410
- const sqls = await options.evolve(events, context);
1411
- await context.execute.batchCommand(sqls);
1412
- },
1413
- init: async (initOptions) => {
1414
- const initSQL = options.init ? await options.init(initOptions) : void 0;
1415
- if (initSQL) {
1416
- if (Array.isArray(initSQL)) {
1417
- await initOptions.context.execute.batchCommand(initSQL);
1418
- } else {
1419
- await initOptions.context.execute.command(initSQL);
1420
- }
1421
- }
1422
- }
156
+ const documentDoesNotExist = (options) => (assertOptions) => withCollection(async (collection) => {
157
+ (0, _event_driven_io_emmett.assertIsNull)(await collection.findOne("withId" in options ? { _id: options.withId } : options.matchingFilter));
158
+ }, {
159
+ ...options,
160
+ ...assertOptions
1423
161
  });
1424
- var sqliteRawSQLProjection = (options) => {
1425
- const { evolve, kind, ...rest } = options;
1426
- return sqliteRawBatchSQLProjection({
1427
- kind: _nullishCoalesce(kind, () => ( "emt:projections:sqlite:raw:_sql:single")),
1428
- ...rest,
1429
- evolve: async (events, context) => {
1430
- const sqls = [];
1431
- for (const event of events) {
1432
- const pendingSqls = await evolve(event, context);
1433
- if (Array.isArray(pendingSqls)) {
1434
- sqls.push(...pendingSqls);
1435
- } else {
1436
- sqls.push(pendingSqls);
1437
- }
1438
- }
1439
- return sqls;
1440
- }
1441
- });
1442
- };
1443
-
1444
- // src/eventStore/projections/sqliteProjectionSpec.ts
1445
- var _dumbo = require('@event-driven-io/dumbo');
1446
-
1447
- var SQLiteProjectionSpec = {
1448
- for: (options) => {
1449
- {
1450
- const driverType = options.driver.driverType;
1451
- const pool = _nullishCoalesce(options.pool, () => ( _dumbo.dumbo.call(void 0, {
1452
- serialization: options.serialization,
1453
- transactionOptions: {
1454
- allowNestedTransactions: true,
1455
- mode: "session_based"
1456
- },
1457
- ...options.driver.mapToDumboOptions(options)
1458
- })));
1459
- const projection2 = options.projection;
1460
- let wasInitialized = false;
1461
- return (givenEvents) => {
1462
- return {
1463
- when: (events, options2) => {
1464
- const allEvents = [];
1465
- const run = async (connection) => {
1466
- let globalPosition = 0n;
1467
- const numberOfTimes = _nullishCoalesce(_optionalChain([options2, 'optionalAccess', _58 => _58.numberOfTimes]), () => ( 1));
1468
- for (const event of [
1469
- ...givenEvents,
1470
- ...Array.from({ length: numberOfTimes }).flatMap(() => events)
1471
- ]) {
1472
- const metadata = {
1473
- checkpoint: bigIntProcessorCheckpoint(++globalPosition),
1474
- globalPosition,
1475
- streamPosition: globalPosition,
1476
- streamName: `test-${_uuid.v4.call(void 0, )}`,
1477
- messageId: _uuid.v4.call(void 0, )
1478
- };
1479
- allEvents.push({
1480
- ...event,
1481
- kind: "Event",
1482
- metadata: {
1483
- ...metadata,
1484
- ..."metadata" in event ? _nullishCoalesce(event.metadata, () => ( {})) : {}
1485
- }
1486
- });
1487
- }
1488
- if (!wasInitialized && projection2.init) {
1489
- await projection2.init({
1490
- registrationType: "async",
1491
- status: "active",
1492
- context: {
1493
- execute: connection.execute,
1494
- connection,
1495
- driverType
1496
- },
1497
- version: _nullishCoalesce(projection2.version, () => ( 1))
1498
- });
1499
- wasInitialized = true;
1500
- }
1501
- await connection.withTransaction(
1502
- () => handleProjections({
1503
- events: allEvents,
1504
- projections: [projection2],
1505
- execute: connection.execute,
1506
- connection,
1507
- driverType
1508
- })
1509
- );
1510
- };
1511
- return {
1512
- then: (assert, message) => pool.withConnection(async (connection) => {
1513
- await run(connection);
1514
- const succeeded = await assert({
1515
- connection
1516
- });
1517
- if (succeeded !== void 0 && succeeded === false)
1518
- assertFails(
1519
- _nullishCoalesce(message, () => ( "Projection specification didn't match the criteria"))
1520
- );
1521
- }),
1522
- thenThrows: (...args) => pool.withConnection(async (connection) => {
1523
- try {
1524
- await run(connection);
1525
- throw new AssertionError(
1526
- "Handler did not fail as expected"
1527
- );
1528
- } catch (error) {
1529
- if (error instanceof AssertionError) throw error;
1530
- if (args.length === 0) return;
1531
- if (!isErrorConstructor(args[0])) {
1532
- assertTrue(
1533
- args[0](error),
1534
- `Error didn't match the error condition: ${_optionalChain([error, 'optionalAccess', _59 => _59.toString, 'call', _60 => _60()])}`
1535
- );
1536
- return;
1537
- }
1538
- assertTrue(
1539
- error instanceof args[0],
1540
- `Caught error is not an instance of the expected type: ${_optionalChain([error, 'optionalAccess', _61 => _61.toString, 'call', _62 => _62()])}`
1541
- );
1542
- if (args[1]) {
1543
- assertTrue(
1544
- args[1](error),
1545
- `Error didn't match the error condition: ${_optionalChain([error, 'optionalAccess', _63 => _63.toString, 'call', _64 => _64()])}`
1546
- );
1547
- }
1548
- }
1549
- })
1550
- };
1551
- }
1552
- };
1553
- };
1554
- }
1555
- }
1556
- };
1557
- var eventInStream = (streamName, event) => {
1558
- return {
1559
- ...event,
1560
- metadata: {
1561
- ..._nullishCoalesce(event.metadata, () => ( {})),
1562
- streamName: _nullishCoalesce(_optionalChain([event, 'access', _65 => _65.metadata, 'optionalAccess', _66 => _66.streamName]), () => ( streamName))
1563
- }
1564
- };
1565
- };
1566
- var eventsInStream = (streamName, events) => {
1567
- return events.map((e) => eventInStream(streamName, e));
1568
- };
1569
- var newEventsInStream = eventsInStream;
1570
- var assertSQLQueryResultMatches = (sql, rows) => async ({
1571
- connection
1572
- }) => {
1573
- const result = await connection.execute.query(sql);
1574
- assertThatArray(rows).containsExactlyInAnyOrder(result.rows);
1575
- };
1576
- var expectSQL = {
1577
- query: (sql) => ({
1578
- resultRows: {
1579
- toBeTheSame: (rows) => assertSQLQueryResultMatches(sql, rows)
1580
- }
1581
- })
1582
- };
1583
-
1584
- // src/eventStore/schema/appendToStream.ts
1585
-
1586
-
1587
-
1588
-
1589
-
1590
-
1591
-
1592
-
1593
-
1594
- // src/eventStore/schema/typing.ts
1595
- var emmettPrefix2 = "emt";
1596
- var globalTag = "global";
1597
- var defaultTag2 = `${emmettPrefix2}:default`;
1598
- var unknownTag2 = `${emmettPrefix2}:unknown`;
1599
- var globalNames = {
1600
- module: `${emmettPrefix2}:module:${globalTag}`
1601
- };
1602
- var columns = {
1603
- partition: {
1604
- name: "partition"
1605
- },
1606
- isArchived: { name: "is_archived" }
1607
- };
1608
- var streamsTable = {
1609
- name: `${emmettPrefix2}_streams`,
1610
- columns: {
1611
- partition: columns.partition,
1612
- isArchived: columns.isArchived
1613
- }
1614
- };
1615
- var messagesTable = {
1616
- name: `${emmettPrefix2}_messages`,
1617
- columns: {
1618
- partition: columns.partition,
1619
- isArchived: columns.isArchived
1620
- }
1621
- };
1622
- var processorsTable = {
1623
- name: `${emmettPrefix2}_processors`
1624
- };
1625
- var projectionsTable = {
1626
- name: `${emmettPrefix2}_projections`
1627
- };
1628
-
1629
- // src/eventStore/schema/appendToStream.ts
1630
- var { identifier, merge } = _dumbo.SQL;
1631
- var appendToStream = async (connection, streamName, streamType, messages, options) => {
1632
- if (messages.length === 0) return { success: false };
1633
- const expectedStreamVersion = toExpectedVersion(
1634
- _optionalChain([options, 'optionalAccess', _67 => _67.expectedStreamVersion])
1635
- );
1636
- const messagesToAppend = messages.map(
1637
- (m, i) => ({
1638
- ...m,
1639
- kind: _nullishCoalesce(m.kind, () => ( "Event")),
1640
- metadata: {
1641
- streamName,
1642
- messageId: _uuid.v4.call(void 0, ),
1643
- streamPosition: BigInt(i + 1),
1644
- ..."metadata" in m ? _nullishCoalesce(m.metadata, () => ( {})) : {}
1645
- }
1646
- })
1647
- );
1648
- try {
1649
- return await connection.withTransaction(
1650
- async (transaction) => {
1651
- const result = await appendToStreamRaw(
1652
- transaction.execute,
1653
- streamName,
1654
- streamType,
1655
- downcastRecordedMessages(
1656
- messagesToAppend,
1657
- _optionalChain([options, 'optionalAccess', _68 => _68.schema, 'optionalAccess', _69 => _69.versioning])
1658
- ),
1659
- {
1660
- expectedStreamVersion
1661
- }
1662
- );
1663
- if (_optionalChain([options, 'optionalAccess', _70 => _70.onBeforeCommit]))
1664
- await options.onBeforeCommit(messagesToAppend, { connection });
1665
- return { success: true, result };
1666
- }
1667
- );
1668
- } catch (err) {
1669
- if (isExpectedVersionConflictError(err) || _dumbo.DumboError.isInstanceOf(err, {
1670
- errorType: _dumbo.UniqueConstraintError.ErrorType
1671
- }) || _dumbo.DumboError.isInstanceOf(err, {
1672
- errorType: _dumbo.BatchCommandNoChangesError.ErrorType
1673
- })) {
1674
- return { success: false };
1675
- }
1676
- throw err;
1677
- }
1678
- };
1679
- var toExpectedVersion = (expected) => {
1680
- if (expected === void 0) return null;
1681
- if (expected === NO_CONCURRENCY_CHECK) return null;
1682
- if (expected == STREAM_DOES_NOT_EXIST) return null;
1683
- if (expected == STREAM_EXISTS) return null;
1684
- return expected;
1685
- };
1686
- var appendToStreamRaw = async (execute, streamId, streamType, messages, options) => {
1687
- let expectedStreamVersion = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _71 => _71.expectedStreamVersion]), () => ( null));
1688
- const currentStreamVersion = await getLastStreamPosition(
1689
- execute,
1690
- streamId,
1691
- expectedStreamVersion
1692
- );
1693
- expectedStreamVersion ??= _nullishCoalesce(currentStreamVersion, () => ( 0n));
1694
- if (expectedStreamVersion !== currentStreamVersion) {
1695
- throw new ExpectedVersionConflictError(
1696
- currentStreamVersion,
1697
- expectedStreamVersion
1698
- );
1699
- }
1700
- const streamSQL = expectedStreamVersion === 0n ? _dumbo.SQL`INSERT INTO ${identifier(streamsTable.name)}
162
+ const expectPongoDocuments = { fromCollection: (collectionName) => {
163
+ return {
164
+ withId: (id) => {
165
+ return {
166
+ toBeEqual: (document) => documentExists(document, {
167
+ withId: id,
168
+ inCollection: collectionName
169
+ }),
170
+ toExist: () => documentMatchingExists({
171
+ withId: id,
172
+ inCollection: collectionName
173
+ }),
174
+ notToExist: () => documentDoesNotExist({
175
+ withId: id,
176
+ inCollection: collectionName
177
+ })
178
+ };
179
+ },
180
+ matching: (filter) => {
181
+ return {
182
+ toBeTheSame: (documents) => documentsAreTheSame(documents, {
183
+ matchingFilter: filter,
184
+ inCollection: collectionName
185
+ }),
186
+ toHaveCount: (expectedCount) => documentsMatchingHaveCount(expectedCount, {
187
+ matchingFilter: filter,
188
+ inCollection: collectionName
189
+ }),
190
+ toExist: () => documentMatchingExists({
191
+ matchingFilter: filter,
192
+ inCollection: collectionName
193
+ }),
194
+ notToExist: () => documentDoesNotExist({
195
+ matchingFilter: filter,
196
+ inCollection: collectionName
197
+ })
198
+ };
199
+ }
200
+ };
201
+ } };
202
+
203
+ //#endregion
204
+ //#region src/eventStore/projections/sqliteProjection.ts
205
+ const handleProjections = async (options) => {
206
+ const { projections: allProjections, events, connection, execute, driverType } = options;
207
+ const eventTypes = events.map((e) => e.type);
208
+ for (const projection of allProjections) {
209
+ if (!projection.canHandle.some((type) => eventTypes.includes(type))) continue;
210
+ await projection.handle(events, {
211
+ connection,
212
+ execute,
213
+ driverType
214
+ });
215
+ }
216
+ };
217
+ const sqliteProjection = (definition) => (0, _event_driven_io_emmett.projection)(definition);
218
+ const sqliteRawBatchSQLProjection = (options) => sqliteProjection({
219
+ name: options.name,
220
+ kind: options.kind ?? "emt:projections:sqlite:raw_sql:batch",
221
+ version: options.version,
222
+ canHandle: options.canHandle,
223
+ eventsOptions: options.eventsOptions,
224
+ handle: async (events, context) => {
225
+ const sqls = await options.evolve(events, context);
226
+ await context.execute.batchCommand(sqls);
227
+ },
228
+ init: async (initOptions) => {
229
+ const initSQL = options.init ? await options.init(initOptions) : void 0;
230
+ if (initSQL) if (Array.isArray(initSQL)) await initOptions.context.execute.batchCommand(initSQL);
231
+ else await initOptions.context.execute.command(initSQL);
232
+ }
233
+ });
234
+ const sqliteRawSQLProjection = (options) => {
235
+ const { evolve, kind, ...rest } = options;
236
+ return sqliteRawBatchSQLProjection({
237
+ kind: kind ?? "emt:projections:sqlite:raw:_sql:single",
238
+ ...rest,
239
+ evolve: async (events, context) => {
240
+ const sqls = [];
241
+ for (const event of events) {
242
+ const pendingSqls = await evolve(event, context);
243
+ if (Array.isArray(pendingSqls)) sqls.push(...pendingSqls);
244
+ else sqls.push(pendingSqls);
245
+ }
246
+ return sqls;
247
+ }
248
+ });
249
+ };
250
+
251
+ //#endregion
252
+ //#region src/eventStore/projections/sqliteProjectionSpec.ts
253
+ const SQLiteProjectionSpec = { for: (options) => {
254
+ {
255
+ const driverType = options.driver.driverType;
256
+ const pool = options.pool ?? (0, _event_driven_io_dumbo.dumbo)({
257
+ serialization: options.serialization,
258
+ transactionOptions: {
259
+ allowNestedTransactions: true,
260
+ mode: "session_based"
261
+ },
262
+ ...options.driver.mapToDumboOptions(options)
263
+ });
264
+ const projection = options.projection;
265
+ let wasInitialized = false;
266
+ return (givenEvents) => {
267
+ return { when: (events, options) => {
268
+ const allEvents = [];
269
+ const run = async (connection) => {
270
+ let globalPosition = 0n;
271
+ const numberOfTimes = options?.numberOfTimes ?? 1;
272
+ for (const event of [...givenEvents, ...Array.from({ length: numberOfTimes }).flatMap(() => events)]) {
273
+ const metadata = {
274
+ checkpoint: (0, _event_driven_io_emmett.bigIntProcessorCheckpoint)(++globalPosition),
275
+ globalPosition,
276
+ streamPosition: globalPosition,
277
+ streamName: `test-${(0, uuid.v4)()}`,
278
+ messageId: (0, uuid.v4)()
279
+ };
280
+ allEvents.push({
281
+ ...event,
282
+ kind: "Event",
283
+ metadata: {
284
+ ...metadata,
285
+ ..."metadata" in event ? event.metadata ?? {} : {}
286
+ }
287
+ });
288
+ }
289
+ if (!wasInitialized && projection.init) {
290
+ await projection.init({
291
+ registrationType: "async",
292
+ status: "active",
293
+ context: {
294
+ execute: connection.execute,
295
+ connection,
296
+ driverType
297
+ },
298
+ version: projection.version ?? 1
299
+ });
300
+ wasInitialized = true;
301
+ }
302
+ await connection.withTransaction(() => handleProjections({
303
+ events: allEvents,
304
+ projections: [projection],
305
+ execute: connection.execute,
306
+ connection,
307
+ driverType
308
+ }));
309
+ };
310
+ return {
311
+ then: (assert, message) => pool.withConnection(async (connection) => {
312
+ await run(connection);
313
+ const succeeded = await assert({ connection });
314
+ if (succeeded !== void 0 && succeeded === false) (0, _event_driven_io_emmett.assertFails)(message ?? "Projection specification didn't match the criteria");
315
+ }),
316
+ thenThrows: (...args) => pool.withConnection(async (connection) => {
317
+ try {
318
+ await run(connection);
319
+ throw new _event_driven_io_emmett.AssertionError("Handler did not fail as expected");
320
+ } catch (error) {
321
+ if (error instanceof _event_driven_io_emmett.AssertionError) throw error;
322
+ if (args.length === 0) return;
323
+ if (!(0, _event_driven_io_emmett.isErrorConstructor)(args[0])) {
324
+ (0, _event_driven_io_emmett.assertTrue)(args[0](error), `Error didn't match the error condition: ${error?.toString()}`);
325
+ return;
326
+ }
327
+ (0, _event_driven_io_emmett.assertTrue)(error instanceof args[0], `Caught error is not an instance of the expected type: ${error?.toString()}`);
328
+ if (args[1]) (0, _event_driven_io_emmett.assertTrue)(args[1](error), `Error didn't match the error condition: ${error?.toString()}`);
329
+ }
330
+ })
331
+ };
332
+ } };
333
+ };
334
+ }
335
+ } };
336
+ const eventInStream = (streamName, event) => {
337
+ return {
338
+ ...event,
339
+ metadata: {
340
+ ...event.metadata ?? {},
341
+ streamName: event.metadata?.streamName ?? streamName
342
+ }
343
+ };
344
+ };
345
+ const eventsInStream = (streamName, events) => {
346
+ return events.map((e) => eventInStream(streamName, e));
347
+ };
348
+ const newEventsInStream = eventsInStream;
349
+ const assertSQLQueryResultMatches = (sql, rows) => async ({ connection }) => {
350
+ const result = await connection.execute.query(sql);
351
+ (0, _event_driven_io_emmett.assertThatArray)(rows).containsExactlyInAnyOrder(result.rows);
352
+ };
353
+ const expectSQL = { query: (sql) => ({ resultRows: { toBeTheSame: (rows) => assertSQLQueryResultMatches(sql, rows) } }) };
354
+
355
+ //#endregion
356
+ //#region src/eventStore/schema/typing.ts
357
+ const emmettPrefix = "emt";
358
+ const globalTag = "global";
359
+ const defaultTag = `${"emt"}:default`;
360
+ const unknownTag = `${"emt"}:unknown`;
361
+ const globalNames = { module: `${"emt"}:module:${globalTag}` };
362
+ const columns = {
363
+ partition: { name: "partition" },
364
+ isArchived: { name: "is_archived" }
365
+ };
366
+ const streamsTable = {
367
+ name: `${"emt"}_streams`,
368
+ columns: {
369
+ partition: columns.partition,
370
+ isArchived: columns.isArchived
371
+ }
372
+ };
373
+ const messagesTable = {
374
+ name: `${"emt"}_messages`,
375
+ columns: {
376
+ partition: columns.partition,
377
+ isArchived: columns.isArchived
378
+ }
379
+ };
380
+ const processorsTable = { name: `${"emt"}_processors` };
381
+ const projectionsTable = { name: `${"emt"}_projections` };
382
+
383
+ //#endregion
384
+ //#region src/eventStore/schema/appendToStream.ts
385
+ const { identifier: identifier$7, merge } = _event_driven_io_dumbo.SQL;
386
+ const appendToStream = async (connection, streamName, streamType, messages, options) => {
387
+ if (messages.length === 0) return { success: false };
388
+ const expectedStreamVersion = toExpectedVersion(options?.expectedStreamVersion);
389
+ const messagesToAppend = messages.map((m, i) => ({
390
+ ...m,
391
+ kind: m.kind ?? "Event",
392
+ metadata: {
393
+ streamName,
394
+ messageId: (0, uuid.v4)(),
395
+ streamPosition: BigInt(i + 1),
396
+ ..."metadata" in m ? m.metadata ?? {} : {}
397
+ }
398
+ }));
399
+ try {
400
+ return await connection.withTransaction(async (transaction) => {
401
+ const result = await appendToStreamRaw(transaction.execute, streamName, streamType, (0, _event_driven_io_emmett.downcastRecordedMessages)(messagesToAppend, options?.schema?.versioning), { expectedStreamVersion });
402
+ if (options?.onBeforeCommit) await options.onBeforeCommit(messagesToAppend, { connection });
403
+ return {
404
+ success: true,
405
+ result
406
+ };
407
+ });
408
+ } catch (err) {
409
+ if ((0, _event_driven_io_emmett.isExpectedVersionConflictError)(err) || _event_driven_io_dumbo.DumboError.isInstanceOf(err, { errorType: _event_driven_io_dumbo.UniqueConstraintError.ErrorType }) || _event_driven_io_dumbo.DumboError.isInstanceOf(err, { errorType: _event_driven_io_dumbo.BatchCommandNoChangesError.ErrorType })) return { success: false };
410
+ throw err;
411
+ }
412
+ };
413
+ const toExpectedVersion = (expected) => {
414
+ if (expected === void 0) return null;
415
+ if (expected === _event_driven_io_emmett.NO_CONCURRENCY_CHECK) return null;
416
+ if (expected == _event_driven_io_emmett.STREAM_DOES_NOT_EXIST) return null;
417
+ if (expected == _event_driven_io_emmett.STREAM_EXISTS) return null;
418
+ return expected;
419
+ };
420
+ const appendToStreamRaw = async (execute, streamId, streamType, messages, options) => {
421
+ let expectedStreamVersion = options?.expectedStreamVersion ?? null;
422
+ const currentStreamVersion = await getLastStreamPosition(execute, streamId, expectedStreamVersion);
423
+ expectedStreamVersion ??= currentStreamVersion ?? 0n;
424
+ if (expectedStreamVersion !== currentStreamVersion) throw new _event_driven_io_emmett.ExpectedVersionConflictError(currentStreamVersion, expectedStreamVersion);
425
+ const streamSQL = expectedStreamVersion === 0n ? _event_driven_io_dumbo.SQL`INSERT INTO ${identifier$7(streamsTable.name)}
1701
426
  (stream_id, stream_position, partition, stream_type, stream_metadata, is_archived)
1702
427
  VALUES (
1703
428
  ${streamId},
1704
429
  ${messages.length},
1705
- ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _72 => _72.partition]), () => ( streamsTable.columns.partition))},
430
+ ${options?.partition ?? streamsTable.columns.partition},
1706
431
  ${streamType},
1707
432
  '[]',
1708
433
  false
1709
434
  )
1710
435
  RETURNING stream_position;
1711
- ` : _dumbo.SQL`UPDATE ${identifier(streamsTable.name)}
436
+ ` : _event_driven_io_dumbo.SQL`UPDATE ${identifier$7(streamsTable.name)}
1712
437
  SET stream_position = stream_position + ${messages.length}
1713
438
  WHERE stream_id = ${streamId}
1714
439
  AND stream_position = ${expectedStreamVersion}
1715
- AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _73 => _73.partition]), () => ( streamsTable.columns.partition))}
440
+ AND partition = ${options?.partition ?? streamsTable.columns.partition}
1716
441
  AND is_archived = false
1717
442
  RETURNING stream_position;
1718
443
  `;
1719
- const insertSQL = buildMessageInsertQuery(
1720
- messages,
1721
- expectedStreamVersion,
1722
- streamId,
1723
- _nullishCoalesce(_optionalChain([options, 'optionalAccess', _74 => _74.partition, 'optionalAccess', _75 => _75.toString, 'call', _76 => _76()]), () => ( defaultTag2))
1724
- );
1725
- const results = await execute.batchCommand([streamSQL, insertSQL], { assertChanges: true });
1726
- const [streamResult, messagesResult] = results;
1727
- const streamPosition = _optionalChain([streamResult, 'optionalAccess', _77 => _77.rows, 'access', _78 => _78[0], 'optionalAccess', _79 => _79.stream_position]);
1728
- const globalPosition = _optionalChain([messagesResult, 'optionalAccess', _80 => _80.rows, 'access', _81 => _81.at, 'call', _82 => _82(-1), 'optionalAccess', _83 => _83.global_position]);
1729
- if (!streamPosition)
1730
- throw new ExpectedVersionConflictError(0n, _nullishCoalesce(expectedStreamVersion, () => ( 0n)));
1731
- if (!globalPosition) throw new Error("Could not find global position");
1732
- return {
1733
- success: true,
1734
- nextStreamPosition: BigInt(streamPosition),
1735
- lastGlobalPosition: BigInt(globalPosition)
1736
- };
444
+ const insertSQL = buildMessageInsertQuery(messages, expectedStreamVersion, streamId, options?.partition?.toString() ?? defaultTag);
445
+ const [streamResult, messagesResult] = await execute.batchCommand([streamSQL, insertSQL], { assertChanges: true });
446
+ const streamPosition = streamResult?.rows[0]?.stream_position;
447
+ const globalPosition = messagesResult?.rows.at(-1)?.global_position;
448
+ if (!streamPosition) throw new _event_driven_io_emmett.ExpectedVersionConflictError(0n, expectedStreamVersion ?? 0n);
449
+ if (!globalPosition) throw new Error("Could not find global position");
450
+ return {
451
+ success: true,
452
+ nextStreamPosition: BigInt(streamPosition),
453
+ lastGlobalPosition: BigInt(globalPosition)
454
+ };
1737
455
  };
1738
456
  async function getLastStreamPosition(execute, streamId, expectedStreamVersion) {
1739
- const result = await _dumbo.singleOrNull.call(void 0,
1740
- execute.query(
1741
- _dumbo.SQL`SELECT CAST(stream_position AS VARCHAR) AS stream_position FROM ${identifier(streamsTable.name)} WHERE stream_id = ${streamId}`
1742
- )
1743
- );
1744
- if (_optionalChain([result, 'optionalAccess', _84 => _84.stream_position]) == null) {
1745
- expectedStreamVersion = 0n;
1746
- } else {
1747
- expectedStreamVersion = BigInt(result.stream_position);
1748
- }
1749
- return expectedStreamVersion;
457
+ const result = await (0, _event_driven_io_dumbo.singleOrNull)(execute.query(_event_driven_io_dumbo.SQL`SELECT CAST(stream_position AS VARCHAR) AS stream_position FROM ${identifier$7(streamsTable.name)} WHERE stream_id = ${streamId}`));
458
+ if (result?.stream_position == null) expectedStreamVersion = 0n;
459
+ else expectedStreamVersion = BigInt(result.stream_position);
460
+ return expectedStreamVersion;
1750
461
  }
1751
- var buildMessageInsertQuery = (messages, expectedStreamVersion, streamId, partition) => {
1752
- const values = messages.map((message) => {
1753
- if (_optionalChain([message, 'access', _85 => _85.metadata, 'optionalAccess', _86 => _86.streamPosition]) == null || typeof message.metadata.streamPosition !== "bigint") {
1754
- throw new Error("Stream position is required");
1755
- }
1756
- const streamPosition = BigInt(message.metadata.streamPosition) + BigInt(expectedStreamVersion);
1757
- return _dumbo.SQL`(${streamId},${_nullishCoalesce(streamPosition, () => ( 0n))},${_nullishCoalesce(partition, () => ( defaultTag2))},${message.kind === "Event" ? "E" : "C"},${message.data},${message.metadata},${_nullishCoalesce(expectedStreamVersion, () => ( 0n))},${message.type},${message.metadata.messageId},${false})`;
1758
- });
1759
- return _dumbo.SQL`
1760
- INSERT INTO ${identifier(messagesTable.name)} (
462
+ const buildMessageInsertQuery = (messages, expectedStreamVersion, streamId, partition) => {
463
+ const values = messages.map((message) => {
464
+ if (message.metadata?.streamPosition == null || typeof message.metadata.streamPosition !== "bigint") throw new Error("Stream position is required");
465
+ return _event_driven_io_dumbo.SQL`(${streamId},${BigInt(message.metadata.streamPosition) + BigInt(expectedStreamVersion) ?? 0n},${partition ?? defaultTag},${message.kind === "Event" ? "E" : "C"},${message.data},${message.metadata},${expectedStreamVersion ?? 0n},${message.type},${message.metadata.messageId},${false})`;
466
+ });
467
+ return _event_driven_io_dumbo.SQL`
468
+ INSERT INTO ${identifier$7(messagesTable.name)} (
1761
469
  stream_id,
1762
470
  stream_position,
1763
471
  partition,
@@ -1775,10 +483,10 @@ var buildMessageInsertQuery = (messages, expectedStreamVersion, streamId, partit
1775
483
  `;
1776
484
  };
1777
485
 
1778
- // src/eventStore/schema/migrations/0_41_0/0_41_0.snapshot.ts
1779
-
1780
- var schema_0_41_0 = [
1781
- _dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_streams(
486
+ //#endregion
487
+ //#region src/eventStore/schema/migrations/0_41_0/0_41_0.snapshot.ts
488
+ const schema_0_41_0 = [
489
+ _event_driven_io_dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_streams(
1782
490
  stream_id TEXT NOT NULL,
1783
491
  stream_position BIGINT NOT NULL DEFAULT 0,
1784
492
  partition TEXT NOT NULL DEFAULT 'global',
@@ -1788,7 +496,7 @@ var schema_0_41_0 = [
1788
496
  PRIMARY KEY (stream_id, partition, is_archived),
1789
497
  UNIQUE (stream_id, partition, is_archived)
1790
498
  )`,
1791
- _dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_messages(
499
+ _event_driven_io_dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_messages(
1792
500
  stream_id TEXT NOT NULL,
1793
501
  stream_position BIGINT NOT NULL,
1794
502
  partition TEXT NOT NULL DEFAULT 'global',
@@ -1803,7 +511,7 @@ var schema_0_41_0 = [
1803
511
  created DATETIME DEFAULT CURRENT_TIMESTAMP,
1804
512
  UNIQUE (stream_id, stream_position, partition, is_archived)
1805
513
  )`,
1806
- _dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_subscriptions(
514
+ _event_driven_io_dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_subscriptions(
1807
515
  subscription_id TEXT NOT NULL,
1808
516
  version INTEGER NOT NULL DEFAULT 1,
1809
517
  partition TEXT NOT NULL DEFAULT 'global',
@@ -1812,30 +520,30 @@ var schema_0_41_0 = [
1812
520
  )`
1813
521
  ];
1814
522
 
1815
- // src/eventStore/schema/migrations/0_42_0/0_42_0.migration.ts
1816
-
1817
- var { identifier: identifier2, plain } = _dumbo.SQL;
1818
- var migration_0_42_0_SQLs = [
1819
- _dumbo.SQL`CREATE TABLE IF NOT EXISTS ${identifier2(processorsTable.name)}(
523
+ //#endregion
524
+ //#region src/eventStore/schema/migrations/0_42_0/0_42_0.migration.ts
525
+ const { identifier: identifier$6, plain: plain$1 } = _event_driven_io_dumbo.SQL;
526
+ const migration_0_42_0_SQLs = [
527
+ _event_driven_io_dumbo.SQL`CREATE TABLE IF NOT EXISTS ${identifier$6(processorsTable.name)}(
1820
528
  processor_id TEXT NOT NULL,
1821
529
  version INTEGER NOT NULL DEFAULT 1,
1822
- partition TEXT NOT NULL DEFAULT '${plain(globalTag)}',
530
+ partition TEXT NOT NULL DEFAULT '${plain$1(globalTag)}',
1823
531
  status TEXT NOT NULL DEFAULT 'stopped',
1824
532
  last_processed_checkpoint TEXT NOT NULL,
1825
533
  processor_instance_id TEXT DEFAULT 'emt:unknown',
1826
534
  PRIMARY KEY (processor_id, partition, version)
1827
535
  )`,
1828
- _dumbo.SQL`CREATE TABLE IF NOT EXISTS ${identifier2(projectionsTable.name)}(
536
+ _event_driven_io_dumbo.SQL`CREATE TABLE IF NOT EXISTS ${identifier$6(projectionsTable.name)}(
1829
537
  name TEXT NOT NULL,
1830
538
  version INTEGER NOT NULL DEFAULT 1,
1831
- partition TEXT NOT NULL DEFAULT '${plain(globalTag)}',
539
+ partition TEXT NOT NULL DEFAULT '${plain$1(globalTag)}',
1832
540
  type CHAR(1) NOT NULL,
1833
541
  kind TEXT NOT NULL,
1834
542
  status TEXT NOT NULL,
1835
543
  definition JSONB NOT NULL DEFAULT '{}',
1836
544
  PRIMARY KEY (name, partition, version)
1837
545
  )`,
1838
- _dumbo.SQL`INSERT INTO ${identifier2(processorsTable.name)}
546
+ _event_driven_io_dumbo.SQL`INSERT INTO ${identifier$6(processorsTable.name)}
1839
547
  (processor_id, version, partition, status, last_processed_checkpoint, processor_instance_id)
1840
548
  SELECT
1841
549
  subscription_id,
@@ -1845,24 +553,17 @@ var migration_0_42_0_SQLs = [
1845
553
  printf('%019d', last_processed_position),
1846
554
  'emt:unknown'
1847
555
  FROM emt_subscriptions`,
1848
- _dumbo.SQL`DROP TABLE emt_subscriptions`
556
+ _event_driven_io_dumbo.SQL`DROP TABLE emt_subscriptions`
1849
557
  ];
1850
- var migration_0_42_0_FromSubscriptionsToProcessors = async (execute) => {
1851
- const tableExists = await _dumbo.singleOrNull.call(void 0,
1852
- execute.query(
1853
- _dumbo.SQL`SELECT name FROM sqlite_master WHERE type='table' AND name='emt_subscriptions'`
1854
- )
1855
- );
1856
- if (!tableExists) {
1857
- return;
1858
- }
1859
- await execute.batchCommand(migration_0_42_0_SQLs);
558
+ const migration_0_42_0_FromSubscriptionsToProcessors = async (execute) => {
559
+ if (!await (0, _event_driven_io_dumbo.singleOrNull)(execute.query(_event_driven_io_dumbo.SQL`SELECT name FROM sqlite_master WHERE type='table' AND name='emt_subscriptions'`))) return;
560
+ await execute.batchCommand(migration_0_42_0_SQLs);
1860
561
  };
1861
562
 
1862
- // src/eventStore/schema/migrations/0_42_0/0_42_0.snapshot.ts
1863
-
1864
- var schema_0_42_0 = [
1865
- _dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_streams(
563
+ //#endregion
564
+ //#region src/eventStore/schema/migrations/0_42_0/0_42_0.snapshot.ts
565
+ const schema_0_42_0 = [
566
+ _event_driven_io_dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_streams(
1866
567
  stream_id TEXT NOT NULL,
1867
568
  stream_position BIGINT NOT NULL DEFAULT 0,
1868
569
  partition TEXT NOT NULL DEFAULT 'global',
@@ -1872,7 +573,7 @@ var schema_0_42_0 = [
1872
573
  PRIMARY KEY (stream_id, partition, is_archived),
1873
574
  UNIQUE (stream_id, partition, is_archived)
1874
575
  )`,
1875
- _dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_messages(
576
+ _event_driven_io_dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_messages(
1876
577
  stream_id TEXT NOT NULL,
1877
578
  stream_position BIGINT NOT NULL,
1878
579
  partition TEXT NOT NULL DEFAULT 'global',
@@ -1887,7 +588,7 @@ var schema_0_42_0 = [
1887
588
  created DATETIME DEFAULT CURRENT_TIMESTAMP,
1888
589
  UNIQUE (stream_id, stream_position, partition, is_archived)
1889
590
  )`,
1890
- _dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_processors(
591
+ _event_driven_io_dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_processors(
1891
592
  processor_id TEXT NOT NULL,
1892
593
  version INTEGER NOT NULL DEFAULT 1,
1893
594
  partition TEXT NOT NULL DEFAULT 'global',
@@ -1896,7 +597,7 @@ var schema_0_42_0 = [
1896
597
  processor_instance_id TEXT DEFAULT 'emt:unknown',
1897
598
  PRIMARY KEY (processor_id, partition, version)
1898
599
  )`,
1899
- _dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_projections(
600
+ _event_driven_io_dumbo.SQL`CREATE TABLE IF NOT EXISTS emt_projections(
1900
601
  name TEXT NOT NULL,
1901
602
  version INTEGER NOT NULL DEFAULT 1,
1902
603
  partition TEXT NOT NULL DEFAULT 'global',
@@ -1908,801 +609,657 @@ var schema_0_42_0 = [
1908
609
  )`
1909
610
  ];
1910
611
 
1911
- // src/eventStore/schema/readLastMessageGlobalPosition.ts
1912
-
1913
- var { identifier: identifier3 } = _dumbo.SQL;
1914
- var readLastMessageGlobalPosition = async (execute, options) => {
1915
- const result = await _dumbo.singleOrNull.call(void 0,
1916
- execute.query(
1917
- _dumbo.SQL`
612
+ //#endregion
613
+ //#region src/eventStore/schema/readLastMessageGlobalPosition.ts
614
+ const { identifier: identifier$5 } = _event_driven_io_dumbo.SQL;
615
+ const readLastMessageGlobalPosition = async (execute, options) => {
616
+ const result = await (0, _event_driven_io_dumbo.singleOrNull)(execute.query(_event_driven_io_dumbo.SQL`
1918
617
  SELECT global_position
1919
- FROM ${identifier3(messagesTable.name)}
1920
- WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _87 => _87.partition]), () => ( defaultTag2))} AND is_archived = FALSE
1921
- ORDER BY global_position
1922
- LIMIT 1`
1923
- )
1924
- );
1925
- return {
1926
- currentGlobalPosition: result !== null ? BigInt(result.global_position) : null
1927
- };
1928
- };
1929
-
1930
- // src/eventStore/schema/readMessagesBatch.ts
1931
-
1932
- var { identifier: identifier4 } = _dumbo.SQL;
1933
- var readMessagesBatch = async (execute, options) => {
1934
- const { serializer } = options;
1935
- const from = "from" in options ? options.from : void 0;
1936
- const after = "after" in options ? options.after : void 0;
1937
- const batchSize = "batchSize" in options ? options.batchSize : options.to - options.from;
1938
- const fromCondition = from !== void 0 ? _dumbo.SQL`AND global_position >= ${from}` : after !== void 0 ? _dumbo.SQL`AND global_position > ${after}` : _dumbo.SQL.EMPTY;
1939
- const toCondition = "to" in options ? _dumbo.SQL`AND global_position <= ${options.to}` : _dumbo.SQL.EMPTY;
1940
- const limitCondition = "batchSize" in options ? _dumbo.SQL`LIMIT ${options.batchSize}` : _dumbo.SQL.EMPTY;
1941
- const messages = await _dumbo.mapRows.call(void 0,
1942
- execute.query(
1943
- _dumbo.SQL`SELECT stream_id, stream_position, global_position, message_data, message_metadata, message_schema_version, message_type, message_id
1944
- FROM ${identifier4(messagesTable.name)}
1945
- WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _88 => _88.partition]), () => ( defaultTag2))} AND is_archived = FALSE ${fromCondition} ${toCondition}
618
+ FROM ${identifier$5(messagesTable.name)}
619
+ WHERE partition = ${options?.partition ?? defaultTag} AND is_archived = FALSE
620
+ ORDER BY global_position DESC
621
+ LIMIT 1`));
622
+ return { currentGlobalPosition: result !== null ? BigInt(result.global_position) : null };
623
+ };
624
+
625
+ //#endregion
626
+ //#region src/eventStore/schema/readMessagesBatch.ts
627
+ const { identifier: identifier$4 } = _event_driven_io_dumbo.SQL;
628
+ const readMessagesBatch = async (execute, options) => {
629
+ const { serializer } = options;
630
+ const from = "from" in options ? options.from : void 0;
631
+ const after = "after" in options ? options.after : void 0;
632
+ const batchSize = "batchSize" in options ? options.batchSize : options.to - options.from;
633
+ const fromCondition = from !== void 0 ? _event_driven_io_dumbo.SQL`AND global_position >= ${from}` : after !== void 0 ? _event_driven_io_dumbo.SQL`AND global_position > ${after}` : _event_driven_io_dumbo.SQL.EMPTY;
634
+ const toCondition = "to" in options ? _event_driven_io_dumbo.SQL`AND global_position <= ${options.to}` : _event_driven_io_dumbo.SQL.EMPTY;
635
+ const limitCondition = "batchSize" in options ? _event_driven_io_dumbo.SQL`LIMIT ${options.batchSize}` : _event_driven_io_dumbo.SQL.EMPTY;
636
+ const messages = await (0, _event_driven_io_dumbo.mapRows)(execute.query(_event_driven_io_dumbo.SQL`SELECT stream_id, stream_position, global_position, message_data, message_metadata, message_schema_version, message_type, message_id
637
+ FROM ${identifier$4(messagesTable.name)}
638
+ WHERE partition = ${options?.partition ?? defaultTag} AND is_archived = FALSE ${fromCondition} ${toCondition}
1946
639
  ORDER BY global_position
1947
- ${limitCondition}`
1948
- ),
1949
- (row) => {
1950
- const rawEvent = {
1951
- type: row.message_type,
1952
- data: serializer.deserialize(row.message_data),
1953
- metadata: serializer.deserialize(row.message_metadata)
1954
- };
1955
- const metadata = {
1956
- ..."metadata" in rawEvent ? _nullishCoalesce(rawEvent.metadata, () => ( {})) : {},
1957
- messageId: row.message_id,
1958
- streamName: row.stream_id,
1959
- streamPosition: BigInt(row.stream_position),
1960
- globalPosition: BigInt(row.global_position),
1961
- checkpoint: bigIntProcessorCheckpoint(BigInt(row.global_position))
1962
- };
1963
- return {
1964
- ...rawEvent,
1965
- kind: "Event",
1966
- metadata
1967
- };
1968
- }
1969
- );
1970
- return messages.length > 0 ? {
1971
- currentGlobalPosition: messages[messages.length - 1].metadata.globalPosition,
1972
- messages,
1973
- areMessagesLeft: messages.length === batchSize
1974
- } : {
1975
- currentGlobalPosition: "from" in options ? options.from : "after" in options ? options.after : 0n,
1976
- messages: [],
1977
- areMessagesLeft: false
1978
- };
1979
- };
1980
-
1981
- // src/eventStore/schema/readProcessorCheckpoint.ts
1982
-
1983
- var { identifier: identifier5 } = _dumbo.SQL;
1984
- var readProcessorCheckpoint = async (execute, options) => {
1985
- const result = await _dumbo.singleOrNull.call(void 0,
1986
- execute.query(
1987
- _dumbo.SQL`SELECT last_processed_checkpoint
1988
- FROM ${identifier5(processorsTable.name)}
1989
- WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _89 => _89.partition]), () => ( defaultTag2))} AND processor_id = ${options.processorId}
1990
- LIMIT 1`
1991
- )
1992
- );
1993
- return {
1994
- lastProcessedCheckpoint: result !== null ? result.last_processed_checkpoint : null
1995
- };
1996
- };
1997
-
1998
- // src/eventStore/schema/readStream.ts
1999
-
2000
-
2001
- // src/eventStore/SQLiteEventStore.ts
2002
-
2003
-
2004
- // src/eventStore/consumers/messageBatchProcessing/index.ts
2005
- var DefaultSQLiteEventStoreProcessorBatchSize = 100;
2006
- var DefaultSQLiteEventStoreProcessorPullingFrequencyInMs = 50;
2007
- var sqliteEventStoreMessageBatchPuller = ({
2008
- executor,
2009
- batchSize,
2010
- eachBatch,
2011
- pullingFrequencyInMs,
2012
- stopWhen,
2013
- signal,
2014
- serialization
2015
- }) => {
2016
- let isRunning = false;
2017
- let start;
2018
- const serializer = JSONSerializer.from({ serialization });
2019
- const pullMessages = async (options) => {
2020
- const after = options.startFrom === "BEGINNING" ? 0n : options.startFrom === "END" ? await _asyncNullishCoalesce((await readLastMessageGlobalPosition(executor)).currentGlobalPosition, async () => ( 0n)) : parseBigIntProcessorCheckpoint(options.startFrom.lastCheckpoint);
2021
- const readMessagesOptions = {
2022
- after,
2023
- batchSize,
2024
- serializer
2025
- };
2026
- let waitTime = 100;
2027
- while (isRunning && !_optionalChain([signal, 'optionalAccess', _90 => _90.aborted])) {
2028
- const { messages, currentGlobalPosition, areMessagesLeft } = await readMessagesBatch(executor, readMessagesOptions);
2029
- if (messages.length > 0) {
2030
- const result = await eachBatch(messages);
2031
- if (result && result.type === "STOP") {
2032
- isRunning = false;
2033
- break;
2034
- }
2035
- }
2036
- readMessagesOptions.after = currentGlobalPosition;
2037
- await new Promise((resolve) => setTimeout(resolve, waitTime));
2038
- if (_optionalChain([stopWhen, 'optionalAccess', _91 => _91.noMessagesLeft]) === true && !areMessagesLeft) {
2039
- isRunning = false;
2040
- break;
2041
- }
2042
- if (!areMessagesLeft) {
2043
- waitTime = Math.min(waitTime * 2, 1e3);
2044
- } else {
2045
- waitTime = pullingFrequencyInMs;
2046
- }
2047
- }
2048
- };
2049
- return {
2050
- get isRunning() {
2051
- return isRunning;
2052
- },
2053
- start: (options) => {
2054
- if (isRunning) return start;
2055
- isRunning = true;
2056
- start = (async () => {
2057
- return pullMessages(options);
2058
- })();
2059
- return start;
2060
- },
2061
- stop: async () => {
2062
- if (!isRunning) return;
2063
- isRunning = false;
2064
- await start;
2065
- }
2066
- };
2067
- };
2068
- var zipSQLiteEventStoreMessageBatchPullerStartFrom = (options) => {
2069
- if (options.length === 0 || options.some((o) => o === void 0 || o === "BEGINNING"))
2070
- return "BEGINNING";
2071
- if (options.every((o) => o === "END")) return "END";
2072
- return options.filter((o) => o !== void 0 && o !== "BEGINNING" && o !== "END").sort((a, b) => a > b ? 1 : -1)[0];
2073
- };
2074
-
2075
- // src/eventStore/consumers/sqliteEventStoreConsumer.ts
2076
-
2077
-
2078
-
2079
- // src/eventStore/consumers/sqliteCheckpointer.ts
2080
- var sqliteCheckpointer = () => ({
2081
- read: async (options, context) => {
2082
- const result = await readProcessorCheckpoint(context.execute, options);
2083
- return { lastCheckpoint: _optionalChain([result, 'optionalAccess', _92 => _92.lastProcessedCheckpoint]) };
2084
- },
2085
- store: async (options, context) => {
2086
- const newCheckpoint = getCheckpoint(options.message);
2087
- const result = await storeProcessorCheckpoint(context.execute, {
2088
- lastProcessedCheckpoint: options.lastCheckpoint,
2089
- newCheckpoint,
2090
- processorId: options.processorId,
2091
- partition: options.partition,
2092
- version: options.version
2093
- });
2094
- return result.success ? { success: true, newCheckpoint: result.newCheckpoint } : result;
2095
- }
640
+ ${limitCondition}`), (row) => {
641
+ const rawEvent = {
642
+ type: row.message_type,
643
+ data: serializer.deserialize(row.message_data),
644
+ metadata: serializer.deserialize(row.message_metadata)
645
+ };
646
+ const metadata = {
647
+ ..."metadata" in rawEvent ? rawEvent.metadata ?? {} : {},
648
+ messageId: row.message_id,
649
+ streamName: row.stream_id,
650
+ streamPosition: BigInt(row.stream_position),
651
+ globalPosition: BigInt(row.global_position),
652
+ checkpoint: (0, _event_driven_io_emmett.bigIntProcessorCheckpoint)(BigInt(row.global_position))
653
+ };
654
+ return {
655
+ ...rawEvent,
656
+ kind: "Event",
657
+ metadata
658
+ };
659
+ });
660
+ return messages.length > 0 ? {
661
+ currentGlobalPosition: messages[messages.length - 1].metadata.globalPosition,
662
+ messages,
663
+ areMessagesLeft: messages.length === batchSize
664
+ } : {
665
+ currentGlobalPosition: "from" in options ? options.from : "after" in options ? options.after : 0n,
666
+ messages: [],
667
+ areMessagesLeft: false
668
+ };
669
+ };
670
+
671
+ //#endregion
672
+ //#region src/eventStore/schema/readProcessorCheckpoint.ts
673
+ const { identifier: identifier$3 } = _event_driven_io_dumbo.SQL;
674
+ const readProcessorCheckpoint = async (execute, options) => {
675
+ const result = await (0, _event_driven_io_dumbo.singleOrNull)(execute.query(_event_driven_io_dumbo.SQL`SELECT last_processed_checkpoint
676
+ FROM ${identifier$3(processorsTable.name)}
677
+ WHERE partition = ${options?.partition ?? defaultTag} AND processor_id = ${options.processorId}
678
+ LIMIT 1`));
679
+ return { lastProcessedCheckpoint: result !== null ? result.last_processed_checkpoint : null };
680
+ };
681
+
682
+ //#endregion
683
+ //#region src/eventStore/consumers/messageBatchProcessing/index.ts
684
+ const sqliteEventStoreMessageBatchPuller = ({ executor, batchSize, eachBatch, pullingFrequencyInMs, stopWhen, signal, serialization }) => {
685
+ let isRunning = false;
686
+ let start;
687
+ const serializer = _event_driven_io_emmett.JSONSerializer.from({ serialization });
688
+ const pullMessages = async (options) => {
689
+ let after;
690
+ try {
691
+ after = options.startFrom === "BEGINNING" ? 0n : options.startFrom === "END" ? (await readLastMessageGlobalPosition(executor)).currentGlobalPosition ?? 0n : (0, _event_driven_io_emmett.parseBigIntProcessorCheckpoint)(options.startFrom.lastCheckpoint);
692
+ } catch (error) {
693
+ options.started?.reject(error);
694
+ throw error;
695
+ }
696
+ options.started?.resolve();
697
+ const readMessagesOptions = {
698
+ after,
699
+ batchSize,
700
+ serializer
701
+ };
702
+ let waitTime = 100;
703
+ while (isRunning && !signal?.aborted) {
704
+ const { messages, currentGlobalPosition, areMessagesLeft } = await readMessagesBatch(executor, readMessagesOptions);
705
+ if (messages.length > 0) {
706
+ const result = await eachBatch(messages);
707
+ if (result && result.type === "STOP") {
708
+ isRunning = false;
709
+ break;
710
+ }
711
+ }
712
+ readMessagesOptions.after = currentGlobalPosition;
713
+ await new Promise((resolve) => setTimeout(resolve, waitTime));
714
+ if (stopWhen?.noMessagesLeft === true && !areMessagesLeft) {
715
+ isRunning = false;
716
+ break;
717
+ }
718
+ if (!areMessagesLeft) waitTime = Math.min(waitTime * 2, 1e3);
719
+ else waitTime = pullingFrequencyInMs;
720
+ }
721
+ };
722
+ return {
723
+ get isRunning() {
724
+ return isRunning;
725
+ },
726
+ start: (options) => {
727
+ if (isRunning) return start;
728
+ isRunning = true;
729
+ start = (async () => {
730
+ return pullMessages(options);
731
+ })();
732
+ return start;
733
+ },
734
+ stop: async () => {
735
+ if (!isRunning) return;
736
+ isRunning = false;
737
+ await start;
738
+ }
739
+ };
740
+ };
741
+ const zipSQLiteEventStoreMessageBatchPullerStartFrom = (options) => {
742
+ if (options.length === 0 || options.some((o) => o === void 0 || o === "BEGINNING")) return "BEGINNING";
743
+ if (options.every((o) => o === "END")) return "END";
744
+ return options.filter((o) => o !== void 0 && o !== "BEGINNING" && o !== "END").sort((a, b) => a > b ? 1 : -1)[0];
745
+ };
746
+
747
+ //#endregion
748
+ //#region src/eventStore/consumers/sqliteCheckpointer.ts
749
+ const sqliteCheckpointer = () => ({
750
+ read: async (options, context) => {
751
+ return { lastCheckpoint: (await readProcessorCheckpoint(context.execute, options))?.lastProcessedCheckpoint };
752
+ },
753
+ store: async (options, context) => {
754
+ const newCheckpoint = (0, _event_driven_io_emmett.getCheckpoint)(options.message);
755
+ const result = await storeProcessorCheckpoint(context.execute, {
756
+ lastProcessedCheckpoint: options.lastCheckpoint,
757
+ newCheckpoint,
758
+ processorId: options.processorId,
759
+ partition: options.partition,
760
+ version: options.version
761
+ });
762
+ return result.success ? {
763
+ success: true,
764
+ newCheckpoint: result.newCheckpoint
765
+ } : result;
766
+ }
2096
767
  });
2097
768
 
2098
- // src/eventStore/consumers/sqliteProcessor.ts
2099
- var sqliteProcessingScope = () => {
2100
- const processingScope = async (handler, partialContext) => {
2101
- const connection = _optionalChain([partialContext, 'optionalAccess', _93 => _93.connection]);
2102
- if (!connection)
2103
- throw new EmmettError("Connection is required in context or options");
2104
- return connection.withTransaction(
2105
- async (transaction) => {
2106
- return handler({
2107
- ...partialContext,
2108
- connection,
2109
- execute: transaction.execute
2110
- });
2111
- }
2112
- );
2113
- };
2114
- return processingScope;
2115
- };
2116
- var sqliteWorkflowProcessingScope = (messageStore) => {
2117
- const processingScope = async (handler, partialContext) => {
2118
- const connection = _optionalChain([partialContext, 'optionalAccess', _94 => _94.connection]);
2119
- if (!connection)
2120
- throw new EmmettError("Connection is required in context or options");
2121
- return connection.withTransaction(
2122
- async (transaction) => {
2123
- return handler({
2124
- ...partialContext,
2125
- connection: Object.assign(connection, { messageStore }),
2126
- execute: transaction.execute
2127
- });
2128
- }
2129
- );
2130
- };
2131
- return processingScope;
2132
- };
2133
- var sqliteWorkflowProcessor = (options) => {
2134
- const {
2135
- processorId = _nullishCoalesce(options.processorId, () => ( getWorkflowId({
2136
- workflowName: _nullishCoalesce(options.workflow.name, () => ( "unknown"))
2137
- }))),
2138
- processorInstanceId = getProcessorInstanceId(processorId),
2139
- version = defaultProcessorVersion,
2140
- partition = defaultProcessorPartition
2141
- } = options;
2142
- const hooks = {
2143
- ..._nullishCoalesce(options.hooks, () => ( {})),
2144
- onClose: _optionalChain([options, 'access', _95 => _95.hooks, 'optionalAccess', _96 => _96.onClose])
2145
- };
2146
- return workflowProcessor({
2147
- ...options,
2148
- processorId,
2149
- processorInstanceId,
2150
- version,
2151
- partition,
2152
- hooks,
2153
- processingScope: sqliteWorkflowProcessingScope(
2154
- options.messageStore
2155
- ),
2156
- checkpoints: sqliteCheckpointer()
2157
- });
2158
- };
2159
- var sqliteReactor = (options) => {
2160
- const {
2161
- processorId = options.processorId,
2162
- processorInstanceId = getProcessorInstanceId(processorId),
2163
- version = defaultProcessorVersion,
2164
- partition = defaultProcessorPartition,
2165
- hooks
2166
- } = options;
2167
- return reactor({
2168
- ...options,
2169
- processorId,
2170
- processorInstanceId,
2171
- version,
2172
- partition,
2173
- hooks,
2174
- processingScope: sqliteProcessingScope(),
2175
- checkpoints: sqliteCheckpointer()
2176
- });
2177
- };
2178
- var sqliteProjector = (options) => {
2179
- const {
2180
- processorId = getProjectorId({
2181
- projectionName: _nullishCoalesce(options.projection.name, () => ( "unknown"))
2182
- }),
2183
- processorInstanceId = getProcessorInstanceId(processorId),
2184
- version = defaultProcessorVersion,
2185
- partition = defaultProcessorPartition
2186
- } = options;
2187
- const hooks = {
2188
- ..._nullishCoalesce(options.hooks, () => ( {})),
2189
- onInit: options.projection.init !== void 0 || _optionalChain([options, 'access', _97 => _97.hooks, 'optionalAccess', _98 => _98.onInit]) ? async (context) => {
2190
- if (options.projection.init)
2191
- await options.projection.init({
2192
- version: _nullishCoalesce(options.projection.version, () => ( version)),
2193
- status: "active",
2194
- registrationType: "async",
2195
- context: {
2196
- ...context,
2197
- migrationOptions: options.migrationOptions
2198
- }
2199
- });
2200
- if (_optionalChain([options, 'access', _99 => _99.hooks, 'optionalAccess', _100 => _100.onInit]))
2201
- await options.hooks.onInit({
2202
- ...context,
2203
- migrationOptions: options.migrationOptions
2204
- });
2205
- } : _optionalChain([options, 'access', _101 => _101.hooks, 'optionalAccess', _102 => _102.onInit]),
2206
- onClose: _optionalChain([options, 'access', _103 => _103.hooks, 'optionalAccess', _104 => _104.onClose])
2207
- };
2208
- const processor = projector({
2209
- ...options,
2210
- processorId,
2211
- processorInstanceId,
2212
- version,
2213
- partition,
2214
- hooks,
2215
- processingScope: sqliteProcessingScope(),
2216
- checkpoints: sqliteCheckpointer()
2217
- });
2218
- return processor;
2219
- };
2220
-
2221
- // src/eventStore/consumers/sqliteEventStoreConsumer.ts
2222
- var sqliteEventStoreConsumer = (options) => {
2223
- let isRunning = false;
2224
- let isInitialized = false;
2225
- const { pulling } = options;
2226
- const processors = _nullishCoalesce(options.processors, () => ( []));
2227
- let abortController = null;
2228
- let start;
2229
- let messagePuller;
2230
- const pool = _nullishCoalesce(options.pool, () => ( _dumbo.dumbo.call(void 0, {
2231
- serialization: options.serialization,
2232
- transactionOptions: {
2233
- allowNestedTransactions: true,
2234
- mode: "session_based"
2235
- },
2236
- ...options.driver.mapToDumboOptions(options)
2237
- })));
2238
- const eachBatch = (messagesBatch) => pool.withConnection(async (connection) => {
2239
- const activeProcessors = processors.filter((s) => s.isActive);
2240
- if (activeProcessors.length === 0)
2241
- return {
2242
- type: "STOP",
2243
- reason: "No active processors"
2244
- };
2245
- const result = await Promise.allSettled(
2246
- activeProcessors.map(async (s) => {
2247
- return await s.handle(messagesBatch, {
2248
- connection,
2249
- execute: connection.execute
2250
- });
2251
- })
2252
- );
2253
- return result.some(
2254
- (r) => r.status === "fulfilled" && _optionalChain([r, 'access', _105 => _105.value, 'optionalAccess', _106 => _106.type]) !== "STOP"
2255
- ) ? void 0 : {
2256
- type: "STOP"
2257
- };
2258
- });
2259
- const processorContext = {
2260
- execute: void 0,
2261
- connection: void 0
2262
- };
2263
- const stopProcessors = () => Promise.all(processors.map((p) => p.close(processorContext)));
2264
- const stop = async () => {
2265
- if (!isRunning) return;
2266
- isRunning = false;
2267
- if (messagePuller) {
2268
- _optionalChain([abortController, 'optionalAccess', _107 => _107.abort, 'call', _108 => _108()]);
2269
- await messagePuller.stop();
2270
- }
2271
- await start;
2272
- messagePuller = void 0;
2273
- abortController = null;
2274
- await stopProcessors();
2275
- };
2276
- const init = async () => {
2277
- if (isInitialized) return;
2278
- const sqliteProcessors = processors;
2279
- await pool.withConnection(async (connection) => {
2280
- for (const processor of sqliteProcessors) {
2281
- if (processor.init) {
2282
- await processor.init({
2283
- ...processorContext,
2284
- connection,
2285
- execute: connection.execute
2286
- });
2287
- }
2288
- }
2289
- });
2290
- isInitialized = true;
2291
- };
2292
- return {
2293
- consumerId: _nullishCoalesce(options.consumerId, () => ( _uuid.v7.call(void 0, ))),
2294
- get isRunning() {
2295
- return isRunning;
2296
- },
2297
- processors,
2298
- init,
2299
- reactor: (options2) => {
2300
- const processor = sqliteReactor(options2);
2301
- processors.push(
2302
- // TODO: change that
2303
- processor
2304
- );
2305
- return processor;
2306
- },
2307
- projector: (options2) => {
2308
- const processor = sqliteProjector(options2);
2309
- processors.push(
2310
- // TODO: change that
2311
- processor
2312
- );
2313
- return processor;
2314
- },
2315
- workflowProcessor: (processorOptions) => {
2316
- const messageStore = getSQLiteEventStore({
2317
- ...options,
2318
- pool,
2319
- schema: { autoMigration: "None" }
2320
- });
2321
- const processor = sqliteWorkflowProcessor({
2322
- ...processorOptions,
2323
- messageStore
2324
- });
2325
- processors.push(
2326
- // TODO: change that
2327
- processor
2328
- );
2329
- return processor;
2330
- },
2331
- start: () => {
2332
- if (isRunning) return start;
2333
- if (processors.length === 0)
2334
- throw new EmmettError(
2335
- "Cannot start consumer without at least a single processor"
2336
- );
2337
- isRunning = true;
2338
- abortController = new AbortController();
2339
- messagePuller = sqliteEventStoreMessageBatchPuller({
2340
- stopWhen: options.stopWhen,
2341
- executor: pool.execute,
2342
- eachBatch,
2343
- batchSize: _nullishCoalesce(_optionalChain([pulling, 'optionalAccess', _109 => _109.batchSize]), () => ( DefaultSQLiteEventStoreProcessorBatchSize)),
2344
- pullingFrequencyInMs: _nullishCoalesce(_optionalChain([pulling, 'optionalAccess', _110 => _110.pullingFrequencyInMs]), () => ( DefaultSQLiteEventStoreProcessorPullingFrequencyInMs)),
2345
- signal: abortController.signal
2346
- });
2347
- start = (async () => {
2348
- if (!isRunning) return;
2349
- if (!isInitialized) {
2350
- await init();
2351
- }
2352
- const startFrom = await pool.withConnection(
2353
- async (connection) => zipSQLiteEventStoreMessageBatchPullerStartFrom(
2354
- await Promise.all(
2355
- processors.map(async (o) => {
2356
- const result = await o.start({
2357
- execute: connection.execute,
2358
- connection
2359
- });
2360
- return result;
2361
- })
2362
- )
2363
- )
2364
- );
2365
- await messagePuller.start({ startFrom });
2366
- await stopProcessors();
2367
- isRunning = false;
2368
- })();
2369
- return start;
2370
- },
2371
- stop,
2372
- close: async () => {
2373
- await stop();
2374
- await pool.close();
2375
- }
2376
- };
2377
- };
2378
-
2379
- // src/eventStore/SQLiteEventStore.ts
2380
- var SQLiteEventStoreDefaultStreamVersion = 0n;
2381
- var getSQLiteEventStore = (options) => {
2382
- let autoGenerateSchema = false;
2383
- const serializer = JSONSerializer.from(options);
2384
- const pool = _nullishCoalesce(options.pool, () => ( _dumbo.dumbo.call(void 0, {
2385
- serialization: options.serialization,
2386
- transactionOptions: {
2387
- allowNestedTransactions: true,
2388
- mode: "session_based"
2389
- },
2390
- ...options.driver.mapToDumboOptions(options)
2391
- })));
2392
- let migrateSchema = void 0;
2393
- const inlineProjections = (_nullishCoalesce(options.projections, () => ( []))).filter(({ type }) => type === "inline").map(({ projection: projection2 }) => projection2);
2394
- const onBeforeCommitHook = _optionalChain([options, 'access', _111 => _111.hooks, 'optionalAccess', _112 => _112.onBeforeCommit]);
2395
- if (options) {
2396
- autoGenerateSchema = _optionalChain([options, 'access', _113 => _113.schema, 'optionalAccess', _114 => _114.autoMigration]) === void 0 || _optionalChain([options, 'access', _115 => _115.schema, 'optionalAccess', _116 => _116.autoMigration]) !== "None";
2397
- }
2398
- const migrate = (connection) => {
2399
- if (!migrateSchema) {
2400
- migrateSchema = createEventStoreSchema(connection, {
2401
- onBeforeSchemaCreated: async (context) => {
2402
- for (const projection2 of inlineProjections) {
2403
- if (projection2.init) {
2404
- await projection2.init({
2405
- version: _nullishCoalesce(projection2.version, () => ( 1)),
2406
- registrationType: "async",
2407
- status: "active",
2408
- context: {
2409
- execute: context.connection.execute,
2410
- connection: context.connection,
2411
- driverType: options.driver.driverType
2412
- }
2413
- });
2414
- }
2415
- }
2416
- if (_optionalChain([options, 'access', _117 => _117.hooks, 'optionalAccess', _118 => _118.onBeforeSchemaCreated])) {
2417
- await options.hooks.onBeforeSchemaCreated(context);
2418
- }
2419
- },
2420
- onAfterSchemaCreated: _optionalChain([options, 'access', _119 => _119.hooks, 'optionalAccess', _120 => _120.onAfterSchemaCreated])
2421
- });
2422
- }
2423
- return migrateSchema;
2424
- };
2425
- const ensureSchemaExists = () => {
2426
- if (!autoGenerateSchema) return Promise.resolve();
2427
- return pool.withConnection((connection) => migrate(connection));
2428
- };
2429
- return {
2430
- async aggregateStream(streamName, options2) {
2431
- await ensureSchemaExists();
2432
- const { evolve, initialState, read } = options2;
2433
- const expectedStreamVersion = _optionalChain([read, 'optionalAccess', _121 => _121.expectedStreamVersion]);
2434
- let state = initialState();
2435
- if (typeof streamName !== "string") {
2436
- throw new Error("Stream name is not string");
2437
- }
2438
- const result = await readStream(
2439
- pool.execute,
2440
- streamName,
2441
- { ...read, serializer: _nullishCoalesce(_optionalChain([read, 'optionalAccess', _122 => _122.serialization, 'optionalAccess', _123 => _123.serializer]), () => ( serializer)) }
2442
- );
2443
- const currentStreamVersion = result.currentStreamVersion;
2444
- assertExpectedVersionMatchesCurrent(
2445
- currentStreamVersion,
2446
- expectedStreamVersion,
2447
- SQLiteEventStoreDefaultStreamVersion
2448
- );
2449
- for (const event of result.events) {
2450
- if (!event) continue;
2451
- state = evolve(state, event);
2452
- }
2453
- return {
2454
- currentStreamVersion,
2455
- state,
2456
- streamExists: result.streamExists
2457
- };
2458
- },
2459
- readStream: async (streamName, readOptions) => {
2460
- await ensureSchemaExists();
2461
- return readStream(pool.execute, streamName, {
2462
- ...readOptions,
2463
- serializer: _nullishCoalesce(_optionalChain([options, 'access', _124 => _124.serialization, 'optionalAccess', _125 => _125.serializer]), () => ( serializer))
2464
- });
2465
- },
2466
- appendToStream: async (streamName, events, appendOptions) => {
2467
- await ensureSchemaExists();
2468
- const [firstPart, ...rest] = streamName.split("-");
2469
- const streamType = firstPart && rest.length > 0 ? firstPart : unknownTag2;
2470
- const appendResult = await pool.withConnection(
2471
- (connection) => appendToStream(connection, streamName, streamType, events, {
2472
- ...appendOptions,
2473
- onBeforeCommit: async (messages, context) => {
2474
- if (inlineProjections.length > 0)
2475
- await handleProjections({
2476
- projections: inlineProjections,
2477
- events: messages,
2478
- execute: context.connection.execute,
2479
- connection: context.connection,
2480
- driverType: options.driver.driverType
2481
- });
2482
- if (onBeforeCommitHook)
2483
- await onBeforeCommitHook(messages, context);
2484
- }
2485
- }),
2486
- { readonly: false }
2487
- );
2488
- if (!appendResult.success)
2489
- throw new ExpectedVersionConflictError(
2490
- -1n,
2491
- //TODO: Return actual version in case of error
2492
- _nullishCoalesce(_optionalChain([appendOptions, 'optionalAccess', _126 => _126.expectedStreamVersion]), () => ( NO_CONCURRENCY_CHECK))
2493
- );
2494
- return {
2495
- nextExpectedStreamVersion: appendResult.nextStreamPosition,
2496
- lastEventGlobalPosition: appendResult.lastGlobalPosition,
2497
- createdNewStream: appendResult.nextStreamPosition >= BigInt(events.length)
2498
- };
2499
- },
2500
- async streamExists(streamName, options2) {
2501
- await ensureSchemaExists();
2502
- return streamExists(pool.execute, streamName, options2);
2503
- },
2504
- consumer: (consumerOptions) => sqliteEventStoreConsumer({
2505
- ..._nullishCoalesce(options, () => ( {})),
2506
- ..._nullishCoalesce(consumerOptions, () => ( {})),
2507
- pool
2508
- }),
2509
- async withSession(callback) {
2510
- return await pool.withConnection(async (connection) => {
2511
- const sessionStore = getSQLiteEventStore({
2512
- ...options,
2513
- pool: _dumbo.dumbo.call(void 0, {
2514
- ...options.driver.mapToDumboOptions(options),
2515
- connection,
2516
- serialization: options.serialization
2517
- }),
2518
- transactionOptions: {
2519
- allowNestedTransactions: true,
2520
- mode: "session_based"
2521
- },
2522
- schema: {
2523
- ...options.schema,
2524
- autoMigration: "None"
2525
- },
2526
- serialization: options.serialization
2527
- });
2528
- await ensureSchemaExists();
2529
- return callback({
2530
- eventStore: sessionStore,
2531
- close: () => Promise.resolve()
2532
- });
2533
- });
2534
- },
2535
- close: () => pool.close(),
2536
- schema: {
2537
- sql: () => schemaSQL.join(""),
2538
- print: () => console.log(schemaSQL.join("")),
2539
- migrate: () => pool.withConnection(migrate)
2540
- }
2541
- };
2542
- };
2543
-
2544
- // src/eventStore/schema/readStream.ts
2545
- var { identifier: identifier6 } = _dumbo.SQL;
2546
- var readStream = async (execute, streamId, options) => {
2547
- const { serializer } = options;
2548
- const fromCondition = options.from ? _dumbo.SQL`AND stream_position >= ${options.from}` : _dumbo.SQL.EMPTY;
2549
- const to = Number(
2550
- _nullishCoalesce(_optionalChain([options, 'optionalAccess', _127 => _127.to]), () => ( (_optionalChain([options, 'optionalAccess', _128 => _128.maxCount]) ? (_nullishCoalesce(options.from, () => ( 0n))) + options.maxCount : NaN)))
2551
- );
2552
- const toCondition = !isNaN(to) ? _dumbo.SQL`AND stream_position <= ${to}` : _dumbo.SQL.EMPTY;
2553
- const { rows: results } = await execute.query(
2554
- _dumbo.SQL`SELECT stream_id, stream_position, global_position, message_data, message_metadata, message_schema_version, message_type, message_id
2555
- FROM ${identifier6(messagesTable.name)}
2556
- WHERE stream_id = ${streamId} AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _129 => _129.partition]), () => ( defaultTag2))} AND is_archived = FALSE ${fromCondition} ${toCondition}
2557
- ORDER BY stream_position ASC`
2558
- );
2559
- const messages = results.map((row) => {
2560
- const rawEvent = {
2561
- type: row.message_type,
2562
- data: serializer.deserialize(row.message_data),
2563
- metadata: serializer.deserialize(row.message_metadata)
2564
- };
2565
- const metadata = {
2566
- ..."metadata" in rawEvent ? _nullishCoalesce(rawEvent.metadata, () => ( {})) : {},
2567
- messageId: row.message_id,
2568
- streamName: streamId,
2569
- streamPosition: BigInt(row.stream_position),
2570
- globalPosition: BigInt(row.global_position),
2571
- checkpoint: bigIntProcessorCheckpoint(BigInt(row.global_position))
2572
- };
2573
- const event = {
2574
- ...rawEvent,
2575
- kind: "Event",
2576
- metadata
2577
- };
2578
- return upcastRecordedMessage(event, _optionalChain([options, 'optionalAccess', _130 => _130.schema, 'optionalAccess', _131 => _131.versioning]));
2579
- });
2580
- return messages.length > 0 ? {
2581
- currentStreamVersion: messages[messages.length - 1].metadata.streamPosition,
2582
- events: messages,
2583
- streamExists: true
2584
- } : {
2585
- currentStreamVersion: SQLiteEventStoreDefaultStreamVersion,
2586
- events: [],
2587
- streamExists: false
2588
- };
2589
- };
2590
-
2591
- // src/eventStore/schema/storeProcessorCheckpoint.ts
2592
-
2593
-
2594
-
2595
-
2596
-
2597
-
2598
- var { identifier: identifier7 } = _dumbo.SQL;
769
+ //#endregion
770
+ //#region src/eventStore/consumers/sqliteProcessor.ts
771
+ const sqliteProcessingScope = () => {
772
+ const processingScope = async (handler, partialContext) => {
773
+ const connection = partialContext?.connection;
774
+ if (!connection) throw new _event_driven_io_emmett.EmmettError("Connection is required in context or options");
775
+ return connection.withTransaction(async (transaction) => {
776
+ return handler({
777
+ ...partialContext,
778
+ connection,
779
+ execute: transaction.execute
780
+ });
781
+ });
782
+ };
783
+ return processingScope;
784
+ };
785
+ const sqliteWorkflowProcessingScope = (messageStore) => {
786
+ const processingScope = async (handler, partialContext) => {
787
+ const connection = partialContext?.connection;
788
+ if (!connection) throw new _event_driven_io_emmett.EmmettError("Connection is required in context or options");
789
+ return connection.withTransaction(async (transaction) => {
790
+ return handler({
791
+ ...partialContext,
792
+ connection: Object.assign(connection, { messageStore }),
793
+ execute: transaction.execute
794
+ });
795
+ });
796
+ };
797
+ return processingScope;
798
+ };
799
+ const sqliteWorkflowProcessor = (options) => {
800
+ const { processorId = options.processorId ?? (0, _event_driven_io_emmett.getWorkflowId)({ workflowName: options.workflow.name ?? "unknown" }), processorInstanceId = (0, _event_driven_io_emmett.getProcessorInstanceId)(processorId), version = _event_driven_io_emmett.defaultProcessorVersion, partition = _event_driven_io_emmett.defaultProcessorPartition } = options;
801
+ const hooks = {
802
+ ...options.hooks ?? {},
803
+ onClose: options.hooks?.onClose
804
+ };
805
+ return (0, _event_driven_io_emmett.workflowProcessor)({
806
+ ...options,
807
+ processorId,
808
+ processorInstanceId,
809
+ version,
810
+ partition,
811
+ hooks,
812
+ processingScope: sqliteWorkflowProcessingScope(options.messageStore),
813
+ checkpoints: sqliteCheckpointer()
814
+ });
815
+ };
816
+ const sqliteReactor = (options) => {
817
+ const { processorId = options.processorId, processorInstanceId = (0, _event_driven_io_emmett.getProcessorInstanceId)(processorId), version = _event_driven_io_emmett.defaultProcessorVersion, partition = _event_driven_io_emmett.defaultProcessorPartition, hooks } = options;
818
+ return (0, _event_driven_io_emmett.reactor)({
819
+ ...options,
820
+ processorId,
821
+ processorInstanceId,
822
+ version,
823
+ partition,
824
+ hooks,
825
+ processingScope: sqliteProcessingScope(),
826
+ checkpoints: sqliteCheckpointer()
827
+ });
828
+ };
829
+ const sqliteProjector = (options) => {
830
+ const { processorId = (0, _event_driven_io_emmett.getProjectorId)({ projectionName: options.projection.name ?? "unknown" }), processorInstanceId = (0, _event_driven_io_emmett.getProcessorInstanceId)(processorId), version = _event_driven_io_emmett.defaultProcessorVersion, partition = _event_driven_io_emmett.defaultProcessorPartition } = options;
831
+ const hooks = {
832
+ ...options.hooks ?? {},
833
+ onInit: options.projection.init !== void 0 || options.hooks?.onInit ? async (context) => {
834
+ if (options.projection.init) await options.projection.init({
835
+ version: options.projection.version ?? version,
836
+ status: "active",
837
+ registrationType: "async",
838
+ context: {
839
+ ...context,
840
+ migrationOptions: options.migrationOptions
841
+ }
842
+ });
843
+ if (options.hooks?.onInit) await options.hooks.onInit({
844
+ ...context,
845
+ migrationOptions: options.migrationOptions
846
+ });
847
+ } : options.hooks?.onInit,
848
+ onClose: options.hooks?.onClose
849
+ };
850
+ return (0, _event_driven_io_emmett.projector)({
851
+ ...options,
852
+ processorId,
853
+ processorInstanceId,
854
+ version,
855
+ partition,
856
+ hooks,
857
+ processingScope: sqliteProcessingScope(),
858
+ checkpoints: sqliteCheckpointer()
859
+ });
860
+ };
861
+
862
+ //#endregion
863
+ //#region src/eventStore/consumers/sqliteEventStoreConsumer.ts
864
+ const sqliteEventStoreConsumer = (options) => {
865
+ let isRunning = false;
866
+ let isInitialized = false;
867
+ const { pulling } = options;
868
+ const processors = options.processors ?? [];
869
+ let abortController = null;
870
+ let start;
871
+ let messagePuller;
872
+ const startedAwaiter = (0, _event_driven_io_emmett.asyncAwaiter)();
873
+ const pool = options.pool ?? (0, _event_driven_io_dumbo.dumbo)({
874
+ serialization: options.serialization,
875
+ transactionOptions: {
876
+ allowNestedTransactions: true,
877
+ mode: "session_based"
878
+ },
879
+ ...options.driver.mapToDumboOptions(options)
880
+ });
881
+ const eachBatch = (messagesBatch) => pool.withConnection(async (connection) => {
882
+ const activeProcessors = processors.filter((s) => s.isActive);
883
+ if (activeProcessors.length === 0) return {
884
+ type: "STOP",
885
+ reason: "No active processors"
886
+ };
887
+ return (await Promise.allSettled(activeProcessors.map(async (s) => {
888
+ return await s.handle(messagesBatch, {
889
+ connection,
890
+ execute: connection.execute
891
+ });
892
+ }))).some((r) => r.status === "fulfilled" && r.value?.type !== "STOP") ? void 0 : { type: "STOP" };
893
+ });
894
+ const processorContext = {
895
+ execute: void 0,
896
+ connection: void 0
897
+ };
898
+ const stopProcessors = () => Promise.all(processors.map((p) => p.close(processorContext)));
899
+ const stop = async () => {
900
+ if (!isRunning) return;
901
+ isRunning = false;
902
+ if (messagePuller) {
903
+ abortController?.abort();
904
+ await messagePuller.stop();
905
+ }
906
+ await start;
907
+ messagePuller = void 0;
908
+ abortController = null;
909
+ await stopProcessors();
910
+ };
911
+ const init = async () => {
912
+ if (isInitialized) return;
913
+ const sqliteProcessors = processors;
914
+ await pool.withConnection(async (connection) => {
915
+ for (const processor of sqliteProcessors) if (processor.init) await processor.init({
916
+ ...processorContext,
917
+ connection,
918
+ execute: connection.execute
919
+ });
920
+ });
921
+ isInitialized = true;
922
+ };
923
+ return {
924
+ consumerId: options.consumerId ?? (0, uuid.v7)(),
925
+ get isRunning() {
926
+ return isRunning;
927
+ },
928
+ whenStarted: () => startedAwaiter.wait,
929
+ processors,
930
+ init,
931
+ reactor: (options) => {
932
+ const processor = sqliteReactor(options);
933
+ processors.push(processor);
934
+ return processor;
935
+ },
936
+ projector: (options) => {
937
+ const processor = sqliteProjector(options);
938
+ processors.push(processor);
939
+ return processor;
940
+ },
941
+ workflowProcessor: (processorOptions) => {
942
+ const messageStore = getSQLiteEventStore({
943
+ ...options,
944
+ pool,
945
+ schema: { autoMigration: "None" }
946
+ });
947
+ const processor = sqliteWorkflowProcessor({
948
+ ...processorOptions,
949
+ messageStore
950
+ });
951
+ processors.push(processor);
952
+ return processor;
953
+ },
954
+ start: () => {
955
+ if (isRunning) return start;
956
+ startedAwaiter.reset();
957
+ if (processors.length === 0) {
958
+ const error = new _event_driven_io_emmett.EmmettError("Cannot start consumer without at least a single processor");
959
+ startedAwaiter.reject(error);
960
+ return Promise.reject(error);
961
+ }
962
+ isRunning = true;
963
+ abortController = new AbortController();
964
+ start = (async () => {
965
+ if (!isRunning) return;
966
+ try {
967
+ messagePuller = sqliteEventStoreMessageBatchPuller({
968
+ stopWhen: options.stopWhen,
969
+ executor: pool.execute,
970
+ eachBatch,
971
+ batchSize: pulling?.batchSize ?? 100,
972
+ pullingFrequencyInMs: pulling?.pullingFrequencyInMs ?? 50,
973
+ signal: abortController.signal
974
+ });
975
+ if (!isInitialized) await init();
976
+ const startFrom = await pool.withConnection(async (connection) => zipSQLiteEventStoreMessageBatchPullerStartFrom(await Promise.all(processors.map(async (o) => {
977
+ return await o.start({
978
+ execute: connection.execute,
979
+ connection
980
+ });
981
+ }))));
982
+ await messagePuller.start({
983
+ startFrom,
984
+ started: startedAwaiter
985
+ });
986
+ } catch (error) {
987
+ isRunning = false;
988
+ startedAwaiter.reject(error);
989
+ throw error;
990
+ } finally {
991
+ await stopProcessors();
992
+ }
993
+ })();
994
+ return start;
995
+ },
996
+ stop,
997
+ close: async () => {
998
+ await stop();
999
+ await pool.close();
1000
+ }
1001
+ };
1002
+ };
1003
+
1004
+ //#endregion
1005
+ //#region src/eventStore/SQLiteEventStore.ts
1006
+ const SQLiteEventStoreDefaultStreamVersion = 0n;
1007
+ const getSQLiteEventStore = (options) => {
1008
+ let autoGenerateSchema = false;
1009
+ const serializer = _event_driven_io_emmett.JSONSerializer.from(options);
1010
+ const pool = options.pool ?? (0, _event_driven_io_dumbo.dumbo)({
1011
+ serialization: options.serialization,
1012
+ transactionOptions: {
1013
+ allowNestedTransactions: true,
1014
+ mode: "session_based"
1015
+ },
1016
+ ...options.driver.mapToDumboOptions(options)
1017
+ });
1018
+ let migrateSchema = void 0;
1019
+ const inlineProjections = (options.projections ?? []).filter(({ type }) => type === "inline").map(({ projection }) => projection);
1020
+ const onBeforeCommitHook = options.hooks?.onBeforeCommit;
1021
+ if (options) autoGenerateSchema = options.schema?.autoMigration === void 0 || options.schema?.autoMigration !== "None";
1022
+ const migrate = (connection) => {
1023
+ if (!migrateSchema) migrateSchema = createEventStoreSchema(connection, {
1024
+ onBeforeSchemaCreated: async (context) => {
1025
+ for (const projection of inlineProjections) if (projection.init) await projection.init({
1026
+ version: projection.version ?? 1,
1027
+ registrationType: "async",
1028
+ status: "active",
1029
+ context: {
1030
+ execute: context.connection.execute,
1031
+ connection: context.connection,
1032
+ driverType: options.driver.driverType
1033
+ }
1034
+ });
1035
+ if (options.hooks?.onBeforeSchemaCreated) await options.hooks.onBeforeSchemaCreated(context);
1036
+ },
1037
+ onAfterSchemaCreated: options.hooks?.onAfterSchemaCreated
1038
+ });
1039
+ return migrateSchema;
1040
+ };
1041
+ const ensureSchemaExists = () => {
1042
+ if (!autoGenerateSchema) return Promise.resolve();
1043
+ return pool.withConnection((connection) => migrate(connection));
1044
+ };
1045
+ return {
1046
+ async aggregateStream(streamName, options) {
1047
+ await ensureSchemaExists();
1048
+ const { evolve, initialState, read } = options;
1049
+ const expectedStreamVersion = read?.expectedStreamVersion;
1050
+ let state = initialState();
1051
+ if (typeof streamName !== "string") throw new Error("Stream name is not string");
1052
+ const result = await readStream(pool.execute, streamName, {
1053
+ ...read,
1054
+ serializer: read?.serialization?.serializer ?? serializer
1055
+ });
1056
+ const currentStreamVersion = result.currentStreamVersion;
1057
+ (0, _event_driven_io_emmett.assertExpectedVersionMatchesCurrent)(currentStreamVersion, expectedStreamVersion, SQLiteEventStoreDefaultStreamVersion);
1058
+ for (const event of result.events) {
1059
+ if (!event) continue;
1060
+ state = evolve(state, event);
1061
+ }
1062
+ return {
1063
+ currentStreamVersion,
1064
+ state,
1065
+ streamExists: result.streamExists
1066
+ };
1067
+ },
1068
+ readStream: async (streamName, readOptions) => {
1069
+ await ensureSchemaExists();
1070
+ return readStream(pool.execute, streamName, {
1071
+ ...readOptions,
1072
+ serializer: options.serialization?.serializer ?? serializer
1073
+ });
1074
+ },
1075
+ appendToStream: async (streamName, events, appendOptions) => {
1076
+ await ensureSchemaExists();
1077
+ const [firstPart, ...rest] = streamName.split("-");
1078
+ const streamType = firstPart && rest.length > 0 ? firstPart : unknownTag;
1079
+ const appendResult = await pool.withConnection((connection) => appendToStream(connection, streamName, streamType, events, {
1080
+ ...appendOptions,
1081
+ onBeforeCommit: async (messages, context) => {
1082
+ if (inlineProjections.length > 0) await handleProjections({
1083
+ projections: inlineProjections,
1084
+ events: messages,
1085
+ execute: context.connection.execute,
1086
+ connection: context.connection,
1087
+ driverType: options.driver.driverType
1088
+ });
1089
+ if (onBeforeCommitHook) await onBeforeCommitHook(messages, context);
1090
+ }
1091
+ }), { readonly: false });
1092
+ if (!appendResult.success) throw new _event_driven_io_emmett.ExpectedVersionConflictError(-1n, appendOptions?.expectedStreamVersion ?? _event_driven_io_emmett.NO_CONCURRENCY_CHECK);
1093
+ return {
1094
+ nextExpectedStreamVersion: appendResult.nextStreamPosition,
1095
+ lastEventGlobalPosition: appendResult.lastGlobalPosition,
1096
+ createdNewStream: appendResult.nextStreamPosition >= BigInt(events.length)
1097
+ };
1098
+ },
1099
+ async streamExists(streamName, options) {
1100
+ await ensureSchemaExists();
1101
+ return streamExists(pool.execute, streamName, options);
1102
+ },
1103
+ consumer: (consumerOptions) => sqliteEventStoreConsumer({
1104
+ ...options ?? {},
1105
+ ...consumerOptions ?? {},
1106
+ pool
1107
+ }),
1108
+ async withSession(callback) {
1109
+ return await pool.withConnection(async (connection) => {
1110
+ const sessionStore = getSQLiteEventStore({
1111
+ ...options,
1112
+ pool: (0, _event_driven_io_dumbo.dumbo)({
1113
+ ...options.driver.mapToDumboOptions(options),
1114
+ connection,
1115
+ serialization: options.serialization
1116
+ }),
1117
+ transactionOptions: {
1118
+ allowNestedTransactions: true,
1119
+ mode: "session_based"
1120
+ },
1121
+ schema: {
1122
+ ...options.schema,
1123
+ autoMigration: "None"
1124
+ },
1125
+ serialization: options.serialization
1126
+ });
1127
+ await ensureSchemaExists();
1128
+ return callback({
1129
+ eventStore: sessionStore,
1130
+ close: () => Promise.resolve()
1131
+ });
1132
+ });
1133
+ },
1134
+ close: () => pool.close(),
1135
+ schema: {
1136
+ sql: () => schemaSQL.join(""),
1137
+ print: () => console.log(schemaSQL.join("")),
1138
+ migrate: () => pool.withConnection(migrate)
1139
+ }
1140
+ };
1141
+ };
1142
+
1143
+ //#endregion
1144
+ //#region src/eventStore/schema/readStream.ts
1145
+ const { identifier: identifier$2 } = _event_driven_io_dumbo.SQL;
1146
+ const readStream = async (execute, streamId, options) => {
1147
+ const { serializer } = options;
1148
+ const fromCondition = options.from ? _event_driven_io_dumbo.SQL`AND stream_position >= ${options.from}` : _event_driven_io_dumbo.SQL.EMPTY;
1149
+ const to = Number(options?.to ?? (options?.maxCount ? (options.from ?? 0n) + options.maxCount : NaN));
1150
+ const toCondition = !isNaN(to) ? _event_driven_io_dumbo.SQL`AND stream_position <= ${to}` : _event_driven_io_dumbo.SQL.EMPTY;
1151
+ const { rows: results } = await execute.query(_event_driven_io_dumbo.SQL`SELECT stream_id, stream_position, global_position, message_data, message_metadata, message_schema_version, message_type, message_id
1152
+ FROM ${identifier$2(messagesTable.name)}
1153
+ WHERE stream_id = ${streamId} AND partition = ${options?.partition ?? defaultTag} AND is_archived = FALSE ${fromCondition} ${toCondition}
1154
+ ORDER BY stream_position ASC`);
1155
+ const messages = results.map((row) => {
1156
+ const rawEvent = {
1157
+ type: row.message_type,
1158
+ data: serializer.deserialize(row.message_data),
1159
+ metadata: serializer.deserialize(row.message_metadata)
1160
+ };
1161
+ const metadata = {
1162
+ ..."metadata" in rawEvent ? rawEvent.metadata ?? {} : {},
1163
+ messageId: row.message_id,
1164
+ streamName: streamId,
1165
+ streamPosition: BigInt(row.stream_position),
1166
+ globalPosition: BigInt(row.global_position),
1167
+ checkpoint: (0, _event_driven_io_emmett.bigIntProcessorCheckpoint)(BigInt(row.global_position))
1168
+ };
1169
+ return (0, _event_driven_io_emmett.upcastRecordedMessage)({
1170
+ ...rawEvent,
1171
+ kind: "Event",
1172
+ metadata
1173
+ }, options?.schema?.versioning);
1174
+ });
1175
+ return messages.length > 0 ? {
1176
+ currentStreamVersion: messages[messages.length - 1].metadata.streamPosition,
1177
+ events: messages,
1178
+ streamExists: true
1179
+ } : {
1180
+ currentStreamVersion: SQLiteEventStoreDefaultStreamVersion,
1181
+ events: [],
1182
+ streamExists: false
1183
+ };
1184
+ };
1185
+
1186
+ //#endregion
1187
+ //#region src/eventStore/schema/storeProcessorCheckpoint.ts
1188
+ const { identifier: identifier$1 } = _event_driven_io_dumbo.SQL;
2599
1189
  async function storeSubscriptionCheckpointSQLite(execute, processorId, version, position, checkPosition, partition, processorInstanceId) {
2600
- processorInstanceId ??= unknownTag2;
2601
- if (checkPosition !== null) {
2602
- const updateResult = await execute.command(
2603
- _dumbo.SQL`
2604
- UPDATE ${identifier7(processorsTable.name)}
1190
+ processorInstanceId ??= unknownTag;
1191
+ if (checkPosition !== null) {
1192
+ const updateResult = await execute.command(_event_driven_io_dumbo.SQL`
1193
+ UPDATE ${identifier$1(processorsTable.name)}
2605
1194
  SET
2606
1195
  last_processed_checkpoint = ${position},
2607
1196
  processor_instance_id = ${processorInstanceId}
2608
1197
  WHERE processor_id = ${processorId}
2609
1198
  AND last_processed_checkpoint = ${checkPosition}
2610
1199
  AND partition = ${partition}
2611
- `
2612
- );
2613
- if (updateResult.rowCount && updateResult.rowCount > 0) {
2614
- return 1;
2615
- }
2616
- const current_position = await _dumbo.singleOrNull.call(void 0,
2617
- execute.query(
2618
- _dumbo.SQL`
2619
- SELECT last_processed_checkpoint FROM ${identifier7(processorsTable.name)}
2620
- WHERE processor_id = ${processorId} AND partition = ${partition}`
2621
- )
2622
- );
2623
- const currentPosition = current_position && _optionalChain([current_position, 'optionalAccess', _132 => _132.last_processed_checkpoint]) !== null ? current_position.last_processed_checkpoint : null;
2624
- if (currentPosition === position) {
2625
- return 0;
2626
- } else if (position !== null && currentPosition !== null && currentPosition > position) {
2627
- return 2;
2628
- } else {
2629
- return 2;
2630
- }
2631
- } else {
2632
- try {
2633
- await execute.command(
2634
- _dumbo.SQL`INSERT INTO ${identifier7(processorsTable.name)} (processor_id, version, last_processed_checkpoint, partition, processor_instance_id)
2635
- VALUES (${processorId}, ${version}, ${position}, ${partition}, ${processorInstanceId})`
2636
- );
2637
- return 1;
2638
- } catch (err) {
2639
- if (!_dumbo.DumboError.isInstanceOf(err, {
2640
- errorType: _dumbo.UniqueConstraintError.ErrorType
2641
- })) {
2642
- throw err;
2643
- }
2644
- const current = await _dumbo.singleOrNull.call(void 0,
2645
- execute.query(
2646
- _dumbo.SQL`
2647
- SELECT last_processed_checkpoint FROM ${identifier7(processorsTable.name)}
2648
- WHERE processor_id = ${processorId} AND partition = ${partition}`
2649
- )
2650
- );
2651
- const currentPosition = current && _optionalChain([current, 'optionalAccess', _133 => _133.last_processed_checkpoint]) !== null ? BigInt(current.last_processed_checkpoint) : null;
2652
- if (currentPosition === position) {
2653
- return 0;
2654
- } else {
2655
- return 2;
2656
- }
2657
- }
2658
- }
1200
+ `);
1201
+ if (updateResult.rowCount && updateResult.rowCount > 0) return 1;
1202
+ const current_position = await (0, _event_driven_io_dumbo.singleOrNull)(execute.query(_event_driven_io_dumbo.SQL`
1203
+ SELECT last_processed_checkpoint FROM ${identifier$1(processorsTable.name)}
1204
+ WHERE processor_id = ${processorId} AND partition = ${partition}`));
1205
+ const currentPosition = current_position && current_position?.last_processed_checkpoint !== null ? current_position.last_processed_checkpoint : null;
1206
+ if (currentPosition === position) return 0;
1207
+ else if (position !== null && currentPosition !== null && currentPosition > position) return 2;
1208
+ else return 2;
1209
+ } else try {
1210
+ await execute.command(_event_driven_io_dumbo.SQL`INSERT INTO ${identifier$1(processorsTable.name)} (processor_id, version, last_processed_checkpoint, partition, processor_instance_id)
1211
+ VALUES (${processorId}, ${version}, ${position}, ${partition}, ${processorInstanceId})`);
1212
+ return 1;
1213
+ } catch (err) {
1214
+ if (!_event_driven_io_dumbo.DumboError.isInstanceOf(err, { errorType: _event_driven_io_dumbo.UniqueConstraintError.ErrorType })) throw err;
1215
+ const current = await (0, _event_driven_io_dumbo.singleOrNull)(execute.query(_event_driven_io_dumbo.SQL`
1216
+ SELECT last_processed_checkpoint FROM ${identifier$1(processorsTable.name)}
1217
+ WHERE processor_id = ${processorId} AND partition = ${partition}`));
1218
+ if ((current && current?.last_processed_checkpoint !== null ? BigInt(current.last_processed_checkpoint) : null) === position) return 0;
1219
+ else return 2;
1220
+ }
2659
1221
  }
2660
1222
  async function storeProcessorCheckpoint(execute, options) {
2661
- try {
2662
- const result = await storeSubscriptionCheckpointSQLite(
2663
- execute,
2664
- options.processorId,
2665
- _nullishCoalesce(options.version, () => ( 1)),
2666
- options.newCheckpoint,
2667
- options.lastProcessedCheckpoint,
2668
- _nullishCoalesce(options.partition, () => ( defaultTag2))
2669
- );
2670
- return result === 1 ? { success: true, newCheckpoint: options.newCheckpoint } : { success: false, reason: result === 0 ? "IGNORED" : "MISMATCH" };
2671
- } catch (error) {
2672
- console.log(error);
2673
- throw error;
2674
- }
1223
+ try {
1224
+ const result = await storeSubscriptionCheckpointSQLite(execute, options.processorId, options.version ?? 1, options.newCheckpoint, options.lastProcessedCheckpoint, options.partition ?? defaultTag);
1225
+ return result === 1 ? {
1226
+ success: true,
1227
+ newCheckpoint: options.newCheckpoint
1228
+ } : {
1229
+ success: false,
1230
+ reason: result === 0 ? "IGNORED" : "MISMATCH"
1231
+ };
1232
+ } catch (error) {
1233
+ console.log(error);
1234
+ throw error;
1235
+ }
2675
1236
  }
2676
1237
 
2677
- // src/eventStore/schema/streamExists.ts
2678
-
2679
- var streamExists = (execute, streamId, options) => _dumbo.exists.call(void 0,
2680
- execute.query(
2681
- _dumbo.SQL`SELECT EXISTS (
1238
+ //#endregion
1239
+ //#region src/eventStore/schema/streamExists.ts
1240
+ const streamExists = (execute, streamId, options) => (0, _event_driven_io_dumbo.exists)(execute.query(_event_driven_io_dumbo.SQL`SELECT EXISTS (
2682
1241
  SELECT 1
2683
- from ${_dumbo.SQL.identifier(streamsTable.name)}
2684
- WHERE stream_id = ${streamId} AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _134 => _134.partition]), () => ( defaultTag2))} AND is_archived = FALSE) as exists
2685
- `
2686
- )
2687
- );
2688
-
2689
- // src/eventStore/schema/tables.ts
2690
-
2691
- var { identifier: identifier8, plain: plain2 } = _dumbo.SQL;
2692
- var streamsTableSQL = _dumbo.SQL`CREATE TABLE IF NOT EXISTS ${identifier8(streamsTable.name)}(
1242
+ from ${_event_driven_io_dumbo.SQL.identifier(streamsTable.name)}
1243
+ WHERE stream_id = ${streamId} AND partition = ${options?.partition ?? defaultTag} AND is_archived = FALSE) as exists
1244
+ `));
1245
+
1246
+ //#endregion
1247
+ //#region src/eventStore/schema/tables.ts
1248
+ const { identifier, plain } = _event_driven_io_dumbo.SQL;
1249
+ const streamsTableSQL = _event_driven_io_dumbo.SQL`CREATE TABLE IF NOT EXISTS ${identifier(streamsTable.name)}(
2693
1250
  stream_id TEXT NOT NULL,
2694
1251
  stream_position BIGINT NOT NULL DEFAULT 0,
2695
- partition TEXT NOT NULL DEFAULT '${plain2(globalTag)}',
1252
+ partition TEXT NOT NULL DEFAULT '${plain(globalTag)}',
2696
1253
  stream_type TEXT NOT NULL,
2697
1254
  stream_metadata JSONB NOT NULL,
2698
1255
  is_archived BOOLEAN NOT NULL DEFAULT FALSE,
2699
1256
  PRIMARY KEY (stream_id, partition, is_archived),
2700
1257
  UNIQUE (stream_id, partition, is_archived)
2701
1258
  );`;
2702
- var messagesTableSQL = _dumbo.SQL`CREATE TABLE IF NOT EXISTS ${identifier8(messagesTable.name)}(
1259
+ const messagesTableSQL = _event_driven_io_dumbo.SQL`CREATE TABLE IF NOT EXISTS ${identifier(messagesTable.name)}(
2703
1260
  stream_id TEXT NOT NULL,
2704
1261
  stream_position BIGINT NOT NULL,
2705
- partition TEXT NOT NULL DEFAULT '${plain2(globalTag)}',
1262
+ partition TEXT NOT NULL DEFAULT '${plain(globalTag)}',
2706
1263
  message_kind CHAR(1) NOT NULL DEFAULT 'E',
2707
1264
  message_data JSONB NOT NULL,
2708
1265
  message_metadata JSONB NOT NULL,
@@ -2715,22 +1272,22 @@ var messagesTableSQL = _dumbo.SQL`CREATE TABLE IF NOT EXISTS ${identifier8(messa
2715
1272
  UNIQUE (stream_id, stream_position, partition, is_archived)
2716
1273
  );
2717
1274
  `;
2718
- var processorsTableSQL = _dumbo.SQL`
2719
- CREATE TABLE IF NOT EXISTS ${_dumbo.SQL.identifier(processorsTable.name)}(
1275
+ const processorsTableSQL = _event_driven_io_dumbo.SQL`
1276
+ CREATE TABLE IF NOT EXISTS ${_event_driven_io_dumbo.SQL.identifier(processorsTable.name)}(
2720
1277
  processor_id TEXT NOT NULL,
2721
1278
  version INTEGER NOT NULL DEFAULT 1,
2722
- partition TEXT NOT NULL DEFAULT '${plain2(globalTag)}',
1279
+ partition TEXT NOT NULL DEFAULT '${plain(globalTag)}',
2723
1280
  status TEXT NOT NULL DEFAULT 'stopped',
2724
1281
  last_processed_checkpoint TEXT NOT NULL,
2725
- processor_instance_id TEXT DEFAULT '${plain2(unknownTag2)}',
1282
+ processor_instance_id TEXT DEFAULT '${plain(unknownTag)}',
2726
1283
  PRIMARY KEY (processor_id, partition, version)
2727
1284
  );
2728
1285
  `;
2729
- var projectionsTableSQL = _dumbo.SQL`
2730
- CREATE TABLE IF NOT EXISTS ${_dumbo.SQL.identifier(projectionsTable.name)}(
1286
+ const projectionsTableSQL = _event_driven_io_dumbo.SQL`
1287
+ CREATE TABLE IF NOT EXISTS ${_event_driven_io_dumbo.SQL.identifier(projectionsTable.name)}(
2731
1288
  name TEXT NOT NULL,
2732
1289
  version INTEGER NOT NULL DEFAULT 1,
2733
- partition TEXT NOT NULL DEFAULT '${plain2(globalTag)}',
1290
+ partition TEXT NOT NULL DEFAULT '${plain(globalTag)}',
2734
1291
  type CHAR(1) NOT NULL,
2735
1292
  kind TEXT NOT NULL,
2736
1293
  status TEXT NOT NULL,
@@ -2738,73 +1295,67 @@ var projectionsTableSQL = _dumbo.SQL`
2738
1295
  PRIMARY KEY (name, partition, version)
2739
1296
  );
2740
1297
  `;
2741
- var schemaSQL = [
2742
- streamsTableSQL,
2743
- messagesTableSQL,
2744
- processorsTableSQL,
2745
- projectionsTableSQL
1298
+ const schemaSQL = [
1299
+ streamsTableSQL,
1300
+ messagesTableSQL,
1301
+ processorsTableSQL,
1302
+ projectionsTableSQL
2746
1303
  ];
2747
- var createEventStoreSchema = async (pool, hooks) => {
2748
- await pool.withTransaction(async (tx) => {
2749
- await migration_0_42_0_FromSubscriptionsToProcessors(tx.execute);
2750
- if (_optionalChain([hooks, 'optionalAccess', _135 => _135.onBeforeSchemaCreated])) {
2751
- await hooks.onBeforeSchemaCreated({
2752
- connection: tx.connection
2753
- });
2754
- }
2755
- await tx.execute.batchCommand(schemaSQL);
2756
- if (_optionalChain([hooks, 'optionalAccess', _136 => _136.onAfterSchemaCreated])) {
2757
- await hooks.onAfterSchemaCreated();
2758
- }
2759
- });
2760
- };
2761
-
2762
-
2763
-
2764
-
2765
-
2766
-
2767
-
2768
-
2769
-
2770
-
2771
-
2772
-
2773
-
2774
-
2775
-
2776
-
2777
-
2778
-
2779
-
2780
-
2781
-
2782
-
2783
-
2784
-
2785
-
2786
-
2787
-
2788
-
2789
-
2790
-
2791
-
2792
-
2793
-
2794
-
2795
-
2796
-
2797
-
2798
-
2799
-
2800
-
2801
-
2802
-
2803
-
2804
-
2805
-
2806
-
2807
-
2808
-
2809
- exports.SQLiteEventStoreDefaultStreamVersion = SQLiteEventStoreDefaultStreamVersion; exports.SQLiteProjectionSpec = SQLiteProjectionSpec; exports.appendToStream = appendToStream; exports.assertSQLQueryResultMatches = assertSQLQueryResultMatches; exports.createEventStoreSchema = createEventStoreSchema; exports.defaultTag = defaultTag2; exports.documentDoesNotExist = documentDoesNotExist; exports.documentExists = documentExists; exports.documentMatchingExists = documentMatchingExists; exports.documentsAreTheSame = documentsAreTheSame; exports.documentsMatchingHaveCount = documentsMatchingHaveCount; exports.emmettPrefix = emmettPrefix2; exports.eventInStream = eventInStream; exports.eventsInStream = eventsInStream; exports.expectPongoDocuments = expectPongoDocuments; exports.expectSQL = expectSQL; exports.getSQLiteEventStore = getSQLiteEventStore; exports.globalNames = globalNames; exports.globalTag = globalTag; exports.handleProjections = handleProjections; exports.messagesTable = messagesTable; exports.messagesTableSQL = messagesTableSQL; exports.migration_0_42_0_FromSubscriptionsToProcessors = migration_0_42_0_FromSubscriptionsToProcessors; exports.migration_0_42_0_SQLs = migration_0_42_0_SQLs; exports.newEventsInStream = newEventsInStream; exports.pongoMultiStreamProjection = pongoMultiStreamProjection; exports.pongoProjection = pongoProjection; exports.pongoSingleStreamProjection = pongoSingleStreamProjection; exports.processorsTable = processorsTable; exports.processorsTableSQL = processorsTableSQL; exports.projectionsTable = projectionsTable; exports.projectionsTableSQL = projectionsTableSQL; exports.readLastMessageGlobalPosition = readLastMessageGlobalPosition; exports.readMessagesBatch = readMessagesBatch; exports.readProcessorCheckpoint = readProcessorCheckpoint; exports.readStream = readStream; exports.schemaSQL = schemaSQL; exports.schema_0_41_0 = schema_0_41_0; exports.schema_0_42_0 = schema_0_42_0; exports.sqliteProjection = sqliteProjection; exports.sqliteRawBatchSQLProjection = sqliteRawBatchSQLProjection; exports.sqliteRawSQLProjection = sqliteRawSQLProjection; exports.storeProcessorCheckpoint = storeProcessorCheckpoint; exports.streamExists = streamExists; exports.streamsTable = streamsTable; exports.streamsTableSQL = streamsTableSQL; exports.unknownTag = unknownTag2;
1304
+ const createEventStoreSchema = async (pool, hooks) => {
1305
+ await pool.withTransaction(async (tx) => {
1306
+ await migration_0_42_0_FromSubscriptionsToProcessors(tx.execute);
1307
+ if (hooks?.onBeforeSchemaCreated) await hooks.onBeforeSchemaCreated({ connection: tx.connection });
1308
+ await tx.execute.batchCommand(schemaSQL);
1309
+ if (hooks?.onAfterSchemaCreated) await hooks.onAfterSchemaCreated();
1310
+ });
1311
+ };
1312
+
1313
+ //#endregion
1314
+ exports.SQLiteEventStoreDefaultStreamVersion = SQLiteEventStoreDefaultStreamVersion;
1315
+ exports.SQLiteProjectionSpec = SQLiteProjectionSpec;
1316
+ exports.appendToStream = appendToStream;
1317
+ exports.assertSQLQueryResultMatches = assertSQLQueryResultMatches;
1318
+ exports.createEventStoreSchema = createEventStoreSchema;
1319
+ exports.defaultTag = defaultTag;
1320
+ exports.documentDoesNotExist = documentDoesNotExist;
1321
+ exports.documentExists = documentExists;
1322
+ exports.documentMatchingExists = documentMatchingExists;
1323
+ exports.documentsAreTheSame = documentsAreTheSame;
1324
+ exports.documentsMatchingHaveCount = documentsMatchingHaveCount;
1325
+ exports.emmettPrefix = emmettPrefix;
1326
+ exports.eventInStream = eventInStream;
1327
+ exports.eventsInStream = eventsInStream;
1328
+ exports.expectPongoDocuments = expectPongoDocuments;
1329
+ exports.expectSQL = expectSQL;
1330
+ exports.getSQLiteEventStore = getSQLiteEventStore;
1331
+ exports.globalNames = globalNames;
1332
+ exports.globalTag = globalTag;
1333
+ exports.handleProjections = handleProjections;
1334
+ exports.messagesTable = messagesTable;
1335
+ exports.messagesTableSQL = messagesTableSQL;
1336
+ exports.migration_0_42_0_FromSubscriptionsToProcessors = migration_0_42_0_FromSubscriptionsToProcessors;
1337
+ exports.migration_0_42_0_SQLs = migration_0_42_0_SQLs;
1338
+ exports.newEventsInStream = newEventsInStream;
1339
+ exports.pongoMultiStreamProjection = pongoMultiStreamProjection;
1340
+ exports.pongoProjection = pongoProjection;
1341
+ exports.pongoSingleStreamProjection = pongoSingleStreamProjection;
1342
+ exports.processorsTable = processorsTable;
1343
+ exports.processorsTableSQL = processorsTableSQL;
1344
+ exports.projectionsTable = projectionsTable;
1345
+ exports.projectionsTableSQL = projectionsTableSQL;
1346
+ exports.readLastMessageGlobalPosition = readLastMessageGlobalPosition;
1347
+ exports.readMessagesBatch = readMessagesBatch;
1348
+ exports.readProcessorCheckpoint = readProcessorCheckpoint;
1349
+ exports.readStream = readStream;
1350
+ exports.schemaSQL = schemaSQL;
1351
+ exports.schema_0_41_0 = schema_0_41_0;
1352
+ exports.schema_0_42_0 = schema_0_42_0;
1353
+ exports.sqliteProjection = sqliteProjection;
1354
+ exports.sqliteRawBatchSQLProjection = sqliteRawBatchSQLProjection;
1355
+ exports.sqliteRawSQLProjection = sqliteRawSQLProjection;
1356
+ exports.storeProcessorCheckpoint = storeProcessorCheckpoint;
1357
+ exports.streamExists = streamExists;
1358
+ exports.streamsTable = streamsTable;
1359
+ exports.streamsTableSQL = streamsTableSQL;
1360
+ exports.unknownTag = unknownTag;
2810
1361
  //# sourceMappingURL=index.cjs.map