@event-driven-io/dumbo 0.13.0-beta.42 → 0.13.0-beta.44

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.
Files changed (63) hide show
  1. package/dist/cloudflare.cjs +2256 -86
  2. package/dist/cloudflare.cjs.map +1 -1
  3. package/dist/cloudflare.d.cts +1102 -3
  4. package/dist/cloudflare.d.ts +1102 -3
  5. package/dist/cloudflare.js +2147 -4
  6. package/dist/cloudflare.js.map +1 -1
  7. package/dist/index.cjs +2623 -160
  8. package/dist/index.cjs.map +1 -1
  9. package/dist/index.d.cts +1694 -2
  10. package/dist/index.d.ts +1694 -2
  11. package/dist/index.js +2437 -4
  12. package/dist/index.js.map +1 -1
  13. package/dist/pg.cjs +2197 -101
  14. package/dist/pg.cjs.map +1 -1
  15. package/dist/pg.d.cts +1059 -5
  16. package/dist/pg.d.ts +1059 -5
  17. package/dist/pg.js +2115 -47
  18. package/dist/pg.js.map +1 -1
  19. package/dist/postgresql.cjs +1845 -25
  20. package/dist/postgresql.cjs.map +1 -0
  21. package/dist/postgresql.d.cts +1037 -3
  22. package/dist/postgresql.d.ts +1037 -3
  23. package/dist/postgresql.js +1795 -3
  24. package/dist/postgresql.js.map +1 -0
  25. package/dist/sqlite.cjs +2187 -30
  26. package/dist/sqlite.cjs.map +1 -0
  27. package/dist/sqlite.d.cts +1103 -3
  28. package/dist/sqlite.d.ts +1103 -3
  29. package/dist/sqlite.js +2133 -3
  30. package/dist/sqlite.js.map +1 -0
  31. package/dist/sqlite3.cjs +2520 -68
  32. package/dist/sqlite3.cjs.map +1 -1
  33. package/dist/sqlite3.d.cts +1102 -4
  34. package/dist/sqlite3.d.ts +1102 -4
  35. package/dist/sqlite3.js +2437 -12
  36. package/dist/sqlite3.js.map +1 -1
  37. package/package.json +1 -1
  38. package/dist/core-BPSzA-lq.cjs +0 -3259
  39. package/dist/core-BPSzA-lq.cjs.map +0 -1
  40. package/dist/core-BuSVyamf.cjs +0 -480
  41. package/dist/core-BuSVyamf.cjs.map +0 -1
  42. package/dist/core-C3xoqqDs.js +0 -403
  43. package/dist/core-C3xoqqDs.js.map +0 -1
  44. package/dist/core-CHw8vO17.js +0 -456
  45. package/dist/core-CHw8vO17.js.map +0 -1
  46. package/dist/core-CUGYxOEQ.cjs +0 -599
  47. package/dist/core-CUGYxOEQ.cjs.map +0 -1
  48. package/dist/core-IV7or0Mj.js +0 -2278
  49. package/dist/core-IV7or0Mj.js.map +0 -1
  50. package/dist/index-BJC_v03L.d.ts +0 -192
  51. package/dist/index-CfH0u2y_.d.cts +0 -1682
  52. package/dist/index-DP9b7v4e.d.cts +0 -192
  53. package/dist/index-QWEAqtHF.d.ts +0 -1682
  54. package/dist/index-qxECrBHo.d.ts +0 -75
  55. package/dist/index-tS9lpLPz.d.cts +0 -75
  56. package/dist/postgreSQLMetadata-CCsCJ-eH.cjs +0 -118
  57. package/dist/postgreSQLMetadata-CCsCJ-eH.cjs.map +0 -1
  58. package/dist/postgreSQLMetadata-bCBDGz1f.js +0 -65
  59. package/dist/postgreSQLMetadata-bCBDGz1f.js.map +0 -1
  60. package/dist/sqliteMetadata-Cc7Z03lm.cjs +0 -46
  61. package/dist/sqliteMetadata-Cc7Z03lm.cjs.map +0 -1
  62. package/dist/sqliteMetadata-CvvEc1-v.js +0 -29
  63. package/dist/sqliteMetadata-CvvEc1-v.js.map +0 -1
package/dist/pg.js CHANGED
@@ -1,8 +1,2032 @@
1
- import { On as mapSQLQueryResult, an as createAmbientConnectionPool, d as tracer, dt as JSONSerializer, kn as sqlExecutor, nn as canHandleDriverWithConnectionString, pn as createConnection, rn as dumboDatabaseDriverRegistry, sn as createConnectionPool, xn as BatchCommandNoChangesError } from "./core-IV7or0Mj.js";
2
- import { a as tableExists, c as defaultPostgreSQLConnectionString, i as functionExistsSQL, l as parseDatabaseName, n as defaultPostgreSqlDatabase, o as tableExistsSQL, r as functionExists, s as PostgreSQLConnectionString, t as postgreSQLMetadata } from "./postgreSQLMetadata-bCBDGz1f.js";
3
- import { a as PostgreSQLArrayProcessor, c as AdvisoryLock, d as releaseAdvisoryLock, f as tryAcquireAdvisoryLock, i as postgreSQLColumnProcessors, l as acquireAdvisoryLock, n as PostgreSQLJSON, o as PostgreSQLExpandSQLInProcessor, p as mapPostgresError, r as pgFormatter, s as DefaultPostgreSQLMigratorOptions, t as PostgreSQLDatabaseName, u as advisoryLock } from "./core-C3xoqqDs.js";
1
+ import "uuid";
2
+ import ansis from "ansis";
4
3
  import pg from "pg";
5
4
 
5
+ //#region src/storage/postgresql/core/connections/connectionString.ts
6
+ const defaultPostgreSQLConnectionString = "postgresql://postgres@localhost:5432/postgres";
7
+ const PostgreSQLConnectionString = (connectionString) => {
8
+ if (!connectionString.startsWith("postgresql://") && !connectionString.startsWith("postgres://")) throw new Error(`Invalid PostgreSQL connection string: ${connectionString}. It should start with "postgresql://".`);
9
+ return connectionString;
10
+ };
11
+ /**
12
+ * Parse database name from a PostgreSQL connection string
13
+ */
14
+ function parseDatabaseName(str) {
15
+ if (str.charAt(0) === "/") return str.split(" ")[1] || null;
16
+ if (/ |%[^a-f0-9]|%[a-f0-9][^a-f0-9]/i.test(str)) str = encodeURI(str).replace(/%25(\d\d)/g, "%$1");
17
+ let result;
18
+ try {
19
+ result = new URL(str, "postgres://base");
20
+ } catch {
21
+ try {
22
+ result = new URL(str.replace("@/", "@___DUMMY___/"), "postgres://base");
23
+ } catch {
24
+ return null;
25
+ }
26
+ }
27
+ if (result.protocol === "socket:") return result.searchParams.get("db");
28
+ const pathname = result.pathname.slice(1) || null;
29
+ return pathname ? decodeURI(pathname) : null;
30
+ }
31
+
32
+ //#endregion
33
+ //#region src/core/errors/index.ts
34
+ const isNumber = (val) => typeof val === "number" && val === val;
35
+ const isString = (val) => typeof val === "string";
36
+ var DumboError = class DumboError extends Error {
37
+ static ErrorCode = 500;
38
+ static ErrorType = "DumboError";
39
+ errorCode;
40
+ errorType;
41
+ innerError;
42
+ constructor(options) {
43
+ const errorCode = options && typeof options === "object" && "errorCode" in options ? options.errorCode : isNumber(options) ? options : DumboError.ErrorCode;
44
+ const errorType = options && typeof options === "object" && "errorType" in options ? options.errorType ?? DumboError.ErrorType : DumboError.ErrorType;
45
+ const message = options && typeof options === "object" && "message" in options ? options.message : isString(options) ? options : `Error with status code '${errorCode}' ocurred during DumboError processing`;
46
+ const innerError = options && typeof options === "object" && "innerError" in options ? options.innerError : void 0;
47
+ super(message, { cause: innerError });
48
+ this.errorCode = errorCode;
49
+ this.errorType = errorType;
50
+ this.innerError = innerError;
51
+ Object.setPrototypeOf(this, DumboError.prototype);
52
+ }
53
+ static isInstanceOf(error, options) {
54
+ if (typeof error !== "object" || error === null || !("errorCode" in error) || !isNumber(error.errorCode) || !("errorType" in error) || !isString(error.errorType)) return false;
55
+ if (!options) return true;
56
+ if (options.errorCode !== void 0 && error.errorCode !== options.errorCode) return false;
57
+ if (options.errorType !== void 0 && error.errorType !== options.errorType) return false;
58
+ return true;
59
+ }
60
+ };
61
+ var TransientDatabaseError = class TransientDatabaseError extends DumboError {
62
+ static ErrorCode = 503;
63
+ static ErrorType = "TransientDatabaseError";
64
+ constructor(message, innerError) {
65
+ super({
66
+ errorCode: TransientDatabaseError.ErrorCode,
67
+ errorType: TransientDatabaseError.ErrorType,
68
+ message: message ?? `A transient error occurred during database operation. Retrying the operation might succeed.`,
69
+ innerError
70
+ });
71
+ Object.setPrototypeOf(this, TransientDatabaseError.prototype);
72
+ }
73
+ };
74
+ var ConnectionError = class ConnectionError extends TransientDatabaseError {
75
+ static ErrorCode = 503;
76
+ static ErrorType = "ConnectionError";
77
+ constructor(message, innerError) {
78
+ super(message ?? `A connection error occurred during database operation.`, innerError);
79
+ this.errorType = ConnectionError.ErrorType;
80
+ Object.setPrototypeOf(this, ConnectionError.prototype);
81
+ }
82
+ };
83
+ var SerializationError = class SerializationError extends TransientDatabaseError {
84
+ static ErrorCode = 503;
85
+ static ErrorType = "SerializationError";
86
+ constructor(message, innerError) {
87
+ super(message ?? `A serialization failure occurred. The transaction can be retried.`, innerError);
88
+ this.errorType = SerializationError.ErrorType;
89
+ Object.setPrototypeOf(this, SerializationError.prototype);
90
+ }
91
+ };
92
+ var DeadlockError = class DeadlockError extends TransientDatabaseError {
93
+ static ErrorCode = 503;
94
+ static ErrorType = "DeadlockError";
95
+ constructor(message, innerError) {
96
+ super(message ?? `A deadlock was detected. The transaction can be retried.`, innerError);
97
+ this.errorType = DeadlockError.ErrorType;
98
+ Object.setPrototypeOf(this, DeadlockError.prototype);
99
+ }
100
+ };
101
+ var LockNotAvailableError = class LockNotAvailableError extends TransientDatabaseError {
102
+ static ErrorCode = 503;
103
+ static ErrorType = "LockNotAvailableError";
104
+ constructor(message, innerError) {
105
+ super(message ?? `The requested lock is not available.`, innerError);
106
+ this.errorType = LockNotAvailableError.ErrorType;
107
+ Object.setPrototypeOf(this, LockNotAvailableError.prototype);
108
+ }
109
+ };
110
+ var InsufficientResourcesError = class InsufficientResourcesError extends TransientDatabaseError {
111
+ static ErrorCode = 503;
112
+ static ErrorType = "InsufficientResourcesError";
113
+ constructor(message, innerError) {
114
+ super(message ?? `Insufficient resources to complete the database operation (e.g. disk full, out of memory, too many connections).`, innerError);
115
+ this.errorType = InsufficientResourcesError.ErrorType;
116
+ Object.setPrototypeOf(this, InsufficientResourcesError.prototype);
117
+ }
118
+ };
119
+ var SystemError = class SystemError extends TransientDatabaseError {
120
+ static ErrorCode = 503;
121
+ static ErrorType = "SystemError";
122
+ constructor(message, innerError) {
123
+ super(message ?? `A system-level error occurred (e.g. I/O error).`, innerError);
124
+ this.errorType = SystemError.ErrorType;
125
+ Object.setPrototypeOf(this, SystemError.prototype);
126
+ }
127
+ };
128
+ var AdminShutdownError = class AdminShutdownError extends TransientDatabaseError {
129
+ static ErrorCode = 503;
130
+ static ErrorType = "AdminShutdownError";
131
+ constructor(message, innerError) {
132
+ super(message ?? `The database server is shutting down or restarting.`, innerError);
133
+ this.errorType = AdminShutdownError.ErrorType;
134
+ Object.setPrototypeOf(this, AdminShutdownError.prototype);
135
+ }
136
+ };
137
+ var QueryCanceledError = class QueryCanceledError extends TransientDatabaseError {
138
+ static ErrorCode = 503;
139
+ static ErrorType = "QueryCanceledError";
140
+ constructor(message, innerError) {
141
+ super(message ?? `The query was canceled, e.g. due to statement timeout or user request.`, innerError);
142
+ this.errorType = QueryCanceledError.ErrorType;
143
+ Object.setPrototypeOf(this, QueryCanceledError.prototype);
144
+ }
145
+ };
146
+ var IntegrityConstraintViolationError = class IntegrityConstraintViolationError extends DumboError {
147
+ static ErrorCode = 409;
148
+ static ErrorType = "IntegrityConstraintViolationError";
149
+ constructor(message, innerError) {
150
+ super({
151
+ errorCode: IntegrityConstraintViolationError.ErrorCode,
152
+ errorType: IntegrityConstraintViolationError.ErrorType,
153
+ message: message ?? `An integrity constraint violation occurred!`,
154
+ innerError
155
+ });
156
+ Object.setPrototypeOf(this, IntegrityConstraintViolationError.prototype);
157
+ }
158
+ };
159
+ var UniqueConstraintError = class UniqueConstraintError extends IntegrityConstraintViolationError {
160
+ static ErrorCode = 409;
161
+ static ErrorType = "UniqueConstraintError";
162
+ constructor(message, innerError) {
163
+ super(message ?? `Unique constraint violation occurred!`, innerError);
164
+ this.errorType = UniqueConstraintError.ErrorType;
165
+ Object.setPrototypeOf(this, UniqueConstraintError.prototype);
166
+ }
167
+ };
168
+ var ForeignKeyViolationError = class ForeignKeyViolationError extends IntegrityConstraintViolationError {
169
+ static ErrorCode = 409;
170
+ static ErrorType = "ForeignKeyViolationError";
171
+ constructor(message, innerError) {
172
+ super(message ?? `Foreign key constraint violation occurred!`, innerError);
173
+ this.errorType = ForeignKeyViolationError.ErrorType;
174
+ Object.setPrototypeOf(this, ForeignKeyViolationError.prototype);
175
+ }
176
+ };
177
+ var NotNullViolationError = class NotNullViolationError extends IntegrityConstraintViolationError {
178
+ static ErrorCode = 409;
179
+ static ErrorType = "NotNullViolationError";
180
+ constructor(message, innerError) {
181
+ super(message ?? `NOT NULL constraint violation occurred!`, innerError);
182
+ this.errorType = NotNullViolationError.ErrorType;
183
+ Object.setPrototypeOf(this, NotNullViolationError.prototype);
184
+ }
185
+ };
186
+ var CheckViolationError = class CheckViolationError extends IntegrityConstraintViolationError {
187
+ static ErrorCode = 409;
188
+ static ErrorType = "CheckViolationError";
189
+ constructor(message, innerError) {
190
+ super(message ?? `CHECK constraint violation occurred!`, innerError);
191
+ this.errorType = CheckViolationError.ErrorType;
192
+ Object.setPrototypeOf(this, CheckViolationError.prototype);
193
+ }
194
+ };
195
+ var ExclusionViolationError = class ExclusionViolationError extends IntegrityConstraintViolationError {
196
+ static ErrorCode = 409;
197
+ static ErrorType = "ExclusionViolationError";
198
+ constructor(message, innerError) {
199
+ super(message ?? `Exclusion constraint violation occurred!`, innerError);
200
+ this.errorType = ExclusionViolationError.ErrorType;
201
+ Object.setPrototypeOf(this, ExclusionViolationError.prototype);
202
+ }
203
+ };
204
+ var DataError = class DataError extends DumboError {
205
+ static ErrorCode = 400;
206
+ static ErrorType = "DataError";
207
+ constructor(message, innerError) {
208
+ super({
209
+ errorCode: DataError.ErrorCode,
210
+ errorType: DataError.ErrorType,
211
+ message: message ?? `A data error occurred (e.g. invalid value, type mismatch).`,
212
+ innerError
213
+ });
214
+ Object.setPrototypeOf(this, DataError.prototype);
215
+ }
216
+ };
217
+ var InvalidOperationError = class InvalidOperationError extends DumboError {
218
+ static ErrorCode = 400;
219
+ static ErrorType = "InvalidOperationError";
220
+ constructor(message, innerError) {
221
+ super({
222
+ errorCode: InvalidOperationError.ErrorCode,
223
+ errorType: InvalidOperationError.ErrorType,
224
+ message: message ?? `Invalid operation (e.g. syntax error, insufficient privileges, undefined table).`,
225
+ innerError
226
+ });
227
+ Object.setPrototypeOf(this, InvalidOperationError.prototype);
228
+ }
229
+ };
230
+
231
+ //#endregion
232
+ //#region src/storage/postgresql/core/errors/errorMapper.ts
233
+ /**
234
+ * Checks whether the given error looks like a PostgreSQL DatabaseError
235
+ * from the `pg` driver (has a string `code` property with a SQLSTATE value).
236
+ */
237
+ const getPostgresErrorCode = (error) => {
238
+ if (error instanceof Error && "code" in error && typeof error.code === "string") return error.code;
239
+ };
240
+ const getErrorMessage = (error) => error instanceof Error ? error.message : void 0;
241
+ const asError = (error) => error instanceof Error ? error : void 0;
242
+ /**
243
+ * Maps a PostgreSQL error (from the `pg` driver) to a typed DumboError
244
+ * based on the SQLSTATE code.
245
+ *
246
+ * SQLSTATE reference: https://www.postgresql.org/docs/current/errcodes-appendix.html
247
+ * Transient classification based on Npgsql's PostgresException.IsTransient.
248
+ *
249
+ * Falls back to a generic DumboError (500) if the error is not a recognized PostgreSQL error.
250
+ */
251
+ const mapPostgresError = (error) => {
252
+ if (DumboError.isInstanceOf(error)) return error;
253
+ const code = getPostgresErrorCode(error);
254
+ if (!code) return new DumboError({
255
+ errorCode: 500,
256
+ message: getErrorMessage(error),
257
+ innerError: asError(error)
258
+ });
259
+ const message = getErrorMessage(error);
260
+ const innerError = asError(error);
261
+ switch (code) {
262
+ case "23505": return new UniqueConstraintError(message, innerError);
263
+ case "23503": return new ForeignKeyViolationError(message, innerError);
264
+ case "23502": return new NotNullViolationError(message, innerError);
265
+ case "23514": return new CheckViolationError(message, innerError);
266
+ case "23P01": return new ExclusionViolationError(message, innerError);
267
+ case "40001": return new SerializationError(message, innerError);
268
+ case "40P01": return new DeadlockError(message, innerError);
269
+ case "55P03":
270
+ case "55006": return new LockNotAvailableError(message, innerError);
271
+ case "57014": return new QueryCanceledError(message, innerError);
272
+ case "57P01":
273
+ case "57P02": return new AdminShutdownError(message, innerError);
274
+ case "57P03":
275
+ case "57P05": return new ConnectionError(message, innerError);
276
+ }
277
+ switch (code.slice(0, 2)) {
278
+ case "08": return new ConnectionError(message, innerError);
279
+ case "22": return new DataError(message, innerError);
280
+ case "23": return new IntegrityConstraintViolationError(message, innerError);
281
+ case "42": return new InvalidOperationError(message, innerError);
282
+ case "53": return new InsufficientResourcesError(message, innerError);
283
+ case "57": return new ConnectionError(message, innerError);
284
+ case "58": return new SystemError(message, innerError);
285
+ }
286
+ return new DumboError({
287
+ errorCode: 500,
288
+ message,
289
+ innerError
290
+ });
291
+ };
292
+
293
+ //#endregion
294
+ //#region src/core/execute/execute.ts
295
+ const mapSQLQueryResult = (result, mapping) => {
296
+ if (typeof result !== "object" || result === null) return result;
297
+ const mappedResult = { ...result };
298
+ for (const column of Object.keys(mapping)) if (column in mappedResult) mappedResult[column] = mapping[column](mappedResult[column]);
299
+ return mappedResult;
300
+ };
301
+ var BatchCommandNoChangesError = class BatchCommandNoChangesError extends DumboError {
302
+ static ErrorCode = 409;
303
+ static ErrorType = "BatchCommandNoChangesError";
304
+ statementIndex;
305
+ constructor(statementIndex) {
306
+ super({
307
+ errorCode: BatchCommandNoChangesError.ErrorCode,
308
+ errorType: BatchCommandNoChangesError.ErrorType,
309
+ message: `Batch command at index ${statementIndex} affected no rows`
310
+ });
311
+ this.name = "BatchCommandNoChangesError";
312
+ this.statementIndex = statementIndex;
313
+ Object.setPrototypeOf(this, BatchCommandNoChangesError.prototype);
314
+ }
315
+ };
316
+ const sqlExecutor = (sqlExecutor, options) => ({
317
+ query: (sql, queryOptions) => executeInNewDbClient((client) => sqlExecutor.query(client, sql, queryOptions), options),
318
+ batchQuery: (sqls, queryOptions) => executeInNewDbClient((client) => sqlExecutor.batchQuery(client, sqls, queryOptions), options),
319
+ command: (sql, commandOptions) => executeInNewDbClient((client) => sqlExecutor.command(client, sql, commandOptions), options),
320
+ batchCommand: (sqls, commandOptions) => executeInNewDbClient((client) => sqlExecutor.batchCommand(client, sqls, commandOptions), options)
321
+ });
322
+ const sqlExecutorInNewConnection = (options) => ({
323
+ query: (sql, queryOptions) => executeInNewConnection((connection) => connection.execute.query(sql, queryOptions), options),
324
+ batchQuery: (sqls, queryOptions) => executeInNewConnection((connection) => connection.execute.batchQuery(sqls, queryOptions), options),
325
+ command: (sql, commandOptions) => executeInNewConnection((connection) => connection.execute.command(sql, commandOptions), options),
326
+ batchCommand: (sqls, commandOptions) => executeInNewConnection((connection) => connection.execute.batchCommand(sqls, commandOptions), options)
327
+ });
328
+ const executeInNewDbClient = async (handle, options) => {
329
+ const { connect, close } = options;
330
+ const client = await connect();
331
+ try {
332
+ return await handle(client);
333
+ } catch (error) {
334
+ if (close) await close(client, error);
335
+ throw error;
336
+ }
337
+ };
338
+ const executeInNewConnection = async (handle, options) => {
339
+ const connection = await options.connection();
340
+ try {
341
+ return await handle(connection);
342
+ } finally {
343
+ await connection.close();
344
+ }
345
+ };
346
+
347
+ //#endregion
348
+ //#region src/core/connections/transaction.ts
349
+ const transactionNestingCounter = () => {
350
+ let transactionLevel = 0;
351
+ return {
352
+ reset: () => {
353
+ transactionLevel = 0;
354
+ },
355
+ increment: () => {
356
+ transactionLevel++;
357
+ },
358
+ decrement: () => {
359
+ transactionLevel--;
360
+ if (transactionLevel < 0) throw new Error("Transaction level is out of bounds");
361
+ },
362
+ get level() {
363
+ return transactionLevel;
364
+ }
365
+ };
366
+ };
367
+ const databaseTransaction = (backend, options) => {
368
+ const allowNestedTransactions = options?.allowNestedTransactions ?? false;
369
+ const useSavepoints = options?.useSavepoints ?? false;
370
+ const counter = transactionNestingCounter();
371
+ let hasBegun = false;
372
+ return {
373
+ begin: async () => {
374
+ if (!allowNestedTransactions && hasBegun) throw new InvalidOperationError("Cannot start a nested transaction: allowNestedTransactions is false. Set transactionOptions: { allowNestedTransactions: true } on your pool or connection.");
375
+ if (allowNestedTransactions) {
376
+ if (counter.level >= 1) {
377
+ counter.increment();
378
+ if (useSavepoints && backend.savepoint) await backend.savepoint(counter.level);
379
+ return;
380
+ }
381
+ counter.increment();
382
+ }
383
+ hasBegun = true;
384
+ await backend.begin();
385
+ },
386
+ commit: async () => {
387
+ if (allowNestedTransactions && counter.level > 1) {
388
+ if (useSavepoints && backend.releaseSavepoint) await backend.releaseSavepoint(counter.level);
389
+ counter.decrement();
390
+ return;
391
+ }
392
+ if (allowNestedTransactions) counter.reset();
393
+ hasBegun = false;
394
+ await backend.commit();
395
+ },
396
+ rollback: async (error) => {
397
+ if (allowNestedTransactions && counter.level > 1) {
398
+ if (useSavepoints && backend.rollbackToSavepoint) await backend.rollbackToSavepoint(counter.level);
399
+ counter.decrement();
400
+ return;
401
+ }
402
+ if (allowNestedTransactions) counter.reset();
403
+ hasBegun = false;
404
+ await backend.rollback(error);
405
+ }
406
+ };
407
+ };
408
+ const toTransactionResult = (transactionResult) => transactionResult !== void 0 && transactionResult !== null && typeof transactionResult === "object" && "success" in transactionResult ? transactionResult : {
409
+ success: true,
410
+ result: transactionResult
411
+ };
412
+ const executeInTransaction = async (transaction, handle) => {
413
+ await transaction.begin();
414
+ try {
415
+ const { success, result } = toTransactionResult(await handle(transaction));
416
+ if (success) await transaction.commit();
417
+ else await transaction.rollback();
418
+ return result;
419
+ } catch (e) {
420
+ await transaction.rollback();
421
+ throw e;
422
+ }
423
+ };
424
+ const transactionFactoryWithDbClient = (connect, initTransaction) => {
425
+ let currentTransaction = void 0;
426
+ const getOrInitCurrentTransaction = (options) => currentTransaction ?? (currentTransaction = initTransaction(connect(), {
427
+ close: () => {
428
+ currentTransaction = void 0;
429
+ return Promise.resolve();
430
+ },
431
+ ...options ?? {}
432
+ }));
433
+ return {
434
+ transaction: getOrInitCurrentTransaction,
435
+ withTransaction: (handle, options) => executeInTransaction(getOrInitCurrentTransaction(options), handle)
436
+ };
437
+ };
438
+ const wrapInConnectionClosure = async (connection, handle) => {
439
+ try {
440
+ return await handle();
441
+ } finally {
442
+ await connection.close();
443
+ }
444
+ };
445
+ const transactionFactoryWithNewConnection = (connect) => ({
446
+ transaction: (options) => {
447
+ const connection = connect();
448
+ const transaction = connection.transaction(options);
449
+ return {
450
+ ...transaction,
451
+ commit: () => wrapInConnectionClosure(connection, () => transaction.commit()),
452
+ rollback: () => wrapInConnectionClosure(connection, () => transaction.rollback())
453
+ };
454
+ },
455
+ withTransaction: (handle, options) => {
456
+ const connection = connect();
457
+ const withTx = connection.withTransaction;
458
+ return wrapInConnectionClosure(connection, () => withTx(handle, options));
459
+ }
460
+ });
461
+
462
+ //#endregion
463
+ //#region src/core/connections/connection.ts
464
+ const createConnection = (options) => {
465
+ const { driverType, connect, close, initTransaction, executor, serializer } = options;
466
+ let client = null;
467
+ let connectPromise = null;
468
+ const getClient = async () => {
469
+ if (client) return client;
470
+ if (!connectPromise) connectPromise = connect().then((c) => {
471
+ client = c;
472
+ return c;
473
+ });
474
+ return connectPromise;
475
+ };
476
+ const typedConnection = {
477
+ driverType,
478
+ open: getClient,
479
+ close: () => client ? close(client) : Promise.resolve(),
480
+ ...transactionFactoryWithDbClient(getClient, initTransaction(() => typedConnection)),
481
+ execute: sqlExecutor(executor({ serializer }), { connect: getClient }),
482
+ _transactionType: void 0
483
+ };
484
+ return typedConnection;
485
+ };
486
+
487
+ //#endregion
488
+ //#region src/core/connections/pool.ts
489
+ const createAmbientConnectionPool = (options) => {
490
+ const { driverType, connection } = options;
491
+ return createConnectionPool({
492
+ driverType,
493
+ getConnection: () => connection,
494
+ execute: connection.execute,
495
+ transaction: (options) => connection.transaction(options),
496
+ withConnection: (handle, _options) => handle(connection),
497
+ withTransaction: (handle, options) => {
498
+ const withTx = connection.withTransaction;
499
+ return withTx(handle, options);
500
+ }
501
+ });
502
+ };
503
+ const createConnectionPool = (pool) => {
504
+ const { driverType, getConnection } = pool;
505
+ const connection = "connection" in pool ? pool.connection : () => Promise.resolve(getConnection());
506
+ return {
507
+ driverType,
508
+ connection,
509
+ withConnection: "withConnection" in pool ? pool.withConnection : (handle, _options) => executeInNewConnection(handle, { connection }),
510
+ close: "close" in pool ? pool.close : () => Promise.resolve(),
511
+ execute: "execute" in pool ? pool.execute : sqlExecutorInNewConnection({
512
+ driverType,
513
+ connection
514
+ }),
515
+ ..."transaction" in pool && "withTransaction" in pool ? {
516
+ transaction: pool.transaction,
517
+ withTransaction: pool.withTransaction
518
+ } : transactionFactoryWithNewConnection(getConnection)
519
+ };
520
+ };
521
+
522
+ //#endregion
523
+ //#region src/core/drivers/databaseDriver.ts
524
+ const canHandleDriverWithConnectionString = (driver, tryParseConnectionString) => (options) => {
525
+ if ("driverType" in options) return options.driverType === driver;
526
+ if ("connectionString" in options && typeof options.connectionString === "string") return tryParseConnectionString(options.connectionString) !== null;
527
+ return false;
528
+ };
529
+ const DumboDatabaseDriverRegistry = () => {
530
+ const drivers = /* @__PURE__ */ new Map();
531
+ const register = (driverType, plugin) => {
532
+ const entry = drivers.get(driverType);
533
+ if (entry && (typeof entry !== "function" || typeof plugin === "function")) return;
534
+ drivers.set(driverType, plugin);
535
+ };
536
+ const getDriver = (options) => options.driverType ? drivers.get(options.driverType) : [...drivers.values()].find((d) => typeof d !== "function" && d.canHandle(options));
537
+ const tryResolve = async (options) => {
538
+ const driver = getDriver(options);
539
+ if (!driver) return null;
540
+ if (typeof driver !== "function") return driver;
541
+ const plugin = await driver();
542
+ register(plugin.driverType, plugin);
543
+ return plugin;
544
+ };
545
+ const tryGet = (options) => {
546
+ const driver = getDriver(options);
547
+ return driver && typeof driver !== "function" ? driver : null;
548
+ };
549
+ const has = (driverType) => drivers.has(driverType);
550
+ return {
551
+ register,
552
+ tryResolve,
553
+ tryGet,
554
+ has,
555
+ get databaseDriverTypes() {
556
+ return Array.from(drivers.keys());
557
+ }
558
+ };
559
+ };
560
+ const dumboDatabaseDriverRegistry = globalThis.dumboDatabaseDriverRegistry = globalThis.dumboDatabaseDriverRegistry ?? DumboDatabaseDriverRegistry();
561
+
562
+ //#endregion
563
+ //#region src/core/locks/databaseLock.ts
564
+ const defaultDatabaseLockOptions = { timeoutMs: 1e4 };
565
+
566
+ //#endregion
567
+ //#region src/core/query/selectors.ts
568
+ const single = async (getResult) => {
569
+ const result = await getResult;
570
+ if (result.rows.length === 0) throw new Error("Query didn't return any result");
571
+ if (result.rows.length > 1) throw new Error("Query had more than one result");
572
+ return result.rows[0];
573
+ };
574
+ const exists = async (getResult) => {
575
+ const result = await single(getResult);
576
+ return result.exists === true || result.exists === 1;
577
+ };
578
+
579
+ //#endregion
580
+ //#region src/core/schema/schemaComponent.ts
581
+ const schemaComponent = (key, options) => {
582
+ const componentsMap = new Map(options.components?.map((comp) => [comp.schemaComponentKey, comp]));
583
+ const migrations = [...options.migrations ?? []];
584
+ return {
585
+ schemaComponentKey: key,
586
+ components: componentsMap,
587
+ get migrations() {
588
+ return [...migrations, ...Array.from(componentsMap.values()).flatMap((c) => c.migrations)];
589
+ },
590
+ addComponent: (component) => {
591
+ componentsMap.set(component.schemaComponentKey, component);
592
+ migrations.push(...component.migrations);
593
+ return component;
594
+ },
595
+ addMigration: (migration) => {
596
+ migrations.push(migration);
597
+ }
598
+ };
599
+ };
600
+ const isSchemaComponentOfType = (component, prefix) => component.schemaComponentKey.startsWith(prefix);
601
+ const mapSchemaComponentsOfType = (components, prefix, keyMapper) => new Map(Array.from(components.entries()).filter(([urn]) => urn.startsWith(prefix)).map(([urn, component]) => [keyMapper ? keyMapper(component) : urn, component]));
602
+
603
+ //#endregion
604
+ //#region src/core/schema/components/columnSchemaComponent.ts
605
+ const ColumnURNType = "sc:dumbo:column";
606
+ const ColumnURN = ({ name }) => `${ColumnURNType}:${name}`;
607
+ const columnSchemaComponent = (params) => {
608
+ const { columnName, type, notNull, unique, primaryKey, default: defaultValue, ...schemaOptions } = params;
609
+ return {
610
+ ...schemaComponent(ColumnURN({ name: columnName }), schemaOptions),
611
+ columnName,
612
+ notNull,
613
+ unique,
614
+ primaryKey,
615
+ defaultValue,
616
+ sqlTokenType: "SQL_COLUMN",
617
+ name: columnName,
618
+ type
619
+ };
620
+ };
621
+
622
+ //#endregion
623
+ //#region src/core/schema/components/indexSchemaComponent.ts
624
+ const IndexURNType = "sc:dumbo:index";
625
+
626
+ //#endregion
627
+ //#region src/core/schema/components/tableSchemaComponent.ts
628
+ const TableURNType = "sc:dumbo:table";
629
+ const TableURN = ({ name }) => `${TableURNType}:${name}`;
630
+ const tableSchemaComponent = ({ tableName, columns, primaryKey, relationships, ...migrationsOrComponents }) => {
631
+ columns ??= {};
632
+ relationships ??= {};
633
+ const base = schemaComponent(TableURN({ name: tableName }), {
634
+ migrations: migrationsOrComponents.migrations ?? [],
635
+ components: [...migrationsOrComponents.components ?? [], ...Object.values(columns)]
636
+ });
637
+ return {
638
+ ...base,
639
+ tableName,
640
+ primaryKey: primaryKey ?? [],
641
+ relationships,
642
+ get columns() {
643
+ const columnsMap = mapSchemaComponentsOfType(base.components, ColumnURNType, (c) => c.columnName);
644
+ return Object.assign(columnsMap, columns);
645
+ },
646
+ get indexes() {
647
+ return mapSchemaComponentsOfType(base.components, IndexURNType, (c) => c.indexName);
648
+ },
649
+ addColumn: (column) => base.addComponent(column),
650
+ addIndex: (index) => base.addComponent(index)
651
+ };
652
+ };
653
+
654
+ //#endregion
655
+ //#region src/core/schema/components/databaseSchemaSchemaComponent.ts
656
+ const DatabaseSchemaURNType = "sc:dumbo:database_schema";
657
+ const DatabaseSchemaURN = ({ name }) => `${DatabaseSchemaURNType}:${name}`;
658
+ const databaseSchemaSchemaComponent = ({ schemaName, tables, ...migrationsOrComponents }) => {
659
+ const base = schemaComponent(DatabaseSchemaURN({ name: schemaName }), {
660
+ migrations: migrationsOrComponents.migrations ?? [],
661
+ components: [...migrationsOrComponents.components ?? [], ...Object.values(tables ?? {})]
662
+ });
663
+ return {
664
+ ...base,
665
+ schemaName,
666
+ get tables() {
667
+ const tablesMap = mapSchemaComponentsOfType(base.components, TableURNType, (c) => c.tableName);
668
+ return Object.assign(tablesMap, tables);
669
+ },
670
+ addTable: (table) => base.addComponent(typeof table === "string" ? tableSchemaComponent({ tableName: table }) : table)
671
+ };
672
+ };
673
+
674
+ //#endregion
675
+ //#region src/core/schema/components/databaseSchemaComponent.ts
676
+ const DatabaseURNType = "sc:dumbo:database";
677
+ const DatabaseURN = ({ name }) => `${DatabaseURNType}:${name}`;
678
+ const databaseSchemaComponent = ({ databaseName, schemas, ...migrationsOrComponents }) => {
679
+ schemas ??= {};
680
+ const base = schemaComponent(DatabaseURN({ name: databaseName }), {
681
+ migrations: migrationsOrComponents.migrations ?? [],
682
+ components: [...migrationsOrComponents.components ?? [], ...Object.values(schemas)]
683
+ });
684
+ return {
685
+ ...base,
686
+ databaseName,
687
+ get schemas() {
688
+ const schemasMap = mapSchemaComponentsOfType(base.components, DatabaseSchemaURNType, (c) => c.schemaName);
689
+ return Object.assign(schemasMap, schemas);
690
+ },
691
+ addSchema: (schema) => base.addComponent(typeof schema === "string" ? databaseSchemaSchemaComponent({ schemaName: schema }) : schema)
692
+ };
693
+ };
694
+
695
+ //#endregion
696
+ //#region src/core/schema/databaseMetadata/databaseMetadata.ts
697
+ const DumboDatabaseMetadataRegistry = () => {
698
+ const infos = /* @__PURE__ */ new Map();
699
+ const register = (databaseType, info) => {
700
+ const entry = infos.get(databaseType);
701
+ if (entry && (typeof entry !== "function" || typeof info === "function")) return;
702
+ infos.set(databaseType, info);
703
+ };
704
+ const tryResolve = async (databaseType) => {
705
+ const entry = infos.get(databaseType);
706
+ if (!entry) return null;
707
+ if (typeof entry !== "function") return entry;
708
+ const resolved = await entry();
709
+ register(databaseType, resolved);
710
+ return resolved;
711
+ };
712
+ const tryGet = (databaseType) => {
713
+ const entry = infos.get(databaseType);
714
+ return entry && typeof entry !== "function" ? entry : null;
715
+ };
716
+ const has = (databaseType) => infos.has(databaseType);
717
+ return {
718
+ register,
719
+ tryResolve,
720
+ tryGet,
721
+ has,
722
+ get databaseTypes() {
723
+ return Array.from(infos.keys());
724
+ }
725
+ };
726
+ };
727
+ const dumboDatabaseMetadataRegistry$1 = globalThis.dumboDatabaseMetadataRegistry = globalThis.dumboDatabaseMetadataRegistry ?? DumboDatabaseMetadataRegistry();
728
+
729
+ //#endregion
730
+ //#region src/core/schema/dumboSchema/dumboSchema.ts
731
+ const DEFAULT_DATABASE_NAME = "__default_database__";
732
+ const DEFAULT_DATABASE_SCHEMA_NAME = "__default_database_schema__";
733
+ const dumboTable = (name, definition) => {
734
+ const { columns, indexes, primaryKey, relationships, ...options } = definition;
735
+ const components = [...indexes ? Object.values(indexes) : []];
736
+ return tableSchemaComponent({
737
+ tableName: name,
738
+ columns: columns ?? {},
739
+ primaryKey: primaryKey ?? [],
740
+ ...relationships !== void 0 ? { relationships } : {},
741
+ components,
742
+ ...options
743
+ });
744
+ };
745
+ function dumboDatabaseSchema(nameOrTables, tables, options) {
746
+ return databaseSchemaSchemaComponent({
747
+ schemaName: typeof nameOrTables === "string" ? nameOrTables : DEFAULT_DATABASE_SCHEMA_NAME,
748
+ tables: (typeof nameOrTables === "string" ? tables : nameOrTables) ?? {},
749
+ ...options
750
+ });
751
+ }
752
+ dumboDatabaseSchema.from = (schemaName, tableNames) => {
753
+ const tables = tableNames.reduce((acc, tableName) => {
754
+ acc[tableName] = dumboTable(tableName, {});
755
+ return acc;
756
+ }, {});
757
+ return schemaName ? dumboDatabaseSchema(schemaName, tables) : dumboDatabaseSchema(tables);
758
+ };
759
+ function dumboDatabase(nameOrSchemas, schemasOrOptions, options) {
760
+ const databaseName = typeof nameOrSchemas === "string" ? nameOrSchemas : DEFAULT_DATABASE_NAME;
761
+ const schemasOrSchema = typeof nameOrSchemas === "string" ? schemasOrOptions ?? {} : nameOrSchemas;
762
+ return databaseSchemaComponent({
763
+ databaseName,
764
+ schemas: "schemaComponentKey" in schemasOrSchema && isSchemaComponentOfType(schemasOrSchema, "sc:dumbo:database_schema") ? { [DEFAULT_DATABASE_SCHEMA_NAME]: schemasOrSchema } : schemasOrSchema,
765
+ ...typeof nameOrSchemas === "string" ? options : schemasOrOptions
766
+ });
767
+ }
768
+ dumboDatabase.from = (databaseName, schemaNames) => {
769
+ const schemas = schemaNames.reduce((acc, schemaName) => {
770
+ acc[schemaName] = dumboDatabaseSchema(schemaName, {});
771
+ return acc;
772
+ }, {});
773
+ return databaseName ? dumboDatabase(databaseName, schemas) : dumboDatabase(schemas);
774
+ };
775
+ dumboDatabase.defaultName = DEFAULT_DATABASE_NAME;
776
+ dumboDatabaseSchema.defaultName = DEFAULT_DATABASE_SCHEMA_NAME;
777
+
778
+ //#endregion
779
+ //#region src/core/serializer/json/index.ts
780
+ const bigIntReplacer = (_key, value) => {
781
+ return typeof value === "bigint" ? value.toString() : value;
782
+ };
783
+ const dateReplacer = (_key, value) => {
784
+ return value instanceof Date ? value.toISOString() : value;
785
+ };
786
+ const isFirstLetterNumeric = (str) => {
787
+ const c = str.charCodeAt(0);
788
+ return c >= 48 && c <= 57;
789
+ };
790
+ const isFirstLetterNumericOrMinus = (str) => {
791
+ const c = str.charCodeAt(0);
792
+ return c >= 48 && c <= 57 || c === 45;
793
+ };
794
+ const bigIntReviver = (_key, value, context) => {
795
+ if (typeof value === "number" && Number.isInteger(value) && !Number.isSafeInteger(value)) try {
796
+ return BigInt(context?.source ?? value.toString());
797
+ } catch {
798
+ return value;
799
+ }
800
+ if (typeof value === "string" && value.length > 15) {
801
+ if (isFirstLetterNumericOrMinus(value)) {
802
+ const num = Number(value);
803
+ if (Number.isFinite(num) && !Number.isSafeInteger(num)) try {
804
+ return BigInt(value);
805
+ } catch {}
806
+ }
807
+ }
808
+ return value;
809
+ };
810
+ const dateReviver = (_key, value) => {
811
+ if (typeof value === "string" && value.length === 24 && isFirstLetterNumeric(value) && value[10] === "T" && value[23] === "Z") {
812
+ const date = new Date(value);
813
+ if (!isNaN(date.getTime())) return date;
814
+ }
815
+ return value;
816
+ };
817
+ const composeJSONReplacers = (...replacers) => {
818
+ const filteredReplacers = replacers.filter((r) => r !== void 0);
819
+ if (filteredReplacers.length === 0) return void 0;
820
+ return (key, value) => filteredReplacers.reduce((accValue, replacer) => replacer(key, accValue), value);
821
+ };
822
+ const composeJSONRevivers = (...revivers) => {
823
+ const filteredRevivers = revivers.filter((r) => r !== void 0);
824
+ if (filteredRevivers.length === 0) return void 0;
825
+ return (key, value, context) => filteredRevivers.reduce((accValue, reviver) => reviver(key, accValue, context), value);
826
+ };
827
+ const JSONReplacer = (opts) => composeJSONReplacers(opts?.replacer, opts?.failOnBigIntSerialization !== true ? JSONReplacers.bigInt : void 0, opts?.useDefaultDateSerialization !== true ? JSONReplacers.date : void 0);
828
+ const JSONReviver = (opts) => composeJSONRevivers(opts?.reviver, opts?.parseBigInts === true ? JSONRevivers.bigInt : void 0, opts?.parseDates === true ? JSONRevivers.date : void 0);
829
+ const JSONReplacers = {
830
+ bigInt: bigIntReplacer,
831
+ date: dateReplacer
832
+ };
833
+ const JSONRevivers = {
834
+ bigInt: bigIntReviver,
835
+ date: dateReviver
836
+ };
837
+ const jsonSerializer = (options) => {
838
+ const defaultReplacer = JSONReplacer(options);
839
+ const defaultReviver = JSONReviver(options);
840
+ return {
841
+ serialize: (object, serializerOptions) => JSON.stringify(object, serializerOptions ? JSONReplacer(serializerOptions) : defaultReplacer),
842
+ deserialize: (payload, deserializerOptions) => JSON.parse(payload, deserializerOptions ? JSONReviver(deserializerOptions) : defaultReviver)
843
+ };
844
+ };
845
+ const JSONSerializer = Object.assign(jsonSerializer(), { from: (options) => options?.serialization?.serializer ?? (options?.serialization?.options ? jsonSerializer(options?.serialization?.options) : JSONSerializer) });
846
+
847
+ //#endregion
848
+ //#region src/core/sql/parametrizedSQL/parametrizedSQL.ts
849
+ const ParametrizedSQLBuilder = ({ mapParamPlaceholder }) => {
850
+ const sql = [];
851
+ const params = [];
852
+ return {
853
+ addSQL(str) {
854
+ sql.push(str);
855
+ return this;
856
+ },
857
+ addParam(value) {
858
+ sql.push(mapParamPlaceholder(params.length, value));
859
+ params.push(value);
860
+ return this;
861
+ },
862
+ addParams(values) {
863
+ const placeholders = values.map((value, i) => mapParamPlaceholder(params.length + i, value));
864
+ this.addSQL(`${placeholders.join(", ")}`);
865
+ params.push(...values);
866
+ return this;
867
+ },
868
+ build() {
869
+ return {
870
+ query: sql.join(""),
871
+ params
872
+ };
873
+ }
874
+ };
875
+ };
876
+
877
+ //#endregion
878
+ //#region src/core/sql/tokens/sqlToken.ts
879
+ const SQLToken = (sqlTokenType, map) => {
880
+ const factory = (input) => {
881
+ let props;
882
+ if (map !== void 0) props = map(input);
883
+ else if (input === void 0 || input === null) props = {};
884
+ else if (typeof input === "object" && !Array.isArray(input)) props = input;
885
+ else throw new Error(`Cannot create SQLToken of type ${sqlTokenType} with input: ${input}`);
886
+ return {
887
+ sqlTokenType,
888
+ [sqlTokenType]: true,
889
+ ...props
890
+ };
891
+ };
892
+ const check = (token) => SQLToken.check(token) && token.sqlTokenType === sqlTokenType;
893
+ return {
894
+ from: factory,
895
+ check,
896
+ type: sqlTokenType
897
+ };
898
+ };
899
+ SQLToken.check = (token) => token !== null && typeof token === "object" && "sqlTokenType" in token;
900
+ const SQLIdentifier = SQLToken("SQL_IDENTIFIER", (value) => ({ value }));
901
+ const SQLPlain = SQLToken("SQL_RAW", (value) => ({ value }));
902
+ const SQLLiteral = SQLToken("SQL_LITERAL", (value) => ({ value }));
903
+ const SQLArray = SQLToken("SQL_ARRAY", (input) => {
904
+ if (Array.isArray(input)) return { value: input };
905
+ return input.mode !== void 0 ? {
906
+ value: input.value,
907
+ mode: input.mode
908
+ } : { value: input.value };
909
+ });
910
+ const SQLIn = SQLToken("SQL_IN", ({ column, values, mode }) => mode !== void 0 ? {
911
+ column: SQLIdentifier.from(column),
912
+ values: SQLArray.from(values),
913
+ mode
914
+ } : {
915
+ column: SQLIdentifier.from(column),
916
+ values: SQLArray.from(values)
917
+ });
918
+
919
+ //#endregion
920
+ //#region src/core/sql/tokens/columnTokens.ts
921
+ const ColumnTypeToken = (sqlTokenType, jsTypeName, map) => {
922
+ const factory = (input) => {
923
+ let props;
924
+ if (map !== void 0) props = map(input);
925
+ else if (input === void 0 || input === null) props = {};
926
+ else if (typeof input === "object" && !Array.isArray(input)) props = input;
927
+ else throw new Error(`Cannot create SQLToken of type ${sqlTokenType} with input: ${input}`);
928
+ return {
929
+ sqlTokenType,
930
+ [sqlTokenType]: true,
931
+ jsTypeName,
932
+ ...props
933
+ };
934
+ };
935
+ const check = (token) => SQLToken.check(token) && token.sqlTokenType === sqlTokenType;
936
+ return {
937
+ from: factory,
938
+ check,
939
+ type: sqlTokenType
940
+ };
941
+ };
942
+ const SerialToken = ColumnTypeToken("SQL_COLUMN_SERIAL", "value_type:js:number");
943
+ const BigSerialToken = ColumnTypeToken("SQL_COLUMN_BIGSERIAL", "value_type:js:bigint");
944
+ const IntegerToken = ColumnTypeToken("SQL_COLUMN_INTEGER", "value_type:js:number");
945
+ const BigIntegerToken = ColumnTypeToken("SQL_COLUMN_BIGINT", "value_type:js:bigint");
946
+ const JSONBToken = {
947
+ type: "SQL_COLUMN_JSONB",
948
+ from: () => {
949
+ return {
950
+ sqlTokenType: "SQL_COLUMN_JSONB",
951
+ ["SQL_COLUMN_JSONB"]: true
952
+ };
953
+ },
954
+ check: (token) => SQLToken.check(token) && token.sqlTokenType === "SQL_COLUMN_JSONB"
955
+ };
956
+ const TimestampToken = ColumnTypeToken("SQL_COLUMN_TIMESTAMP", "value_type:js:date");
957
+ const TimestamptzToken = ColumnTypeToken("SQL_COLUMN_TIMESTAMPTZ", "value_type:js:date");
958
+ const VarcharToken = ColumnTypeToken("SQL_COLUMN_VARCHAR", "value_type:js:string", (length) => ({
959
+ length: length ?? "max",
960
+ jsTypeName: "value_type:js:string"
961
+ }));
962
+ const AutoIncrementSQLColumnToken = ColumnTypeToken("SQL_COLUMN_AUTO_INCREMENT", "value_type:js:bigint");
963
+ const SQLColumnTypeTokensFactory = {
964
+ AutoIncrement: AutoIncrementSQLColumnToken.from,
965
+ BigInteger: BigIntegerToken.from(),
966
+ BigSerial: BigSerialToken.from(),
967
+ Integer: IntegerToken.from(),
968
+ JSONB: JSONBToken.from,
969
+ Serial: SerialToken.from(),
970
+ Timestamp: TimestampToken.from(),
971
+ Timestamptz: TimestamptzToken.from(),
972
+ Varchar: VarcharToken.from
973
+ };
974
+ const SQLColumnToken = SQLToken("SQL_COLUMN");
975
+
976
+ //#endregion
977
+ //#region src/core/sql/processors/sqlProcessor.ts
978
+ const SQLProcessor = (options) => options;
979
+
980
+ //#endregion
981
+ //#region src/core/sql/processors/defaultProcessors.ts
982
+ const ExpandArrayProcessor = SQLProcessor({
983
+ canHandle: "SQL_ARRAY",
984
+ handle: (token, { builder, serializer, mapper }) => {
985
+ if (token.value.length === 0) throw new Error("Empty arrays are not supported. If you're using it with SELECT IN statement Use SQL.in(column, array) helper instead.");
986
+ builder.addParams(mapper.mapValue(token.value, serializer));
987
+ }
988
+ });
989
+ const ExpandSQLInProcessor = SQLProcessor({
990
+ canHandle: "SQL_IN",
991
+ handle: (token, context) => {
992
+ const { builder, mapper, processorsRegistry, serializer } = context;
993
+ const { values: inValues, column } = token;
994
+ if (inValues.value.length === 0) {
995
+ builder.addParam(mapper.mapValue(false, serializer));
996
+ return;
997
+ }
998
+ builder.addSQL(mapper.mapValue(column.value, serializer));
999
+ builder.addSQL(` IN (`);
1000
+ const arrayProcessor = processorsRegistry.get(SQLArray.type);
1001
+ if (!arrayProcessor) throw new Error("No sql processor registered for an array. Cannot expand IN statement");
1002
+ arrayProcessor.handle(inValues, {
1003
+ builder,
1004
+ mapper,
1005
+ processorsRegistry,
1006
+ serializer
1007
+ });
1008
+ builder.addSQL(`)`);
1009
+ }
1010
+ });
1011
+ const FormatIdentifierProcessor = SQLProcessor({
1012
+ canHandle: "SQL_IDENTIFIER",
1013
+ handle: (token, { builder, mapper, serializer }) => {
1014
+ builder.addSQL(mapper.mapValue(token, serializer));
1015
+ }
1016
+ });
1017
+ const MapLiteralProcessor = SQLProcessor({
1018
+ canHandle: "SQL_LITERAL",
1019
+ handle: (token, { builder, mapper, serializer }) => builder.addParam(mapper.mapValue(token.value, serializer))
1020
+ });
1021
+
1022
+ //#endregion
1023
+ //#region src/core/sql/processors/sqlProcessorRegistry.ts
1024
+ const SQLProcessorsRegistry = (options) => {
1025
+ const processors = options ? new Map(options.from.all()) : /* @__PURE__ */ new Map();
1026
+ function register(...args) {
1027
+ if (args.length === 1 && typeof args[0] === "object" && !Array.isArray(args[0])) Object.entries(args[0]).forEach(([_, processor]) => {
1028
+ processors.set(processor.canHandle, processor);
1029
+ });
1030
+ else args.forEach((p) => processors.set(p.canHandle, p));
1031
+ return registry;
1032
+ }
1033
+ const registry = {
1034
+ register,
1035
+ get: (tokenType) => {
1036
+ return processors.get(tokenType) ?? null;
1037
+ },
1038
+ all: () => processors
1039
+ };
1040
+ return registry;
1041
+ };
1042
+
1043
+ //#endregion
1044
+ //#region src/core/sql/processors/columnProcessors.ts
1045
+ const mapDefaultSQLColumnProcessors = (mapColumnType) => ({
1046
+ AutoIncrement: SQLProcessor({
1047
+ canHandle: "SQL_COLUMN_AUTO_INCREMENT",
1048
+ handle: (token, context) => {
1049
+ mapColumnType(token, context);
1050
+ }
1051
+ }),
1052
+ BigInteger: SQLProcessor({
1053
+ canHandle: "SQL_COLUMN_BIGINT",
1054
+ handle: (token, context) => mapColumnType(token, context)
1055
+ }),
1056
+ BigSerial: SQLProcessor({
1057
+ canHandle: "SQL_COLUMN_BIGSERIAL",
1058
+ handle: (token, context) => mapColumnType(token, context)
1059
+ }),
1060
+ Serial: SQLProcessor({
1061
+ canHandle: "SQL_COLUMN_SERIAL",
1062
+ handle: (token, context) => mapColumnType(token, context)
1063
+ }),
1064
+ Integer: SQLProcessor({
1065
+ canHandle: "SQL_COLUMN_INTEGER",
1066
+ handle: (token, context) => mapColumnType(token, context)
1067
+ }),
1068
+ JSONB: SQLProcessor({
1069
+ canHandle: "SQL_COLUMN_JSONB",
1070
+ handle: (token, context) => mapColumnType(token, context)
1071
+ }),
1072
+ Timestamp: SQLProcessor({
1073
+ canHandle: "SQL_COLUMN_TIMESTAMP",
1074
+ handle: (token, context) => mapColumnType(token, context)
1075
+ }),
1076
+ Timestamptz: SQLProcessor({
1077
+ canHandle: "SQL_COLUMN_TIMESTAMPTZ",
1078
+ handle: (token, context) => mapColumnType(token, context)
1079
+ }),
1080
+ Varchar: SQLProcessor({
1081
+ canHandle: "SQL_COLUMN_VARCHAR",
1082
+ handle: (token, context) => mapColumnType(token, context)
1083
+ })
1084
+ });
1085
+
1086
+ //#endregion
1087
+ //#region src/core/sql/processors/index.ts
1088
+ const defaultProcessorsRegistry = globalThis.defaultProcessorsRegistry = globalThis.defaultProcessorsRegistry ?? SQLProcessorsRegistry().register(FormatIdentifierProcessor, MapLiteralProcessor, ExpandArrayProcessor, ExpandSQLInProcessor);
1089
+
1090
+ //#endregion
1091
+ //#region src/core/sql/tokenizedSQL/tokenizedSQL.ts
1092
+ const TokenizedSQLBuilder = () => {
1093
+ const sqlChunks = [];
1094
+ const sqlTokens = [];
1095
+ return {
1096
+ addSQL(str) {
1097
+ sqlChunks.push(str);
1098
+ },
1099
+ addSQLs(str) {
1100
+ sqlChunks.push(...str);
1101
+ },
1102
+ addToken(value) {
1103
+ sqlTokens.push(value);
1104
+ },
1105
+ addTokens(vals) {
1106
+ sqlTokens.push(...vals);
1107
+ },
1108
+ build() {
1109
+ return sqlChunks.length > 0 ? {
1110
+ __brand: "tokenized-sql",
1111
+ sqlChunks,
1112
+ sqlTokens
1113
+ } : TokenizedSQL.empty;
1114
+ }
1115
+ };
1116
+ };
1117
+ const TokenizedSQL = (strings, values) => {
1118
+ const builder = TokenizedSQLBuilder();
1119
+ for (let i = 0; i < strings.length; i++) {
1120
+ if (strings[i] !== "") builder.addSQL(strings[i]);
1121
+ if (i >= values.length) break;
1122
+ const value = values[i];
1123
+ if (isTokenizedSQL(value)) {
1124
+ builder.addSQLs(value.sqlChunks);
1125
+ builder.addTokens(value.sqlTokens);
1126
+ } else if (SQLPlain.check(value)) builder.addSQL(value.value);
1127
+ else {
1128
+ builder.addSQL(TokenizedSQL.paramPlaceholder);
1129
+ builder.addToken(SQLToken.check(value) ? value : Array.isArray(value) ? SQLArray.from(value) : SQLLiteral.from(value));
1130
+ }
1131
+ }
1132
+ return builder.build();
1133
+ };
1134
+ const isTokenizedSQL = (value) => {
1135
+ return value !== null && typeof value === "object" && "__brand" in value && value.__brand === "tokenized-sql";
1136
+ };
1137
+ TokenizedSQL.paramPlaceholder = `__P__`;
1138
+ TokenizedSQL.empty = {
1139
+ __brand: "tokenized-sql",
1140
+ sqlChunks: [""],
1141
+ sqlTokens: []
1142
+ };
1143
+
1144
+ //#endregion
1145
+ //#region src/core/sql/sql.ts
1146
+ const createSQL = (strings, ...values) => {
1147
+ return TokenizedSQL(strings, values);
1148
+ };
1149
+ /** Returns true when the value is a tokenized SQL statement. */
1150
+ const isSQL = (value) => {
1151
+ if (value === void 0 || value === null) return false;
1152
+ return isTokenizedSQL(value);
1153
+ };
1154
+ const emptySQL = {
1155
+ __brand: "tokenized-sql",
1156
+ sqlChunks: [""],
1157
+ sqlTokens: []
1158
+ };
1159
+ const mergeSQL = (sqls, separator = " ") => {
1160
+ const parametrized = sqls.filter((sql) => !isEmpty(sql)).map((sql) => sql);
1161
+ const params = parametrized.flatMap((p) => p.sqlTokens);
1162
+ const sqlChunks = parametrized.flatMap((p, i) => i == parametrized.length - 1 || separator === "" ? p.sqlChunks : [...p.sqlChunks, separator]);
1163
+ return sqlChunks.length > 0 ? {
1164
+ __brand: "tokenized-sql",
1165
+ sqlChunks,
1166
+ sqlTokens: params
1167
+ } : TokenizedSQL.empty;
1168
+ };
1169
+ const concatSQL = (...sqls) => mergeSQL(sqls, "");
1170
+ const literal = (value) => SQLPlain.from(`'${value.replace(/'/g, "''")}'`);
1171
+ const isEmpty = (sql) => {
1172
+ if (isTokenizedSQL(sql)) {
1173
+ const parametrized = sql;
1174
+ return parametrized.sqlChunks.every((chunk) => chunk.trim() === "") && parametrized.sqlTokens.length === 0;
1175
+ }
1176
+ return false;
1177
+ };
1178
+ const columnFactory = SQLColumnToken.from;
1179
+ columnFactory.type = SQLColumnTypeTokensFactory;
1180
+ const schemaColumnFactory = ((name, type, options) => columnSchemaComponent({
1181
+ columnName: name,
1182
+ type,
1183
+ ...options
1184
+ }));
1185
+ const SQL = Object.assign(createSQL, {
1186
+ EMPTY: emptySQL,
1187
+ concat: concatSQL,
1188
+ merge: mergeSQL,
1189
+ format: (sql, formatter, options) => formatSQL(sql, formatter, options?.serializer ?? JSONSerializer, options),
1190
+ describe: (sql, formatter, options) => describeSQL(sql, formatter, options?.serializer ?? JSONSerializer, options),
1191
+ in: (column, values, options) => options?.mode ? SQLIn.from({
1192
+ column,
1193
+ values,
1194
+ mode: options.mode
1195
+ }) : SQLIn.from({
1196
+ column,
1197
+ values
1198
+ }),
1199
+ array: (values, options) => SQLArray.from(options?.mode ? {
1200
+ value: values,
1201
+ mode: options.mode
1202
+ } : values),
1203
+ identifier: SQLIdentifier.from,
1204
+ plain: SQLPlain.from,
1205
+ literal,
1206
+ check: {
1207
+ isSQL,
1208
+ isTokenizedSQL: (value) => isTokenizedSQL(value),
1209
+ isEmpty,
1210
+ isIdentifier: SQLIdentifier.check,
1211
+ isPlain: SQLPlain.check,
1212
+ isSQLIn: SQLIn.check
1213
+ },
1214
+ column: columnFactory,
1215
+ columnN: Object.assign(schemaColumnFactory, { type: SQLColumnTypeTokensFactory })
1216
+ });
1217
+
1218
+ //#endregion
1219
+ //#region src/core/sql/valueMappers/reservedSqlWords.ts
1220
+ const ansiSqlReservedMap = {
1221
+ ALL: true,
1222
+ AND: true,
1223
+ ANY: true,
1224
+ ARRAY: true,
1225
+ AS: true,
1226
+ ASC: true,
1227
+ AUTHORIZATION: true,
1228
+ BETWEEN: true,
1229
+ BINARY: true,
1230
+ BOTH: true,
1231
+ CASE: true,
1232
+ CAST: true,
1233
+ CHECK: true,
1234
+ COLLATE: true,
1235
+ COLUMN: true,
1236
+ CONSTRAINT: true,
1237
+ CREATE: true,
1238
+ CROSS: true,
1239
+ CURRENT_DATE: true,
1240
+ CURRENT_TIME: true,
1241
+ CURRENT_TIMESTAMP: true,
1242
+ CURRENT_USER: true,
1243
+ DEFAULT: true,
1244
+ DEFERRABLE: true,
1245
+ DESC: true,
1246
+ DISTINCT: true,
1247
+ DO: true,
1248
+ ELSE: true,
1249
+ END: true,
1250
+ EXCEPT: true,
1251
+ FALSE: true,
1252
+ FOR: true,
1253
+ FOREIGN: true,
1254
+ FROM: true,
1255
+ FULL: true,
1256
+ GRANT: true,
1257
+ GROUP: true,
1258
+ HAVING: true,
1259
+ IN: true,
1260
+ INITIALLY: true,
1261
+ INNER: true,
1262
+ INTERSECT: true,
1263
+ INTO: true,
1264
+ IS: true,
1265
+ JOIN: true,
1266
+ LEADING: true,
1267
+ LEFT: true,
1268
+ LIKE: true,
1269
+ LOCALTIME: true,
1270
+ LOCALTIMESTAMP: true,
1271
+ NATURAL: true,
1272
+ NEW: true,
1273
+ NOT: true,
1274
+ NULL: true,
1275
+ NULLS: true,
1276
+ OLD: true,
1277
+ ON: true,
1278
+ ONLY: true,
1279
+ OPEN: true,
1280
+ OR: true,
1281
+ ORDER: true,
1282
+ OUTER: true,
1283
+ OVERLAPS: true,
1284
+ PARTITION: true,
1285
+ PLACING: true,
1286
+ PRIMARY: true,
1287
+ REFERENCES: true,
1288
+ RIGHT: true,
1289
+ SELECT: true,
1290
+ SESSION_USER: true,
1291
+ SIMILAR: true,
1292
+ SOME: true,
1293
+ TABLE: true,
1294
+ THEN: true,
1295
+ TO: true,
1296
+ TRAILING: true,
1297
+ TRUE: true,
1298
+ UNION: true,
1299
+ UNIQUE: true,
1300
+ USER: true,
1301
+ USING: true,
1302
+ WHEN: true,
1303
+ WHERE: true,
1304
+ WITH: true,
1305
+ WITHOUT: true,
1306
+ ADD: true,
1307
+ ALTER: true,
1308
+ ARE: true,
1309
+ AT: true,
1310
+ BEGIN: true,
1311
+ BY: true,
1312
+ CASCADE: true,
1313
+ CLOSE: true,
1314
+ COMMIT: true,
1315
+ CONNECT: true,
1316
+ CONTINUE: true,
1317
+ CORRESPONDING: true,
1318
+ CURSOR: true,
1319
+ DEALLOCATE: true,
1320
+ DECLARE: true,
1321
+ DELETE: true,
1322
+ DESCRIBE: true,
1323
+ DISCONNECT: true,
1324
+ DROP: true,
1325
+ ESCAPE: true,
1326
+ EXECUTE: true,
1327
+ EXISTS: true,
1328
+ FETCH: true,
1329
+ FIRST: true,
1330
+ FLOAT: true,
1331
+ GET: true,
1332
+ GLOBAL: true,
1333
+ GO: true,
1334
+ GOTO: true,
1335
+ HOUR: true,
1336
+ IMMEDIATE: true,
1337
+ INDICATOR: true,
1338
+ INPUT: true,
1339
+ INSERT: true,
1340
+ INT: true,
1341
+ INTEGER: true,
1342
+ INTERVAL: true,
1343
+ LANGUAGE: true,
1344
+ LAST: true,
1345
+ LOCAL: true,
1346
+ MATCH: true,
1347
+ MINUTE: true,
1348
+ MODULE: true,
1349
+ MONTH: true,
1350
+ NATIONAL: true,
1351
+ NEXT: true,
1352
+ NO: true,
1353
+ OF: true,
1354
+ OUTPUT: true,
1355
+ PARTIAL: true,
1356
+ PREPARE: true,
1357
+ PRESERVE: true,
1358
+ PRIOR: true,
1359
+ PRIVILEGES: true,
1360
+ PROCEDURE: true,
1361
+ PUBLIC: true,
1362
+ READ: true,
1363
+ REAL: true,
1364
+ RESTRICT: true,
1365
+ REVOKE: true,
1366
+ ROLLBACK: true,
1367
+ ROWS: true,
1368
+ SCHEMA: true,
1369
+ SCROLL: true,
1370
+ SECOND: true,
1371
+ SECTION: true,
1372
+ SET: true,
1373
+ SIZE: true,
1374
+ SMALLINT: true,
1375
+ SQL: true,
1376
+ SQLCODE: true,
1377
+ SQLERROR: true,
1378
+ SQLSTATE: true,
1379
+ TEMPORARY: true,
1380
+ TIMEZONE_HOUR: true,
1381
+ TIMEZONE_MINUTE: true,
1382
+ TRANSACTION: true,
1383
+ TRANSLATE: true,
1384
+ TRANSLATION: true,
1385
+ UNKNOWN: true,
1386
+ UPDATE: true,
1387
+ VALUE: true,
1388
+ VALUES: true,
1389
+ VARCHAR: true,
1390
+ VARYING: true,
1391
+ VIEW: true,
1392
+ WHENEVER: true,
1393
+ WORK: true,
1394
+ WRITE: true,
1395
+ YEAR: true,
1396
+ ZONE: true
1397
+ };
1398
+
1399
+ //#endregion
1400
+ //#region src/core/sql/valueMappers/sqlValueMapper.ts
1401
+ const ANSISQLParamPlaceholder = "?";
1402
+ const ANSISQLIdentifierQuote = "\"";
1403
+ const mapANSISQLParamPlaceholder = () => "?";
1404
+ const isReserved = (value, reserved) => !!reserved[value.toUpperCase()];
1405
+ const mapSQLIdentifier = (value, options) => {
1406
+ if (value === void 0 || value === null) throw new Error("SQL identifier cannot be null or undefined");
1407
+ const ident = value.toString().slice(0);
1408
+ const quoteSign = options?.quote ?? "\"";
1409
+ if (/^[a-z_][a-z0-9_$]*$/.test(ident) && !isReserved(ident, options?.reservedWords ?? ansiSqlReservedMap)) return ident;
1410
+ let quoted = quoteSign;
1411
+ for (let i = 0; i < ident.length; i++) {
1412
+ const c = ident[i];
1413
+ quoted += c === quoteSign ? c + c : c;
1414
+ }
1415
+ quoted += quoteSign;
1416
+ return quoted;
1417
+ };
1418
+ const DefaultMapSQLParamValueOptions = {
1419
+ mapPlaceholder: mapANSISQLParamPlaceholder,
1420
+ mapIdentifier: mapSQLIdentifier
1421
+ };
1422
+ const SQLValueMapper = (options) => {
1423
+ const mapSQLParamValueOptions = {
1424
+ ...DefaultMapSQLParamValueOptions,
1425
+ ...options ?? {}
1426
+ };
1427
+ return {
1428
+ mapValue: (value, serializer, mapOptions) => mapSQLParamValue(value, serializer, {
1429
+ ...mapSQLParamValueOptions,
1430
+ ...mapOptions
1431
+ }),
1432
+ mapPlaceholder: mapSQLParamValueOptions.mapPlaceholder,
1433
+ mapIdentifier: mapSQLParamValueOptions.mapIdentifier
1434
+ };
1435
+ };
1436
+ function mapSQLParamValue(value, serializer, options) {
1437
+ if (value === null || value === void 0) return null;
1438
+ else if (typeof value === "number") return value;
1439
+ else if (typeof value === "string") return value;
1440
+ else if (Array.isArray(value)) {
1441
+ const mapValue = options?.mapValue ?? mapSQLParamValue;
1442
+ return options?.mapArray ? options.mapArray(value, mapValue) : value.map((item) => mapValue(item, serializer, options));
1443
+ } else if (typeof value === "boolean") return options?.mapBoolean ? options.mapBoolean(value) : value;
1444
+ else if (typeof value === "bigint") return options?.mapBigInt ? options.mapBigInt(value) : value.toString();
1445
+ else if (value instanceof Date) return options?.mapDate ? options.mapDate(value) : value.toISOString();
1446
+ else if (SQL.check.isIdentifier(value)) return (options?.mapIdentifier ?? mapSQLIdentifier)(value.value);
1447
+ else if (typeof value === "object") return options?.mapObject ? options.mapObject(value) : serializer.serialize(value);
1448
+ else return serializer.serialize(value);
1449
+ }
1450
+
1451
+ //#endregion
1452
+ //#region src/core/sql/formatters/sqlFormatter.ts
1453
+ const SQLFormatter = ({ format, describe, valueMapper: valueMapperOptions, processorsRegistry }) => {
1454
+ const valueMapper = SQLValueMapper(valueMapperOptions);
1455
+ const options = {
1456
+ builder: ParametrizedSQLBuilder({ mapParamPlaceholder: valueMapper.mapPlaceholder }),
1457
+ mapper: valueMapper,
1458
+ processorsRegistry: processorsRegistry ?? defaultProcessorsRegistry
1459
+ };
1460
+ const resultFormatter = {
1461
+ format: format ?? ((sql, methodOptions) => formatSQL(sql, resultFormatter, methodOptions?.serializer ?? JSONSerializer, {
1462
+ ...options,
1463
+ ...methodOptions ?? {}
1464
+ })),
1465
+ describe: describe ?? ((sql, methodOptions) => describeSQL(sql, resultFormatter, methodOptions?.serializer ?? JSONSerializer, {
1466
+ ...options,
1467
+ ...methodOptions ?? {}
1468
+ })),
1469
+ valueMapper
1470
+ };
1471
+ return resultFormatter;
1472
+ };
1473
+ const dumboSQLFormatters = globalThis.dumboSQLFormatters = globalThis.dumboSQLFormatters ?? {};
1474
+ const registerFormatter = (dialect, formatter) => {
1475
+ dumboSQLFormatters[dialect] = formatter;
1476
+ };
1477
+ function formatSQL(sql, formatter, serializer, context) {
1478
+ const mapper = context?.mapper == void 0 ? formatter.valueMapper : {
1479
+ ...formatter.valueMapper,
1480
+ ...context.mapper
1481
+ };
1482
+ const processorsRegistry = context?.processorsRegistry ?? defaultProcessorsRegistry;
1483
+ const merged = Array.isArray(sql) ? SQL.merge(sql, "\n") : sql;
1484
+ if (!isTokenizedSQL(merged)) throw new Error("Expected TokenizedSQL, got string-based SQL");
1485
+ const builder = ParametrizedSQLBuilder({ mapParamPlaceholder: mapper.mapPlaceholder });
1486
+ let paramIndex = 0;
1487
+ for (let i = 0; i < merged.sqlChunks.length; i++) {
1488
+ const sqlChunk = merged.sqlChunks[i];
1489
+ if (sqlChunk !== TokenizedSQL.paramPlaceholder) {
1490
+ builder.addSQL(sqlChunk);
1491
+ continue;
1492
+ }
1493
+ const token = merged.sqlTokens[paramIndex++];
1494
+ const processor = processorsRegistry.get(token.sqlTokenType);
1495
+ if (!processor) throw new Error(`No SQL processor registered for token type: ${token.sqlTokenType}`);
1496
+ processor.handle(token, {
1497
+ builder,
1498
+ processorsRegistry,
1499
+ serializer,
1500
+ mapper
1501
+ });
1502
+ }
1503
+ return builder.build();
1504
+ }
1505
+ const describeSQL = (sql, formatter, serializer, options) => formatSQL(sql, formatter, serializer, {
1506
+ ...options ?? {},
1507
+ mapper: { mapPlaceholder: (_, value) => serializer.serialize(value) }
1508
+ }).query;
1509
+
1510
+ //#endregion
1511
+ //#region src/core/tracing/printing/color.ts
1512
+ let enableColors = true;
1513
+ const color = {
1514
+ set level(value) {
1515
+ enableColors = value === 1;
1516
+ },
1517
+ hex: (value) => (text) => enableColors ? ansis.hex(value)(text) : text,
1518
+ red: (value) => enableColors ? ansis.red(value) : value,
1519
+ green: (value) => enableColors ? ansis.green(value) : value,
1520
+ blue: (value) => enableColors ? ansis.blue(value) : value,
1521
+ cyan: (value) => enableColors ? ansis.cyan(value) : value,
1522
+ yellow: (value) => enableColors ? ansis.yellow(value) : value
1523
+ };
1524
+
1525
+ //#endregion
1526
+ //#region src/core/tracing/printing/pretty.ts
1527
+ const TWO_SPACES = " ";
1528
+ const COLOR_STRING = color.hex("#98c379");
1529
+ const COLOR_KEY = color.hex("#61afef");
1530
+ const COLOR_NUMBER_OR_DATE = color.hex("#d19a66");
1531
+ const COLOR_BOOLEAN = color.hex("#c678dd");
1532
+ const COLOR_NULL_OR_UNDEFINED = color.hex("#c678dd");
1533
+ const COLOR_BRACKETS = color.hex("#abb2bf");
1534
+ const processString = (str, indent, handleMultiline) => {
1535
+ if (handleMultiline && str.includes("\n")) {
1536
+ const indentedLines = str.split("\n").map((line) => indent + TWO_SPACES + COLOR_STRING(line));
1537
+ return COLOR_STRING("\"") + "\n" + indentedLines.join("\n") + "\n" + indent + COLOR_STRING("\"");
1538
+ }
1539
+ return COLOR_STRING(`"${str}"`);
1540
+ };
1541
+ const shouldPrint = (obj) => typeof obj !== "function" && typeof obj !== "symbol";
1542
+ const formatJson = (obj, indentLevel = 0, handleMultiline = false) => {
1543
+ const indent = TWO_SPACES.repeat(indentLevel);
1544
+ if (obj === null) return COLOR_NULL_OR_UNDEFINED("null");
1545
+ if (obj === void 0) return COLOR_NULL_OR_UNDEFINED("undefined");
1546
+ if (typeof obj === "string") return processString(obj, indent, handleMultiline);
1547
+ if (typeof obj === "number" || typeof obj === "bigint" || obj instanceof Date) return COLOR_NUMBER_OR_DATE(String(obj));
1548
+ if (typeof obj === "boolean") return COLOR_BOOLEAN(String(obj));
1549
+ if (obj instanceof Error) {
1550
+ const errorObj = {};
1551
+ Object.getOwnPropertyNames(obj).forEach((key) => {
1552
+ errorObj[key] = obj[key];
1553
+ });
1554
+ return formatJson(errorObj, indentLevel, handleMultiline);
1555
+ }
1556
+ if (obj instanceof Promise) return COLOR_STRING("Promise {pending}");
1557
+ if (Array.isArray(obj)) {
1558
+ const arrayItems = obj.map((item) => formatJson(item, indentLevel + 1, handleMultiline));
1559
+ return `${COLOR_BRACKETS("[")}\n${indent} ${arrayItems.join(`,\n${indent} `)}\n${indent}${COLOR_BRACKETS("]")}`;
1560
+ }
1561
+ const entries = Object.entries(obj).filter(([_, value]) => shouldPrint(value)).map(([key, value]) => `${COLOR_KEY(`"${key}"`)}: ${formatJson(value, indentLevel + 1, handleMultiline)}`);
1562
+ return `${COLOR_BRACKETS("{")}\n${indent} ${entries.join(`,\n${indent} `)}\n${indent}${COLOR_BRACKETS("}")}`;
1563
+ };
1564
+ const prettyJson = (obj, options) => formatJson(obj, 0, options?.handleMultiline);
1565
+
1566
+ //#endregion
1567
+ //#region src/core/tracing/index.ts
1568
+ const tracer = () => {};
1569
+ const LogLevel = {
1570
+ DISABLED: "DISABLED",
1571
+ INFO: "INFO",
1572
+ LOG: "LOG",
1573
+ WARN: "WARN",
1574
+ ERROR: "ERROR"
1575
+ };
1576
+ const getEnvVariable = (name) => {
1577
+ try {
1578
+ if (typeof process !== "undefined" && process.env) return process.env[name];
1579
+ return;
1580
+ } catch {
1581
+ return;
1582
+ }
1583
+ };
1584
+ const shouldLog = (logLevel) => {
1585
+ const definedLogLevel = getEnvVariable("DUMBO_LOG_LEVEL") ?? LogLevel.ERROR;
1586
+ if (definedLogLevel === LogLevel.ERROR && logLevel === LogLevel.ERROR) return true;
1587
+ if (definedLogLevel === LogLevel.WARN && [LogLevel.ERROR, LogLevel.WARN].includes(logLevel)) return true;
1588
+ if (definedLogLevel === LogLevel.LOG && [
1589
+ LogLevel.ERROR,
1590
+ LogLevel.WARN,
1591
+ LogLevel.LOG
1592
+ ].includes(logLevel)) return true;
1593
+ if (definedLogLevel === LogLevel.INFO && [
1594
+ LogLevel.ERROR,
1595
+ LogLevel.WARN,
1596
+ LogLevel.LOG,
1597
+ LogLevel.INFO
1598
+ ].includes(logLevel)) return true;
1599
+ return false;
1600
+ };
1601
+ const nulloTraceEventRecorder = () => {};
1602
+ const getTraceEventFormatter = (logStyle, serializer = JSONSerializer) => (event) => {
1603
+ switch (logStyle) {
1604
+ case "RAW": return serializer.serialize(event);
1605
+ case "PRETTY": return prettyJson(event, { handleMultiline: true });
1606
+ }
1607
+ };
1608
+ const getTraceEventRecorder = (logLevel, logStyle) => {
1609
+ const format = getTraceEventFormatter(logStyle);
1610
+ switch (logLevel) {
1611
+ case "DISABLED": return nulloTraceEventRecorder;
1612
+ case "INFO": return (event) => console.info(format(event));
1613
+ case "LOG": return (event) => console.log(format(event));
1614
+ case "WARN": return (event) => console.warn(format(event));
1615
+ case "ERROR": return (event) => console.error(format(event));
1616
+ }
1617
+ };
1618
+ const recordTraceEvent = (logLevel, eventName, attributes) => {
1619
+ if (!shouldLog(LogLevel.LOG)) return;
1620
+ const event = {
1621
+ name: eventName,
1622
+ timestamp: (/* @__PURE__ */ new Date()).getTime(),
1623
+ ...attributes
1624
+ };
1625
+ getTraceEventRecorder(logLevel, getEnvVariable("DUMBO_LOG_STYLE") ?? "RAW")(event);
1626
+ };
1627
+ tracer.info = (eventName, attributes) => recordTraceEvent(LogLevel.INFO, eventName, attributes);
1628
+ tracer.warn = (eventName, attributes) => recordTraceEvent(LogLevel.WARN, eventName, attributes);
1629
+ tracer.log = (eventName, attributes) => recordTraceEvent(LogLevel.LOG, eventName, attributes);
1630
+ tracer.error = (eventName, attributes) => recordTraceEvent(LogLevel.ERROR, eventName, attributes);
1631
+
1632
+ //#endregion
1633
+ //#region src/core/schema/sqlMigration.ts
1634
+ const sqlMigration = (name, sqls) => ({
1635
+ name,
1636
+ sqls
1637
+ });
1638
+
1639
+ //#endregion
1640
+ //#region src/core/schema/migrators/schemaComponentMigrator.ts
1641
+ const { AutoIncrement, Varchar, Timestamp } = SQL.column.type;
1642
+ const migrationTableSQL = SQL`
1643
+ CREATE TABLE IF NOT EXISTS dmb_migrations (
1644
+ id ${AutoIncrement({ primaryKey: true })},
1645
+ name ${Varchar(255)} NOT NULL UNIQUE,
1646
+ application ${Varchar(255)} NOT NULL DEFAULT 'default',
1647
+ sql_hash ${Varchar(64)} NOT NULL,
1648
+ timestamp ${Timestamp} NOT NULL DEFAULT CURRENT_TIMESTAMP
1649
+ );
1650
+ `;
1651
+ const migrationTableSchemaComponent = schemaComponent("dumbo:schema-component:migrations-table", { migrations: [sqlMigration("dumbo:migrationTable:001", [migrationTableSQL])] });
1652
+
1653
+ //#endregion
1654
+ //#region src/core/schema/migrators/migrator.ts
1655
+ const defaultMigratorOptions = globalThis.defaultMigratorOptions = globalThis.defaultMigratorOptions ?? {};
1656
+ const registerDefaultMigratorOptions = (databaseType, options) => {
1657
+ defaultMigratorOptions[databaseType] = options;
1658
+ };
1659
+
1660
+ //#endregion
1661
+ //#region src/storage/postgresql/core/locks/advisoryLocks.ts
1662
+ const tryAcquireAdvisoryLock = async (execute, options) => {
1663
+ const timeoutMs = options.timeoutMs ?? defaultDatabaseLockOptions.timeoutMs;
1664
+ const advisoryLock = options.mode === "Permanent" ? "pg_advisory_lock" : "pg_advisory_xact_lock";
1665
+ try {
1666
+ await single(execute.query(SQL`SELECT ${SQL.plain(advisoryLock)}(${options.lockId}) AS locked`, { timeoutMs }));
1667
+ return true;
1668
+ } catch (error) {
1669
+ if (error instanceof QueryCanceledError || DumboError.isInstanceOf(error, { errorType: QueryCanceledError.ErrorType })) return false;
1670
+ throw error;
1671
+ }
1672
+ };
1673
+ const releaseAdvisoryLock = async (execute, options) => {
1674
+ const timeoutMs = options.timeoutMs ?? defaultDatabaseLockOptions.timeoutMs;
1675
+ try {
1676
+ await single(execute.query(SQL`SELECT pg_advisory_unlock(${options.lockId}) AS locked`, { timeoutMs }));
1677
+ return true;
1678
+ } catch (error) {
1679
+ if (error instanceof QueryCanceledError || DumboError.isInstanceOf(error, { errorType: QueryCanceledError.ErrorType })) return false;
1680
+ throw error;
1681
+ }
1682
+ };
1683
+ const acquireAdvisoryLock = async (execute, options) => {
1684
+ if (!await tryAcquireAdvisoryLock(execute, options)) throw new Error("Failed to acquire advisory lock within the specified timeout. Migration aborted.");
1685
+ };
1686
+ const AdvisoryLock = {
1687
+ acquire: acquireAdvisoryLock,
1688
+ tryAcquire: tryAcquireAdvisoryLock,
1689
+ release: releaseAdvisoryLock,
1690
+ withAcquire: async (execute, handle, options) => {
1691
+ await acquireAdvisoryLock(execute, options);
1692
+ try {
1693
+ return await handle();
1694
+ } finally {
1695
+ if (options.mode === "Permanent") await releaseAdvisoryLock(execute, options);
1696
+ }
1697
+ }
1698
+ };
1699
+ const advisoryLock = (execute, options) => ({
1700
+ acquire: (acquireOptions) => acquireAdvisoryLock(execute, {
1701
+ ...options,
1702
+ ...acquireOptions ?? {}
1703
+ }),
1704
+ tryAcquire: (acquireOptions) => tryAcquireAdvisoryLock(execute, {
1705
+ ...options,
1706
+ ...acquireOptions ?? {}
1707
+ }),
1708
+ release: () => releaseAdvisoryLock(execute, options),
1709
+ withAcquire: async (handle, acquireOptions) => {
1710
+ await acquireAdvisoryLock(execute, {
1711
+ ...options,
1712
+ ...acquireOptions ?? {}
1713
+ });
1714
+ try {
1715
+ return await handle();
1716
+ } finally {
1717
+ await releaseAdvisoryLock(execute, options);
1718
+ }
1719
+ }
1720
+ });
1721
+
1722
+ //#endregion
1723
+ //#region src/storage/postgresql/core/schema/migrations.ts
1724
+ const DefaultPostgreSQLMigratorOptions = { lock: { databaseLock: AdvisoryLock } };
1725
+ registerDefaultMigratorOptions("PostgreSQL", DefaultPostgreSQLMigratorOptions);
1726
+
1727
+ //#endregion
1728
+ //#region src/storage/postgresql/core/schema/schema.ts
1729
+ const defaultPostgreSqlDatabase = "postgres";
1730
+ const tableExistsSQL = (tableName) => SQL`
1731
+ SELECT EXISTS (
1732
+ SELECT FROM pg_tables
1733
+ WHERE tablename = ${tableName}
1734
+ ) AS exists;`;
1735
+ const tableExists = async (execute, tableName) => exists(execute.query(tableExistsSQL(tableName)));
1736
+ const functionExistsSQL = (functionName) => SQL`
1737
+ SELECT EXISTS (
1738
+ SELECT FROM pg_proc
1739
+ WHERE
1740
+ proname = ${functionName}
1741
+ ) AS exists;`;
1742
+ const functionExists = async (execute, functionName) => exists(execute.query(functionExistsSQL(functionName)));
1743
+
1744
+ //#endregion
1745
+ //#region src/storage/postgresql/core/schema/postgreSQLMetadata.ts
1746
+ const postgreSQLMetadata = {
1747
+ databaseType: "PostgreSQL",
1748
+ defaultDatabaseName: defaultPostgreSqlDatabase,
1749
+ capabilities: {
1750
+ supportsSchemas: true,
1751
+ supportsFunctions: true,
1752
+ supportsMultipleDatabases: true
1753
+ },
1754
+ tableExists,
1755
+ functionExists,
1756
+ parseDatabaseName: (connectionString) => (connectionString ? parseDatabaseName(connectionString) : null) ?? "postgres"
1757
+ };
1758
+ dumboDatabaseMetadataRegistry.register("PostgreSQL", postgreSQLMetadata);
1759
+
1760
+ //#endregion
1761
+ //#region src/storage/postgresql/core/sql/processors/arrayProcessors.ts
1762
+ const PostgreSQLArrayProcessor = SQLProcessor({
1763
+ canHandle: "SQL_ARRAY",
1764
+ handle: (token, { builder, mapper, serializer }) => {
1765
+ if (token.value.length === 0) throw new Error("Empty arrays are not supported. If you're using it with SELECT IN statement Use SQL.in(column, array) helper instead.");
1766
+ const mappedValue = mapper.mapValue(token.value, serializer);
1767
+ if (token.mode === "params") builder.addParams(mappedValue);
1768
+ else builder.addParam(mappedValue);
1769
+ }
1770
+ });
1771
+ const PostgreSQLExpandSQLInProcessor = SQLProcessor({
1772
+ canHandle: "SQL_IN",
1773
+ handle: (token, context) => {
1774
+ const { builder, mapper, processorsRegistry } = context;
1775
+ const { values: inValues, column, mode } = token;
1776
+ if (inValues.value.length === 0) {
1777
+ builder.addParam(mapper.mapValue(false, context.serializer));
1778
+ return;
1779
+ }
1780
+ builder.addSQL(mapper.mapValue(column.value, context.serializer));
1781
+ const arrayProcessor = processorsRegistry.get(SQLArray.type);
1782
+ if (!arrayProcessor) throw new Error("No sql processor registered for an array. Cannot expand IN statement");
1783
+ if (mode === "params") {
1784
+ builder.addSQL(` IN (`);
1785
+ const expandedArray = {
1786
+ ...inValues,
1787
+ mode: "params"
1788
+ };
1789
+ arrayProcessor.handle(expandedArray, context);
1790
+ builder.addSQL(`)`);
1791
+ } else {
1792
+ builder.addSQL(` = ANY (`);
1793
+ arrayProcessor.handle(inValues, context);
1794
+ builder.addSQL(`)`);
1795
+ }
1796
+ }
1797
+ });
1798
+
1799
+ //#endregion
1800
+ //#region src/storage/postgresql/core/sql/processors/columProcessors.ts
1801
+ const mapColumnType = (token, { builder }) => {
1802
+ let columnSQL;
1803
+ const { sqlTokenType } = token;
1804
+ switch (sqlTokenType) {
1805
+ case "SQL_COLUMN_AUTO_INCREMENT":
1806
+ columnSQL = `${token.bigint ? "BIGSERIAL" : "SERIAL"} ${token.primaryKey ? "PRIMARY KEY" : ""}`;
1807
+ break;
1808
+ case "SQL_COLUMN_BIGINT":
1809
+ columnSQL = "BIGINT";
1810
+ break;
1811
+ case "SQL_COLUMN_SERIAL":
1812
+ columnSQL = "SERIAL";
1813
+ break;
1814
+ case "SQL_COLUMN_INTEGER":
1815
+ columnSQL = "INTEGER";
1816
+ break;
1817
+ case "SQL_COLUMN_JSONB":
1818
+ columnSQL = "JSONB";
1819
+ break;
1820
+ case "SQL_COLUMN_BIGSERIAL":
1821
+ columnSQL = "BIGSERIAL";
1822
+ break;
1823
+ case "SQL_COLUMN_TIMESTAMP":
1824
+ columnSQL = "TIMESTAMP";
1825
+ break;
1826
+ case "SQL_COLUMN_TIMESTAMPTZ":
1827
+ columnSQL = "TIMESTAMPTZ";
1828
+ break;
1829
+ case "SQL_COLUMN_VARCHAR":
1830
+ columnSQL = `VARCHAR ${Number.isNaN(token.length) ? "" : `(${token.length})`}`;
1831
+ break;
1832
+ default: throw new Error(`Unknown column type: ${sqlTokenType}`);
1833
+ }
1834
+ builder.addSQL(columnSQL);
1835
+ };
1836
+ const postgreSQLColumnProcessors = mapDefaultSQLColumnProcessors(mapColumnType);
1837
+
1838
+ //#endregion
1839
+ //#region src/storage/postgresql/core/sql/formatter/reserved.ts
1840
+ const reservedMap = {
1841
+ AES128: true,
1842
+ AES256: true,
1843
+ ALL: true,
1844
+ ALLOWOVERWRITE: true,
1845
+ ANALYSE: true,
1846
+ ANALYZE: true,
1847
+ AND: true,
1848
+ ANY: true,
1849
+ ARRAY: true,
1850
+ AS: true,
1851
+ ASC: true,
1852
+ AUTHORIZATION: true,
1853
+ BACKUP: true,
1854
+ BETWEEN: true,
1855
+ BINARY: true,
1856
+ BLANKSASNULL: true,
1857
+ BOTH: true,
1858
+ BYTEDICT: true,
1859
+ CASE: true,
1860
+ CAST: true,
1861
+ CHECK: true,
1862
+ COLLATE: true,
1863
+ COLUMN: true,
1864
+ CONSTRAINT: true,
1865
+ CREATE: true,
1866
+ CREDENTIALS: true,
1867
+ CROSS: true,
1868
+ CURRENT_DATE: true,
1869
+ CURRENT_TIME: true,
1870
+ CURRENT_TIMESTAMP: true,
1871
+ CURRENT_USER: true,
1872
+ CURRENT_USER_ID: true,
1873
+ DEFAULT: true,
1874
+ DEFERRABLE: true,
1875
+ DEFLATE: true,
1876
+ DEFRAG: true,
1877
+ DELTA: true,
1878
+ DELTA32K: true,
1879
+ DESC: true,
1880
+ DISABLE: true,
1881
+ DISTINCT: true,
1882
+ DO: true,
1883
+ ELSE: true,
1884
+ EMPTYASNULL: true,
1885
+ ENABLE: true,
1886
+ ENCODE: true,
1887
+ ENCRYPT: true,
1888
+ ENCRYPTION: true,
1889
+ END: true,
1890
+ EXCEPT: true,
1891
+ EXPLICIT: true,
1892
+ FALSE: true,
1893
+ FOR: true,
1894
+ FOREIGN: true,
1895
+ FREEZE: true,
1896
+ FROM: true,
1897
+ FULL: true,
1898
+ GLOBALDICT256: true,
1899
+ GLOBALDICT64K: true,
1900
+ GRANT: true,
1901
+ GROUP: true,
1902
+ GZIP: true,
1903
+ HAVING: true,
1904
+ IDENTITY: true,
1905
+ IGNORE: true,
1906
+ ILIKE: true,
1907
+ IN: true,
1908
+ INITIALLY: true,
1909
+ INNER: true,
1910
+ INTERSECT: true,
1911
+ INTO: true,
1912
+ IS: true,
1913
+ ISNULL: true,
1914
+ JOIN: true,
1915
+ LEADING: true,
1916
+ LEFT: true,
1917
+ LIKE: true,
1918
+ LIMIT: true,
1919
+ LOCALTIME: true,
1920
+ LOCALTIMESTAMP: true,
1921
+ LUN: true,
1922
+ LUNS: true,
1923
+ LZO: true,
1924
+ LZOP: true,
1925
+ MINUS: true,
1926
+ MOSTLY13: true,
1927
+ MOSTLY32: true,
1928
+ MOSTLY8: true,
1929
+ NATURAL: true,
1930
+ NEW: true,
1931
+ NOT: true,
1932
+ NOTNULL: true,
1933
+ NULL: true,
1934
+ NULLS: true,
1935
+ OFF: true,
1936
+ OFFLINE: true,
1937
+ OFFSET: true,
1938
+ OLD: true,
1939
+ ON: true,
1940
+ ONLY: true,
1941
+ OPEN: true,
1942
+ OR: true,
1943
+ ORDER: true,
1944
+ OUTER: true,
1945
+ OVERLAPS: true,
1946
+ PARALLEL: true,
1947
+ PARTITION: true,
1948
+ PERCENT: true,
1949
+ PLACING: true,
1950
+ PRIMARY: true,
1951
+ RAW: true,
1952
+ READRATIO: true,
1953
+ RECOVER: true,
1954
+ REFERENCES: true,
1955
+ REJECTLOG: true,
1956
+ RESORT: true,
1957
+ RESTORE: true,
1958
+ RIGHT: true,
1959
+ SELECT: true,
1960
+ SESSION_USER: true,
1961
+ SIMILAR: true,
1962
+ SOME: true,
1963
+ SYSDATE: true,
1964
+ SYSTEM: true,
1965
+ TABLE: true,
1966
+ TAG: true,
1967
+ TDES: true,
1968
+ TEXT255: true,
1969
+ TEXT32K: true,
1970
+ THEN: true,
1971
+ TO: true,
1972
+ TOP: true,
1973
+ TRAILING: true,
1974
+ TRUE: true,
1975
+ TRUNCATECOLUMNS: true,
1976
+ UNION: true,
1977
+ UNIQUE: true,
1978
+ USER: true,
1979
+ USING: true,
1980
+ VERBOSE: true,
1981
+ WALLET: true,
1982
+ WHEN: true,
1983
+ WHERE: true,
1984
+ WITH: true,
1985
+ WITHOUT: true
1986
+ };
1987
+
1988
+ //#endregion
1989
+ //#region src/storage/postgresql/core/sql/formatter/index.ts
1990
+ const pgFormatter = SQLFormatter({
1991
+ processorsRegistry: SQLProcessorsRegistry({ from: defaultProcessorsRegistry }).register(postgreSQLColumnProcessors).register(PostgreSQLArrayProcessor, PostgreSQLExpandSQLInProcessor),
1992
+ valueMapper: {
1993
+ mapDate: (value) => value.toISOString().replace("T", " ").replace("Z", "+00"),
1994
+ mapPlaceholder: (index) => `$${index + 1}`,
1995
+ mapIdentifier: (value) => mapSQLIdentifier(value, { reservedWords: reservedMap }),
1996
+ mapArray: (values) => values
1997
+ }
1998
+ });
1999
+ registerFormatter("PostgreSQL", pgFormatter);
2000
+
2001
+ //#endregion
2002
+ //#region src/storage/postgresql/core/sql/json.ts
2003
+ const pathParts = (path) => path.split(".");
2004
+ const canUseUnquotedArrayElement = (value) => /^[A-Za-z0-9_$]+$/.test(value);
2005
+ const arrayElement = (value) => canUseUnquotedArrayElement(value) ? value : `"${value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"")}"`;
2006
+ const pathArrayLiteral = (values) => {
2007
+ const arrayValue = `{${values.map(arrayElement).join(",")}}`;
2008
+ return SQL.literal(arrayValue).value;
2009
+ };
2010
+ const path = (path) => SQL.plain(pathArrayLiteral(pathParts(path)));
2011
+ const field = (source, path) => {
2012
+ const parts = pathParts(path);
2013
+ return parts.length === 1 ? SQL`${source} -> ${SQL.literal(parts[0])}` : SQL`${source} #> ${PostgreSQLJSON.path(path)}`;
2014
+ };
2015
+ const textField = (source, path) => {
2016
+ const parts = pathParts(path);
2017
+ return parts.length === 1 ? SQL`${source} ->> ${SQL.literal(parts[0])}` : SQL`${source} #>> ${PostgreSQLJSON.path(path)}`;
2018
+ };
2019
+ const PostgreSQLJSON = {
2020
+ field,
2021
+ path,
2022
+ textField
2023
+ };
2024
+
2025
+ //#endregion
2026
+ //#region src/storage/postgresql/core/index.ts
2027
+ const PostgreSQLDatabaseName = "PostgreSQL";
2028
+
2029
+ //#endregion
6
2030
  //#region src/storage/postgresql/pg/execute/execute.ts
7
2031
  const isPgNativePool = (poolOrClient) => {
8
2032
  return poolOrClient instanceof pg.Pool;
@@ -87,57 +2111,92 @@ async function batchCommand(client, sqls, serializer, options) {
87
2111
 
88
2112
  //#endregion
89
2113
  //#region src/storage/postgresql/pg/connections/transaction.ts
90
- const pgTransaction = (connection, serializer) => (getClient, options) => ({
91
- connection: connection(),
92
- driverType: PgDriverType,
93
- begin: async () => {
94
- const client = await getClient;
95
- const parts = ["BEGIN"];
96
- if (options?.isolationLevel) parts.push(`ISOLATION LEVEL ${options.isolationLevel}`);
97
- if (options?.readonly) parts.push("READ ONLY");
98
- await client.query(parts.join(" "));
99
- },
100
- commit: async () => {
101
- const client = await getClient;
102
- try {
103
- await client.query("COMMIT");
104
- } finally {
105
- if (options?.close) await options?.close(client);
2114
+ const pgTransaction = (connection, serializer) => (getClient, options) => {
2115
+ const allowNestedTransactions = options?.allowNestedTransactions ?? false;
2116
+ const tx = databaseTransaction({
2117
+ begin: async () => {
2118
+ const client = await getClient;
2119
+ const parts = ["BEGIN"];
2120
+ if (options?.isolationLevel) parts.push(`ISOLATION LEVEL ${options.isolationLevel}`);
2121
+ if (options?.readonly) parts.push("READ ONLY");
2122
+ await client.query(parts.join(" "));
2123
+ },
2124
+ commit: async () => {
2125
+ const client = await getClient;
2126
+ try {
2127
+ await client.query("COMMIT");
2128
+ } finally {
2129
+ if (options?.close) await options.close(client);
2130
+ }
2131
+ },
2132
+ rollback: async (error) => {
2133
+ const client = await getClient;
2134
+ try {
2135
+ await client.query("ROLLBACK");
2136
+ } finally {
2137
+ if (options?.close) await options.close(client, error);
2138
+ }
2139
+ },
2140
+ savepoint: async (level) => {
2141
+ await (await getClient).query(`SAVEPOINT pg_savepoint_${level}`);
2142
+ },
2143
+ releaseSavepoint: async (level) => {
2144
+ await (await getClient).query(`RELEASE SAVEPOINT pg_savepoint_${level}`);
2145
+ },
2146
+ rollbackToSavepoint: async (level) => {
2147
+ await (await getClient).query(`ROLLBACK TO SAVEPOINT pg_savepoint_${level}`);
106
2148
  }
107
- },
108
- rollback: async (error) => {
109
- const client = await getClient;
110
- try {
111
- await client.query("ROLLBACK");
112
- } finally {
113
- if (options?.close) await options?.close(client, error);
2149
+ }, {
2150
+ allowNestedTransactions,
2151
+ useSavepoints: options?.useSavepoints ?? false
2152
+ });
2153
+ return {
2154
+ connection: connection(),
2155
+ driverType: PgDriverType,
2156
+ begin: tx.begin,
2157
+ commit: tx.commit,
2158
+ rollback: tx.rollback,
2159
+ execute: sqlExecutor(pgSQLExecutor({ serializer }), { connect: () => getClient }),
2160
+ _transactionOptions: {
2161
+ ...options ?? {},
2162
+ allowNestedTransactions
114
2163
  }
115
- },
116
- execute: sqlExecutor(pgSQLExecutor({ serializer }), { connect: () => getClient }),
117
- _transactionOptions: options ?? {}
118
- });
2164
+ };
2165
+ };
119
2166
 
120
2167
  //#endregion
121
2168
  //#region src/storage/postgresql/pg/connections/connection.ts
122
2169
  const PgDriverType = "PostgreSQL:pg";
123
2170
  const pgClientConnection = (options) => {
124
- const { connect, close } = options;
2171
+ const { connect, close, transactionOptions } = options;
125
2172
  return createConnection({
126
2173
  driverType: PgDriverType,
127
2174
  connect,
128
2175
  close,
129
- initTransaction: (connection) => pgTransaction(connection, options.serializer),
2176
+ initTransaction: (connection) => {
2177
+ const txFactory = pgTransaction(connection, options.serializer);
2178
+ return (client, perCallOptions) => txFactory(client, {
2179
+ ...transactionOptions ?? {},
2180
+ ...perCallOptions ?? {}
2181
+ });
2182
+ },
130
2183
  executor: pgSQLExecutor,
131
2184
  serializer: options.serializer
132
2185
  });
133
2186
  };
134
2187
  const pgPoolClientConnection = (options) => {
135
- const { connect, close } = options;
2188
+ const { connect, close, transactionOptions } = options;
136
2189
  return createConnection({
137
2190
  driverType: PgDriverType,
138
2191
  connect,
139
2192
  close,
140
- initTransaction: (connection) => pgTransaction(connection, options.serializer),
2193
+ initTransaction: (connection) => {
2194
+ const txFactory = pgTransaction(connection, options.serializer);
2195
+ return (client, perCallOptions) => txFactory(client, {
2196
+ ...transactionOptions ?? {},
2197
+ ...perCallOptions ?? {}
2198
+ });
2199
+ },
141
2200
  executor: pgSQLExecutor,
142
2201
  serializer: options.serializer
143
2202
  });
@@ -176,7 +2235,7 @@ const setPgTypeParser = (client, options) => {
176
2235
  //#endregion
177
2236
  //#region src/storage/postgresql/pg/connections/pool.ts
178
2237
  const pgNativePool = (options) => {
179
- const { connectionString, database } = options;
2238
+ const { connectionString, database, transactionOptions } = options;
180
2239
  const pool = getPgPool({
181
2240
  connectionString,
182
2241
  database
@@ -192,7 +2251,8 @@ const pgNativePool = (options) => {
192
2251
  return client;
193
2252
  },
194
2253
  close: (client) => Promise.resolve(client.release()),
195
- serializer: options.serializer
2254
+ serializer: options.serializer,
2255
+ ...transactionOptions ? { transactionOptions } : {}
196
2256
  });
197
2257
  const open = () => Promise.resolve(getConnection());
198
2258
  const close = () => endPgPool({
@@ -207,14 +2267,15 @@ const pgNativePool = (options) => {
207
2267
  });
208
2268
  };
209
2269
  const pgAmbientNativePool = (options) => {
210
- const { pool } = options;
2270
+ const { pool, transactionOptions } = options;
211
2271
  return createConnectionPool({
212
2272
  driverType: PgDriverType,
213
2273
  getConnection: () => pgConnection({
214
2274
  type: "PoolClient",
215
2275
  connect: () => pool.connect(),
216
2276
  close: (client) => Promise.resolve(client.release()),
217
- serializer: options.serializer
2277
+ serializer: options.serializer,
2278
+ ...transactionOptions ? { transactionOptions } : {}
218
2279
  })
219
2280
  });
220
2281
  };
@@ -226,7 +2287,7 @@ const pgAmbientConnectionPool = (options) => {
226
2287
  });
227
2288
  };
228
2289
  const pgClientPool = (options) => {
229
- const { connectionString, database } = options;
2290
+ const { connectionString, database, transactionOptions } = options;
230
2291
  return createConnectionPool({
231
2292
  driverType: PgDriverType,
232
2293
  getConnection: () => {
@@ -246,20 +2307,22 @@ const pgClientPool = (options) => {
246
2307
  type: "Client",
247
2308
  connect,
248
2309
  close: (client) => client.end(),
249
- serializer: options.serializer
2310
+ serializer: options.serializer,
2311
+ ...transactionOptions ? { transactionOptions } : {}
250
2312
  });
251
2313
  }
252
2314
  });
253
2315
  };
254
2316
  const pgAmbientClientPool = (options) => {
255
- const { client } = options;
2317
+ const { client, transactionOptions } = options;
256
2318
  const getConnection = () => {
257
2319
  const connect = () => Promise.resolve(client);
258
2320
  return pgConnection({
259
2321
  type: "Client",
260
2322
  connect,
261
2323
  close: () => Promise.resolve(),
262
- serializer: options.serializer
2324
+ serializer: options.serializer,
2325
+ ...transactionOptions ? { transactionOptions } : {}
263
2326
  });
264
2327
  };
265
2328
  const open = () => Promise.resolve(getConnection());
@@ -272,26 +2335,31 @@ const pgAmbientClientPool = (options) => {
272
2335
  });
273
2336
  };
274
2337
  function pgPool(options) {
275
- const { connectionString, database } = options;
2338
+ const { connectionString, database, transactionOptions } = options;
276
2339
  const serializer = options.serialization?.serializer ?? JSONSerializer;
2340
+ const txOpts = transactionOptions ? { transactionOptions } : {};
277
2341
  if ("client" in options && options.client) return pgAmbientClientPool({
278
2342
  client: options.client,
279
- serializer
2343
+ serializer,
2344
+ ...txOpts
280
2345
  });
281
2346
  if ("connection" in options && options.connection) return pgAmbientConnectionPool({ connection: options.connection });
282
2347
  if ("pooled" in options && options.pooled === false) return pgClientPool({
283
2348
  connectionString,
284
2349
  database,
285
- serializer
2350
+ serializer,
2351
+ ...txOpts
286
2352
  });
287
2353
  if ("pool" in options && options.pool) return pgAmbientNativePool({
288
2354
  pool: options.pool,
289
- serializer
2355
+ serializer,
2356
+ ...txOpts
290
2357
  });
291
2358
  return pgNativePool({
292
2359
  connectionString,
293
2360
  database,
294
- serializer
2361
+ serializer,
2362
+ ...txOpts
295
2363
  });
296
2364
  }
297
2365
  const pools = /* @__PURE__ */ new Map();