@event-driven-io/dumbo 0.13.0-beta.43 → 0.13.0-beta.45

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.
@@ -0,0 +1,74 @@
1
+ import { Bt as DatabaseLockOptions, Ea as SQLProcessor, Ht as ReleaseDatabaseLockOptions, In as DumboError, Ji as SQL, Lt as AcquireDatabaseLockMode, Rt as AcquireDatabaseLockOptions, Vi as SQLFormatter, go as SQLPlain, i as DatabaseConnectionString, jt as MigratorOptions, lo as SQLArray, mo as SQLIn, pt as DatabaseDriverType, rn as SQLExecutor, xa as DefaultSQLColumnProcessors, zt as DatabaseLock } from "./index-_dj3upBo.cjs";
2
+
3
+ //#region src/storage/postgresql/core/connections/connectionString.d.ts
4
+ declare const defaultPostgreSQLConnectionString: PostgreSQLConnectionString;
5
+ type PostgreSQLConnectionString = DatabaseConnectionString<'PostgreSQL', `postgresql://${string}` | `postgres://${string}`>;
6
+ declare const PostgreSQLConnectionString: (connectionString: string) => PostgreSQLConnectionString;
7
+ /**
8
+ * Parse database name from a PostgreSQL connection string
9
+ */
10
+ declare function parseDatabaseName(str: string): string | null;
11
+ //#endregion
12
+ //#region src/storage/postgresql/core/errors/errorMapper.d.ts
13
+ /**
14
+ * Maps a PostgreSQL error (from the `pg` driver) to a typed DumboError
15
+ * based on the SQLSTATE code.
16
+ *
17
+ * SQLSTATE reference: https://www.postgresql.org/docs/current/errcodes-appendix.html
18
+ * Transient classification based on Npgsql's PostgresException.IsTransient.
19
+ *
20
+ * Falls back to a generic DumboError (500) if the error is not a recognized PostgreSQL error.
21
+ */
22
+ declare const mapPostgresError: (error: unknown) => DumboError;
23
+ //#endregion
24
+ //#region src/storage/postgresql/core/locks/advisoryLocks.d.ts
25
+ declare const tryAcquireAdvisoryLock: (execute: SQLExecutor, options: AcquireDatabaseLockOptions) => Promise<boolean>;
26
+ declare const releaseAdvisoryLock: (execute: SQLExecutor, options: ReleaseDatabaseLockOptions) => Promise<boolean>;
27
+ declare const acquireAdvisoryLock: (execute: SQLExecutor, options: AcquireDatabaseLockOptions) => Promise<void>;
28
+ declare const AdvisoryLock: DatabaseLock;
29
+ declare const advisoryLock: (execute: SQLExecutor, options: DatabaseLockOptions) => {
30
+ acquire: (acquireOptions?: {
31
+ mode: AcquireDatabaseLockMode;
32
+ }) => Promise<void>;
33
+ tryAcquire: (acquireOptions?: {
34
+ mode: AcquireDatabaseLockMode;
35
+ }) => Promise<boolean>;
36
+ release: () => Promise<boolean>;
37
+ withAcquire: <Result>(handle: () => Promise<Result>, acquireOptions?: {
38
+ mode: AcquireDatabaseLockMode;
39
+ }) => Promise<Result>;
40
+ };
41
+ //#endregion
42
+ //#region src/storage/postgresql/core/schema/migrations.d.ts
43
+ declare const DefaultPostgreSQLMigratorOptions: MigratorOptions;
44
+ //#endregion
45
+ //#region src/storage/postgresql/core/schema/schema.d.ts
46
+ declare const defaultPostgreSqlDatabase = "postgres";
47
+ declare const tableExistsSQL: (tableName: string) => SQL;
48
+ declare const tableExists: (execute: SQLExecutor, tableName: string) => Promise<boolean>;
49
+ declare const functionExistsSQL: (functionName: string) => SQL;
50
+ declare const functionExists: (execute: SQLExecutor, functionName: string) => Promise<boolean>;
51
+ //#endregion
52
+ //#region src/storage/postgresql/core/sql/formatter/index.d.ts
53
+ declare const pgFormatter: SQLFormatter;
54
+ //#endregion
55
+ //#region src/storage/postgresql/core/sql/json.d.ts
56
+ declare const PostgreSQLJSON: {
57
+ readonly field: (source: SQL, path: string) => SQL;
58
+ readonly path: (path: string) => SQLPlain;
59
+ readonly textField: (source: SQL, path: string) => SQL;
60
+ };
61
+ //#endregion
62
+ //#region src/storage/postgresql/core/sql/processors/arrayProcessors.d.ts
63
+ declare const PostgreSQLArrayProcessor: SQLProcessor<SQLArray>;
64
+ declare const PostgreSQLExpandSQLInProcessor: SQLProcessor<SQLIn>;
65
+ //#endregion
66
+ //#region src/storage/postgresql/core/sql/processors/columProcessors.d.ts
67
+ declare const postgreSQLColumnProcessors: DefaultSQLColumnProcessors;
68
+ //#endregion
69
+ //#region src/storage/postgresql/core/index.d.ts
70
+ type PostgreSQLDatabaseName = 'PostgreSQL';
71
+ declare const PostgreSQLDatabaseName = "PostgreSQL";
72
+ type PostgreSQLDriverType<DriverName extends string = string> = DatabaseDriverType<PostgreSQLDatabaseName, DriverName>;
73
+ //#endregion
74
+ export { parseDatabaseName as S, releaseAdvisoryLock as _, PostgreSQLExpandSQLInProcessor as a, PostgreSQLConnectionString as b, defaultPostgreSqlDatabase as c, tableExists as d, tableExistsSQL as f, advisoryLock as g, acquireAdvisoryLock as h, PostgreSQLArrayProcessor as i, functionExists as l, AdvisoryLock as m, PostgreSQLDriverType as n, PostgreSQLJSON as o, DefaultPostgreSQLMigratorOptions as p, postgreSQLColumnProcessors as r, pgFormatter as s, PostgreSQLDatabaseName as t, functionExistsSQL as u, tryAcquireAdvisoryLock as v, defaultPostgreSQLConnectionString as x, mapPostgresError as y };
package/dist/index.cjs CHANGED
@@ -323,6 +323,65 @@ const executeInAmbientConnection = async (handle, options) => {
323
323
 
324
324
  //#endregion
325
325
  //#region src/core/connections/transaction.ts
326
+ const transactionNestingCounter = () => {
327
+ let transactionLevel = 0;
328
+ return {
329
+ reset: () => {
330
+ transactionLevel = 0;
331
+ },
332
+ increment: () => {
333
+ transactionLevel++;
334
+ },
335
+ decrement: () => {
336
+ transactionLevel--;
337
+ if (transactionLevel < 0) throw new Error("Transaction level is out of bounds");
338
+ },
339
+ get level() {
340
+ return transactionLevel;
341
+ }
342
+ };
343
+ };
344
+ const databaseTransaction = (backend, options) => {
345
+ const allowNestedTransactions = options?.allowNestedTransactions ?? false;
346
+ const useSavepoints = options?.useSavepoints ?? false;
347
+ const counter = transactionNestingCounter();
348
+ let hasBegun = false;
349
+ return {
350
+ begin: async () => {
351
+ if (!allowNestedTransactions && hasBegun) throw new InvalidOperationError("Cannot start a nested transaction: allowNestedTransactions is false. Set transactionOptions: { allowNestedTransactions: true } on your pool or connection.");
352
+ if (allowNestedTransactions) {
353
+ if (counter.level >= 1) {
354
+ counter.increment();
355
+ if (useSavepoints && backend.savepoint) await backend.savepoint(counter.level);
356
+ return;
357
+ }
358
+ counter.increment();
359
+ }
360
+ hasBegun = true;
361
+ await backend.begin();
362
+ },
363
+ commit: async () => {
364
+ if (allowNestedTransactions && counter.level > 1) {
365
+ if (useSavepoints && backend.releaseSavepoint) await backend.releaseSavepoint(counter.level);
366
+ counter.decrement();
367
+ return;
368
+ }
369
+ if (allowNestedTransactions) counter.reset();
370
+ hasBegun = false;
371
+ await backend.commit();
372
+ },
373
+ rollback: async (error) => {
374
+ if (allowNestedTransactions && counter.level > 1) {
375
+ if (useSavepoints && backend.rollbackToSavepoint) await backend.rollbackToSavepoint(counter.level);
376
+ counter.decrement();
377
+ return;
378
+ }
379
+ if (allowNestedTransactions) counter.reset();
380
+ hasBegun = false;
381
+ await backend.rollback(error);
382
+ }
383
+ };
384
+ };
326
385
  const toTransactionResult = (transactionResult) => transactionResult !== void 0 && transactionResult !== null && typeof transactionResult === "object" && "success" in transactionResult ? transactionResult : {
327
386
  success: true,
328
387
  result: transactionResult
@@ -729,33 +788,80 @@ const createAmbientConnectionPool = (options) => {
729
788
  const createSingletonConnectionPool = (options) => {
730
789
  const { driverType, getConnection } = options;
731
790
  let connectionPromise = null;
791
+ let closed = false;
792
+ const activeOperations = /* @__PURE__ */ new Set();
793
+ const closedError = () => /* @__PURE__ */ new Error("Singleton connection pool has been closed");
794
+ const run = async (operation) => {
795
+ if (closed) throw closedError();
796
+ const activeOperation = operation();
797
+ activeOperations.add(activeOperation);
798
+ try {
799
+ return await activeOperation;
800
+ } finally {
801
+ activeOperations.delete(activeOperation);
802
+ }
803
+ };
732
804
  const getExistingOrNewConnection = () => {
733
805
  if (!connectionPromise) connectionPromise ??= Promise.resolve(getConnection());
734
806
  return connectionPromise;
735
807
  };
808
+ const innerTransactionFactory = transactionFactoryWithAsyncAmbientConnection(options.driverType, getExistingOrNewConnection, options.closeConnection);
736
809
  return {
737
810
  driverType,
738
- connection: () => getExistingOrNewConnection().then((conn) => wrapPooledConnection(conn, () => Promise.resolve())),
739
- execute: sqlExecutorInAmbientConnection({
740
- driverType,
741
- connection: getExistingOrNewConnection
742
- }),
743
- withConnection: (handle, _options) => executeInAmbientConnection(handle, { connection: getExistingOrNewConnection }),
744
- ...transactionFactoryWithAsyncAmbientConnection(options.driverType, getExistingOrNewConnection, options.closeConnection),
745
- close: async () => {
811
+ connection: () => run(() => getExistingOrNewConnection().then((conn) => wrapPooledConnection(conn, () => Promise.resolve()))),
812
+ execute: (() => {
813
+ const ambientExecutor = sqlExecutorInAmbientConnection({
814
+ driverType,
815
+ connection: getExistingOrNewConnection
816
+ });
817
+ return {
818
+ query: (sql, opts) => run(() => ambientExecutor.query(sql, opts)),
819
+ batchQuery: (sqls, opts) => run(() => ambientExecutor.batchQuery(sqls, opts)),
820
+ command: (sql, opts) => run(() => ambientExecutor.command(sql, opts)),
821
+ batchCommand: (sqls, opts) => run(() => ambientExecutor.batchCommand(sqls, opts))
822
+ };
823
+ })(),
824
+ withConnection: (handle, _options) => run(() => executeInAmbientConnection(handle, { connection: getExistingOrNewConnection })),
825
+ transaction: (transactionOptions) => {
826
+ if (closed) throw closedError();
827
+ return innerTransactionFactory.transaction(transactionOptions);
828
+ },
829
+ withTransaction: (handle, transactionOptions) => run(() => innerTransactionFactory.withTransaction(handle, transactionOptions)),
830
+ close: async (closeOptions) => {
831
+ if (closed) return;
832
+ closed = true;
833
+ if (!closeOptions?.force) await Promise.allSettled([...activeOperations]);
746
834
  if (!connectionPromise) return;
747
- await (await connectionPromise).close();
835
+ const connection = await connectionPromise;
836
+ connectionPromise = null;
837
+ await connection.close();
748
838
  }
749
839
  };
750
840
  };
751
841
  const createBoundedConnectionPool = (options) => {
752
842
  const { driverType, maxConnections } = options;
753
- const guardMaxConnections = guardBoundedAccess(options.getConnection, {
843
+ const allConnections = /* @__PURE__ */ new Set();
844
+ const getTrackedConnection = async () => {
845
+ const connection = await options.getConnection();
846
+ allConnections.add(connection);
847
+ return connection;
848
+ };
849
+ const guardMaxConnections = guardBoundedAccess(getTrackedConnection, {
754
850
  maxResources: maxConnections,
755
851
  reuseResources: true
756
852
  });
757
853
  let closed = false;
854
+ const closedError = () => /* @__PURE__ */ new Error("Bounded connection pool has been closed");
855
+ const ensureOpen = () => {
856
+ if (closed) throw closedError();
857
+ };
858
+ const closeAllConnections = async () => {
859
+ const connections = [...allConnections];
860
+ allConnections.clear();
861
+ await Promise.all(connections.map((conn) => conn.close()));
862
+ };
758
863
  const executeWithPooling = async (operation) => {
864
+ ensureOpen();
759
865
  const conn = await guardMaxConnections.acquire();
760
866
  try {
761
867
  return await operation(conn);
@@ -766,6 +872,7 @@ const createBoundedConnectionPool = (options) => {
766
872
  return {
767
873
  driverType,
768
874
  connection: async () => {
875
+ ensureOpen();
769
876
  const conn = await guardMaxConnections.acquire();
770
877
  return wrapPooledConnection(conn, () => Promise.resolve(guardMaxConnections.release(conn)));
771
878
  },
@@ -776,11 +883,20 @@ const createBoundedConnectionPool = (options) => {
776
883
  batchCommand: (sqls, opts) => executeWithPooling((c) => c.execute.batchCommand(sqls, opts))
777
884
  },
778
885
  withConnection: executeWithPooling,
779
- ...transactionFactoryWithAsyncAmbientConnection(driverType, guardMaxConnections.acquire, guardMaxConnections.release),
780
- close: async () => {
886
+ transaction: (transactionOptions) => {
887
+ ensureOpen();
888
+ return transactionFactoryWithAsyncAmbientConnection(driverType, guardMaxConnections.acquire, guardMaxConnections.release).transaction(transactionOptions);
889
+ },
890
+ withTransaction: (handle, transactionOptions) => executeWithPooling((conn) => {
891
+ const withTx = conn.withTransaction;
892
+ return withTx(handle, transactionOptions);
893
+ }),
894
+ close: async (closeOptions) => {
781
895
  if (closed) return;
782
896
  closed = true;
897
+ if (!closeOptions?.force) await guardMaxConnections.waitForIdle();
783
898
  await guardMaxConnections.stop({ force: true });
899
+ await closeAllConnections();
784
900
  }
785
901
  };
786
902
  };
@@ -2509,6 +2625,7 @@ exports.createSingletonConnectionPool = createSingletonConnectionPool;
2509
2625
  exports.createTransientConnection = createTransientConnection;
2510
2626
  exports.databaseSchemaComponent = databaseSchemaComponent;
2511
2627
  exports.databaseSchemaSchemaComponent = databaseSchemaSchemaComponent;
2628
+ exports.databaseTransaction = databaseTransaction;
2512
2629
  exports.defaultDatabaseLockOptions = defaultDatabaseLockOptions;
2513
2630
  exports.defaultProcessorsRegistry = defaultProcessorsRegistry;
2514
2631
  exports.describeSQL = describeSQL;
@@ -2574,4 +2691,5 @@ exports.transactionFactoryWithAmbientConnection = transactionFactoryWithAmbientC
2574
2691
  exports.transactionFactoryWithAsyncAmbientConnection = transactionFactoryWithAsyncAmbientConnection;
2575
2692
  exports.transactionFactoryWithDbClient = transactionFactoryWithDbClient;
2576
2693
  exports.transactionFactoryWithNewConnection = transactionFactoryWithNewConnection;
2694
+ exports.transactionNestingCounter = transactionNestingCounter;
2577
2695
  //# sourceMappingURL=index.cjs.map