@event-driven-io/emmett-sqlite 0.43.0-alpha.4 → 0.43.0-beta.1

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,6 +1,5 @@
1
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
2
  var isNumber = (val) => typeof val === "number" && val === val;
3
- var isBigint = (val) => typeof val === "bigint" && val === val;
4
3
  var isString = (val) => typeof val === "string";
5
4
  var isErrorConstructor = (expect) => {
6
5
  return typeof expect === "function" && expect.prototype && // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
@@ -281,6 +280,10 @@ var deepEquals = (left, right) => {
281
280
  var isEquatable = (left) => {
282
281
  return left !== null && left !== void 0 && typeof left === "object" && "equals" in left && typeof left["equals"] === "function";
283
282
  };
283
+ var toNormalizedString = (value) => value.toString().padStart(19, "0");
284
+ var bigInt = {
285
+ toNormalizedString
286
+ };
284
287
  var ParseError = class extends Error {
285
288
  constructor(text) {
286
289
  super(`Cannot parse! ${text}`);
@@ -302,7 +305,204 @@ var JSONParser = {
302
305
  return _optionalChain([options, 'optionalAccess', _13 => _13.map]) ? options.map(parsed) : parsed;
303
306
  }
304
307
  };
308
+ var onShutdown = (handler) => {
309
+ const signals = ["SIGTERM", "SIGINT"];
310
+ if (typeof process !== "undefined" && typeof process.on === "function") {
311
+ for (const signal of signals) {
312
+ process.on(signal, handler);
313
+ }
314
+ return () => {
315
+ for (const signal of signals) {
316
+ process.off(signal, handler);
317
+ }
318
+ };
319
+ }
320
+ const deno = globalThis.Deno;
321
+ if (deno && typeof deno.addSignalListener === "function") {
322
+ for (const signal of signals) {
323
+ deno.addSignalListener(signal, handler);
324
+ }
325
+ return () => {
326
+ for (const signal of signals) {
327
+ deno.removeSignalListener(signal, handler);
328
+ }
329
+ };
330
+ }
331
+ return () => {
332
+ };
333
+ };
305
334
  var textEncoder = new TextEncoder();
335
+ var getCheckpoint = (message2) => {
336
+ return message2.metadata.checkpoint;
337
+ };
338
+ var wasMessageHandled = (message2, checkpoint) => {
339
+ const messageCheckpoint = getCheckpoint(message2);
340
+ return messageCheckpoint !== null && messageCheckpoint !== void 0 && checkpoint !== null && checkpoint !== void 0 && messageCheckpoint <= checkpoint;
341
+ };
342
+ var MessageProcessorType = {
343
+ PROJECTOR: "projector",
344
+ REACTOR: "reactor"
345
+ };
346
+ var defaultProcessingMessageProcessingScope = (handler, partialContext) => handler(partialContext);
347
+ var bigIntProcessorCheckpoint = (value) => bigInt.toNormalizedString(value);
348
+ var parseBigIntProcessorCheckpoint = (value) => BigInt(value);
349
+ var defaultProcessorVersion = 1;
350
+ var defaultProcessorPartition = defaultTag;
351
+ var getProcessorInstanceId = (processorId) => `${processorId}:${_uuid.v7.call(void 0, )}`;
352
+ var getProjectorId = (options) => `emt:processor:projector:${options.projectionName}`;
353
+ var reactor = (options) => {
354
+ const {
355
+ checkpoints,
356
+ processorId,
357
+ processorInstanceId: instanceId = getProcessorInstanceId(processorId),
358
+ type = MessageProcessorType.REACTOR,
359
+ version = defaultProcessorVersion,
360
+ partition = defaultProcessorPartition,
361
+ hooks = {},
362
+ processingScope = defaultProcessingMessageProcessingScope,
363
+ startFrom,
364
+ canHandle,
365
+ stopAfter
366
+ } = options;
367
+ const eachMessage = "eachMessage" in options && options.eachMessage ? options.eachMessage : () => Promise.resolve();
368
+ let isInitiated = false;
369
+ let isActive = false;
370
+ let lastCheckpoint = null;
371
+ let closeSignal = null;
372
+ const init = async (initOptions) => {
373
+ if (isInitiated) return;
374
+ if (hooks.onInit === void 0) {
375
+ isInitiated = true;
376
+ return;
377
+ }
378
+ return await processingScope(async (context) => {
379
+ await hooks.onInit(context);
380
+ isInitiated = true;
381
+ }, initOptions);
382
+ };
383
+ const close = async (closeOptions) => {
384
+ isActive = false;
385
+ if (closeSignal) {
386
+ closeSignal();
387
+ closeSignal = null;
388
+ }
389
+ if (hooks.onClose) {
390
+ await processingScope(hooks.onClose, closeOptions);
391
+ }
392
+ };
393
+ return {
394
+ // TODO: Consider whether not make it optional or add URN prefix
395
+ id: processorId,
396
+ instanceId,
397
+ type,
398
+ init,
399
+ start: async (startOptions) => {
400
+ if (isActive) return;
401
+ await init(startOptions);
402
+ isActive = true;
403
+ closeSignal = onShutdown(() => close({}));
404
+ if (lastCheckpoint !== null)
405
+ return {
406
+ lastCheckpoint
407
+ };
408
+ return await processingScope(async (context) => {
409
+ if (hooks.onStart) {
410
+ await hooks.onStart(context);
411
+ }
412
+ if (startFrom && startFrom !== "CURRENT") return startFrom;
413
+ if (checkpoints) {
414
+ const readResult = await _optionalChain([checkpoints, 'optionalAccess', _14 => _14.read, 'call', _15 => _15(
415
+ {
416
+ processorId,
417
+ partition
418
+ },
419
+ { ...startOptions, ...context }
420
+ )]);
421
+ lastCheckpoint = readResult.lastCheckpoint;
422
+ }
423
+ if (lastCheckpoint === null) return "BEGINNING";
424
+ return {
425
+ lastCheckpoint
426
+ };
427
+ }, startOptions);
428
+ },
429
+ close,
430
+ get isActive() {
431
+ return isActive;
432
+ },
433
+ handle: async (messages, partialContext) => {
434
+ if (!isActive) return Promise.resolve();
435
+ return await processingScope(async (context) => {
436
+ let result = void 0;
437
+ for (const message2 of messages) {
438
+ if (wasMessageHandled(message2, lastCheckpoint)) continue;
439
+ const upcasted = upcastRecordedMessage(
440
+ // TODO: Make it smarter
441
+ message2,
442
+ _optionalChain([options, 'access', _16 => _16.messageOptions, 'optionalAccess', _17 => _17.schema, 'optionalAccess', _18 => _18.versioning])
443
+ );
444
+ if (canHandle !== void 0 && !canHandle.includes(upcasted.type))
445
+ continue;
446
+ const messageProcessingResult = await eachMessage(upcasted, context);
447
+ if (checkpoints) {
448
+ const storeCheckpointResult = await checkpoints.store(
449
+ {
450
+ processorId,
451
+ version,
452
+ message: upcasted,
453
+ lastCheckpoint,
454
+ partition
455
+ },
456
+ context
457
+ );
458
+ if (storeCheckpointResult.success) {
459
+ lastCheckpoint = storeCheckpointResult.newCheckpoint;
460
+ }
461
+ }
462
+ if (messageProcessingResult && messageProcessingResult.type === "STOP") {
463
+ isActive = false;
464
+ result = messageProcessingResult;
465
+ break;
466
+ }
467
+ if (stopAfter && stopAfter(upcasted)) {
468
+ isActive = false;
469
+ result = { type: "STOP", reason: "Stop condition reached" };
470
+ break;
471
+ }
472
+ if (messageProcessingResult && messageProcessingResult.type === "SKIP")
473
+ continue;
474
+ }
475
+ return result;
476
+ }, partialContext);
477
+ }
478
+ };
479
+ };
480
+ var projector = (options) => {
481
+ const {
482
+ projection: projection2,
483
+ processorId = getProjectorId({
484
+ projectionName: _nullishCoalesce(projection2.name, () => ( "unknown"))
485
+ }),
486
+ ...rest
487
+ } = options;
488
+ return reactor({
489
+ ...rest,
490
+ type: MessageProcessorType.PROJECTOR,
491
+ canHandle: projection2.canHandle,
492
+ processorId,
493
+ messageOptions: options.projection.eventsOptions,
494
+ hooks: {
495
+ onInit: _optionalChain([options, 'access', _19 => _19.hooks, 'optionalAccess', _20 => _20.onInit]),
496
+ onStart: options.truncateOnStart && options.projection.truncate || _optionalChain([options, 'access', _21 => _21.hooks, 'optionalAccess', _22 => _22.onStart]) ? async (context) => {
497
+ if (options.truncateOnStart && options.projection.truncate)
498
+ await options.projection.truncate(context);
499
+ if (_optionalChain([options, 'access', _23 => _23.hooks, 'optionalAccess', _24 => _24.onStart])) await _optionalChain([options, 'access', _25 => _25.hooks, 'optionalAccess', _26 => _26.onStart, 'call', _27 => _27(context)]);
500
+ } : void 0,
501
+ onClose: _optionalChain([options, 'access', _28 => _28.hooks, 'optionalAccess', _29 => _29.onClose])
502
+ },
503
+ eachMessage: async (event2, context) => projection2.handle([event2], context)
504
+ });
505
+ };
306
506
  var AssertionError = class extends Error {
307
507
  constructor(message2) {
308
508
  super(message2);
@@ -314,7 +514,7 @@ var isSubset = (superObj, subObj) => {
314
514
  assertOk(sup);
315
515
  assertOk(sub);
316
516
  return Object.keys(sub).every((ele) => {
317
- if (typeof sub[ele] == "object") {
517
+ if (sub[ele] !== null && typeof sub[ele] == "object") {
318
518
  return isSubset(sup[ele], sub[ele]);
319
519
  }
320
520
  return sub[ele] === sup[ele];
@@ -406,7 +606,7 @@ var assertThatArray = (array) => {
406
606
  };
407
607
  };
408
608
  var downcastRecordedMessage = (recordedMessage, options) => {
409
- if (!_optionalChain([options, 'optionalAccess', _14 => _14.downcast]))
609
+ if (!_optionalChain([options, 'optionalAccess', _30 => _30.downcast]))
410
610
  return recordedMessage;
411
611
  const downcasted = options.downcast(
412
612
  recordedMessage
@@ -424,14 +624,14 @@ var downcastRecordedMessage = (recordedMessage, options) => {
424
624
  };
425
625
  };
426
626
  var downcastRecordedMessages = (recordedMessages, options) => {
427
- if (!_optionalChain([options, 'optionalAccess', _15 => _15.downcast]))
627
+ if (!_optionalChain([options, 'optionalAccess', _31 => _31.downcast]))
428
628
  return recordedMessages;
429
629
  return recordedMessages.map(
430
630
  (recordedMessage) => downcastRecordedMessage(recordedMessage, options)
431
631
  );
432
632
  };
433
633
  var upcastRecordedMessage = (recordedMessage, options) => {
434
- if (!_optionalChain([options, 'optionalAccess', _16 => _16.upcast]))
634
+ if (!_optionalChain([options, 'optionalAccess', _32 => _32.upcast]))
435
635
  return recordedMessage;
436
636
  const upcasted = options.upcast(
437
637
  recordedMessage
@@ -448,56 +648,55 @@ var upcastRecordedMessage = (recordedMessage, options) => {
448
648
  } : {}
449
649
  };
450
650
  };
451
- var getCheckpoint = (message2) => {
452
- return "checkpoint" in message2.metadata ? (
453
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
454
- message2.metadata.checkpoint
455
- ) : "globalPosition" in message2.metadata && // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
456
- isBigint(message2.metadata.globalPosition) ? (
457
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
458
- message2.metadata.globalPosition
459
- ) : "streamPosition" in message2.metadata && // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
460
- isBigint(message2.metadata.streamPosition) ? (
461
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
462
- message2.metadata.streamPosition
463
- ) : null;
464
- };
465
651
  var projection = (definition) => definition;
466
652
 
467
653
  // src/eventStore/projections/sqliteProjection.ts
468
654
  var handleProjections = async (options) => {
469
- const { projections: allProjections, events, connection } = options;
655
+ const {
656
+ projections: allProjections,
657
+ events,
658
+ connection,
659
+ execute,
660
+ driverType
661
+ } = options;
470
662
  const eventTypes = events.map((e) => e.type);
471
663
  for (const projection2 of allProjections) {
472
664
  if (!projection2.canHandle.some((type) => eventTypes.includes(type))) {
473
665
  continue;
474
666
  }
475
667
  await projection2.handle(events, {
476
- connection
668
+ connection,
669
+ execute,
670
+ driverType
477
671
  });
478
672
  }
479
673
  };
480
674
  var sqliteProjection = (definition) => projection(definition);
481
675
  var sqliteRawBatchSQLProjection = (options) => sqliteProjection({
676
+ name: options.name,
677
+ kind: _nullishCoalesce(options.kind, () => ( "emt:projections:sqlite:raw_sql:batch")),
678
+ version: options.version,
482
679
  canHandle: options.canHandle,
680
+ eventsOptions: options.eventsOptions,
483
681
  handle: async (events, context) => {
484
682
  const sqls = await options.evolve(events, context);
485
- for (const sql of sqls) await context.connection.execute.command(sql);
683
+ await context.execute.batchCommand(sqls);
486
684
  },
487
685
  init: async (initOptions) => {
488
- if (options.init) {
489
- await options.init(initOptions);
490
- }
491
- if (options.initSQL) {
492
- const initSQLs = Array.isArray(options.initSQL) ? options.initSQL : [options.initSQL];
493
- for (const sql of initSQLs)
494
- await initOptions.context.connection.execute.command(sql);
686
+ const initSQL = options.init ? await options.init(initOptions) : void 0;
687
+ if (initSQL) {
688
+ if (Array.isArray(initSQL)) {
689
+ await initOptions.context.execute.batchCommand(initSQL);
690
+ } else {
691
+ await initOptions.context.execute.command(initSQL);
692
+ }
495
693
  }
496
694
  }
497
695
  });
498
696
  var sqliteRawSQLProjection = (options) => {
499
- const { evolve, ...rest } = options;
697
+ const { evolve, kind, ...rest } = options;
500
698
  return sqliteRawBatchSQLProjection({
699
+ kind: _nullishCoalesce(kind, () => ( "emt:projections:sqlite:raw:_sql:single")),
501
700
  ...rest,
502
701
  evolve: async (events, context) => {
503
702
  const sqls = [];
@@ -520,6 +719,7 @@ var _dumbo = require('@event-driven-io/dumbo');
520
719
  var SQLiteProjectionSpec = {
521
720
  for: (options) => {
522
721
  {
722
+ const driverType = options.driver.driverType;
523
723
  const pool = _nullishCoalesce(options.pool, () => ( _dumbo.dumbo.call(void 0, {
524
724
  ...options.driver.mapToDumboOptions(options)
525
725
  })));
@@ -531,13 +731,14 @@ var SQLiteProjectionSpec = {
531
731
  const allEvents = [];
532
732
  const run = async (connection) => {
533
733
  let globalPosition = 0n;
534
- const numberOfTimes = _nullishCoalesce(_optionalChain([options2, 'optionalAccess', _17 => _17.numberOfTimes]), () => ( 1));
734
+ const numberOfTimes = _nullishCoalesce(_optionalChain([options2, 'optionalAccess', _33 => _33.numberOfTimes]), () => ( 1));
535
735
  for (const event of [
536
736
  ...givenEvents,
537
737
  ...Array.from({ length: numberOfTimes }).flatMap(() => events)
538
738
  ]) {
539
739
  const metadata = {
540
- globalPosition: ++globalPosition,
740
+ checkpoint: bigIntProcessorCheckpoint(++globalPosition),
741
+ globalPosition,
541
742
  streamPosition: globalPosition,
542
743
  streamName: `test-${_uuid.v4.call(void 0, )}`,
543
744
  messageId: _uuid.v4.call(void 0, )
@@ -555,7 +756,11 @@ var SQLiteProjectionSpec = {
555
756
  await projection2.init({
556
757
  registrationType: "async",
557
758
  status: "active",
558
- context: { connection },
759
+ context: {
760
+ execute: connection.execute,
761
+ connection,
762
+ driverType
763
+ },
559
764
  version: _nullishCoalesce(projection2.version, () => ( 1))
560
765
  });
561
766
  wasInitialized = true;
@@ -564,7 +769,9 @@ var SQLiteProjectionSpec = {
564
769
  () => handleProjections({
565
770
  events: allEvents,
566
771
  projections: [projection2],
567
- connection
772
+ execute: connection.execute,
773
+ connection,
774
+ driverType
568
775
  })
569
776
  );
570
777
  };
@@ -591,18 +798,18 @@ var SQLiteProjectionSpec = {
591
798
  if (!isErrorConstructor(args[0])) {
592
799
  assertTrue(
593
800
  args[0](error),
594
- `Error didn't match the error condition: ${_optionalChain([error, 'optionalAccess', _18 => _18.toString, 'call', _19 => _19()])}`
801
+ `Error didn't match the error condition: ${_optionalChain([error, 'optionalAccess', _34 => _34.toString, 'call', _35 => _35()])}`
595
802
  );
596
803
  return;
597
804
  }
598
805
  assertTrue(
599
806
  error instanceof args[0],
600
- `Caught error is not an instance of the expected type: ${_optionalChain([error, 'optionalAccess', _20 => _20.toString, 'call', _21 => _21()])}`
807
+ `Caught error is not an instance of the expected type: ${_optionalChain([error, 'optionalAccess', _36 => _36.toString, 'call', _37 => _37()])}`
601
808
  );
602
809
  if (args[1]) {
603
810
  assertTrue(
604
811
  args[1](error),
605
- `Error didn't match the error condition: ${_optionalChain([error, 'optionalAccess', _22 => _22.toString, 'call', _23 => _23()])}`
812
+ `Error didn't match the error condition: ${_optionalChain([error, 'optionalAccess', _38 => _38.toString, 'call', _39 => _39()])}`
606
813
  );
607
814
  }
608
815
  }
@@ -619,7 +826,7 @@ var eventInStream = (streamName, event) => {
619
826
  ...event,
620
827
  metadata: {
621
828
  ..._nullishCoalesce(event.metadata, () => ( {})),
622
- streamName: _nullishCoalesce(_optionalChain([event, 'access', _24 => _24.metadata, 'optionalAccess', _25 => _25.streamName]), () => ( streamName))
829
+ streamName: _nullishCoalesce(_optionalChain([event, 'access', _40 => _40.metadata, 'optionalAccess', _41 => _41.streamName]), () => ( streamName))
623
830
  }
624
831
  };
625
832
  };
@@ -691,7 +898,7 @@ var { identifier, merge } = _dumbo.SQL;
691
898
  var appendToStream = async (connection, streamName, streamType, messages, options) => {
692
899
  if (messages.length === 0) return { success: false };
693
900
  const expectedStreamVersion = toExpectedVersion(
694
- _optionalChain([options, 'optionalAccess', _26 => _26.expectedStreamVersion])
901
+ _optionalChain([options, 'optionalAccess', _42 => _42.expectedStreamVersion])
695
902
  );
696
903
  const messagesToAppend = messages.map(
697
904
  (m, i) => ({
@@ -714,13 +921,13 @@ var appendToStream = async (connection, streamName, streamType, messages, option
714
921
  streamType,
715
922
  downcastRecordedMessages(
716
923
  messagesToAppend,
717
- _optionalChain([options, 'optionalAccess', _27 => _27.schema, 'optionalAccess', _28 => _28.versioning])
924
+ _optionalChain([options, 'optionalAccess', _43 => _43.schema, 'optionalAccess', _44 => _44.versioning])
718
925
  ),
719
926
  {
720
927
  expectedStreamVersion
721
928
  }
722
929
  );
723
- if (_optionalChain([options, 'optionalAccess', _29 => _29.onBeforeCommit]))
930
+ if (_optionalChain([options, 'optionalAccess', _45 => _45.onBeforeCommit]))
724
931
  await options.onBeforeCommit(messagesToAppend, { connection });
725
932
  return { success: true, result };
726
933
  }
@@ -744,7 +951,7 @@ var toExpectedVersion = (expected) => {
744
951
  return expected;
745
952
  };
746
953
  var appendToStreamRaw = async (execute, streamId, streamType, messages, options) => {
747
- let expectedStreamVersion = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _30 => _30.expectedStreamVersion]), () => ( null));
954
+ let expectedStreamVersion = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _46 => _46.expectedStreamVersion]), () => ( null));
748
955
  const currentStreamVersion = await getLastStreamPosition(
749
956
  execute,
750
957
  streamId,
@@ -762,7 +969,7 @@ var appendToStreamRaw = async (execute, streamId, streamType, messages, options)
762
969
  VALUES (
763
970
  ${streamId},
764
971
  ${messages.length},
765
- ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _31 => _31.partition]), () => ( streamsTable.columns.partition))},
972
+ ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _47 => _47.partition]), () => ( streamsTable.columns.partition))},
766
973
  ${streamType},
767
974
  '[]',
768
975
  false
@@ -772,7 +979,7 @@ var appendToStreamRaw = async (execute, streamId, streamType, messages, options)
772
979
  SET stream_position = stream_position + ${messages.length}
773
980
  WHERE stream_id = ${streamId}
774
981
  AND stream_position = ${expectedStreamVersion}
775
- AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _32 => _32.partition]), () => ( streamsTable.columns.partition))}
982
+ AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _48 => _48.partition]), () => ( streamsTable.columns.partition))}
776
983
  AND is_archived = false
777
984
  RETURNING stream_position;
778
985
  `;
@@ -780,12 +987,12 @@ var appendToStreamRaw = async (execute, streamId, streamType, messages, options)
780
987
  messages,
781
988
  expectedStreamVersion,
782
989
  streamId,
783
- _nullishCoalesce(_optionalChain([options, 'optionalAccess', _33 => _33.partition, 'optionalAccess', _34 => _34.toString, 'call', _35 => _35()]), () => ( defaultTag2))
990
+ _nullishCoalesce(_optionalChain([options, 'optionalAccess', _49 => _49.partition, 'optionalAccess', _50 => _50.toString, 'call', _51 => _51()]), () => ( defaultTag2))
784
991
  );
785
992
  const results = await execute.batchCommand([streamSQL, insertSQL], { assertChanges: true });
786
993
  const [streamResult, messagesResult] = results;
787
- const streamPosition = _optionalChain([streamResult, 'optionalAccess', _36 => _36.rows, 'access', _37 => _37[0], 'optionalAccess', _38 => _38.stream_position]);
788
- const globalPosition = _optionalChain([messagesResult, 'optionalAccess', _39 => _39.rows, 'access', _40 => _40.at, 'call', _41 => _41(-1), 'optionalAccess', _42 => _42.global_position]);
994
+ const streamPosition = _optionalChain([streamResult, 'optionalAccess', _52 => _52.rows, 'access', _53 => _53[0], 'optionalAccess', _54 => _54.stream_position]);
995
+ const globalPosition = _optionalChain([messagesResult, 'optionalAccess', _55 => _55.rows, 'access', _56 => _56.at, 'call', _57 => _57(-1), 'optionalAccess', _58 => _58.global_position]);
789
996
  if (!streamPosition)
790
997
  throw new ExpectedVersionConflictError(0n, _nullishCoalesce(expectedStreamVersion, () => ( 0n)));
791
998
  if (!globalPosition) throw new Error("Could not find global position");
@@ -801,7 +1008,7 @@ async function getLastStreamPosition(execute, streamId, expectedStreamVersion) {
801
1008
  _dumbo.SQL`SELECT CAST(stream_position AS VARCHAR) AS stream_position FROM ${identifier(streamsTable.name)} WHERE stream_id = ${streamId}`
802
1009
  )
803
1010
  );
804
- if (_optionalChain([result, 'optionalAccess', _43 => _43.stream_position]) == null) {
1011
+ if (_optionalChain([result, 'optionalAccess', _59 => _59.stream_position]) == null) {
805
1012
  expectedStreamVersion = 0n;
806
1013
  } else {
807
1014
  expectedStreamVersion = BigInt(result.stream_position);
@@ -810,7 +1017,7 @@ async function getLastStreamPosition(execute, streamId, expectedStreamVersion) {
810
1017
  }
811
1018
  var buildMessageInsertQuery = (messages, expectedStreamVersion, streamId, partition) => {
812
1019
  const values = messages.map((message) => {
813
- if (_optionalChain([message, 'access', _44 => _44.metadata, 'optionalAccess', _45 => _45.streamPosition]) == null || typeof message.metadata.streamPosition !== "bigint") {
1020
+ if (_optionalChain([message, 'access', _60 => _60.metadata, 'optionalAccess', _61 => _61.streamPosition]) == null || typeof message.metadata.streamPosition !== "bigint") {
814
1021
  throw new Error("Stream position is required");
815
1022
  }
816
1023
  const streamPosition = BigInt(message.metadata.streamPosition) + BigInt(expectedStreamVersion);
@@ -977,7 +1184,7 @@ var readLastMessageGlobalPosition = async (execute, options) => {
977
1184
  _dumbo.SQL`
978
1185
  SELECT global_position
979
1186
  FROM ${identifier3(messagesTable.name)}
980
- WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _46 => _46.partition]), () => ( defaultTag2))} AND is_archived = FALSE
1187
+ WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _62 => _62.partition]), () => ( defaultTag2))} AND is_archived = FALSE
981
1188
  ORDER BY global_position
982
1189
  LIMIT 1`
983
1190
  )
@@ -991,44 +1198,49 @@ var readLastMessageGlobalPosition = async (execute, options) => {
991
1198
 
992
1199
  var { identifier: identifier4 } = _dumbo.SQL;
993
1200
  var readMessagesBatch = async (execute, options) => {
994
- const from = "from" in options ? options.from : "after" in options ? options.after + 1n : 0n;
995
- const batchSize = options && "batchSize" in options ? options.batchSize : options.to - options.from;
996
- const fromCondition = from !== -0n ? _dumbo.SQL`AND global_position >= ${from}` : "";
1201
+ const from = "from" in options ? options.from : void 0;
1202
+ const after = "after" in options ? options.after : void 0;
1203
+ const batchSize = "batchSize" in options ? options.batchSize : options.to - options.from;
1204
+ const fromCondition = from !== void 0 ? _dumbo.SQL`AND global_position >= ${from}` : after !== void 0 ? _dumbo.SQL`AND global_position > ${after}` : _dumbo.SQL.EMPTY;
997
1205
  const toCondition = "to" in options ? _dumbo.SQL`AND global_position <= ${options.to}` : _dumbo.SQL.EMPTY;
998
1206
  const limitCondition = "batchSize" in options ? _dumbo.SQL`LIMIT ${options.batchSize}` : _dumbo.SQL.EMPTY;
999
- const events = (await execute.query(
1000
- _dumbo.SQL`SELECT stream_id, stream_position, global_position, message_data, message_metadata, message_schema_version, message_type, message_id
1207
+ const messages = await _dumbo.mapRows.call(void 0,
1208
+ execute.query(
1209
+ _dumbo.SQL`SELECT stream_id, stream_position, global_position, message_data, message_metadata, message_schema_version, message_type, message_id
1001
1210
  FROM ${identifier4(messagesTable.name)}
1002
- WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _47 => _47.partition]), () => ( defaultTag2))} AND is_archived = FALSE ${fromCondition} ${toCondition}
1211
+ WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _63 => _63.partition]), () => ( defaultTag2))} AND is_archived = FALSE ${fromCondition} ${toCondition}
1003
1212
  ORDER BY global_position
1004
1213
  ${limitCondition}`
1005
- )).rows.map((row) => {
1006
- const rawEvent = {
1007
- type: row.message_type,
1008
- data: JSONParser.parse(row.message_data),
1009
- metadata: JSONParser.parse(row.message_metadata)
1010
- };
1011
- const metadata = {
1012
- ..."metadata" in rawEvent ? _nullishCoalesce(rawEvent.metadata, () => ( {})) : {},
1013
- messageId: row.message_id,
1014
- streamName: row.stream_id,
1015
- streamPosition: BigInt(row.stream_position),
1016
- globalPosition: BigInt(row.global_position)
1017
- };
1018
- return {
1019
- ...rawEvent,
1020
- kind: "Event",
1021
- metadata
1022
- };
1023
- });
1024
- return events.length > 0 ? {
1025
- currentGlobalPosition: events[events.length - 1].metadata.globalPosition,
1026
- messages: events,
1027
- areEventsLeft: events.length === batchSize
1214
+ ),
1215
+ (row) => {
1216
+ const rawEvent = {
1217
+ type: row.message_type,
1218
+ data: JSONParser.parse(row.message_data),
1219
+ metadata: JSONParser.parse(row.message_metadata)
1220
+ };
1221
+ const metadata = {
1222
+ ..."metadata" in rawEvent ? _nullishCoalesce(rawEvent.metadata, () => ( {})) : {},
1223
+ messageId: row.message_id,
1224
+ streamName: row.stream_id,
1225
+ streamPosition: BigInt(row.stream_position),
1226
+ globalPosition: BigInt(row.global_position),
1227
+ checkpoint: bigIntProcessorCheckpoint(BigInt(row.global_position))
1228
+ };
1229
+ return {
1230
+ ...rawEvent,
1231
+ kind: "Event",
1232
+ metadata
1233
+ };
1234
+ }
1235
+ );
1236
+ return messages.length > 0 ? {
1237
+ currentGlobalPosition: messages[messages.length - 1].metadata.globalPosition,
1238
+ messages,
1239
+ areMessagesLeft: messages.length === batchSize
1028
1240
  } : {
1029
1241
  currentGlobalPosition: "from" in options ? options.from : "after" in options ? options.after : 0n,
1030
1242
  messages: [],
1031
- areEventsLeft: false
1243
+ areMessagesLeft: false
1032
1244
  };
1033
1245
  };
1034
1246
 
@@ -1040,12 +1252,12 @@ var readProcessorCheckpoint = async (execute, options) => {
1040
1252
  execute.query(
1041
1253
  _dumbo.SQL`SELECT last_processed_checkpoint
1042
1254
  FROM ${identifier5(processorsTable.name)}
1043
- WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _48 => _48.partition]), () => ( defaultTag2))} AND processor_id = ${options.processorId}
1255
+ WHERE partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _64 => _64.partition]), () => ( defaultTag2))} AND processor_id = ${options.processorId}
1044
1256
  LIMIT 1`
1045
1257
  )
1046
1258
  );
1047
1259
  return {
1048
- lastProcessedPosition: result !== null ? BigInt(result.last_processed_checkpoint) : null
1260
+ lastProcessedCheckpoint: result !== null ? result.last_processed_checkpoint : null
1049
1261
  };
1050
1262
  };
1051
1263
 
@@ -1059,28 +1271,26 @@ var readProcessorCheckpoint = async (execute, options) => {
1059
1271
  var DefaultSQLiteEventStoreProcessorBatchSize = 100;
1060
1272
  var DefaultSQLiteEventStoreProcessorPullingFrequencyInMs = 50;
1061
1273
  var sqliteEventStoreMessageBatchPuller = ({
1062
- pool,
1274
+ executor,
1063
1275
  batchSize,
1064
1276
  eachBatch,
1065
- pullingFrequencyInMs
1277
+ pullingFrequencyInMs,
1278
+ stopWhen,
1279
+ signal
1066
1280
  }) => {
1067
1281
  let isRunning = false;
1068
1282
  let start;
1069
1283
  const pullMessages = async (options) => {
1070
- const after = options.startFrom === "BEGINNING" ? 0n : options.startFrom === "END" ? await _asyncNullishCoalesce((await pool.withConnection(
1071
- async ({ execute }) => readLastMessageGlobalPosition(execute)
1072
- )).currentGlobalPosition, async () => ( 0n)) : options.startFrom.globalPosition;
1284
+ const after = options.startFrom === "BEGINNING" ? 0n : options.startFrom === "END" ? await _asyncNullishCoalesce((await readLastMessageGlobalPosition(executor)).currentGlobalPosition, async () => ( 0n)) : parseBigIntProcessorCheckpoint(options.startFrom.lastCheckpoint);
1073
1285
  const readMessagesOptions = {
1074
1286
  after,
1075
1287
  batchSize
1076
1288
  };
1077
1289
  let waitTime = 100;
1078
- do {
1079
- const { messages, currentGlobalPosition, areEventsLeft } = await pool.withConnection(
1080
- ({ execute }) => readMessagesBatch(execute, readMessagesOptions)
1081
- );
1290
+ while (isRunning && !_optionalChain([signal, 'optionalAccess', _65 => _65.aborted])) {
1291
+ const { messages, currentGlobalPosition, areMessagesLeft } = await readMessagesBatch(executor, readMessagesOptions);
1082
1292
  if (messages.length > 0) {
1083
- const result = await eachBatch({ messages });
1293
+ const result = await eachBatch(messages);
1084
1294
  if (result && result.type === "STOP") {
1085
1295
  isRunning = false;
1086
1296
  break;
@@ -1088,12 +1298,16 @@ var sqliteEventStoreMessageBatchPuller = ({
1088
1298
  }
1089
1299
  readMessagesOptions.after = currentGlobalPosition;
1090
1300
  await new Promise((resolve) => setTimeout(resolve, waitTime));
1091
- if (!areEventsLeft) {
1301
+ if (_optionalChain([stopWhen, 'optionalAccess', _66 => _66.noMessagesLeft]) === true && !areMessagesLeft) {
1302
+ isRunning = false;
1303
+ break;
1304
+ }
1305
+ if (!areMessagesLeft) {
1092
1306
  waitTime = Math.min(waitTime * 2, 1e3);
1093
1307
  } else {
1094
1308
  waitTime = pullingFrequencyInMs;
1095
1309
  }
1096
- } while (isRunning);
1310
+ }
1097
1311
  };
1098
1312
  return {
1099
1313
  get isRunning() {
@@ -1101,8 +1315,8 @@ var sqliteEventStoreMessageBatchPuller = ({
1101
1315
  },
1102
1316
  start: (options) => {
1103
1317
  if (isRunning) return start;
1318
+ isRunning = true;
1104
1319
  start = (async () => {
1105
- isRunning = true;
1106
1320
  return pullMessages(options);
1107
1321
  })();
1108
1322
  return start;
@@ -1124,96 +1338,115 @@ var zipSQLiteEventStoreMessageBatchPullerStartFrom = (options) => {
1124
1338
  // src/eventStore/consumers/sqliteEventStoreConsumer.ts
1125
1339
 
1126
1340
 
1341
+
1342
+ // src/eventStore/consumers/sqliteCheckpointer.ts
1343
+ var sqliteCheckpointer = () => ({
1344
+ read: async (options, context) => {
1345
+ const result = await readProcessorCheckpoint(context.execute, options);
1346
+ return { lastCheckpoint: _optionalChain([result, 'optionalAccess', _67 => _67.lastProcessedCheckpoint]) };
1347
+ },
1348
+ store: async (options, context) => {
1349
+ const newCheckpoint = getCheckpoint(options.message);
1350
+ const result = await storeProcessorCheckpoint(context.execute, {
1351
+ lastProcessedCheckpoint: options.lastCheckpoint,
1352
+ newCheckpoint,
1353
+ processorId: options.processorId,
1354
+ partition: options.partition,
1355
+ version: options.version
1356
+ });
1357
+ return result.success ? { success: true, newCheckpoint: result.newCheckpoint } : result;
1358
+ }
1359
+ });
1360
+
1127
1361
  // src/eventStore/consumers/sqliteProcessor.ts
1128
- var genericSQLiteProcessor = (options) => {
1129
- const { eachMessage } = options;
1130
- let isActive = true;
1131
- const mapToContext = (context) => {
1132
- const connection = _nullishCoalesce(context.connection, () => ( _optionalChain([options, 'access', _49 => _49.connectionOptions, 'optionalAccess', _50 => _50.connection])));
1362
+ var sqliteProcessingScope = () => {
1363
+ const processingScope = async (handler, partialContext) => {
1364
+ const connection = _optionalChain([partialContext, 'optionalAccess', _68 => _68.connection]);
1133
1365
  if (!connection)
1134
- throw new Error("Connection is required in context or options");
1135
- return { connection };
1136
- };
1137
- return {
1138
- id: options.processorId,
1139
- start: async ({
1140
- execute
1141
- }) => {
1142
- isActive = true;
1143
- if (options.startFrom !== "CURRENT") return options.startFrom;
1144
- const { lastProcessedPosition } = await readProcessorCheckpoint(execute, {
1145
- processorId: options.processorId,
1146
- partition: options.partition
1147
- });
1148
- if (lastProcessedPosition === null) return "BEGINNING";
1149
- return { globalPosition: lastProcessedPosition };
1150
- },
1151
- get isActive() {
1152
- return isActive;
1153
- },
1154
- handle: async ({ messages }, context) => {
1155
- if (!isActive) return;
1156
- const { connection } = mapToContext(context);
1157
- return connection.withTransaction(async (tx) => {
1158
- let result = void 0;
1159
- let lastProcessedPosition = null;
1160
- for (const message of messages) {
1161
- const typedMessage = message;
1162
- const messageProcessingResult = await eachMessage(typedMessage, {
1163
- connection: tx.connection
1164
- });
1165
- const newPosition = getCheckpoint(typedMessage);
1166
- await storeProcessorCheckpoint(tx.execute, {
1167
- processorId: options.processorId,
1168
- version: options.version,
1169
- lastProcessedPosition,
1170
- newPosition,
1171
- partition: options.partition
1172
- });
1173
- lastProcessedPosition = typedMessage.metadata.globalPosition;
1174
- if (messageProcessingResult && messageProcessingResult.type === "STOP") {
1175
- isActive = false;
1176
- result = messageProcessingResult;
1177
- break;
1178
- }
1179
- if (options.stopAfter && options.stopAfter(typedMessage)) {
1180
- isActive = false;
1181
- result = { type: "STOP", reason: "Stop condition reached" };
1182
- break;
1183
- }
1184
- if (messageProcessingResult && messageProcessingResult.type === "SKIP")
1185
- continue;
1186
- }
1187
- return result;
1188
- });
1189
- }
1366
+ throw new EmmettError("Connection is required in context or options");
1367
+ return connection.withTransaction(
1368
+ async (transaction) => {
1369
+ return handler({
1370
+ ...partialContext,
1371
+ connection,
1372
+ execute: transaction.execute
1373
+ });
1374
+ }
1375
+ );
1190
1376
  };
1377
+ return processingScope;
1191
1378
  };
1192
- var sqliteProjectionProcessor = (options) => {
1193
- const projection2 = options.projection;
1194
- return genericSQLiteProcessor({
1195
- processorId: _nullishCoalesce(options.processorId, () => ( `projection:${projection2.name}`)),
1196
- eachMessage: async (event, context) => {
1197
- if (!projection2.canHandle.includes(event.type)) return;
1198
- await projection2.handle([event], { connection: context.connection });
1199
- },
1200
- ...options
1379
+ var sqliteReactor = (options) => {
1380
+ const {
1381
+ processorId = options.processorId,
1382
+ processorInstanceId = getProcessorInstanceId(processorId),
1383
+ version = defaultProcessorVersion,
1384
+ partition = defaultProcessorPartition,
1385
+ hooks
1386
+ } = options;
1387
+ return reactor({
1388
+ ...options,
1389
+ processorId,
1390
+ processorInstanceId,
1391
+ version,
1392
+ partition,
1393
+ hooks,
1394
+ processingScope: sqliteProcessingScope(),
1395
+ checkpoints: sqliteCheckpointer()
1201
1396
  });
1202
1397
  };
1203
- var sqliteProcessor = (options) => {
1204
- if ("projection" in options) {
1205
- return sqliteProjectionProcessor(options);
1206
- }
1207
- return genericSQLiteProcessor(options);
1398
+ var sqliteProjector = (options) => {
1399
+ const {
1400
+ processorId = getProjectorId({
1401
+ projectionName: _nullishCoalesce(options.projection.name, () => ( "unknown"))
1402
+ }),
1403
+ processorInstanceId = getProcessorInstanceId(processorId),
1404
+ version = defaultProcessorVersion,
1405
+ partition = defaultProcessorPartition
1406
+ } = options;
1407
+ const hooks = {
1408
+ ..._nullishCoalesce(options.hooks, () => ( {})),
1409
+ onInit: options.projection.init !== void 0 || _optionalChain([options, 'access', _69 => _69.hooks, 'optionalAccess', _70 => _70.onInit]) ? async (context) => {
1410
+ if (options.projection.init)
1411
+ await options.projection.init({
1412
+ version: _nullishCoalesce(options.projection.version, () => ( version)),
1413
+ status: "active",
1414
+ registrationType: "async",
1415
+ context: {
1416
+ ...context,
1417
+ migrationOptions: options.migrationOptions
1418
+ }
1419
+ });
1420
+ if (_optionalChain([options, 'access', _71 => _71.hooks, 'optionalAccess', _72 => _72.onInit]))
1421
+ await options.hooks.onInit({
1422
+ ...context,
1423
+ migrationOptions: options.migrationOptions
1424
+ });
1425
+ } : _optionalChain([options, 'access', _73 => _73.hooks, 'optionalAccess', _74 => _74.onInit]),
1426
+ onClose: _optionalChain([options, 'access', _75 => _75.hooks, 'optionalAccess', _76 => _76.onClose])
1427
+ };
1428
+ const processor = projector({
1429
+ ...options,
1430
+ processorId,
1431
+ processorInstanceId,
1432
+ version,
1433
+ partition,
1434
+ hooks,
1435
+ processingScope: sqliteProcessingScope(),
1436
+ checkpoints: sqliteCheckpointer()
1437
+ });
1438
+ return processor;
1208
1439
  };
1209
1440
 
1210
1441
  // src/eventStore/consumers/sqliteEventStoreConsumer.ts
1211
1442
  var sqliteEventStoreConsumer = (options) => {
1212
1443
  let isRunning = false;
1444
+ let isInitialized = false;
1213
1445
  const { pulling } = options;
1214
1446
  const processors = _nullishCoalesce(options.processors, () => ( []));
1447
+ let abortController = null;
1215
1448
  let start;
1216
- let currentMessagePuller;
1449
+ let messagePuller;
1217
1450
  const pool = _nullishCoalesce(options.pool, () => ( _dumbo.dumbo.call(void 0, {
1218
1451
  ...options.driver.mapToDumboOptions(options),
1219
1452
  transactionOptions: {
@@ -1229,59 +1462,112 @@ var sqliteEventStoreConsumer = (options) => {
1229
1462
  reason: "No active processors"
1230
1463
  };
1231
1464
  const result = await Promise.allSettled(
1232
- activeProcessors.map((s) => {
1233
- return s.handle(messagesBatch, {
1234
- connection
1465
+ activeProcessors.map(async (s) => {
1466
+ return await s.handle(messagesBatch, {
1467
+ connection,
1468
+ execute: connection.execute
1235
1469
  });
1236
1470
  })
1237
1471
  );
1238
1472
  return result.some(
1239
- (r) => r.status === "fulfilled" && _optionalChain([r, 'access', _51 => _51.value, 'optionalAccess', _52 => _52.type]) !== "STOP"
1473
+ (r) => r.status === "fulfilled" && _optionalChain([r, 'access', _77 => _77.value, 'optionalAccess', _78 => _78.type]) !== "STOP"
1240
1474
  ) ? void 0 : {
1241
1475
  type: "STOP"
1242
1476
  };
1243
1477
  });
1244
- const messagePooler = currentMessagePuller = sqliteEventStoreMessageBatchPuller({
1245
- pool,
1246
- eachBatch,
1247
- batchSize: _nullishCoalesce(_optionalChain([pulling, 'optionalAccess', _53 => _53.batchSize]), () => ( DefaultSQLiteEventStoreProcessorBatchSize)),
1248
- pullingFrequencyInMs: _nullishCoalesce(_optionalChain([pulling, 'optionalAccess', _54 => _54.pullingFrequencyInMs]), () => ( DefaultSQLiteEventStoreProcessorPullingFrequencyInMs))
1249
- });
1478
+ const processorContext = {
1479
+ execute: void 0,
1480
+ connection: void 0
1481
+ };
1482
+ const stopProcessors = () => Promise.all(processors.map((p) => p.close(processorContext)));
1250
1483
  const stop = async () => {
1251
1484
  if (!isRunning) return;
1252
1485
  isRunning = false;
1253
- if (currentMessagePuller) {
1254
- await currentMessagePuller.stop();
1255
- currentMessagePuller = void 0;
1486
+ if (messagePuller) {
1487
+ _optionalChain([abortController, 'optionalAccess', _79 => _79.abort, 'call', _80 => _80()]);
1488
+ await messagePuller.stop();
1489
+ messagePuller = void 0;
1490
+ abortController = null;
1256
1491
  }
1257
1492
  await start;
1493
+ await stopProcessors();
1494
+ };
1495
+ const init = async () => {
1496
+ if (isInitialized) return;
1497
+ const sqliteProcessors = processors;
1498
+ await pool.withConnection(async (connection) => {
1499
+ for (const processor of sqliteProcessors) {
1500
+ if (processor.init) {
1501
+ await processor.init({
1502
+ ...processorContext,
1503
+ connection,
1504
+ execute: connection.execute
1505
+ });
1506
+ }
1507
+ }
1508
+ });
1509
+ isInitialized = true;
1258
1510
  };
1259
1511
  return {
1260
- processors,
1512
+ consumerId: _nullishCoalesce(options.consumerId, () => ( _uuid.v7.call(void 0, ))),
1261
1513
  get isRunning() {
1262
1514
  return isRunning;
1263
1515
  },
1264
- processor: (options2) => {
1265
- const processor = sqliteProcessor(options2);
1266
- processors.push(processor);
1516
+ processors,
1517
+ init,
1518
+ reactor: (options2) => {
1519
+ const processor = sqliteReactor(options2);
1520
+ processors.push(
1521
+ // TODO: change that
1522
+ processor
1523
+ );
1524
+ return processor;
1525
+ },
1526
+ projector: (options2) => {
1527
+ const processor = sqliteProjector(options2);
1528
+ processors.push(
1529
+ // TODO: change that
1530
+ processor
1531
+ );
1267
1532
  return processor;
1268
1533
  },
1269
1534
  start: () => {
1270
1535
  if (isRunning) return start;
1536
+ if (processors.length === 0)
1537
+ throw new EmmettError(
1538
+ "Cannot start consumer without at least a single processor"
1539
+ );
1540
+ isRunning = true;
1541
+ abortController = new AbortController();
1542
+ messagePuller = sqliteEventStoreMessageBatchPuller({
1543
+ stopWhen: options.stopWhen,
1544
+ executor: pool.execute,
1545
+ eachBatch,
1546
+ batchSize: _nullishCoalesce(_optionalChain([pulling, 'optionalAccess', _81 => _81.batchSize]), () => ( DefaultSQLiteEventStoreProcessorBatchSize)),
1547
+ pullingFrequencyInMs: _nullishCoalesce(_optionalChain([pulling, 'optionalAccess', _82 => _82.pullingFrequencyInMs]), () => ( DefaultSQLiteEventStoreProcessorPullingFrequencyInMs)),
1548
+ signal: abortController.signal
1549
+ });
1271
1550
  start = (async () => {
1272
- if (processors.length === 0)
1273
- return Promise.reject(
1274
- new EmmettError(
1275
- "Cannot start consumer without at least a single processor"
1551
+ if (!isRunning) return;
1552
+ if (!isInitialized) {
1553
+ await init();
1554
+ }
1555
+ const startFrom = await pool.withConnection(
1556
+ async (connection) => zipSQLiteEventStoreMessageBatchPullerStartFrom(
1557
+ await Promise.all(
1558
+ processors.map(async (o) => {
1559
+ const result = await o.start({
1560
+ execute: connection.execute,
1561
+ connection
1562
+ });
1563
+ return result;
1564
+ })
1276
1565
  )
1277
- );
1278
- isRunning = true;
1279
- const startFrom = zipSQLiteEventStoreMessageBatchPullerStartFrom(
1280
- await pool.withConnection(
1281
- (connection) => Promise.all(processors.map((o) => o.start(connection)))
1282
1566
  )
1283
1567
  );
1284
- return messagePooler.start({ startFrom });
1568
+ await messagePuller.start({ startFrom });
1569
+ await stopProcessors();
1570
+ isRunning = false;
1285
1571
  })();
1286
1572
  return start;
1287
1573
  },
@@ -1289,7 +1575,6 @@ var sqliteEventStoreConsumer = (options) => {
1289
1575
  close: async () => {
1290
1576
  await stop();
1291
1577
  await pool.close();
1292
- await new Promise((resolve) => setTimeout(resolve, 250));
1293
1578
  }
1294
1579
  };
1295
1580
  };
@@ -1307,13 +1592,13 @@ var getSQLiteEventStore = (options) => {
1307
1592
  })));
1308
1593
  let migrateSchema = void 0;
1309
1594
  const inlineProjections = (_nullishCoalesce(options.projections, () => ( []))).filter(({ type }) => type === "inline").map(({ projection: projection2 }) => projection2);
1310
- const onBeforeCommitHook = _optionalChain([options, 'access', _55 => _55.hooks, 'optionalAccess', _56 => _56.onBeforeCommit]);
1595
+ const onBeforeCommitHook = _optionalChain([options, 'access', _83 => _83.hooks, 'optionalAccess', _84 => _84.onBeforeCommit]);
1311
1596
  const withConnection = async (handler) => pool.withConnection(async (connection) => {
1312
1597
  await ensureSchemaExists(connection);
1313
1598
  return await handler(connection);
1314
1599
  });
1315
1600
  if (options) {
1316
- autoGenerateSchema = _optionalChain([options, 'access', _57 => _57.schema, 'optionalAccess', _58 => _58.autoMigration]) === void 0 || _optionalChain([options, 'access', _59 => _59.schema, 'optionalAccess', _60 => _60.autoMigration]) !== "None";
1601
+ autoGenerateSchema = _optionalChain([options, 'access', _85 => _85.schema, 'optionalAccess', _86 => _86.autoMigration]) === void 0 || _optionalChain([options, 'access', _87 => _87.schema, 'optionalAccess', _88 => _88.autoMigration]) !== "None";
1317
1602
  }
1318
1603
  const migrate = (connection) => {
1319
1604
  if (!migrateSchema) {
@@ -1325,15 +1610,19 @@ var getSQLiteEventStore = (options) => {
1325
1610
  version: _nullishCoalesce(projection2.version, () => ( 1)),
1326
1611
  registrationType: "async",
1327
1612
  status: "active",
1328
- context
1613
+ context: {
1614
+ execute: context.connection.execute,
1615
+ connection: context.connection,
1616
+ driverType: options.driver.driverType
1617
+ }
1329
1618
  });
1330
1619
  }
1331
1620
  }
1332
- if (_optionalChain([options, 'access', _61 => _61.hooks, 'optionalAccess', _62 => _62.onBeforeSchemaCreated])) {
1621
+ if (_optionalChain([options, 'access', _89 => _89.hooks, 'optionalAccess', _90 => _90.onBeforeSchemaCreated])) {
1333
1622
  await options.hooks.onBeforeSchemaCreated(context);
1334
1623
  }
1335
1624
  },
1336
- onAfterSchemaCreated: _optionalChain([options, 'access', _63 => _63.hooks, 'optionalAccess', _64 => _64.onAfterSchemaCreated])
1625
+ onAfterSchemaCreated: _optionalChain([options, 'access', _91 => _91.hooks, 'optionalAccess', _92 => _92.onAfterSchemaCreated])
1337
1626
  });
1338
1627
  }
1339
1628
  return migrateSchema;
@@ -1345,7 +1634,7 @@ var getSQLiteEventStore = (options) => {
1345
1634
  return {
1346
1635
  async aggregateStream(streamName, options2) {
1347
1636
  const { evolve, initialState, read } = options2;
1348
- const expectedStreamVersion = _optionalChain([read, 'optionalAccess', _65 => _65.expectedStreamVersion]);
1637
+ const expectedStreamVersion = _optionalChain([read, 'optionalAccess', _93 => _93.expectedStreamVersion]);
1349
1638
  let state = initialState();
1350
1639
  if (typeof streamName !== "string") {
1351
1640
  throw new Error("Stream name is not string");
@@ -1372,18 +1661,20 @@ var getSQLiteEventStore = (options) => {
1372
1661
  readStream: async (streamName, options2) => withConnection(
1373
1662
  ({ execute }) => readStream(execute, streamName, options2)
1374
1663
  ),
1375
- appendToStream: async (streamName, events, options2) => {
1664
+ appendToStream: async (streamName, events, appendOptions) => {
1376
1665
  const [firstPart, ...rest] = streamName.split("-");
1377
1666
  const streamType = firstPart && rest.length > 0 ? firstPart : unknownTag2;
1378
1667
  const appendResult = await withConnection(
1379
1668
  (connection) => appendToStream(connection, streamName, streamType, events, {
1380
- ...options2,
1669
+ ...appendOptions,
1381
1670
  onBeforeCommit: async (messages, context) => {
1382
1671
  if (inlineProjections.length > 0)
1383
1672
  await handleProjections({
1384
1673
  projections: inlineProjections,
1385
1674
  events: messages,
1386
- ...context
1675
+ execute: context.connection.execute,
1676
+ connection: context.connection,
1677
+ driverType: options.driver.driverType
1387
1678
  });
1388
1679
  if (onBeforeCommitHook) await onBeforeCommitHook(messages, context);
1389
1680
  }
@@ -1393,7 +1684,7 @@ var getSQLiteEventStore = (options) => {
1393
1684
  throw new ExpectedVersionConflictError(
1394
1685
  -1n,
1395
1686
  //TODO: Return actual version in case of error
1396
- _nullishCoalesce(_optionalChain([options2, 'optionalAccess', _66 => _66.expectedStreamVersion]), () => ( NO_CONCURRENCY_CHECK))
1687
+ _nullishCoalesce(_optionalChain([appendOptions, 'optionalAccess', _94 => _94.expectedStreamVersion]), () => ( NO_CONCURRENCY_CHECK))
1397
1688
  );
1398
1689
  return {
1399
1690
  nextExpectedStreamVersion: appendResult.nextStreamPosition,
@@ -1423,15 +1714,15 @@ var getSQLiteEventStore = (options) => {
1423
1714
  // src/eventStore/schema/readStream.ts
1424
1715
  var { identifier: identifier6 } = _dumbo.SQL;
1425
1716
  var readStream = async (execute, streamId, options) => {
1426
- const fromCondition = _optionalChain([options, 'optionalAccess', _67 => _67.from]) ? _dumbo.SQL`AND stream_position >= ${options.from}` : _dumbo.SQL.EMPTY;
1717
+ const fromCondition = _optionalChain([options, 'optionalAccess', _95 => _95.from]) ? _dumbo.SQL`AND stream_position >= ${options.from}` : _dumbo.SQL.EMPTY;
1427
1718
  const to = Number(
1428
- _nullishCoalesce(_optionalChain([options, 'optionalAccess', _68 => _68.to]), () => ( (_optionalChain([options, 'optionalAccess', _69 => _69.maxCount]) ? (_nullishCoalesce(options.from, () => ( 0n))) + options.maxCount : NaN)))
1719
+ _nullishCoalesce(_optionalChain([options, 'optionalAccess', _96 => _96.to]), () => ( (_optionalChain([options, 'optionalAccess', _97 => _97.maxCount]) ? (_nullishCoalesce(options.from, () => ( 0n))) + options.maxCount : NaN)))
1429
1720
  );
1430
1721
  const toCondition = !isNaN(to) ? _dumbo.SQL`AND stream_position <= ${to}` : _dumbo.SQL.EMPTY;
1431
1722
  const { rows: results } = await execute.query(
1432
1723
  _dumbo.SQL`SELECT stream_id, stream_position, global_position, message_data, message_metadata, message_schema_version, message_type, message_id
1433
1724
  FROM ${identifier6(messagesTable.name)}
1434
- WHERE stream_id = ${streamId} AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _70 => _70.partition]), () => ( defaultTag2))} AND is_archived = FALSE ${fromCondition} ${toCondition}
1725
+ WHERE stream_id = ${streamId} AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _98 => _98.partition]), () => ( defaultTag2))} AND is_archived = FALSE ${fromCondition} ${toCondition}
1435
1726
  ORDER BY stream_position ASC`
1436
1727
  );
1437
1728
  const messages = results.map((row) => {
@@ -1445,14 +1736,15 @@ var readStream = async (execute, streamId, options) => {
1445
1736
  messageId: row.message_id,
1446
1737
  streamName: streamId,
1447
1738
  streamPosition: BigInt(row.stream_position),
1448
- globalPosition: BigInt(row.global_position)
1739
+ globalPosition: BigInt(row.global_position),
1740
+ checkpoint: bigIntProcessorCheckpoint(BigInt(row.global_position))
1449
1741
  };
1450
1742
  const event = {
1451
1743
  ...rawEvent,
1452
1744
  kind: "Event",
1453
1745
  metadata
1454
1746
  };
1455
- return upcastRecordedMessage(event, _optionalChain([options, 'optionalAccess', _71 => _71.schema, 'optionalAccess', _72 => _72.versioning]));
1747
+ return upcastRecordedMessage(event, _optionalChain([options, 'optionalAccess', _99 => _99.schema, 'optionalAccess', _100 => _100.versioning]));
1456
1748
  });
1457
1749
  return messages.length > 0 ? {
1458
1750
  currentStreamVersion: messages[messages.length - 1].metadata.streamPosition,
@@ -1497,7 +1789,7 @@ async function storeSubscriptionCheckpointSQLite(execute, processorId, version,
1497
1789
  WHERE processor_id = ${processorId} AND partition = ${partition}`
1498
1790
  )
1499
1791
  );
1500
- const currentPosition = current_position && _optionalChain([current_position, 'optionalAccess', _73 => _73.last_processed_checkpoint]) !== null ? BigInt(current_position.last_processed_checkpoint) : null;
1792
+ const currentPosition = current_position && _optionalChain([current_position, 'optionalAccess', _101 => _101.last_processed_checkpoint]) !== null ? current_position.last_processed_checkpoint : null;
1501
1793
  if (currentPosition === position) {
1502
1794
  return 0;
1503
1795
  } else if (position !== null && currentPosition !== null && currentPosition > position) {
@@ -1525,7 +1817,7 @@ async function storeSubscriptionCheckpointSQLite(execute, processorId, version,
1525
1817
  WHERE processor_id = ${processorId} AND partition = ${partition}`
1526
1818
  )
1527
1819
  );
1528
- const currentPosition = current && _optionalChain([current, 'optionalAccess', _74 => _74.last_processed_checkpoint]) !== null ? BigInt(current.last_processed_checkpoint) : null;
1820
+ const currentPosition = current && _optionalChain([current, 'optionalAccess', _102 => _102.last_processed_checkpoint]) !== null ? BigInt(current.last_processed_checkpoint) : null;
1529
1821
  if (currentPosition === position) {
1530
1822
  return 0;
1531
1823
  } else {
@@ -1540,11 +1832,11 @@ async function storeProcessorCheckpoint(execute, options) {
1540
1832
  execute,
1541
1833
  options.processorId,
1542
1834
  _nullishCoalesce(options.version, () => ( 1)),
1543
- options.newPosition,
1544
- options.lastProcessedPosition,
1835
+ options.newCheckpoint,
1836
+ options.lastProcessedCheckpoint,
1545
1837
  _nullishCoalesce(options.partition, () => ( defaultTag2))
1546
1838
  );
1547
- return result === 1 ? { success: true, newPosition: options.newPosition } : { success: false, reason: result === 0 ? "IGNORED" : "MISMATCH" };
1839
+ return result === 1 ? { success: true, newCheckpoint: options.newCheckpoint } : { success: false, reason: result === 0 ? "IGNORED" : "MISMATCH" };
1548
1840
  } catch (error) {
1549
1841
  console.log(error);
1550
1842
  throw error;
@@ -1558,7 +1850,7 @@ var streamExists = (execute, streamId, options) => _dumbo.exists.call(void 0,
1558
1850
  _dumbo.SQL`SELECT EXISTS (
1559
1851
  SELECT 1
1560
1852
  from ${_dumbo.SQL.identifier(streamsTable.name)}
1561
- WHERE stream_id = ${streamId} AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _75 => _75.partition]), () => ( defaultTag2))} AND is_archived = FALSE) as exists
1853
+ WHERE stream_id = ${streamId} AND partition = ${_nullishCoalesce(_optionalChain([options, 'optionalAccess', _103 => _103.partition]), () => ( defaultTag2))} AND is_archived = FALSE) as exists
1562
1854
  `
1563
1855
  )
1564
1856
  );
@@ -1624,13 +1916,13 @@ var schemaSQL = [
1624
1916
  var createEventStoreSchema = async (pool, hooks) => {
1625
1917
  await pool.withTransaction(async (tx) => {
1626
1918
  await migration_0_42_0_FromSubscriptionsToProcessors(tx.execute);
1627
- if (_optionalChain([hooks, 'optionalAccess', _76 => _76.onBeforeSchemaCreated])) {
1919
+ if (_optionalChain([hooks, 'optionalAccess', _104 => _104.onBeforeSchemaCreated])) {
1628
1920
  await hooks.onBeforeSchemaCreated({
1629
1921
  connection: tx.connection
1630
1922
  });
1631
1923
  }
1632
1924
  await tx.execute.batchCommand(schemaSQL);
1633
- if (_optionalChain([hooks, 'optionalAccess', _77 => _77.onAfterSchemaCreated])) {
1925
+ if (_optionalChain([hooks, 'optionalAccess', _105 => _105.onAfterSchemaCreated])) {
1634
1926
  await hooks.onAfterSchemaCreated();
1635
1927
  }
1636
1928
  });