@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.d.cts CHANGED
@@ -22,6 +22,23 @@ type SQLiteConnectionOptions = {
22
22
  };
23
23
  declare const sqliteConnection: (options: SQLiteConnectionOptions) => SQLiteConnection;
24
24
 
25
+ type SQLiteConnectionPoolOptions = {
26
+ fileName: InMemorySQLiteDatabase | InMemorySharedCacheSQLiteDatabase | string | undefined;
27
+ connectionOptions?: {
28
+ singleton: true;
29
+ connection?: SQLiteConnection;
30
+ } | {
31
+ singleton?: false;
32
+ connection?: never;
33
+ };
34
+ };
35
+ type SQLiteConnectionPool = {
36
+ connection: () => Promise<SQLiteConnection>;
37
+ withConnection: <Result = unknown>(handle: (connection: SQLiteConnection) => Promise<Result>) => Promise<Result>;
38
+ close: () => Promise<void>;
39
+ };
40
+ declare const SQLiteConnectionPool: (options: SQLiteConnectionPoolOptions) => SQLiteConnectionPool;
41
+
25
42
  type SQLiteEventStoreMessageBatchPullerStartFrom = {
26
43
  globalPosition: bigint;
27
44
  } | 'BEGINNING' | 'END';
@@ -107,16 +124,29 @@ declare const SQLiteEventStoreDefaultStreamVersion = 0n;
107
124
  interface SQLiteEventStore extends EventStore<SQLiteReadEventMetadata> {
108
125
  appendToStream<EventType extends Event>(streamName: string, events: EventType[], options?: AppendToStreamOptions): Promise<AppendToStreamResultWithGlobalPosition>;
109
126
  consumer<ConsumerEventType extends Event = Event>(options?: SQLiteEventStoreConsumerConfig<ConsumerEventType>): SQLiteEventStoreConsumer<ConsumerEventType>;
127
+ schema: {
128
+ sql(): string;
129
+ print(): void;
130
+ migrate(): Promise<void>;
131
+ };
110
132
  }
111
133
  type SQLiteReadEventMetadata = ReadEventMetadataWithGlobalPosition;
112
134
  type SQLiteReadEvent<EventType extends Event = Event> = ReadEvent<EventType, SQLiteReadEventMetadata>;
135
+ type SQLiteEventStoreConnectionOptions = {
136
+ connection: SQLiteConnection;
137
+ };
113
138
  type SQLiteEventStoreOptions = {
114
- fileName: InMemorySQLiteDatabase | InMemorySharedCacheSQLiteDatabase | string | undefined;
115
139
  projections?: ProjectionRegistration<'inline', SQLiteReadEventMetadata, SQLiteProjectionHandlerContext>[];
116
140
  schema?: {
117
141
  autoMigration?: 'None' | 'CreateOrUpdate';
118
142
  };
119
143
  hooks?: {
144
+ /**
145
+ * This hook will be called **BEFORE** event store schema is created
146
+ */
147
+ onBeforeSchemaCreated?: (context: {
148
+ connection: SQLiteConnection;
149
+ }) => Promise<void> | void;
120
150
  /**
121
151
  * This hook will be called **BEFORE** events were stored in the event store.
122
152
  * @type {BeforeEventStoreCommitHandler<SQLiteEventStore, HandlerContext>}
@@ -124,7 +154,13 @@ type SQLiteEventStoreOptions = {
124
154
  onBeforeCommit?: BeforeEventStoreCommitHandler<SQLiteEventStore, {
125
155
  connection: SQLiteConnection;
126
156
  }>;
157
+ /**
158
+ * This hook will be called **AFTER** event store schema was created
159
+ */
160
+ onAfterSchemaCreated?: () => Promise<void> | void;
127
161
  };
162
+ } & SQLiteConnectionPoolOptions & {
163
+ pool?: SQLiteConnectionPool;
128
164
  };
129
165
  declare const getSQLiteEventStore: (options: SQLiteEventStoreOptions) => SQLiteEventStore;
130
166
 
@@ -140,8 +176,20 @@ type SQLiteProjectionHandlerOptions<EventType extends Event = Event> = {
140
176
  };
141
177
  declare const handleProjections: <EventType extends Event = Event>(options: SQLiteProjectionHandlerOptions<EventType>) => Promise<void>;
142
178
  declare const sqliteProjection: <EventType extends Event>(definition: SQLiteProjectionDefinition<EventType>) => SQLiteProjectionDefinition<EventType>;
143
- declare const sqliteRawBatchSQLProjection: <EventType extends Event>(handle: (events: EventType[], context: SQLiteProjectionHandlerContext) => Promise<string[]> | string[], ...canHandle: CanHandle<EventType>) => SQLiteProjectionDefinition<EventType>;
144
- declare const sqliteRawSQLProjection: <EventType extends Event>(handle: (event: EventType, context: SQLiteProjectionHandlerContext) => Promise<string> | string, ...canHandle: CanHandle<EventType>) => SQLiteProjectionDefinition<EventType>;
179
+ type SQLiteRawBatchSQLProjection<EventType extends Event> = {
180
+ evolve: (events: EventType[], context: SQLiteProjectionHandlerContext) => Promise<string[]> | string[];
181
+ canHandle: CanHandle<EventType>;
182
+ initSQL?: string;
183
+ init?: (context: SQLiteProjectionHandlerContext) => void | Promise<void>;
184
+ };
185
+ declare const sqliteRawBatchSQLProjection: <EventType extends Event>(options: SQLiteRawBatchSQLProjection<EventType>) => SQLiteProjectionDefinition<EventType>;
186
+ type SQLiteRawSQLProjection<EventType extends Event> = {
187
+ evolve: (events: EventType, context: SQLiteProjectionHandlerContext) => Promise<string[]> | string[] | Promise<string> | string;
188
+ canHandle: CanHandle<EventType>;
189
+ initSQL?: string;
190
+ init?: (context: SQLiteProjectionHandlerContext) => void | Promise<void>;
191
+ };
192
+ declare const sqliteRawSQLProjection: <EventType extends Event>(options: SQLiteRawSQLProjection<EventType>) => SQLiteProjectionDefinition<EventType>;
145
193
 
146
194
  type SQLiteProjectionSpecEvent<EventType extends Event, EventMetaDataType extends SQLiteReadEventMetadata = SQLiteReadEventMetadata> = EventType & {
147
195
  metadata?: Partial<EventMetaDataType>;
@@ -153,7 +201,8 @@ type SQLiteProjectionAssert = (options: {
153
201
  connection: SQLiteConnection;
154
202
  }) => Promise<void | boolean>;
155
203
  type SQLiteProjectionSpecOptions<EventType extends Event> = {
156
- connection: SQLiteConnection;
204
+ fileName?: string;
205
+ connection?: SQLiteConnection;
157
206
  projection: SQLiteProjectionDefinition<EventType>;
158
207
  };
159
208
  type SQLiteProjectionSpec<EventType extends Event> = (givenEvents: SQLiteProjectionSpecEvent<EventType>[]) => {
@@ -252,7 +301,7 @@ declare const streamsTableSQL: string;
252
301
  declare const messagesTableSQL: string;
253
302
  declare const subscriptionsTableSQL: string;
254
303
  declare const schemaSQL: string[];
255
- declare const createEventStoreSchema: (db: SQLiteConnection) => Promise<void>;
304
+ declare const createEventStoreSchema: (connection: SQLiteConnection, hooks?: SQLiteEventStoreOptions["hooks"]) => Promise<void>;
256
305
 
257
306
  declare const emmettPrefix = "emt";
258
307
  declare const globalTag = "global";
@@ -286,4 +335,4 @@ declare const subscriptionsTable: {
286
335
  name: string;
287
336
  };
288
337
 
289
- export { type AppendEventResult, type EventHandler, InMemorySQLiteDatabase, InMemorySharedCacheSQLiteDatabase, type Parameters$1 as Parameters, type ReadLastMessageGlobalPositionResult, type ReadMessagesBatchOptions, type ReadMessagesBatchResult, type ReadProcessorCheckpointResult, type SQLiteConnection, type SQLiteError, type SQLiteEventStore, SQLiteEventStoreDefaultStreamVersion, type SQLiteEventStoreOptions, type SQLiteProjectionAssert, type SQLiteProjectionDefinition, type SQLiteProjectionHandler, type SQLiteProjectionHandlerContext, type SQLiteProjectionHandlerOptions, SQLiteProjectionSpec, type SQLiteProjectionSpecEvent, type SQLiteProjectionSpecOptions, type SQLiteProjectionSpecWhenOptions, type SQLiteReadEvent, type SQLiteReadEventMetadata, type StoreLastProcessedProcessorPositionResult, appendToStream, assertSQLQueryResultMatches, createEventStoreSchema, defaultTag, emmettPrefix, eventInStream, eventsInStream, expectSQL, getSQLiteEventStore, globalNames, globalTag, handleProjections, isSQLiteError, messagesTable, messagesTableSQL, newEventsInStream, readLastMessageGlobalPosition, readMessagesBatch, readProcessorCheckpoint, readStream, schemaSQL, sql, sqliteConnection, sqliteProjection, sqliteRawBatchSQLProjection, sqliteRawSQLProjection, storeProcessorCheckpoint, streamsTable, streamsTableSQL, subscriptionsTable, subscriptionsTableSQL };
338
+ export { type AppendEventResult, type EventHandler, InMemorySQLiteDatabase, InMemorySharedCacheSQLiteDatabase, type Parameters$1 as Parameters, type ReadLastMessageGlobalPositionResult, type ReadMessagesBatchOptions, type ReadMessagesBatchResult, type ReadProcessorCheckpointResult, type SQLiteConnection, type SQLiteError, type SQLiteEventStore, type SQLiteEventStoreConnectionOptions, SQLiteEventStoreDefaultStreamVersion, type SQLiteEventStoreOptions, type SQLiteProjectionAssert, type SQLiteProjectionDefinition, type SQLiteProjectionHandler, type SQLiteProjectionHandlerContext, type SQLiteProjectionHandlerOptions, SQLiteProjectionSpec, type SQLiteProjectionSpecEvent, type SQLiteProjectionSpecOptions, type SQLiteProjectionSpecWhenOptions, type SQLiteRawBatchSQLProjection, type SQLiteRawSQLProjection, type SQLiteReadEvent, type SQLiteReadEventMetadata, type StoreLastProcessedProcessorPositionResult, appendToStream, assertSQLQueryResultMatches, createEventStoreSchema, defaultTag, emmettPrefix, eventInStream, eventsInStream, expectSQL, getSQLiteEventStore, globalNames, globalTag, handleProjections, isSQLiteError, messagesTable, messagesTableSQL, newEventsInStream, readLastMessageGlobalPosition, readMessagesBatch, readProcessorCheckpoint, readStream, schemaSQL, sql, sqliteConnection, sqliteProjection, sqliteRawBatchSQLProjection, sqliteRawSQLProjection, storeProcessorCheckpoint, streamsTable, streamsTableSQL, subscriptionsTable, subscriptionsTableSQL };
package/dist/index.d.ts CHANGED
@@ -22,6 +22,23 @@ type SQLiteConnectionOptions = {
22
22
  };
23
23
  declare const sqliteConnection: (options: SQLiteConnectionOptions) => SQLiteConnection;
24
24
 
25
+ type SQLiteConnectionPoolOptions = {
26
+ fileName: InMemorySQLiteDatabase | InMemorySharedCacheSQLiteDatabase | string | undefined;
27
+ connectionOptions?: {
28
+ singleton: true;
29
+ connection?: SQLiteConnection;
30
+ } | {
31
+ singleton?: false;
32
+ connection?: never;
33
+ };
34
+ };
35
+ type SQLiteConnectionPool = {
36
+ connection: () => Promise<SQLiteConnection>;
37
+ withConnection: <Result = unknown>(handle: (connection: SQLiteConnection) => Promise<Result>) => Promise<Result>;
38
+ close: () => Promise<void>;
39
+ };
40
+ declare const SQLiteConnectionPool: (options: SQLiteConnectionPoolOptions) => SQLiteConnectionPool;
41
+
25
42
  type SQLiteEventStoreMessageBatchPullerStartFrom = {
26
43
  globalPosition: bigint;
27
44
  } | 'BEGINNING' | 'END';
@@ -107,16 +124,29 @@ declare const SQLiteEventStoreDefaultStreamVersion = 0n;
107
124
  interface SQLiteEventStore extends EventStore<SQLiteReadEventMetadata> {
108
125
  appendToStream<EventType extends Event>(streamName: string, events: EventType[], options?: AppendToStreamOptions): Promise<AppendToStreamResultWithGlobalPosition>;
109
126
  consumer<ConsumerEventType extends Event = Event>(options?: SQLiteEventStoreConsumerConfig<ConsumerEventType>): SQLiteEventStoreConsumer<ConsumerEventType>;
127
+ schema: {
128
+ sql(): string;
129
+ print(): void;
130
+ migrate(): Promise<void>;
131
+ };
110
132
  }
111
133
  type SQLiteReadEventMetadata = ReadEventMetadataWithGlobalPosition;
112
134
  type SQLiteReadEvent<EventType extends Event = Event> = ReadEvent<EventType, SQLiteReadEventMetadata>;
135
+ type SQLiteEventStoreConnectionOptions = {
136
+ connection: SQLiteConnection;
137
+ };
113
138
  type SQLiteEventStoreOptions = {
114
- fileName: InMemorySQLiteDatabase | InMemorySharedCacheSQLiteDatabase | string | undefined;
115
139
  projections?: ProjectionRegistration<'inline', SQLiteReadEventMetadata, SQLiteProjectionHandlerContext>[];
116
140
  schema?: {
117
141
  autoMigration?: 'None' | 'CreateOrUpdate';
118
142
  };
119
143
  hooks?: {
144
+ /**
145
+ * This hook will be called **BEFORE** event store schema is created
146
+ */
147
+ onBeforeSchemaCreated?: (context: {
148
+ connection: SQLiteConnection;
149
+ }) => Promise<void> | void;
120
150
  /**
121
151
  * This hook will be called **BEFORE** events were stored in the event store.
122
152
  * @type {BeforeEventStoreCommitHandler<SQLiteEventStore, HandlerContext>}
@@ -124,7 +154,13 @@ type SQLiteEventStoreOptions = {
124
154
  onBeforeCommit?: BeforeEventStoreCommitHandler<SQLiteEventStore, {
125
155
  connection: SQLiteConnection;
126
156
  }>;
157
+ /**
158
+ * This hook will be called **AFTER** event store schema was created
159
+ */
160
+ onAfterSchemaCreated?: () => Promise<void> | void;
127
161
  };
162
+ } & SQLiteConnectionPoolOptions & {
163
+ pool?: SQLiteConnectionPool;
128
164
  };
129
165
  declare const getSQLiteEventStore: (options: SQLiteEventStoreOptions) => SQLiteEventStore;
130
166
 
@@ -140,8 +176,20 @@ type SQLiteProjectionHandlerOptions<EventType extends Event = Event> = {
140
176
  };
141
177
  declare const handleProjections: <EventType extends Event = Event>(options: SQLiteProjectionHandlerOptions<EventType>) => Promise<void>;
142
178
  declare const sqliteProjection: <EventType extends Event>(definition: SQLiteProjectionDefinition<EventType>) => SQLiteProjectionDefinition<EventType>;
143
- declare const sqliteRawBatchSQLProjection: <EventType extends Event>(handle: (events: EventType[], context: SQLiteProjectionHandlerContext) => Promise<string[]> | string[], ...canHandle: CanHandle<EventType>) => SQLiteProjectionDefinition<EventType>;
144
- declare const sqliteRawSQLProjection: <EventType extends Event>(handle: (event: EventType, context: SQLiteProjectionHandlerContext) => Promise<string> | string, ...canHandle: CanHandle<EventType>) => SQLiteProjectionDefinition<EventType>;
179
+ type SQLiteRawBatchSQLProjection<EventType extends Event> = {
180
+ evolve: (events: EventType[], context: SQLiteProjectionHandlerContext) => Promise<string[]> | string[];
181
+ canHandle: CanHandle<EventType>;
182
+ initSQL?: string;
183
+ init?: (context: SQLiteProjectionHandlerContext) => void | Promise<void>;
184
+ };
185
+ declare const sqliteRawBatchSQLProjection: <EventType extends Event>(options: SQLiteRawBatchSQLProjection<EventType>) => SQLiteProjectionDefinition<EventType>;
186
+ type SQLiteRawSQLProjection<EventType extends Event> = {
187
+ evolve: (events: EventType, context: SQLiteProjectionHandlerContext) => Promise<string[]> | string[] | Promise<string> | string;
188
+ canHandle: CanHandle<EventType>;
189
+ initSQL?: string;
190
+ init?: (context: SQLiteProjectionHandlerContext) => void | Promise<void>;
191
+ };
192
+ declare const sqliteRawSQLProjection: <EventType extends Event>(options: SQLiteRawSQLProjection<EventType>) => SQLiteProjectionDefinition<EventType>;
145
193
 
146
194
  type SQLiteProjectionSpecEvent<EventType extends Event, EventMetaDataType extends SQLiteReadEventMetadata = SQLiteReadEventMetadata> = EventType & {
147
195
  metadata?: Partial<EventMetaDataType>;
@@ -153,7 +201,8 @@ type SQLiteProjectionAssert = (options: {
153
201
  connection: SQLiteConnection;
154
202
  }) => Promise<void | boolean>;
155
203
  type SQLiteProjectionSpecOptions<EventType extends Event> = {
156
- connection: SQLiteConnection;
204
+ fileName?: string;
205
+ connection?: SQLiteConnection;
157
206
  projection: SQLiteProjectionDefinition<EventType>;
158
207
  };
159
208
  type SQLiteProjectionSpec<EventType extends Event> = (givenEvents: SQLiteProjectionSpecEvent<EventType>[]) => {
@@ -252,7 +301,7 @@ declare const streamsTableSQL: string;
252
301
  declare const messagesTableSQL: string;
253
302
  declare const subscriptionsTableSQL: string;
254
303
  declare const schemaSQL: string[];
255
- declare const createEventStoreSchema: (db: SQLiteConnection) => Promise<void>;
304
+ declare const createEventStoreSchema: (connection: SQLiteConnection, hooks?: SQLiteEventStoreOptions["hooks"]) => Promise<void>;
256
305
 
257
306
  declare const emmettPrefix = "emt";
258
307
  declare const globalTag = "global";
@@ -286,4 +335,4 @@ declare const subscriptionsTable: {
286
335
  name: string;
287
336
  };
288
337
 
289
- export { type AppendEventResult, type EventHandler, InMemorySQLiteDatabase, InMemorySharedCacheSQLiteDatabase, type Parameters$1 as Parameters, type ReadLastMessageGlobalPositionResult, type ReadMessagesBatchOptions, type ReadMessagesBatchResult, type ReadProcessorCheckpointResult, type SQLiteConnection, type SQLiteError, type SQLiteEventStore, SQLiteEventStoreDefaultStreamVersion, type SQLiteEventStoreOptions, type SQLiteProjectionAssert, type SQLiteProjectionDefinition, type SQLiteProjectionHandler, type SQLiteProjectionHandlerContext, type SQLiteProjectionHandlerOptions, SQLiteProjectionSpec, type SQLiteProjectionSpecEvent, type SQLiteProjectionSpecOptions, type SQLiteProjectionSpecWhenOptions, type SQLiteReadEvent, type SQLiteReadEventMetadata, type StoreLastProcessedProcessorPositionResult, appendToStream, assertSQLQueryResultMatches, createEventStoreSchema, defaultTag, emmettPrefix, eventInStream, eventsInStream, expectSQL, getSQLiteEventStore, globalNames, globalTag, handleProjections, isSQLiteError, messagesTable, messagesTableSQL, newEventsInStream, readLastMessageGlobalPosition, readMessagesBatch, readProcessorCheckpoint, readStream, schemaSQL, sql, sqliteConnection, sqliteProjection, sqliteRawBatchSQLProjection, sqliteRawSQLProjection, storeProcessorCheckpoint, streamsTable, streamsTableSQL, subscriptionsTable, subscriptionsTableSQL };
338
+ export { type AppendEventResult, type EventHandler, InMemorySQLiteDatabase, InMemorySharedCacheSQLiteDatabase, type Parameters$1 as Parameters, type ReadLastMessageGlobalPositionResult, type ReadMessagesBatchOptions, type ReadMessagesBatchResult, type ReadProcessorCheckpointResult, type SQLiteConnection, type SQLiteError, type SQLiteEventStore, type SQLiteEventStoreConnectionOptions, SQLiteEventStoreDefaultStreamVersion, type SQLiteEventStoreOptions, type SQLiteProjectionAssert, type SQLiteProjectionDefinition, type SQLiteProjectionHandler, type SQLiteProjectionHandlerContext, type SQLiteProjectionHandlerOptions, SQLiteProjectionSpec, type SQLiteProjectionSpecEvent, type SQLiteProjectionSpecOptions, type SQLiteProjectionSpecWhenOptions, type SQLiteRawBatchSQLProjection, type SQLiteRawSQLProjection, type SQLiteReadEvent, type SQLiteReadEventMetadata, type StoreLastProcessedProcessorPositionResult, appendToStream, assertSQLQueryResultMatches, createEventStoreSchema, defaultTag, emmettPrefix, eventInStream, eventsInStream, expectSQL, getSQLiteEventStore, globalNames, globalTag, handleProjections, isSQLiteError, messagesTable, messagesTableSQL, newEventsInStream, readLastMessageGlobalPosition, readMessagesBatch, readProcessorCheckpoint, readStream, schemaSQL, sql, sqliteConnection, sqliteProjection, sqliteRawBatchSQLProjection, sqliteRawSQLProjection, storeProcessorCheckpoint, streamsTable, streamsTableSQL, subscriptionsTable, subscriptionsTableSQL };
package/dist/index.js 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
  import { v4 as uuid5 } from "uuid";
550
566
 
567
+ // src/connection/sqliteConnectionPool.ts
568
+ var SQLiteConnectionPool = (options) => {
569
+ const fileName = options.fileName ?? InMemorySQLiteDatabase;
570
+ const isInMemory = fileName === InMemorySQLiteDatabase || fileName === InMemorySharedCacheSQLiteDatabase;
571
+ const singletonConnection = options.connectionOptions?.connection ?? (isInMemory ? sqliteConnection({
572
+ fileName
573
+ }) : null);
574
+ const isAmbientConnection = options.connectionOptions?.singleton === true && options.connectionOptions?.connection !== void 0;
575
+ const createConnection = () => {
576
+ return 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 = 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 (hooks?.onBeforeSchemaCreated) {
688
+ await hooks.onBeforeSchemaCreated({ connection });
689
+ }
690
+ for (const sql2 of schemaSQL) {
691
+ await connection.command(sql2);
692
+ }
693
+ });
694
+ if (hooks?.onAfterSchemaCreated) {
695
+ await hooks.onAfterSchemaCreated();
633
696
  }
634
697
  };
635
698
 
@@ -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 readLastMessageGlobalPosition(connection)).currentGlobalPosition ?? 0n : options.startFrom.globalPosition;
783
+ const after = options.startFrom === "BEGINNING" ? 0n : options.startFrom === "END" ? (await pool.withConnection(
784
+ async (connection) => readLastMessageGlobalPosition(connection)
785
+ )).currentGlobalPosition ?? 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") {
@@ -1196,8 +1263,8 @@ var sqliteEventStoreConsumer = (options) => {
1196
1263
  const processors = options.processors ?? [];
1197
1264
  let start;
1198
1265
  let currentMessagePuller;
1199
- const connection = options.connection ?? sqliteConnection({ fileName: options.fileName });
1200
- const eachBatch = async (messagesBatch) => {
1266
+ const pool = 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 {
@@ -1217,9 +1284,9 @@ var sqliteEventStoreConsumer = (options) => {
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
1291
  batchSize: pulling?.batchSize ?? DefaultSQLiteEventStoreProcessorBatchSize,
1225
1292
  pullingFrequencyInMs: pulling?.pullingFrequencyInMs ?? DefaultSQLiteEventStoreProcessorPullingFrequencyInMs
@@ -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,51 +1341,40 @@ 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 = options.fileName ?? InMemorySQLiteDatabase;
1279
- const isInMemory = fileName === InMemorySQLiteDatabase || fileName === InMemorySharedCacheSQLiteDatabase;
1346
+ const pool = options.pool ?? SQLiteConnectionPool(options);
1347
+ let migrateSchema = void 0;
1280
1348
  const inlineProjections = (options.projections ?? []).filter(({ type }) => type === "inline").map(({ projection: projection2 }) => projection2);
1281
1349
  const onBeforeCommitHook = options.hooks?.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
- };
1350
+ const withConnection = async (handler) => pool.withConnection(async (database) => {
1351
+ await ensureSchemaExists(database);
1352
+ return await handler(database);
1353
+ });
1310
1354
  if (options) {
1311
1355
  autoGenerateSchema = options.schema?.autoMigration === void 0 || options.schema?.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 (options.hooks?.onBeforeSchemaCreated) {
1367
+ await options.hooks.onBeforeSchemaCreated(context);
1368
+ }
1369
+ },
1370
+ onAfterSchemaCreated: options.hooks?.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) {
@@ -1326,9 +1384,6 @@ var getSQLiteEventStore = (options) => {
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(
@@ -1386,8 +1438,13 @@ var getSQLiteEventStore = (options) => {
1386
1438
  consumer: (options2) => sqliteEventStoreConsumer({
1387
1439
  ...options2 ?? {},
1388
1440
  fileName,
1389
- connection: 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,8 +1452,11 @@ var getSQLiteEventStore = (options) => {
1395
1452
  var SQLiteProjectionSpec = {
1396
1453
  for: (options) => {
1397
1454
  {
1398
- const connection = options.connection;
1455
+ const connection = options.connection ?? sqliteConnection({
1456
+ fileName: 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) => {
@@ -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,