@event-driven-io/emmett-sqlite 0.40.1 → 0.41.0-alpha.2

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
@@ -527,27 +527,82 @@ var handleProjections = async (options) => {
527
527
  }
528
528
  };
529
529
  var sqliteProjection = (definition) => projection(definition);
530
- var sqliteRawBatchSQLProjection = (handle, ...canHandle) => sqliteProjection({
531
- canHandle,
530
+ var sqliteRawBatchSQLProjection = (options) => sqliteProjection({
531
+ canHandle: options.canHandle,
532
532
  handle: async (events, context) => {
533
- const sqls = await handle(events, context);
533
+ const sqls = await options.evolve(events, context);
534
534
  for (const sql2 of sqls) await context.connection.command(sql2);
535
+ },
536
+ init: async (context) => {
537
+ if (options.init) {
538
+ await options.init(context);
539
+ }
540
+ if (options.initSQL) {
541
+ await context.connection.command(options.initSQL);
542
+ }
535
543
  }
536
544
  });
537
- var sqliteRawSQLProjection = (handle, ...canHandle) => sqliteRawBatchSQLProjection(
538
- async (events, context) => {
539
- const sqls = [];
540
- for (const event of events) {
541
- sqls.push(await handle(event, context));
545
+ var sqliteRawSQLProjection = (options) => {
546
+ const { evolve, ...rest } = options;
547
+ return sqliteRawBatchSQLProjection({
548
+ ...rest,
549
+ evolve: async (events, context) => {
550
+ const sqls = [];
551
+ for (const event of events) {
552
+ const pendingSqls = await evolve(event, context);
553
+ if (Array.isArray(pendingSqls)) {
554
+ sqls.push(...pendingSqls);
555
+ } else {
556
+ sqls.push(pendingSqls);
557
+ }
558
+ }
559
+ return sqls;
542
560
  }
543
- return sqls;
544
- },
545
- ...canHandle
546
- );
561
+ });
562
+ };
547
563
 
548
564
  // src/eventStore/projections/sqliteProjectionSpec.ts
549
565
 
550
566
 
567
+ // src/connection/sqliteConnectionPool.ts
568
+ var SQLiteConnectionPool = (options) => {
569
+ const fileName = _nullishCoalesce(options.fileName, () => ( InMemorySQLiteDatabase));
570
+ const isInMemory = fileName === InMemorySQLiteDatabase || fileName === InMemorySharedCacheSQLiteDatabase;
571
+ const singletonConnection = _nullishCoalesce(_optionalChain([options, 'access', _14 => _14.connectionOptions, 'optionalAccess', _15 => _15.connection]), () => ( (isInMemory ? sqliteConnection({
572
+ fileName
573
+ }) : null)));
574
+ const isAmbientConnection = _optionalChain([options, 'access', _16 => _16.connectionOptions, 'optionalAccess', _17 => _17.singleton]) === true && _optionalChain([options, 'access', _18 => _18.connectionOptions, 'optionalAccess', _19 => _19.connection]) !== void 0;
575
+ const createConnection = () => {
576
+ return _nullishCoalesce(singletonConnection, () => ( sqliteConnection({
577
+ fileName
578
+ })));
579
+ };
580
+ const closeConnection = (connection) => {
581
+ if (isInMemory || isAmbientConnection) {
582
+ return;
583
+ }
584
+ connection.close();
585
+ };
586
+ const withConnection = async (handler) => {
587
+ const connection = _nullishCoalesce(singletonConnection, () => ( createConnection()));
588
+ try {
589
+ return await handler(connection);
590
+ } finally {
591
+ closeConnection(connection);
592
+ }
593
+ };
594
+ return {
595
+ connection: () => Promise.resolve(createConnection()),
596
+ withConnection,
597
+ close: () => {
598
+ if (singletonConnection && !isAmbientConnection) {
599
+ closeConnection(singletonConnection);
600
+ }
601
+ return Promise.resolve();
602
+ }
603
+ };
604
+ };
605
+
551
606
  // src/eventStore/schema/typing.ts
552
607
  var emmettPrefix = "emt";
553
608
  var globalTag = "global";
@@ -627,9 +682,17 @@ var schemaSQL = [
627
682
  messagesTableSQL,
628
683
  subscriptionsTableSQL
629
684
  ];
630
- var createEventStoreSchema = async (db) => {
631
- for (const sql2 of schemaSQL) {
632
- await db.command(sql2);
685
+ var createEventStoreSchema = async (connection, hooks) => {
686
+ await connection.withTransaction(async () => {
687
+ if (_optionalChain([hooks, 'optionalAccess', _20 => _20.onBeforeSchemaCreated])) {
688
+ await hooks.onBeforeSchemaCreated({ connection });
689
+ }
690
+ for (const sql2 of schemaSQL) {
691
+ await connection.command(sql2);
692
+ }
693
+ });
694
+ if (_optionalChain([hooks, 'optionalAccess', _21 => _21.onAfterSchemaCreated])) {
695
+ await hooks.onAfterSchemaCreated();
633
696
  }
634
697
  };
635
698
 
@@ -651,7 +714,7 @@ var readLastMessageGlobalPosition = async (db, options) => {
651
714
  ORDER BY global_position
652
715
  LIMIT 1`
653
716
  ),
654
- [_nullishCoalesce(_optionalChain([options, 'optionalAccess', _14 => _14.partition]), () => ( defaultTag))]
717
+ [_nullishCoalesce(_optionalChain([options, 'optionalAccess', _22 => _22.partition]), () => ( defaultTag))]
655
718
  )
656
719
  );
657
720
  return {
@@ -674,7 +737,7 @@ var readMessagesBatch = async (db, options) => {
674
737
  ORDER BY global_position
675
738
  ${limitCondition}`
676
739
  ),
677
- [_nullishCoalesce(_optionalChain([options, 'optionalAccess', _15 => _15.partition]), () => ( defaultTag))]
740
+ [_nullishCoalesce(_optionalChain([options, 'optionalAccess', _23 => _23.partition]), () => ( defaultTag))]
678
741
  )).map((row) => {
679
742
  const rawEvent = {
680
743
  type: row.message_type,
@@ -709,7 +772,7 @@ var readMessagesBatch = async (db, options) => {
709
772
  var DefaultSQLiteEventStoreProcessorBatchSize = 100;
710
773
  var DefaultSQLiteEventStoreProcessorPullingFrequencyInMs = 50;
711
774
  var sqliteEventStoreMessageBatchPuller = ({
712
- connection,
775
+ pool,
713
776
  batchSize,
714
777
  eachBatch,
715
778
  pullingFrequencyInMs
@@ -717,14 +780,18 @@ var sqliteEventStoreMessageBatchPuller = ({
717
780
  let isRunning = false;
718
781
  let start;
719
782
  const pullMessages = async (options) => {
720
- const after = options.startFrom === "BEGINNING" ? 0n : options.startFrom === "END" ? await _asyncNullishCoalesce((await readLastMessageGlobalPosition(connection)).currentGlobalPosition, async () => ( 0n)) : options.startFrom.globalPosition;
783
+ const after = options.startFrom === "BEGINNING" ? 0n : options.startFrom === "END" ? await _asyncNullishCoalesce((await pool.withConnection(
784
+ async (connection) => readLastMessageGlobalPosition(connection)
785
+ )).currentGlobalPosition, async () => ( 0n)) : options.startFrom.globalPosition;
721
786
  const readMessagesOptions = {
722
787
  after,
723
788
  batchSize
724
789
  };
725
790
  let waitTime = 100;
726
791
  do {
727
- const { messages, currentGlobalPosition, areEventsLeft } = await readMessagesBatch(connection, readMessagesOptions);
792
+ const { messages, currentGlobalPosition, areEventsLeft } = await pool.withConnection(
793
+ (connection) => readMessagesBatch(connection, readMessagesOptions)
794
+ );
728
795
  if (messages.length > 0) {
729
796
  const result = await eachBatch({ messages });
730
797
  if (result && result.type === "STOP") {
@@ -772,7 +839,7 @@ var zipSQLiteEventStoreMessageBatchPullerStartFrom = (options) => {
772
839
  var appendToStream = async (connection, streamName, streamType, messages, options) => {
773
840
  if (messages.length === 0) return { success: false };
774
841
  const expectedStreamVersion = toExpectedVersion(
775
- _optionalChain([options, 'optionalAccess', _16 => _16.expectedStreamVersion])
842
+ _optionalChain([options, 'optionalAccess', _24 => _24.expectedStreamVersion])
776
843
  );
777
844
  const messagesToAppend = messages.map(
778
845
  (m, i) => ({
@@ -797,7 +864,7 @@ var appendToStream = async (connection, streamName, streamType, messages, option
797
864
  expectedStreamVersion
798
865
  }
799
866
  );
800
- if (_optionalChain([options, 'optionalAccess', _17 => _17.onBeforeCommit]))
867
+ if (_optionalChain([options, 'optionalAccess', _25 => _25.onBeforeCommit]))
801
868
  await options.onBeforeCommit(messagesToAppend, { connection });
802
869
  return result;
803
870
  });
@@ -813,7 +880,7 @@ var appendToStreamRaw = async (connection, streamId, streamType, messages, optio
813
880
  let streamPosition;
814
881
  let globalPosition;
815
882
  try {
816
- let expectedStreamVersion = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _18 => _18.expectedStreamVersion]), () => ( null));
883
+ let expectedStreamVersion = _nullishCoalesce(_optionalChain([options, 'optionalAccess', _26 => _26.expectedStreamVersion]), () => ( null));
817
884
  if (expectedStreamVersion == null) {
818
885
  expectedStreamVersion = await getLastStreamPosition(
819
886
  connection,
@@ -839,7 +906,7 @@ var appendToStreamRaw = async (connection, streamId, streamType, messages, optio
839
906
  [
840
907
  streamId,
841
908
  messages.length,
842
- _nullishCoalesce(_optionalChain([options, 'optionalAccess', _19 => _19.partition]), () => ( streamsTable.columns.partition)),
909
+ _nullishCoalesce(_optionalChain([options, 'optionalAccess', _27 => _27.partition]), () => ( streamsTable.columns.partition)),
843
910
  streamType
844
911
  ]
845
912
  );
@@ -855,7 +922,7 @@ var appendToStreamRaw = async (connection, streamId, streamType, messages, optio
855
922
  [
856
923
  messages.length,
857
924
  streamId,
858
- _nullishCoalesce(_optionalChain([options, 'optionalAccess', _20 => _20.partition]), () => ( streamsTable.columns.partition))
925
+ _nullishCoalesce(_optionalChain([options, 'optionalAccess', _28 => _28.partition]), () => ( streamsTable.columns.partition))
859
926
  ]
860
927
  );
861
928
  }
@@ -875,10 +942,10 @@ var appendToStreamRaw = async (connection, streamId, streamType, messages, optio
875
942
  messages,
876
943
  expectedStreamVersion,
877
944
  streamId,
878
- _nullishCoalesce(_optionalChain([options, 'optionalAccess', _21 => _21.partition, 'optionalAccess', _22 => _22.toString, 'call', _23 => _23()]), () => ( defaultTag))
945
+ _nullishCoalesce(_optionalChain([options, 'optionalAccess', _29 => _29.partition, 'optionalAccess', _30 => _30.toString, 'call', _31 => _31()]), () => ( defaultTag))
879
946
  );
880
947
  const returningIds = await connection.query(sqlString, values);
881
- if (returningIds.length === 0 || !_optionalChain([returningIds, 'access', _24 => _24[returningIds.length - 1], 'optionalAccess', _25 => _25.global_position])) {
948
+ if (returningIds.length === 0 || !_optionalChain([returningIds, 'access', _32 => _32[returningIds.length - 1], 'optionalAccess', _33 => _33.global_position])) {
882
949
  throw new Error("Could not find global position");
883
950
  }
884
951
  globalPosition = BigInt(
@@ -899,14 +966,14 @@ var appendToStreamRaw = async (connection, streamId, streamType, messages, optio
899
966
  };
900
967
  };
901
968
  var isOptimisticConcurrencyError = (error) => {
902
- return _optionalChain([error, 'optionalAccess', _26 => _26.errno]) !== void 0 && error.errno === 19;
969
+ return _optionalChain([error, 'optionalAccess', _34 => _34.errno]) !== void 0 && error.errno === 19;
903
970
  };
904
971
  async function getLastStreamPosition(connection, streamId, expectedStreamVersion) {
905
972
  const result = await connection.querySingle(
906
973
  `SELECT CAST(stream_position AS VARCHAR) AS stream_position FROM ${streamsTable.name} WHERE stream_id = ?`,
907
974
  [streamId]
908
975
  );
909
- if (_optionalChain([result, 'optionalAccess', _27 => _27.stream_position]) == null) {
976
+ if (_optionalChain([result, 'optionalAccess', _35 => _35.stream_position]) == null) {
910
977
  expectedStreamVersion = 0n;
911
978
  } else {
912
979
  expectedStreamVersion = BigInt(result.stream_position);
@@ -916,7 +983,7 @@ async function getLastStreamPosition(connection, streamId, expectedStreamVersion
916
983
  var buildMessageInsertQuery = (messages, expectedStreamVersion, streamId, partition) => {
917
984
  const query = messages.reduce(
918
985
  (queryBuilder, message) => {
919
- if (_optionalChain([message, 'access', _28 => _28.metadata, 'optionalAccess', _29 => _29.streamPosition]) == null || typeof message.metadata.streamPosition !== "bigint") {
986
+ if (_optionalChain([message, 'access', _36 => _36.metadata, 'optionalAccess', _37 => _37.streamPosition]) == null || typeof message.metadata.streamPosition !== "bigint") {
920
987
  throw new Error("Stream position is required");
921
988
  }
922
989
  const streamPosition = BigInt(message.metadata.streamPosition) + BigInt(expectedStreamVersion);
@@ -928,7 +995,7 @@ var buildMessageInsertQuery = (messages, expectedStreamVersion, streamId, partit
928
995
  message.kind === "Event" ? "E" : "C",
929
996
  JSONParser.stringify(message.data),
930
997
  JSONParser.stringify(message.metadata),
931
- _nullishCoalesce(_optionalChain([expectedStreamVersion, 'optionalAccess', _30 => _30.toString, 'call', _31 => _31()]), () => ( 0)),
998
+ _nullishCoalesce(_optionalChain([expectedStreamVersion, 'optionalAccess', _38 => _38.toString, 'call', _39 => _39()]), () => ( 0)),
932
999
  message.type,
933
1000
  message.metadata.messageId,
934
1001
  false
@@ -970,7 +1037,7 @@ var readProcessorCheckpoint = async (db, options) => {
970
1037
  WHERE partition = ? AND subscription_id = ?
971
1038
  LIMIT 1`
972
1039
  ),
973
- [_nullishCoalesce(_optionalChain([options, 'optionalAccess', _32 => _32.partition]), () => ( defaultTag)), options.processorId]
1040
+ [_nullishCoalesce(_optionalChain([options, 'optionalAccess', _40 => _40.partition]), () => ( defaultTag)), options.processorId]
974
1041
  )
975
1042
  );
976
1043
  return {
@@ -990,7 +1057,7 @@ var readStream = async (db, streamId, options) => {
990
1057
  FROM ${messagesTable.name}
991
1058
  WHERE stream_id = ? AND partition = ? AND is_archived = FALSE ${fromCondition} ${toCondition}
992
1059
  ORDER BY stream_position ASC`,
993
- [streamId, _nullishCoalesce(_optionalChain([options, 'optionalAccess', _33 => _33.partition]), () => ( defaultTag))]
1060
+ [streamId, _nullishCoalesce(_optionalChain([options, 'optionalAccess', _41 => _41.partition]), () => ( defaultTag))]
994
1061
  );
995
1062
  const messages = results.map((row) => {
996
1063
  const rawEvent = {
@@ -1047,9 +1114,9 @@ async function storeSubscriptionCheckpointSQLite(db, processorId, version, posit
1047
1114
  [processorId, partition]
1048
1115
  )
1049
1116
  );
1050
- if (_optionalChain([current_position, 'optionalAccess', _34 => _34.last_processed_position]) === position) {
1117
+ if (_optionalChain([current_position, 'optionalAccess', _42 => _42.last_processed_position]) === position) {
1051
1118
  return 0;
1052
- } else if (position !== null && current_position !== null && _optionalChain([current_position, 'optionalAccess', _35 => _35.last_processed_position]) > position) {
1119
+ } else if (position !== null && current_position !== null && _optionalChain([current_position, 'optionalAccess', _43 => _43.last_processed_position]) > position) {
1053
1120
  return 2;
1054
1121
  } else {
1055
1122
  return 2;
@@ -1076,7 +1143,7 @@ async function storeSubscriptionCheckpointSQLite(db, processorId, version, posit
1076
1143
  [processorId, partition]
1077
1144
  )
1078
1145
  );
1079
- if (_optionalChain([current, 'optionalAccess', _36 => _36.last_processed_position]) === position) {
1146
+ if (_optionalChain([current, 'optionalAccess', _44 => _44.last_processed_position]) === position) {
1080
1147
  return 0;
1081
1148
  } else {
1082
1149
  return 2;
@@ -1106,12 +1173,12 @@ var genericSQLiteProcessor = (options) => {
1106
1173
  const { eachMessage } = options;
1107
1174
  let isActive = true;
1108
1175
  const getDb = (context) => {
1109
- const fileName = _nullishCoalesce(context.fileName, () => ( _optionalChain([options, 'access', _37 => _37.connectionOptions, 'optionalAccess', _38 => _38.fileName])));
1176
+ const fileName = _nullishCoalesce(context.fileName, () => ( _optionalChain([options, 'access', _45 => _45.connectionOptions, 'optionalAccess', _46 => _46.fileName])));
1110
1177
  if (!fileName)
1111
1178
  throw new EmmettError(
1112
1179
  `SQLite processor '${options.processorId}' is missing file name. Ensure that you passed it through options`
1113
1180
  );
1114
- const connection = _nullishCoalesce(_nullishCoalesce(context.connection, () => ( _optionalChain([options, 'access', _39 => _39.connectionOptions, 'optionalAccess', _40 => _40.connection]))), () => ( sqliteConnection({ fileName })));
1181
+ const connection = _nullishCoalesce(_nullishCoalesce(context.connection, () => ( _optionalChain([options, 'access', _47 => _47.connectionOptions, 'optionalAccess', _48 => _48.connection]))), () => ( sqliteConnection({ fileName })));
1115
1182
  return { connection, fileName };
1116
1183
  };
1117
1184
  return {
@@ -1196,8 +1263,8 @@ var sqliteEventStoreConsumer = (options) => {
1196
1263
  const processors = _nullishCoalesce(options.processors, () => ( []));
1197
1264
  let start;
1198
1265
  let currentMessagePuller;
1199
- const connection = _nullishCoalesce(options.connection, () => ( sqliteConnection({ fileName: options.fileName })));
1200
- const eachBatch = async (messagesBatch) => {
1266
+ const pool = _nullishCoalesce(options.pool, () => ( SQLiteConnectionPool(options)));
1267
+ const eachBatch = (messagesBatch) => pool.withConnection(async (connection) => {
1201
1268
  const activeProcessors = processors.filter((s) => s.isActive);
1202
1269
  if (activeProcessors.length === 0)
1203
1270
  return {
@@ -1213,16 +1280,16 @@ var sqliteEventStoreConsumer = (options) => {
1213
1280
  })
1214
1281
  );
1215
1282
  return result.some(
1216
- (r) => r.status === "fulfilled" && _optionalChain([r, 'access', _41 => _41.value, 'optionalAccess', _42 => _42.type]) !== "STOP"
1283
+ (r) => r.status === "fulfilled" && _optionalChain([r, 'access', _49 => _49.value, 'optionalAccess', _50 => _50.type]) !== "STOP"
1217
1284
  ) ? void 0 : {
1218
1285
  type: "STOP"
1219
1286
  };
1220
- };
1287
+ });
1221
1288
  const messagePooler = currentMessagePuller = sqliteEventStoreMessageBatchPuller({
1222
- connection,
1289
+ pool,
1223
1290
  eachBatch,
1224
- batchSize: _nullishCoalesce(_optionalChain([pulling, 'optionalAccess', _43 => _43.batchSize]), () => ( DefaultSQLiteEventStoreProcessorBatchSize)),
1225
- pullingFrequencyInMs: _nullishCoalesce(_optionalChain([pulling, 'optionalAccess', _44 => _44.pullingFrequencyInMs]), () => ( DefaultSQLiteEventStoreProcessorPullingFrequencyInMs))
1291
+ batchSize: _nullishCoalesce(_optionalChain([pulling, 'optionalAccess', _51 => _51.batchSize]), () => ( DefaultSQLiteEventStoreProcessorBatchSize)),
1292
+ pullingFrequencyInMs: _nullishCoalesce(_optionalChain([pulling, 'optionalAccess', _52 => _52.pullingFrequencyInMs]), () => ( DefaultSQLiteEventStoreProcessorPullingFrequencyInMs))
1226
1293
  });
1227
1294
  const stop = async () => {
1228
1295
  if (!isRunning) return;
@@ -1254,7 +1321,9 @@ var sqliteEventStoreConsumer = (options) => {
1254
1321
  );
1255
1322
  isRunning = true;
1256
1323
  const startFrom = zipSQLiteEventStoreMessageBatchPullerStartFrom(
1257
- await Promise.all(processors.map((o) => o.start(connection)))
1324
+ await pool.withConnection(
1325
+ (connection) => Promise.all(processors.map((o) => o.start(connection)))
1326
+ )
1258
1327
  );
1259
1328
  return messagePooler.start({ startFrom });
1260
1329
  })();
@@ -1263,7 +1332,7 @@ var sqliteEventStoreConsumer = (options) => {
1263
1332
  stop,
1264
1333
  close: async () => {
1265
1334
  await stop();
1266
- connection.close();
1335
+ await pool.close();
1267
1336
  await new Promise((resolve) => setTimeout(resolve, 250));
1268
1337
  }
1269
1338
  };
@@ -1272,63 +1341,49 @@ var sqliteEventStoreConsumer = (options) => {
1272
1341
  // src/eventStore/SQLiteEventStore.ts
1273
1342
  var SQLiteEventStoreDefaultStreamVersion = 0n;
1274
1343
  var getSQLiteEventStore = (options) => {
1275
- let schemaMigrated = false;
1276
1344
  let autoGenerateSchema = false;
1277
- let database;
1278
1345
  const fileName = _nullishCoalesce(options.fileName, () => ( InMemorySQLiteDatabase));
1279
- const isInMemory = fileName === InMemorySQLiteDatabase || fileName === InMemorySharedCacheSQLiteDatabase;
1346
+ const pool = _nullishCoalesce(options.pool, () => ( SQLiteConnectionPool(options)));
1347
+ let migrateSchema = void 0;
1280
1348
  const inlineProjections = (_nullishCoalesce(options.projections, () => ( []))).filter(({ type }) => type === "inline").map(({ projection: projection2 }) => projection2);
1281
- const onBeforeCommitHook = _optionalChain([options, 'access', _45 => _45.hooks, 'optionalAccess', _46 => _46.onBeforeCommit]);
1282
- const createConnection = () => {
1283
- if (database != null) {
1284
- return database;
1285
- }
1286
- return sqliteConnection({
1287
- fileName
1288
- });
1289
- };
1290
- const closeConnection = () => {
1291
- if (isInMemory) {
1292
- return;
1293
- }
1294
- if (database != null) {
1295
- database.close();
1296
- database = null;
1297
- }
1298
- };
1299
- const withConnection = async (handler) => {
1300
- if (database == null) {
1301
- database = createConnection();
1302
- }
1303
- try {
1304
- await ensureSchemaExists(database);
1305
- return await handler(database);
1306
- } finally {
1307
- closeConnection();
1308
- }
1309
- };
1349
+ const onBeforeCommitHook = _optionalChain([options, 'access', _53 => _53.hooks, 'optionalAccess', _54 => _54.onBeforeCommit]);
1350
+ const withConnection = async (handler) => pool.withConnection(async (database) => {
1351
+ await ensureSchemaExists(database);
1352
+ return await handler(database);
1353
+ });
1310
1354
  if (options) {
1311
- autoGenerateSchema = _optionalChain([options, 'access', _47 => _47.schema, 'optionalAccess', _48 => _48.autoMigration]) === void 0 || _optionalChain([options, 'access', _49 => _49.schema, 'optionalAccess', _50 => _50.autoMigration]) !== "None";
1355
+ autoGenerateSchema = _optionalChain([options, 'access', _55 => _55.schema, 'optionalAccess', _56 => _56.autoMigration]) === void 0 || _optionalChain([options, 'access', _57 => _57.schema, 'optionalAccess', _58 => _58.autoMigration]) !== "None";
1312
1356
  }
1313
- const ensureSchemaExists = async (connection) => {
1314
- if (!autoGenerateSchema) return Promise.resolve();
1315
- if (!schemaMigrated) {
1316
- await createEventStoreSchema(connection);
1317
- schemaMigrated = true;
1357
+ const migrate = (connection) => {
1358
+ if (!migrateSchema) {
1359
+ migrateSchema = createEventStoreSchema(connection, {
1360
+ onBeforeSchemaCreated: async (context) => {
1361
+ for (const projection2 of inlineProjections) {
1362
+ if (projection2.init) {
1363
+ await projection2.init(context);
1364
+ }
1365
+ }
1366
+ if (_optionalChain([options, 'access', _59 => _59.hooks, 'optionalAccess', _60 => _60.onBeforeSchemaCreated])) {
1367
+ await options.hooks.onBeforeSchemaCreated(context);
1368
+ }
1369
+ },
1370
+ onAfterSchemaCreated: _optionalChain([options, 'access', _61 => _61.hooks, 'optionalAccess', _62 => _62.onAfterSchemaCreated])
1371
+ });
1318
1372
  }
1319
- return Promise.resolve();
1373
+ return migrateSchema;
1374
+ };
1375
+ const ensureSchemaExists = (connection) => {
1376
+ if (!autoGenerateSchema) return Promise.resolve();
1377
+ return migrate(connection);
1320
1378
  };
1321
1379
  return {
1322
1380
  async aggregateStream(streamName, options2) {
1323
1381
  const { evolve, initialState, read } = options2;
1324
- const expectedStreamVersion = _optionalChain([read, 'optionalAccess', _51 => _51.expectedStreamVersion]);
1382
+ const expectedStreamVersion = _optionalChain([read, 'optionalAccess', _63 => _63.expectedStreamVersion]);
1325
1383
  let state = initialState();
1326
1384
  if (typeof streamName !== "string") {
1327
1385
  throw new Error("Stream name is not string");
1328
1386
  }
1329
- if (database == null) {
1330
- database = createConnection();
1331
- }
1332
1387
  const result = await withConnection(
1333
1388
  (connection) => readStream(connection, streamName, options2.read)
1334
1389
  );
@@ -1352,9 +1407,6 @@ var getSQLiteEventStore = (options) => {
1352
1407
  (connection) => readStream(connection, streamName, options2)
1353
1408
  ),
1354
1409
  appendToStream: async (streamName, events, options2) => {
1355
- if (database == null) {
1356
- database = createConnection();
1357
- }
1358
1410
  const [firstPart, ...rest] = streamName.split("-");
1359
1411
  const streamType = firstPart && rest.length > 0 ? firstPart : "emt:unknown";
1360
1412
  const appendResult = await withConnection(
@@ -1375,7 +1427,7 @@ var getSQLiteEventStore = (options) => {
1375
1427
  throw new ExpectedVersionConflictError(
1376
1428
  -1n,
1377
1429
  //TODO: Return actual version in case of error
1378
- _nullishCoalesce(_optionalChain([options2, 'optionalAccess', _52 => _52.expectedStreamVersion]), () => ( NO_CONCURRENCY_CHECK))
1430
+ _nullishCoalesce(_optionalChain([options2, 'optionalAccess', _64 => _64.expectedStreamVersion]), () => ( NO_CONCURRENCY_CHECK))
1379
1431
  );
1380
1432
  return {
1381
1433
  nextExpectedStreamVersion: appendResult.nextStreamPosition,
@@ -1386,8 +1438,13 @@ var getSQLiteEventStore = (options) => {
1386
1438
  consumer: (options2) => sqliteEventStoreConsumer({
1387
1439
  ..._nullishCoalesce(options2, () => ( {})),
1388
1440
  fileName,
1389
- connection: _nullishCoalesce(database, () => ( void 0))
1390
- })
1441
+ pool
1442
+ }),
1443
+ schema: {
1444
+ sql: () => schemaSQL.join(""),
1445
+ print: () => console.log(schemaSQL.join("")),
1446
+ migrate: () => pool.withConnection(migrate)
1447
+ }
1391
1448
  };
1392
1449
  };
1393
1450
 
@@ -1395,15 +1452,18 @@ var getSQLiteEventStore = (options) => {
1395
1452
  var SQLiteProjectionSpec = {
1396
1453
  for: (options) => {
1397
1454
  {
1398
- const connection = options.connection;
1455
+ const connection = _nullishCoalesce(options.connection, () => ( sqliteConnection({
1456
+ fileName: _nullishCoalesce(options.fileName, () => ( InMemorySQLiteDatabase))
1457
+ })));
1399
1458
  const projection2 = options.projection;
1459
+ let wasInitialized = false;
1400
1460
  return (givenEvents) => {
1401
1461
  return {
1402
1462
  when: (events, options2) => {
1403
1463
  const allEvents = [];
1404
1464
  const run = async (connection2) => {
1405
1465
  let globalPosition = 0n;
1406
- const numberOfTimes = _nullishCoalesce(_optionalChain([options2, 'optionalAccess', _53 => _53.numberOfTimes]), () => ( 1));
1466
+ const numberOfTimes = _nullishCoalesce(_optionalChain([options2, 'optionalAccess', _65 => _65.numberOfTimes]), () => ( 1));
1407
1467
  for (const event of [
1408
1468
  ...givenEvents,
1409
1469
  ...Array.from({ length: numberOfTimes }).flatMap(() => events)
@@ -1423,6 +1483,10 @@ var SQLiteProjectionSpec = {
1423
1483
  }
1424
1484
  });
1425
1485
  }
1486
+ if (!wasInitialized && projection2.init) {
1487
+ await projection2.init({ connection: connection2 });
1488
+ wasInitialized = true;
1489
+ }
1426
1490
  await connection2.withTransaction(
1427
1491
  () => handleProjections({
1428
1492
  events: allEvents,
@@ -1456,18 +1520,18 @@ var SQLiteProjectionSpec = {
1456
1520
  if (!isErrorConstructor(args[0])) {
1457
1521
  assertTrue(
1458
1522
  args[0](error),
1459
- `Error didn't match the error condition: ${_optionalChain([error, 'optionalAccess', _54 => _54.toString, 'call', _55 => _55()])}`
1523
+ `Error didn't match the error condition: ${_optionalChain([error, 'optionalAccess', _66 => _66.toString, 'call', _67 => _67()])}`
1460
1524
  );
1461
1525
  return;
1462
1526
  }
1463
1527
  assertTrue(
1464
1528
  error instanceof args[0],
1465
- `Caught error is not an instance of the expected type: ${_optionalChain([error, 'optionalAccess', _56 => _56.toString, 'call', _57 => _57()])}`
1529
+ `Caught error is not an instance of the expected type: ${_optionalChain([error, 'optionalAccess', _68 => _68.toString, 'call', _69 => _69()])}`
1466
1530
  );
1467
1531
  if (args[1]) {
1468
1532
  assertTrue(
1469
1533
  args[1](error),
1470
- `Error didn't match the error condition: ${_optionalChain([error, 'optionalAccess', _58 => _58.toString, 'call', _59 => _59()])}`
1534
+ `Error didn't match the error condition: ${_optionalChain([error, 'optionalAccess', _70 => _70.toString, 'call', _71 => _71()])}`
1471
1535
  );
1472
1536
  }
1473
1537
  } finally {
@@ -1486,7 +1550,7 @@ var eventInStream = (streamName, event) => {
1486
1550
  ...event,
1487
1551
  metadata: {
1488
1552
  ..._nullishCoalesce(event.metadata, () => ( {})),
1489
- streamName: _nullishCoalesce(_optionalChain([event, 'access', _60 => _60.metadata, 'optionalAccess', _61 => _61.streamName]), () => ( streamName))
1553
+ streamName: _nullishCoalesce(_optionalChain([event, 'access', _72 => _72.metadata, 'optionalAccess', _73 => _73.streamName]), () => ( streamName))
1490
1554
  }
1491
1555
  };
1492
1556
  };