@event-driven-io/dumbo 0.13.0-beta.3 → 0.13.0-beta.30

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 (91) hide show
  1. package/dist/chunk-4SM4JJJZ.js +83 -0
  2. package/dist/chunk-4SM4JJJZ.js.map +1 -0
  3. package/dist/chunk-EEKBLOCH.cjs +706 -0
  4. package/dist/chunk-EEKBLOCH.cjs.map +1 -0
  5. package/dist/{chunk-OJ34O3Q2.cjs → chunk-GVR3PSDL.cjs} +2474 -1636
  6. package/dist/chunk-GVR3PSDL.cjs.map +1 -0
  7. package/dist/chunk-HZM7GDOT.cjs +34 -0
  8. package/dist/chunk-HZM7GDOT.cjs.map +1 -0
  9. package/dist/{chunk-N7RWT46K.js → chunk-JKE6SULM.js} +2522 -1684
  10. package/dist/chunk-JKE6SULM.js.map +1 -0
  11. package/dist/chunk-MOPKHYYU.cjs +83 -0
  12. package/dist/chunk-MOPKHYYU.cjs.map +1 -0
  13. package/dist/chunk-RA2L3FQW.js +481 -0
  14. package/dist/chunk-RA2L3FQW.js.map +1 -0
  15. package/dist/chunk-UA542GT3.cjs +481 -0
  16. package/dist/chunk-UA542GT3.cjs.map +1 -0
  17. package/dist/chunk-WLWELSA2.js +34 -0
  18. package/dist/chunk-WLWELSA2.js.map +1 -0
  19. package/dist/chunk-XFEGS3YT.js +706 -0
  20. package/dist/chunk-XFEGS3YT.js.map +1 -0
  21. package/dist/cloudflare.cjs +456 -0
  22. package/dist/cloudflare.cjs.map +1 -0
  23. package/dist/cloudflare.d.cts +92 -0
  24. package/dist/cloudflare.d.ts +92 -0
  25. package/dist/cloudflare.js +456 -0
  26. package/dist/cloudflare.js.map +1 -0
  27. package/dist/{columnProcessors-DMPpTPqM.d.ts → columnProcessors-Be2uMYjS.d.cts} +1 -1
  28. package/dist/{columnProcessors-BX-sH7ah.d.cts → columnProcessors-D0ivj_SU.d.ts} +1 -1
  29. package/dist/{connectionString-B1wm0TFc.d.cts → connectionString-Dch_MIRU.d.cts} +394 -168
  30. package/dist/{connectionString-B1wm0TFc.d.ts → connectionString-Dch_MIRU.d.ts} +394 -168
  31. package/dist/index.cjs +100 -4
  32. package/dist/index.cjs.map +1 -1
  33. package/dist/index.d.cts +23 -18
  34. package/dist/index.d.ts +23 -18
  35. package/dist/index.js +105 -9
  36. package/dist/index.js.map +1 -1
  37. package/dist/pg.cjs +383 -9
  38. package/dist/pg.cjs.map +1 -1
  39. package/dist/pg.d.cts +81 -105
  40. package/dist/pg.d.ts +81 -105
  41. package/dist/pg.js +435 -61
  42. package/dist/pg.js.map +1 -1
  43. package/dist/postgresql.cjs +50 -0
  44. package/dist/postgresql.cjs.map +1 -0
  45. package/dist/postgresql.d.cts +61 -0
  46. package/dist/postgresql.d.ts +61 -0
  47. package/dist/postgresql.js +50 -0
  48. package/dist/sqlite.cjs +60 -0
  49. package/dist/sqlite.cjs.map +1 -0
  50. package/dist/{index-C2z_XBn6.d.ts → sqlite.d.cts} +69 -20
  51. package/dist/{index-C0h0c380.d.cts → sqlite.d.ts} +69 -20
  52. package/dist/sqlite.js +60 -0
  53. package/dist/sqlite3.cjs +319 -6
  54. package/dist/sqlite3.cjs.map +1 -1
  55. package/dist/sqlite3.d.cts +45 -25
  56. package/dist/sqlite3.d.ts +45 -25
  57. package/dist/sqlite3.js +335 -22
  58. package/dist/sqlite3.js.map +1 -1
  59. package/package.json +55 -33
  60. package/dist/chunk-A7TC7IOP.cjs +0 -55
  61. package/dist/chunk-A7TC7IOP.cjs.map +0 -1
  62. package/dist/chunk-F7JQ7BX7.js +0 -240
  63. package/dist/chunk-F7JQ7BX7.js.map +0 -1
  64. package/dist/chunk-I34X53VL.js +0 -688
  65. package/dist/chunk-I34X53VL.js.map +0 -1
  66. package/dist/chunk-ISNF6USX.cjs +0 -688
  67. package/dist/chunk-ISNF6USX.cjs.map +0 -1
  68. package/dist/chunk-IYEHOE4S.cjs +0 -405
  69. package/dist/chunk-IYEHOE4S.cjs.map +0 -1
  70. package/dist/chunk-L2YZQAG3.cjs +0 -240
  71. package/dist/chunk-L2YZQAG3.cjs.map +0 -1
  72. package/dist/chunk-N7RWT46K.js.map +0 -1
  73. package/dist/chunk-OJ34O3Q2.cjs.map +0 -1
  74. package/dist/chunk-TXSETOGH.js +0 -55
  75. package/dist/chunk-TXSETOGH.js.map +0 -1
  76. package/dist/chunk-XVV3OOQX.js +0 -405
  77. package/dist/chunk-XVV3OOQX.js.map +0 -1
  78. package/dist/d1.cjs +0 -277
  79. package/dist/d1.cjs.map +0 -1
  80. package/dist/d1.d.cts +0 -72
  81. package/dist/d1.d.ts +0 -72
  82. package/dist/d1.js +0 -277
  83. package/dist/d1.js.map +0 -1
  84. package/dist/pg-3ACXFMU4.cjs +0 -59
  85. package/dist/pg-3ACXFMU4.cjs.map +0 -1
  86. package/dist/pg-GHOW3XSG.js +0 -59
  87. package/dist/sqlite3-EEIKQCJR.js +0 -25
  88. package/dist/sqlite3-SE4DDYZE.cjs +0 -25
  89. package/dist/sqlite3-SE4DDYZE.cjs.map +0 -1
  90. /package/dist/{pg-GHOW3XSG.js.map → postgresql.js.map} +0 -0
  91. /package/dist/{sqlite3-EEIKQCJR.js.map → sqlite.js.map} +0 -0
@@ -1,1718 +1,2487 @@
1
- // src/core/drivers/index.ts
2
- function toDatabaseDriverType(databaseType, driverName) {
3
- return `${databaseType}:${driverName}`;
4
- }
5
- function fromDatabaseDriverType(databaseDriverType) {
6
- const parts = databaseDriverType.split(":");
1
+ // src/core/schema/schemaComponent.ts
2
+ var schemaComponent = (key, options) => {
3
+ const componentsMap = new Map(
4
+ options.components?.map((comp) => [comp.schemaComponentKey, comp])
5
+ );
6
+ const migrations = [...options.migrations ?? []];
7
7
  return {
8
- databaseType: parts[0],
9
- driverName: parts[1]
8
+ schemaComponentKey: key,
9
+ components: componentsMap,
10
+ get migrations() {
11
+ return [
12
+ ...migrations,
13
+ ...Array.from(componentsMap.values()).flatMap((c) => c.migrations)
14
+ ];
15
+ },
16
+ addComponent: (component) => {
17
+ componentsMap.set(component.schemaComponentKey, component);
18
+ migrations.push(...component.migrations);
19
+ return component;
20
+ },
21
+ addMigration: (migration) => {
22
+ migrations.push(migration);
23
+ }
10
24
  };
11
- }
12
- function getDatabaseDriverName(databaseDriverType) {
13
- const { driverName } = fromDatabaseDriverType(databaseDriverType);
14
- return driverName;
15
- }
16
- function getDatabaseType(databaseDriverType) {
17
- const { databaseType } = fromDatabaseDriverType(databaseDriverType);
18
- return databaseType;
19
- }
20
-
21
- // src/core/serializer/json/index.ts
22
- var bigIntReplacer = (_key, value) => {
23
- return typeof value === "bigint" ? value.toString() : value;
24
- };
25
- var bigIntReviver = (_key, value) => {
26
- if (typeof value === "string" && /^[+-]?\d+n?$/.test(value)) {
27
- return BigInt(value);
28
- }
29
- return value;
30
25
  };
31
- var composeJSONReplacers = (...replacers) => (key, value) => (
32
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
33
- replacers.reduce((accValue, replacer) => replacer(key, accValue), value)
34
- );
35
- var composeJSONRevivers = (...revivers) => (key, value) => (
36
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
37
- revivers.reduce((accValue, reviver) => reviver(key, accValue), value)
26
+ var isSchemaComponentOfType = (component, prefix) => component.schemaComponentKey.startsWith(prefix);
27
+ var filterSchemaComponentsOfType = (components, prefix) => mapSchemaComponentsOfType(components, prefix);
28
+ var mapSchemaComponentsOfType = (components, prefix, keyMapper) => new Map(
29
+ Array.from(components.entries()).filter(([urn]) => urn.startsWith(prefix)).map(([urn, component]) => [
30
+ keyMapper ? keyMapper(component) : urn,
31
+ component
32
+ ])
38
33
  );
39
- var JSONReplacer = (opts) => opts?.disableBigIntSerialization == true ? opts.replacer ? opts.replacer : void 0 : opts?.replacer ? composeJSONReplacers(JSONReplacers.bigInt, opts.replacer) : JSONReplacers.bigInt;
40
- var JSONReviver = (opts) => opts?.disableBigIntSerialization == true ? opts.reviver ? opts.reviver : void 0 : opts?.reviver ? composeJSONRevivers(JSONRevivers.bigInt, opts.reviver) : JSONRevivers.bigInt;
41
- var JSONReplacers = {
42
- bigInt: bigIntReplacer
34
+ var findSchemaComponentsOfType = (root, prefix) => {
35
+ const results = [];
36
+ const traverse = (component) => {
37
+ if (component.schemaComponentKey.startsWith(prefix)) {
38
+ results.push(component);
39
+ }
40
+ for (const child of component.components.values()) {
41
+ traverse(child);
42
+ }
43
+ };
44
+ traverse(root);
45
+ return results;
43
46
  };
44
- var JSONRevivers = {
45
- bigInt: bigIntReviver
47
+
48
+ // src/core/schema/components/columnSchemaComponent.ts
49
+ var ColumnURNType = "sc:dumbo:column";
50
+ var ColumnURN = ({
51
+ name
52
+ }) => `${ColumnURNType}:${name}`;
53
+ var columnSchemaComponent = (params) => {
54
+ const {
55
+ columnName,
56
+ type,
57
+ notNull,
58
+ unique,
59
+ primaryKey,
60
+ default: defaultValue,
61
+ ...schemaOptions
62
+ } = params;
63
+ const sc = schemaComponent(ColumnURN({ name: columnName }), schemaOptions);
64
+ const result = {
65
+ ...sc,
66
+ columnName,
67
+ notNull,
68
+ unique,
69
+ primaryKey,
70
+ defaultValue,
71
+ sqlTokenType: "SQL_COLUMN",
72
+ name: columnName,
73
+ type
74
+ };
75
+ return result;
46
76
  };
47
- var jsonSerializer = (options) => {
48
- const defaultReplacer = JSONReplacer(options);
49
- const defaultReviver = JSONReviver(options);
77
+
78
+ // src/core/schema/components/indexSchemaComponent.ts
79
+ var IndexURNType = "sc:dumbo:index";
80
+ var IndexURN = ({ name }) => `${IndexURNType}:${name}`;
81
+ var indexSchemaComponent = ({
82
+ indexName,
83
+ columnNames,
84
+ isUnique,
85
+ ...migrationsOrComponents
86
+ }) => {
87
+ const sc = schemaComponent(IndexURN({ name: indexName }), {
88
+ migrations: migrationsOrComponents.migrations ?? [],
89
+ components: [...migrationsOrComponents.components ?? []]
90
+ });
50
91
  return {
51
- serialize: (object, options2) => JSON.stringify(object, options2 ? JSONReplacer(options2) : defaultReplacer),
52
- deserialize: (payload, options2) => JSON.parse(payload, options2 ? JSONReviver(options2) : defaultReviver)
92
+ ...sc,
93
+ indexName,
94
+ get columnNames() {
95
+ return columnNames;
96
+ },
97
+ addColumn: (column) => columnNames.push(typeof column === "string" ? column : column.columnName),
98
+ isUnique
53
99
  };
54
100
  };
55
- var JSONSerializer = jsonSerializer({ disableBigIntSerialization: false });
56
- var RawJSONSerializer = jsonSerializer({ disableBigIntSerialization: true });
57
101
 
58
- // src/core/sql/parametrizedSQL/parametrizedSQL.ts
59
- var ParametrizedSQLBuilder = ({
60
- mapParamPlaceholder
102
+ // src/core/schema/components/tableSchemaComponent.ts
103
+ var TableURNType = "sc:dumbo:table";
104
+ var TableURN = ({ name }) => `${TableURNType}:${name}`;
105
+ var tableSchemaComponent = ({
106
+ tableName,
107
+ columns,
108
+ primaryKey,
109
+ relationships,
110
+ ...migrationsOrComponents
61
111
  }) => {
62
- const sql = [];
63
- const params = [];
112
+ columns ??= {};
113
+ relationships ??= {};
114
+ const base = schemaComponent(TableURN({ name: tableName }), {
115
+ migrations: migrationsOrComponents.migrations ?? [],
116
+ components: [
117
+ ...migrationsOrComponents.components ?? [],
118
+ ...Object.values(columns)
119
+ ]
120
+ });
64
121
  return {
65
- addSQL(str) {
66
- sql.push(str);
67
- return this;
68
- },
69
- addParam(value) {
70
- sql.push(mapParamPlaceholder(params.length, value));
71
- params.push(value);
72
- return this;
122
+ ...base,
123
+ tableName,
124
+ primaryKey: primaryKey ?? [],
125
+ relationships,
126
+ get columns() {
127
+ const columnsMap = mapSchemaComponentsOfType(
128
+ base.components,
129
+ ColumnURNType,
130
+ (c) => c.columnName
131
+ );
132
+ return Object.assign(columnsMap, columns);
73
133
  },
74
- addParams(values) {
75
- const placeholders = values.map(
76
- (value, i) => mapParamPlaceholder(params.length + i, value)
134
+ get indexes() {
135
+ return mapSchemaComponentsOfType(
136
+ base.components,
137
+ IndexURNType,
138
+ (c) => c.indexName
77
139
  );
78
- this.addSQL(`(${placeholders.join(", ")})`);
79
- params.push(...values);
80
- return this;
81
140
  },
82
- build() {
83
- return {
84
- query: sql.join(""),
85
- params
86
- };
87
- }
141
+ addColumn: (column) => base.addComponent(column),
142
+ addIndex: (index) => base.addComponent(index)
88
143
  };
89
144
  };
90
145
 
91
- // src/core/sql/tokens/sqlToken.ts
92
- var SQLToken = (sqlTokenType, map) => {
93
- const factory = (input) => {
94
- let props;
95
- if (map !== void 0) {
96
- props = map(input);
97
- } else if (input === void 0 || input === null) {
98
- props = {};
99
- } else if (typeof input === "object" && !Array.isArray(input)) {
100
- props = input;
101
- } else {
102
- throw new Error(
103
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
104
- `Cannot create SQLToken of type ${sqlTokenType} with input: ${input}`
146
+ // src/core/schema/components/databaseSchemaSchemaComponent.ts
147
+ var DatabaseSchemaURNType = "sc:dumbo:database_schema";
148
+ var DatabaseSchemaURN = ({
149
+ name
150
+ }) => `${DatabaseSchemaURNType}:${name}`;
151
+ var databaseSchemaSchemaComponent = ({
152
+ schemaName,
153
+ tables,
154
+ ...migrationsOrComponents
155
+ }) => {
156
+ const base = schemaComponent(DatabaseSchemaURN({ name: schemaName }), {
157
+ migrations: migrationsOrComponents.migrations ?? [],
158
+ components: [
159
+ ...migrationsOrComponents.components ?? [],
160
+ ...Object.values(tables ?? {})
161
+ ]
162
+ });
163
+ return {
164
+ ...base,
165
+ schemaName,
166
+ get tables() {
167
+ const tablesMap = mapSchemaComponentsOfType(
168
+ base.components,
169
+ TableURNType,
170
+ (c) => c.tableName
105
171
  );
106
- }
107
- return {
108
- sqlTokenType,
109
- [sqlTokenType]: true,
110
- ...props
111
- };
172
+ return Object.assign(tablesMap, tables);
173
+ },
174
+ addTable: (table) => base.addComponent(
175
+ typeof table === "string" ? tableSchemaComponent({ tableName: table }) : table
176
+ )
112
177
  };
113
- const check = (token) => SQLToken.check(token) && token.sqlTokenType === sqlTokenType;
114
- return { from: factory, check, type: sqlTokenType };
115
178
  };
116
- SQLToken.check = (token) => token !== null && typeof token === "object" && "sqlTokenType" in token;
117
- var SQLIdentifier = SQLToken(
118
- "SQL_IDENTIFIER",
119
- (value) => ({
120
- value
121
- })
122
- );
123
- var SQLPlain = SQLToken("SQL_RAW", (value) => ({
124
- value
125
- }));
126
- var SQLLiteral = SQLToken(
127
- "SQL_LITERAL",
128
- (value) => ({
129
- value
130
- })
131
- );
132
- var SQLArray = SQLToken("SQL_ARRAY", (value) => ({
133
- value
134
- }));
135
- var SQLIn = SQLToken(
136
- "SQL_IN",
137
- ({ column, values }) => ({
138
- column: SQLIdentifier.from(column),
139
- values: SQLArray.from(values)
140
- })
141
- );
142
179
 
143
- // src/core/sql/tokens/columnTokens.ts
144
- var ColumnTypeToken = (sqlTokenType, jsTypeName, map) => {
145
- const factory = (input) => {
146
- let props;
147
- if (map !== void 0) {
148
- props = map(input);
149
- } else if (input === void 0 || input === null) {
150
- props = {};
151
- } else if (typeof input === "object" && !Array.isArray(input)) {
152
- props = input;
153
- } else {
154
- throw new Error(
155
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
156
- `Cannot create SQLToken of type ${sqlTokenType} with input: ${input}`
180
+ // src/core/schema/components/databaseSchemaComponent.ts
181
+ var DatabaseURNType = "sc:dumbo:database";
182
+ var DatabaseURN = ({ name }) => `${DatabaseURNType}:${name}`;
183
+ var databaseSchemaComponent = ({
184
+ databaseName,
185
+ schemas,
186
+ ...migrationsOrComponents
187
+ }) => {
188
+ schemas ??= {};
189
+ const base = schemaComponent(DatabaseURN({ name: databaseName }), {
190
+ migrations: migrationsOrComponents.migrations ?? [],
191
+ components: [
192
+ ...migrationsOrComponents.components ?? [],
193
+ ...Object.values(schemas)
194
+ ]
195
+ });
196
+ return {
197
+ ...base,
198
+ databaseName,
199
+ get schemas() {
200
+ const schemasMap = mapSchemaComponentsOfType(
201
+ base.components,
202
+ DatabaseSchemaURNType,
203
+ (c) => c.schemaName
157
204
  );
158
- }
159
- return {
160
- sqlTokenType,
161
- [sqlTokenType]: true,
162
- jsTypeName,
163
- ...props
164
- };
205
+ return Object.assign(schemasMap, schemas);
206
+ },
207
+ addSchema: (schema) => base.addComponent(
208
+ typeof schema === "string" ? databaseSchemaSchemaComponent({ schemaName: schema }) : schema
209
+ )
165
210
  };
166
- const check = (token) => SQLToken.check(token) && token.sqlTokenType === sqlTokenType;
167
- return { from: factory, check, type: sqlTokenType };
168
211
  };
169
- var SerialToken = ColumnTypeToken(
170
- "SQL_COLUMN_SERIAL",
171
- "value_type:js:number"
172
- );
173
- var BigSerialToken = ColumnTypeToken(
174
- "SQL_COLUMN_BIGSERIAL",
175
- "value_type:js:bigint"
176
- );
177
- var IntegerToken = ColumnTypeToken(
178
- "SQL_COLUMN_INTEGER",
179
- "value_type:js:number"
180
- );
181
- var BigIntegerToken = ColumnTypeToken(
182
- "SQL_COLUMN_BIGINT",
183
- "value_type:js:bigint"
184
- );
185
- var JSONBToken = {
186
- type: "SQL_COLUMN_JSONB",
187
- from: () => {
188
- return {
189
- sqlTokenType: "SQL_COLUMN_JSONB",
190
- ["SQL_COLUMN_JSONB"]: true
191
- };
192
- },
193
- check: (token) => SQLToken.check(token) && token.sqlTokenType === "SQL_COLUMN_JSONB"
212
+
213
+ // src/core/schema/components/relationships/relationshipTypes.ts
214
+ var relationship = (columns, references, type) => {
215
+ return {
216
+ columns,
217
+ references,
218
+ type
219
+ };
194
220
  };
195
- var TimestampToken = ColumnTypeToken(
196
- "SQL_COLUMN_TIMESTAMP",
197
- "value_type:js:date"
198
- );
199
- var TimestamptzToken = ColumnTypeToken(
200
- "SQL_COLUMN_TIMESTAMPTZ",
201
- "value_type:js:date"
202
- );
203
- var VarcharToken = ColumnTypeToken(
204
- "SQL_COLUMN_VARCHAR",
205
- "value_type:js:string",
206
- (length) => ({
207
- length: length ?? "max",
208
- jsTypeName: "value_type:js:string"
209
- })
210
- );
211
- var AutoIncrementSQLColumnToken = ColumnTypeToken(
212
- "SQL_COLUMN_AUTO_INCREMENT",
213
- "value_type:js:bigint"
214
- );
215
- var SQLColumnTypeTokens = {
216
- AutoIncrement: AutoIncrementSQLColumnToken,
217
- BigInteger: BigIntegerToken,
218
- BigSerial: BigSerialToken,
219
- Integer: IntegerToken,
220
- JSONB: JSONBToken,
221
- Serial: SerialToken,
222
- Timestamp: TimestampToken,
223
- Timestamptz: TimestamptzToken,
224
- Varchar: VarcharToken
221
+
222
+ // src/core/schema/components/index.ts
223
+ var schemaComponentURN = {
224
+ database: DatabaseURN,
225
+ schema: DatabaseSchemaURN,
226
+ table: TableURN,
227
+ column: ColumnURN,
228
+ index: IndexURN,
229
+ extractName: (urn) => {
230
+ const parts = urn.split(":");
231
+ return parts[parts.length - 1] || "";
232
+ }
225
233
  };
226
- var SQLColumnTypeTokensFactory = {
227
- AutoIncrement: AutoIncrementSQLColumnToken.from,
228
- BigInteger: BigIntegerToken.from(),
229
- BigSerial: BigSerialToken.from(),
230
- Integer: IntegerToken.from(),
231
- JSONB: JSONBToken.from,
232
- Serial: SerialToken.from(),
233
- Timestamp: TimestampToken.from(),
234
- Timestamptz: TimestamptzToken.from(),
235
- Varchar: VarcharToken.from
234
+
235
+ // src/core/drivers/databaseDriver.ts
236
+ var canHandleDriverWithConnectionString = (driver, tryParseConnectionString) => (options) => {
237
+ if ("driverType" in options) return options.driverType === driver;
238
+ if ("connectionString" in options && typeof options.connectionString === "string")
239
+ return tryParseConnectionString(options.connectionString) !== null;
240
+ return false;
236
241
  };
237
- var SQLColumnToken = SQLToken("SQL_COLUMN");
242
+ var DumboDatabaseDriverRegistry = () => {
243
+ const drivers = /* @__PURE__ */ new Map();
244
+ const register = (driverType, plugin) => {
245
+ const entry = drivers.get(driverType);
246
+ if (entry && (typeof entry !== "function" || typeof plugin === "function")) {
247
+ return;
248
+ }
249
+ drivers.set(driverType, plugin);
250
+ };
251
+ const getDriver = (options) => options.driverType ? drivers.get(options.driverType) : [...drivers.values()].find(
252
+ (d) => typeof d !== "function" && d.canHandle(options)
253
+ );
254
+ const tryResolve = async (options) => {
255
+ const driver = getDriver(options);
256
+ if (!driver) return null;
257
+ if (typeof driver !== "function") return driver;
258
+ const plugin = await driver();
259
+ register(plugin.driverType, plugin);
260
+ return plugin;
261
+ };
262
+ const tryGet = (options) => {
263
+ const driver = getDriver(options);
264
+ return driver && typeof driver !== "function" ? driver : null;
265
+ };
266
+ const has = (driverType) => drivers.has(driverType);
267
+ return {
268
+ register,
269
+ tryResolve,
270
+ tryGet,
271
+ has,
272
+ get databaseDriverTypes() {
273
+ return Array.from(drivers.keys());
274
+ }
275
+ };
276
+ };
277
+ var dumboDatabaseDriverRegistry = globalThis.dumboDatabaseDriverRegistry = globalThis.dumboDatabaseDriverRegistry ?? DumboDatabaseDriverRegistry();
238
278
 
239
- // src/core/sql/processors/sqlProcessor.ts
240
- var SQLProcessor = (options) => options;
279
+ // src/core/drivers/index.ts
280
+ function toDatabaseDriverType(databaseType, driverName) {
281
+ return `${databaseType}:${driverName}`;
282
+ }
283
+ function fromDatabaseDriverType(databaseDriverType) {
284
+ const parts = databaseDriverType.split(":");
285
+ return {
286
+ databaseType: parts[0],
287
+ driverName: parts[1]
288
+ };
289
+ }
290
+ function getDatabaseDriverName(databaseDriverType) {
291
+ const { driverName } = fromDatabaseDriverType(databaseDriverType);
292
+ return driverName;
293
+ }
294
+ function getDatabaseType(databaseDriverType) {
295
+ const { databaseType } = fromDatabaseDriverType(databaseDriverType);
296
+ return databaseType;
297
+ }
241
298
 
242
- // src/core/sql/processors/defaultProcessors.ts
243
- var ExpandArrayProcessor = SQLProcessor({
244
- canHandle: "SQL_ARRAY",
245
- handle: (token, { builder, mapper }) => {
246
- if (token.value.length === 0) {
247
- throw new Error(
248
- "Empty arrays are not supported. If you're using it with SELECT IN statement Use SQL.in(column, array) helper instead."
249
- );
250
- }
251
- builder.addParams(mapper.mapValue(token.value));
252
- }
253
- });
254
- var ExpandSQLInProcessor = SQLProcessor({
255
- canHandle: "SQL_IN",
256
- handle: (token, context) => {
257
- const { builder, mapper, processorsRegistry } = context;
258
- const { values: inValues, column } = token;
259
- if (inValues.value.length === 0) {
260
- builder.addParam(mapper.mapValue(false));
299
+ // src/core/schema/databaseMetadata/databaseMetadata.ts
300
+ var DumboDatabaseMetadataRegistry = () => {
301
+ const infos = /* @__PURE__ */ new Map();
302
+ const register = (databaseType, info) => {
303
+ const entry = infos.get(databaseType);
304
+ if (entry && (typeof entry !== "function" || typeof info === "function")) {
261
305
  return;
262
306
  }
263
- builder.addSQL(mapper.mapValue(column.value));
264
- builder.addSQL(` IN `);
265
- const arrayProcessor = processorsRegistry.get(SQLArray.type);
266
- if (!arrayProcessor) {
267
- throw new Error(
268
- "No sql processor registered for an array. Cannot expand IN statement"
269
- );
307
+ infos.set(databaseType, info);
308
+ };
309
+ const tryResolve = async (databaseType) => {
310
+ const entry = infos.get(databaseType);
311
+ if (!entry) return null;
312
+ if (typeof entry !== "function") return entry;
313
+ const resolved = await entry();
314
+ register(databaseType, resolved);
315
+ return resolved;
316
+ };
317
+ const tryGet = (databaseType) => {
318
+ const entry = infos.get(databaseType);
319
+ return entry && typeof entry !== "function" ? entry : null;
320
+ };
321
+ const has = (databaseType) => infos.has(databaseType);
322
+ return {
323
+ register,
324
+ tryResolve,
325
+ tryGet,
326
+ has,
327
+ get databaseTypes() {
328
+ return Array.from(infos.keys());
270
329
  }
271
- arrayProcessor.handle(inValues, { builder, mapper, processorsRegistry });
272
- }
330
+ };
331
+ };
332
+ var dumboDatabaseMetadataRegistry = globalThis.dumboDatabaseMetadataRegistry = globalThis.dumboDatabaseMetadataRegistry ?? DumboDatabaseMetadataRegistry();
333
+ var getDatabaseMetadata = (driverType) => {
334
+ const { databaseType } = fromDatabaseDriverType(driverType);
335
+ return dumboDatabaseMetadataRegistry.tryGet(databaseType);
336
+ };
337
+ var resolveDatabaseMetadata = async (driverType, driverOverride) => {
338
+ if (driverOverride) return driverOverride;
339
+ const { databaseType } = fromDatabaseDriverType(driverType);
340
+ return dumboDatabaseMetadataRegistry.tryResolve(databaseType);
341
+ };
342
+ var getDefaultDatabase = (driverType) => {
343
+ const metadata = getDatabaseMetadata(driverType);
344
+ return metadata?.defaultDatabaseName;
345
+ };
346
+ var getDefaultDatabaseAsync = async (driverType) => {
347
+ const metadata = await resolveDatabaseMetadata(driverType);
348
+ return metadata?.defaultDatabaseName;
349
+ };
350
+
351
+ // src/core/schema/dumboSchema/dumboSchema.ts
352
+ var DEFAULT_DATABASE_NAME = "__default_database__";
353
+ var DEFAULT_DATABASE_SCHEMA_NAME = "__default_database_schema__";
354
+ var dumboColumn = (name, type, options) => columnSchemaComponent({
355
+ columnName: name,
356
+ type,
357
+ ...options
273
358
  });
274
- var FormatIdentifierProcessor = SQLProcessor({
275
- canHandle: "SQL_IDENTIFIER",
276
- handle: (token, { builder, mapper }) => {
277
- builder.addSQL(mapper.mapValue(token));
278
- }
359
+ var dumboIndex = (name, columnNames, options) => indexSchemaComponent({
360
+ indexName: name,
361
+ columnNames,
362
+ isUnique: options?.unique ?? false,
363
+ ...options
279
364
  });
280
- var MapLiteralProcessor = SQLProcessor({
281
- canHandle: "SQL_LITERAL",
282
- handle: (token, { builder, mapper }) => builder.addParam(mapper.mapValue(token.value))
283
- });
284
-
285
- // src/core/sql/processors/sqlProcessorRegistry.ts
286
- var SQLProcessorsRegistry = (options) => {
287
- const processors = options ? new Map(options.from.all()) : /* @__PURE__ */ new Map();
288
- function register(...args) {
289
- if (args.length === 1 && typeof args[0] === "object" && !Array.isArray(args[0])) {
290
- Object.entries(args[0]).forEach(
291
- ([_, processor]) => {
292
- processors.set(processor.canHandle, processor);
293
- }
294
- );
295
- } else {
296
- args.forEach(
297
- (p) => processors.set(p.canHandle, p)
365
+ var dumboTable = (name, definition) => {
366
+ const { columns, indexes, primaryKey, relationships, ...options } = definition;
367
+ const components = [...indexes ? Object.values(indexes) : []];
368
+ return tableSchemaComponent({
369
+ tableName: name,
370
+ columns: columns ?? {},
371
+ primaryKey: primaryKey ?? [],
372
+ ...relationships !== void 0 ? { relationships } : {},
373
+ components,
374
+ ...options
375
+ });
376
+ };
377
+ function dumboDatabaseSchema(nameOrTables, tables, options) {
378
+ const schemaName = typeof nameOrTables === "string" ? nameOrTables : DEFAULT_DATABASE_SCHEMA_NAME;
379
+ const tablesMap = (typeof nameOrTables === "string" ? tables : nameOrTables) ?? {};
380
+ return databaseSchemaSchemaComponent({
381
+ schemaName,
382
+ tables: tablesMap,
383
+ ...options
384
+ });
385
+ }
386
+ dumboDatabaseSchema.from = (schemaName, tableNames) => {
387
+ const tables = tableNames.reduce(
388
+ (acc, tableName) => {
389
+ acc[tableName] = dumboTable(tableName, {});
390
+ return acc;
391
+ },
392
+ {}
393
+ );
394
+ return schemaName ? dumboDatabaseSchema(schemaName, tables) : dumboDatabaseSchema(tables);
395
+ };
396
+ function dumboDatabase(nameOrSchemas, schemasOrOptions, options) {
397
+ const databaseName = typeof nameOrSchemas === "string" ? nameOrSchemas : DEFAULT_DATABASE_NAME;
398
+ const schemasOrSchema = typeof nameOrSchemas === "string" ? schemasOrOptions ?? {} : nameOrSchemas;
399
+ const schemaMap = "schemaComponentKey" in schemasOrSchema && isSchemaComponentOfType(
400
+ schemasOrSchema,
401
+ "sc:dumbo:database_schema"
402
+ ) ? {
403
+ [DEFAULT_DATABASE_SCHEMA_NAME]: schemasOrSchema
404
+ } : schemasOrSchema;
405
+ const dbOptions = typeof nameOrSchemas === "string" ? options : schemasOrOptions;
406
+ return databaseSchemaComponent({
407
+ databaseName,
408
+ schemas: schemaMap,
409
+ ...dbOptions
410
+ });
411
+ }
412
+ dumboDatabase.from = (databaseName, schemaNames) => {
413
+ const schemas = schemaNames.reduce(
414
+ (acc, schemaName) => {
415
+ acc[schemaName] = dumboDatabaseSchema(
416
+ schemaName,
417
+ {}
298
418
  );
299
- }
300
- return registry;
301
- }
302
- const registry = {
303
- register,
304
- get: (tokenType) => {
305
- return processors.get(tokenType) ?? null;
419
+ return acc;
306
420
  },
307
- all: () => processors
308
- };
309
- return registry;
421
+ {}
422
+ );
423
+ return databaseName ? dumboDatabase(databaseName, schemas) : dumboDatabase(schemas);
424
+ };
425
+ dumboDatabase.defaultName = DEFAULT_DATABASE_NAME;
426
+ dumboDatabaseSchema.defaultName = DEFAULT_DATABASE_SCHEMA_NAME;
427
+ var dumboSchema = {
428
+ database: dumboDatabase,
429
+ schema: dumboDatabaseSchema,
430
+ table: dumboTable,
431
+ column: dumboColumn,
432
+ index: dumboIndex
310
433
  };
311
434
 
312
- // src/core/sql/processors/columnProcessors.ts
313
- var mapDefaultSQLColumnProcessors = (mapColumnType) => ({
314
- AutoIncrement: SQLProcessor({
315
- canHandle: "SQL_COLUMN_AUTO_INCREMENT",
316
- handle: (token, context) => {
317
- mapColumnType(token, context);
318
- }
319
- }),
320
- BigInteger: SQLProcessor({
321
- canHandle: "SQL_COLUMN_BIGINT",
322
- handle: (token, context) => mapColumnType(token, context)
323
- }),
324
- BigSerial: SQLProcessor({
325
- canHandle: "SQL_COLUMN_BIGSERIAL",
326
- handle: (token, context) => mapColumnType(token, context)
327
- }),
328
- Serial: SQLProcessor({
329
- canHandle: "SQL_COLUMN_SERIAL",
330
- handle: (token, context) => mapColumnType(token, context)
331
- }),
332
- Integer: SQLProcessor({
333
- canHandle: "SQL_COLUMN_INTEGER",
334
- handle: (token, context) => mapColumnType(token, context)
335
- }),
336
- JSONB: SQLProcessor({
337
- canHandle: "SQL_COLUMN_JSONB",
338
- handle: (token, context) => mapColumnType(token, context)
339
- }),
340
- Timestamp: SQLProcessor({
341
- canHandle: "SQL_COLUMN_TIMESTAMP",
342
- handle: (token, context) => mapColumnType(token, context)
343
- }),
344
- Timestamptz: SQLProcessor({
345
- canHandle: "SQL_COLUMN_TIMESTAMPTZ",
346
- handle: (token, context) => mapColumnType(token, context)
347
- }),
348
- Varchar: SQLProcessor({
349
- canHandle: "SQL_COLUMN_VARCHAR",
350
- handle: (token, context) => mapColumnType(token, context)
351
- })
352
- });
353
-
354
- // src/core/sql/processors/index.ts
355
- var defaultProcessorsRegistry = globalThis.defaultProcessorsRegistry = globalThis.defaultProcessorsRegistry ?? SQLProcessorsRegistry().register(
356
- FormatIdentifierProcessor,
357
- MapLiteralProcessor,
358
- ExpandArrayProcessor,
359
- ExpandSQLInProcessor
360
- );
435
+ // src/core/locks/databaseLock.ts
436
+ var defaultDatabaseLockOptions = {
437
+ timeoutMs: 1e4
438
+ };
439
+ var NoDatabaseLock = {
440
+ acquire: () => Promise.resolve(),
441
+ tryAcquire: () => Promise.resolve(true),
442
+ release: () => Promise.resolve(true),
443
+ withAcquire: (_execute, handle, _options) => handle()
444
+ };
361
445
 
362
- // src/core/sql/tokenizedSQL/tokenizedSQL.ts
363
- var TokenizedSQLBuilder = () => {
364
- const sqlChunks = [];
365
- const sqlTokens = [];
366
- return {
367
- addSQL(str) {
368
- sqlChunks.push(str);
369
- },
370
- addSQLs(str) {
371
- sqlChunks.push(...str);
372
- },
373
- addToken(value) {
374
- sqlTokens.push(value);
375
- },
376
- addTokens(vals) {
377
- sqlTokens.push(...vals);
378
- },
379
- build() {
380
- return sqlChunks.length > 0 ? {
381
- __brand: "tokenized-sql",
382
- sqlChunks,
383
- sqlTokens
384
- } : TokenizedSQL.empty;
385
- }
386
- };
446
+ // src/core/query/mappers.ts
447
+ var mapRows = async (getResult, map) => {
448
+ const result = await getResult;
449
+ return result.rows.map(map);
387
450
  };
388
- var TokenizedSQL = (strings, values) => {
389
- const builder = TokenizedSQLBuilder();
390
- for (let i = 0; i < strings.length; i++) {
391
- if (strings[i] !== "") builder.addSQL(strings[i]);
392
- if (i >= values.length) break;
393
- const value = values[i];
394
- if (isTokenizedSQL(value)) {
395
- builder.addSQLs(value.sqlChunks);
396
- builder.addTokens(value.sqlTokens);
397
- } else if (SQLPlain.check(value)) {
398
- builder.addSQL(value.value);
399
- } else {
400
- builder.addSQL(TokenizedSQL.paramPlaceholder);
401
- builder.addToken(
402
- SQLToken.check(value) ? value : Array.isArray(value) ? SQLArray.from(value) : SQLLiteral.from(value)
403
- );
451
+ var toCamelCase = (snakeStr) => snakeStr.replace(/_([a-z])/g, (g) => g[1]?.toUpperCase() ?? "");
452
+ var mapToCamelCase = (obj) => {
453
+ const newObj = {};
454
+ for (const key in obj) {
455
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
456
+ newObj[toCamelCase(key)] = obj[key];
404
457
  }
405
458
  }
406
- return builder.build();
407
- };
408
- var isTokenizedSQL = (value) => {
409
- return value !== null && typeof value === "object" && "__brand" in value && value.__brand === "tokenized-sql";
410
- };
411
- TokenizedSQL.paramPlaceholder = `__P__`;
412
- TokenizedSQL.empty = {
413
- __brand: "tokenized-sql",
414
- sqlChunks: [""],
415
- sqlTokens: []
459
+ return newObj;
416
460
  };
417
461
 
418
- // src/core/sql/sql.ts
419
- function SQL(strings, ...values) {
420
- const parametrized = TokenizedSQL(strings, values);
421
- return parametrized;
422
- }
423
- var isSQL = (value) => {
424
- if (value === void 0 || value === null) {
425
- return false;
426
- }
427
- return isTokenizedSQL(value);
462
+ // src/core/query/selectors.ts
463
+ var firstOrNull = async (getResult) => {
464
+ const result = await getResult;
465
+ return result.rows.length > 0 ? result.rows[0] ?? null : null;
428
466
  };
429
- var emptySQL = {
430
- __brand: "tokenized-sql",
431
- sqlChunks: [""],
432
- sqlTokens: []
467
+ var first = async (getResult) => {
468
+ const result = await getResult;
469
+ if (result.rows.length === 0)
470
+ throw new Error("Query didn't return any result");
471
+ return result.rows[0];
433
472
  };
434
- var mergeSQL = (sqls, separator = " ") => {
435
- const parametrized = sqls.filter((sql) => !isEmpty(sql)).map((sql) => sql);
436
- const params = parametrized.flatMap((p) => p.sqlTokens);
437
- const sqlChunks = parametrized.flatMap(
438
- (p, i) => i == parametrized.length - 1 || separator === "" ? p.sqlChunks : [...p.sqlChunks, separator]
439
- );
440
- const merged = sqlChunks.length > 0 ? {
441
- __brand: "tokenized-sql",
442
- sqlChunks,
443
- sqlTokens: params
444
- } : TokenizedSQL.empty;
445
- return merged;
473
+ var singleOrNull = async (getResult) => {
474
+ const result = await getResult;
475
+ if (result.rows.length > 1) throw new Error("Query had more than one result");
476
+ return result.rows.length > 0 ? result.rows[0] ?? null : null;
446
477
  };
447
- var concatSQL = (...sqls) => mergeSQL(sqls, "");
448
- var isEmpty = (sql) => {
449
- if (isTokenizedSQL(sql)) {
450
- const parametrized = sql;
451
- return parametrized.sqlChunks.every((chunk) => chunk.trim() === "") && parametrized.sqlTokens.length === 0;
452
- }
453
- return false;
478
+ var single = async (getResult) => {
479
+ const result = await getResult;
480
+ if (result.rows.length === 0)
481
+ throw new Error("Query didn't return any result");
482
+ if (result.rows.length > 1) throw new Error("Query had more than one result");
483
+ return result.rows[0];
454
484
  };
455
- SQL.EMPTY = emptySQL;
456
- SQL.concat = concatSQL;
457
- SQL.merge = mergeSQL;
458
- SQL.format = (sql, formatter, options) => formatSQL(sql, formatter, options);
459
- SQL.describe = (sql, formatter, options) => describeSQL(sql, formatter, options);
460
- SQL.in = (column, values) => SQLIn.from({ column, values });
461
- SQL.identifier = SQLIdentifier.from;
462
- SQL.plain = SQLPlain.from;
463
- SQL.check = {
464
- isSQL,
465
- isTokenizedSQL: (value) => isTokenizedSQL(value),
466
- isEmpty,
467
- isIdentifier: SQLIdentifier.check,
468
- isPlain: SQLPlain.check,
469
- isSQLIn: SQLIn.check
485
+ var count = async (getResult) => {
486
+ const result = await single(getResult);
487
+ return Number(result.count);
470
488
  };
471
- var columnFactory = SQLColumnToken.from;
472
- columnFactory.type = SQLColumnTypeTokensFactory;
473
- SQL.column = columnFactory;
474
-
475
- // src/core/sql/valueMappers/reservedSqlWords.ts
476
- var ansiSqlReservedMap = {
477
- ALL: true,
478
- AND: true,
479
- ANY: true,
480
- ARRAY: true,
481
- AS: true,
482
- ASC: true,
483
- AUTHORIZATION: true,
484
- BETWEEN: true,
485
- BINARY: true,
486
- BOTH: true,
487
- CASE: true,
488
- CAST: true,
489
- CHECK: true,
490
- COLLATE: true,
491
- COLUMN: true,
492
- CONSTRAINT: true,
493
- CREATE: true,
494
- CROSS: true,
495
- CURRENT_DATE: true,
496
- CURRENT_TIME: true,
497
- CURRENT_TIMESTAMP: true,
498
- CURRENT_USER: true,
499
- DEFAULT: true,
500
- DEFERRABLE: true,
501
- DESC: true,
502
- DISTINCT: true,
503
- DO: true,
504
- ELSE: true,
505
- END: true,
506
- EXCEPT: true,
507
- FALSE: true,
508
- FOR: true,
509
- FOREIGN: true,
510
- FROM: true,
511
- FULL: true,
512
- GRANT: true,
513
- GROUP: true,
514
- HAVING: true,
515
- IN: true,
516
- INITIALLY: true,
517
- INNER: true,
518
- INTERSECT: true,
519
- INTO: true,
520
- IS: true,
521
- JOIN: true,
522
- LEADING: true,
523
- LEFT: true,
524
- LIKE: true,
525
- LOCALTIME: true,
526
- LOCALTIMESTAMP: true,
527
- NATURAL: true,
528
- NEW: true,
529
- NOT: true,
530
- NULL: true,
531
- NULLS: true,
532
- OLD: true,
533
- ON: true,
534
- ONLY: true,
535
- OPEN: true,
536
- OR: true,
537
- ORDER: true,
538
- OUTER: true,
539
- OVERLAPS: true,
540
- PARTITION: true,
541
- PLACING: true,
542
- PRIMARY: true,
543
- REFERENCES: true,
544
- RIGHT: true,
545
- SELECT: true,
546
- SESSION_USER: true,
547
- SIMILAR: true,
548
- SOME: true,
549
- TABLE: true,
550
- THEN: true,
551
- TO: true,
552
- TRAILING: true,
553
- TRUE: true,
554
- UNION: true,
555
- UNIQUE: true,
556
- USER: true,
557
- USING: true,
558
- WHEN: true,
559
- WHERE: true,
560
- WITH: true,
561
- WITHOUT: true,
562
- ADD: true,
563
- ALTER: true,
564
- ARE: true,
565
- AT: true,
566
- BEGIN: true,
567
- BY: true,
568
- CASCADE: true,
569
- CLOSE: true,
570
- COMMIT: true,
571
- CONNECT: true,
572
- CONTINUE: true,
573
- CORRESPONDING: true,
574
- CURSOR: true,
575
- DEALLOCATE: true,
576
- DECLARE: true,
577
- DELETE: true,
578
- DESCRIBE: true,
579
- DISCONNECT: true,
580
- DROP: true,
581
- ESCAPE: true,
582
- EXECUTE: true,
583
- EXISTS: true,
584
- FETCH: true,
585
- FIRST: true,
586
- FLOAT: true,
587
- GET: true,
588
- GLOBAL: true,
589
- GO: true,
590
- GOTO: true,
591
- HOUR: true,
592
- IMMEDIATE: true,
593
- INDICATOR: true,
594
- INPUT: true,
595
- INSERT: true,
596
- INT: true,
597
- INTEGER: true,
598
- INTERVAL: true,
599
- LANGUAGE: true,
600
- LAST: true,
601
- LOCAL: true,
602
- MATCH: true,
603
- MINUTE: true,
604
- MODULE: true,
605
- MONTH: true,
606
- NATIONAL: true,
607
- NEXT: true,
608
- NO: true,
609
- OF: true,
610
- OUTPUT: true,
611
- PARTIAL: true,
612
- PREPARE: true,
613
- PRESERVE: true,
614
- PRIOR: true,
615
- PRIVILEGES: true,
616
- PROCEDURE: true,
617
- PUBLIC: true,
618
- READ: true,
619
- REAL: true,
620
- RESTRICT: true,
621
- REVOKE: true,
622
- ROLLBACK: true,
623
- ROWS: true,
624
- SCHEMA: true,
625
- SCROLL: true,
626
- SECOND: true,
627
- SECTION: true,
628
- SET: true,
629
- SIZE: true,
630
- SMALLINT: true,
631
- SQL: true,
632
- SQLCODE: true,
633
- SQLERROR: true,
634
- SQLSTATE: true,
635
- TEMPORARY: true,
636
- TIMEZONE_HOUR: true,
637
- TIMEZONE_MINUTE: true,
638
- TRANSACTION: true,
639
- TRANSLATE: true,
640
- TRANSLATION: true,
641
- UNKNOWN: true,
642
- UPDATE: true,
643
- VALUE: true,
644
- VALUES: true,
645
- VARCHAR: true,
646
- VARYING: true,
647
- VIEW: true,
648
- WHENEVER: true,
649
- WORK: true,
650
- WRITE: true,
651
- YEAR: true,
652
- ZONE: true
489
+ var exists = async (getResult) => {
490
+ const result = await single(getResult);
491
+ return result.exists === true || result.exists === 1;
653
492
  };
654
493
 
655
- // src/core/sql/valueMappers/sqlValueMapper.ts
656
- var ANSISQLParamPlaceholder = "?";
657
- var ANSISQLIdentifierQuote = '"';
658
- var mapANSISQLParamPlaceholder = () => ANSISQLParamPlaceholder;
659
- var isReserved = (value, reserved) => !!reserved[value.toUpperCase()];
660
- var mapSQLIdentifier = (value, options) => {
661
- if (value === void 0 || value === null) {
662
- throw new Error("SQL identifier cannot be null or undefined");
494
+ // src/core/serializer/json/index.ts
495
+ var bigIntReplacer = (_key, value) => {
496
+ return typeof value === "bigint" ? value.toString() : value;
497
+ };
498
+ var dateReplacer = (_key, value) => {
499
+ return value instanceof Date ? value.toISOString() : value;
500
+ };
501
+ var isFirstLetterNumeric = (str) => {
502
+ const c = str.charCodeAt(0);
503
+ return c >= 48 && c <= 57;
504
+ };
505
+ var isFirstLetterNumericOrMinus = (str) => {
506
+ const c = str.charCodeAt(0);
507
+ return c >= 48 && c <= 57 || c === 45;
508
+ };
509
+ var bigIntReviver = (_key, value, context) => {
510
+ if (typeof value === "number" && Number.isInteger(value) && !Number.isSafeInteger(value)) {
511
+ try {
512
+ return BigInt(context?.source ?? value.toString());
513
+ } catch {
514
+ return value;
515
+ }
663
516
  }
664
- const ident = value.toString().slice(0);
665
- const quoteSign = options?.quote ?? ANSISQLIdentifierQuote;
666
- if (/^[a-z_][a-z0-9_$]*$/.test(ident) && !isReserved(ident, options?.reservedWords ?? ansiSqlReservedMap)) {
667
- return ident;
517
+ if (typeof value === "string" && value.length > 15) {
518
+ if (isFirstLetterNumericOrMinus(value)) {
519
+ const num = Number(value);
520
+ if (Number.isFinite(num) && !Number.isSafeInteger(num)) {
521
+ try {
522
+ return BigInt(value);
523
+ } catch {
524
+ }
525
+ }
526
+ }
668
527
  }
669
- let quoted = quoteSign;
670
- for (let i = 0; i < ident.length; i++) {
671
- const c = ident[i];
672
- quoted += c === quoteSign ? c + c : c;
528
+ return value;
529
+ };
530
+ var dateReviver = (_key, value) => {
531
+ if (typeof value === "string" && value.length === 24 && isFirstLetterNumeric(value) && value[10] === "T" && value[23] === "Z") {
532
+ const date = new Date(value);
533
+ if (!isNaN(date.getTime())) {
534
+ return date;
535
+ }
673
536
  }
674
- quoted += quoteSign;
675
- return quoted;
537
+ return value;
676
538
  };
677
- var DefaultMapSQLParamValueOptions = {
678
- mapPlaceholder: mapANSISQLParamPlaceholder,
679
- mapIdentifier: mapSQLIdentifier
539
+ var composeJSONReplacers = (...replacers) => {
540
+ const filteredReplacers = replacers.filter((r) => r !== void 0);
541
+ if (filteredReplacers.length === 0) return void 0;
542
+ return (key, value) => (
543
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
544
+ filteredReplacers.reduce(
545
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
546
+ (accValue, replacer) => replacer(key, accValue),
547
+ value
548
+ )
549
+ );
680
550
  };
681
- var SQLValueMapper = (options) => {
682
- const mapSQLParamValueOptions = {
683
- ...DefaultMapSQLParamValueOptions,
684
- ...options ?? {}
685
- };
686
- const resultMapper = {
687
- mapValue: (value) => mapSQLParamValue(value, mapSQLParamValueOptions),
688
- mapPlaceholder: mapSQLParamValueOptions.mapPlaceholder,
689
- mapIdentifier: mapSQLParamValueOptions.mapIdentifier
690
- };
691
- return resultMapper;
551
+ var composeJSONRevivers = (...revivers) => {
552
+ const filteredRevivers = revivers.filter((r) => r !== void 0);
553
+ if (filteredRevivers.length === 0) return void 0;
554
+ return (key, value, context) => (
555
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
556
+ filteredRevivers.reduce(
557
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return
558
+ (accValue, reviver) => reviver(key, accValue, context),
559
+ value
560
+ )
561
+ );
692
562
  };
693
- function mapSQLParamValue(value, options) {
694
- if (value === null || value === void 0) {
695
- return null;
696
- } else if (typeof value === "number") {
697
- return value;
698
- } else if (typeof value === "string") {
699
- return value;
700
- } else if (Array.isArray(value)) {
701
- const mapValue = options?.mapValue ?? mapSQLParamValue;
702
- return options?.mapArray ? options.mapArray(value, mapValue) : value.map((item) => mapValue(item, options));
703
- } else if (typeof value === "boolean") {
704
- return options?.mapBoolean ? options.mapBoolean(value) : value;
705
- } else if (typeof value === "bigint") {
706
- return options?.mapBigInt ? options.mapBigInt(value) : value.toString();
707
- } else if (value instanceof Date) {
708
- return options?.mapDate ? options.mapDate(value) : value.toISOString();
709
- } else if (SQL.check.isIdentifier(value)) {
710
- return (options?.mapIdentifier ?? mapSQLIdentifier)(value.value);
711
- } else if (typeof value === "object") {
712
- return options?.mapObject ? options.mapObject(value) : `${JSONSerializer.serialize(value).replace(/'/g, "''")}`;
713
- } else {
714
- return JSONSerializer.serialize(value);
715
- }
716
- }
717
-
718
- // src/core/sql/formatters/sqlFormatter.ts
719
- var SQLFormatter2 = ({
720
- format,
721
- describe,
722
- valueMapper: valueMapperOptions,
723
- processorsRegistry
724
- }) => {
725
- const valueMapper = SQLValueMapper(valueMapperOptions);
726
- const options = {
727
- builder: ParametrizedSQLBuilder({
728
- mapParamPlaceholder: valueMapper.mapPlaceholder
729
- }),
730
- mapper: valueMapper,
731
- processorsRegistry: processorsRegistry ?? defaultProcessorsRegistry
732
- };
733
- const resultFormatter = {
734
- format: format ?? ((sql, methodOptions) => formatSQL(sql, resultFormatter, {
735
- ...options,
736
- ...methodOptions ?? {}
737
- })),
738
- describe: describe ?? ((sql, methodOptions) => describeSQL(sql, resultFormatter, {
739
- ...options,
740
- ...methodOptions ?? {}
741
- })),
742
- valueMapper
743
- };
744
- return resultFormatter;
563
+ var JSONReplacer = (opts) => composeJSONReplacers(
564
+ opts?.replacer,
565
+ opts?.failOnBigIntSerialization !== true ? JSONReplacers.bigInt : void 0,
566
+ opts?.useDefaultDateSerialization !== true ? JSONReplacers.date : void 0
567
+ );
568
+ var JSONReviver = (opts) => composeJSONRevivers(
569
+ opts?.reviver,
570
+ opts?.parseBigInts === true ? JSONRevivers.bigInt : void 0,
571
+ opts?.parseDates === true ? JSONRevivers.date : void 0
572
+ );
573
+ var JSONReplacers = {
574
+ bigInt: bigIntReplacer,
575
+ date: dateReplacer
745
576
  };
746
- var dumboSQLFormatters = globalThis.dumboSQLFormatters = globalThis.dumboSQLFormatters ?? {};
747
- var registerFormatter = (dialect, formatter) => {
748
- dumboSQLFormatters[dialect] = formatter;
577
+ var JSONRevivers = {
578
+ bigInt: bigIntReviver,
579
+ date: dateReviver
749
580
  };
750
- var getFormatter = (dialect) => {
751
- const formatterKey = dialect;
752
- if (!dumboSQLFormatters[formatterKey]) {
753
- throw new Error(`No SQL formatter registered for dialect: ${dialect}`);
754
- }
755
- return dumboSQLFormatters[formatterKey];
581
+ var jsonSerializer = (options) => {
582
+ const defaultReplacer = JSONReplacer(options);
583
+ const defaultReviver = JSONReviver(options);
584
+ return {
585
+ serialize: (object, serializerOptions) => JSON.stringify(
586
+ object,
587
+ serializerOptions ? JSONReplacer(serializerOptions) : defaultReplacer
588
+ ),
589
+ deserialize: (payload, deserializerOptions) => JSON.parse(
590
+ payload,
591
+ deserializerOptions ? JSONReviver(deserializerOptions) : defaultReviver
592
+ )
593
+ };
756
594
  };
757
- function formatSQL(sql, formatter, context) {
758
- const mapper = context?.mapper == void 0 ? formatter.valueMapper : {
759
- ...formatter.valueMapper,
760
- ...context.mapper
595
+ var JSONSerializer = Object.assign(jsonSerializer(), {
596
+ from: (options) => options?.serialization?.serializer ?? (options?.serialization?.options ? jsonSerializer(options?.serialization?.options) : JSONSerializer)
597
+ });
598
+ var JSONCodec = (options) => {
599
+ const serializer = "serializer" in options ? options.serializer : jsonSerializer(
600
+ "serializerOptions" in options ? options.serializerOptions : void 0
601
+ );
602
+ const upcast = options.upcast ?? ((doc) => doc);
603
+ const downcast = options.downcast ?? ((doc) => doc);
604
+ return {
605
+ decode: (payload, decodeOptions) => {
606
+ const deserialized = decodeOptions ? serializer.deserialize(payload, decodeOptions) : serializer.deserialize(payload);
607
+ return upcast(deserialized);
608
+ },
609
+ encode: (object, encodeOptions) => {
610
+ const downcasted = downcast(object);
611
+ return encodeOptions ? serializer.serialize(downcasted, encodeOptions) : serializer.serialize(downcasted);
612
+ }
761
613
  };
762
- const processorsRegistry = context?.processorsRegistry ?? defaultProcessorsRegistry;
763
- const merged = Array.isArray(sql) ? SQL.merge(sql, "\n") : sql;
764
- if (!isTokenizedSQL(merged)) {
765
- throw new Error("Expected TokenizedSQL, got string-based SQL");
766
- }
767
- const builder = ParametrizedSQLBuilder({
768
- mapParamPlaceholder: mapper.mapPlaceholder
769
- });
770
- let paramIndex = 0;
771
- for (let i = 0; i < merged.sqlChunks.length; i++) {
772
- const sqlChunk = merged.sqlChunks[i];
773
- if (sqlChunk !== TokenizedSQL.paramPlaceholder) {
774
- builder.addSQL(sqlChunk);
775
- continue;
614
+ };
615
+
616
+ // src/core/sql/parametrizedSQL/parametrizedSQL.ts
617
+ var ParametrizedSQLBuilder = ({
618
+ mapParamPlaceholder
619
+ }) => {
620
+ const sql = [];
621
+ const params = [];
622
+ return {
623
+ addSQL(str) {
624
+ sql.push(str);
625
+ return this;
626
+ },
627
+ addParam(value) {
628
+ sql.push(mapParamPlaceholder(params.length, value));
629
+ params.push(value);
630
+ return this;
631
+ },
632
+ addParams(values) {
633
+ const placeholders = values.map(
634
+ (value, i) => mapParamPlaceholder(params.length + i, value)
635
+ );
636
+ this.addSQL(`${placeholders.join(", ")}`);
637
+ params.push(...values);
638
+ return this;
639
+ },
640
+ build() {
641
+ return {
642
+ query: sql.join(""),
643
+ params
644
+ };
776
645
  }
777
- const token = merged.sqlTokens[paramIndex++];
778
- const processor = processorsRegistry.get(token.sqlTokenType);
779
- if (!processor) {
646
+ };
647
+ };
648
+
649
+ // src/core/sql/tokens/sqlToken.ts
650
+ var SQLToken = (sqlTokenType, map) => {
651
+ const factory = (input) => {
652
+ let props;
653
+ if (map !== void 0) {
654
+ props = map(input);
655
+ } else if (input === void 0 || input === null) {
656
+ props = {};
657
+ } else if (typeof input === "object" && !Array.isArray(input)) {
658
+ props = input;
659
+ } else {
780
660
  throw new Error(
781
- `No SQL processor registered for token type: ${token.sqlTokenType}`
661
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
662
+ `Cannot create SQLToken of type ${sqlTokenType} with input: ${input}`
782
663
  );
783
664
  }
784
- processor.handle(token, {
785
- builder,
786
- processorsRegistry,
787
- mapper
788
- });
665
+ return {
666
+ sqlTokenType,
667
+ [sqlTokenType]: true,
668
+ ...props
669
+ };
670
+ };
671
+ const check = (token) => SQLToken.check(token) && token.sqlTokenType === sqlTokenType;
672
+ return { from: factory, check, type: sqlTokenType };
673
+ };
674
+ SQLToken.check = (token) => token !== null && typeof token === "object" && "sqlTokenType" in token;
675
+ var SQLIdentifier = SQLToken(
676
+ "SQL_IDENTIFIER",
677
+ (value) => ({
678
+ value
679
+ })
680
+ );
681
+ var SQLPlain = SQLToken("SQL_RAW", (value) => ({
682
+ value
683
+ }));
684
+ var SQLLiteral = SQLToken(
685
+ "SQL_LITERAL",
686
+ (value) => ({
687
+ value
688
+ })
689
+ );
690
+ var SQLArray = SQLToken("SQL_ARRAY", (input) => {
691
+ if (Array.isArray(input)) {
692
+ return { value: input };
789
693
  }
790
- return builder.build();
791
- }
792
- var describeSQL = (sql, formatter, options) => formatSQL(sql, formatter, {
793
- ...options ?? {},
794
- mapper: {
795
- mapPlaceholder: (_, value) => JSONSerializer.serialize(value)
694
+ return input.mode !== void 0 ? { value: input.value, mode: input.mode } : { value: input.value };
695
+ });
696
+ var SQLIn = SQLToken(
697
+ "SQL_IN",
698
+ ({ column, values, mode }) => mode !== void 0 ? {
699
+ column: SQLIdentifier.from(column),
700
+ values: SQLArray.from(values),
701
+ mode
702
+ } : {
703
+ column: SQLIdentifier.from(column),
704
+ values: SQLArray.from(values)
796
705
  }
797
- }).query;
706
+ );
798
707
 
799
- // src/core/execute/execute.ts
800
- var mapColumnToJSON = (column, options) => ({
801
- [column]: (value) => {
802
- if (typeof value === "string") {
803
- try {
804
- return JSONSerializer.deserialize(value, options);
805
- } catch {
806
- }
807
- }
808
- return value;
809
- }
810
- });
811
- var mapColumnToBigint = (column) => ({
812
- [column]: (value) => {
813
- if (typeof value === "number" || typeof value === "string") {
814
- return BigInt(value);
708
+ // src/core/sql/tokens/columnTokens.ts
709
+ var ColumnTypeToken = (sqlTokenType, jsTypeName, map) => {
710
+ const factory = (input) => {
711
+ let props;
712
+ if (map !== void 0) {
713
+ props = map(input);
714
+ } else if (input === void 0 || input === null) {
715
+ props = {};
716
+ } else if (typeof input === "object" && !Array.isArray(input)) {
717
+ props = input;
718
+ } else {
719
+ throw new Error(
720
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
721
+ `Cannot create SQLToken of type ${sqlTokenType} with input: ${input}`
722
+ );
815
723
  }
816
- return value;
817
- }
818
- });
819
- var mapSQLQueryResult = (result, mapping) => {
820
- if (typeof result !== "object" || result === null) return result;
821
- const mappedResult = {
822
- ...result
724
+ return {
725
+ sqlTokenType,
726
+ [sqlTokenType]: true,
727
+ jsTypeName,
728
+ ...props
729
+ };
823
730
  };
824
- for (const column of Object.keys(mapping)) {
825
- if (column in mappedResult) {
826
- mappedResult[column] = mapping[column](mappedResult[column]);
827
- }
828
- }
829
- return mappedResult;
731
+ const check = (token) => SQLToken.check(token) && token.sqlTokenType === sqlTokenType;
732
+ return { from: factory, check, type: sqlTokenType };
830
733
  };
831
- var sqlExecutor = (sqlExecutor2, options) => ({
832
- query: (sql, queryOptions) => executeInNewDbClient(
833
- (client) => sqlExecutor2.query(client, sql, queryOptions),
834
- options
835
- ),
836
- batchQuery: (sqls, queryOptions) => executeInNewDbClient(
837
- (client) => sqlExecutor2.batchQuery(client, sqls, queryOptions),
838
- options
839
- ),
840
- command: (sql, commandOptions) => executeInNewDbClient(
841
- (client) => sqlExecutor2.command(client, sql, commandOptions),
842
- options
843
- ),
844
- batchCommand: (sqls, commandOptions) => executeInNewDbClient(
845
- (client) => sqlExecutor2.batchCommand(client, sqls, commandOptions),
846
- options
847
- )
848
- });
849
- var sqlExecutorInNewConnection = (options) => ({
850
- query: (sql, queryOptions) => executeInNewConnection(
851
- (connection) => connection.execute.query(sql, queryOptions),
852
- options
853
- ),
854
- batchQuery: (sqls, queryOptions) => executeInNewConnection(
855
- (connection) => connection.execute.batchQuery(sqls, queryOptions),
856
- options
857
- ),
858
- command: (sql, commandOptions) => executeInNewConnection(
859
- (connection) => connection.execute.command(sql, commandOptions),
860
- options
861
- ),
862
- batchCommand: (sqls, commandOptions) => executeInNewConnection(
863
- (connection) => connection.execute.batchCommand(sqls, commandOptions),
864
- options
865
- )
866
- });
867
- var sqlExecutorInAmbientConnection = (options) => ({
868
- query: (sql, queryOptions) => executeInAmbientConnection(
869
- (connection) => connection.execute.query(sql, queryOptions),
870
- options
871
- ),
872
- batchQuery: (sqls, queryOptions) => executeInAmbientConnection(
873
- (connection) => connection.execute.batchQuery(sqls, queryOptions),
874
- options
875
- ),
876
- command: (sql, commandOptions) => executeInAmbientConnection(
877
- (connection) => connection.execute.command(sql, commandOptions),
878
- options
879
- ),
880
- batchCommand: (sqls, commandOptions) => executeInAmbientConnection(
881
- (connection) => connection.execute.batchCommand(sqls, commandOptions),
882
- options
883
- )
884
- });
885
- var executeInNewDbClient = async (handle, options) => {
886
- const { connect, close } = options;
887
- const client = await connect();
888
- try {
889
- return await handle(client);
890
- } catch (error) {
891
- if (close) await close(client, error);
892
- throw error;
893
- }
734
+ var SerialToken = ColumnTypeToken(
735
+ "SQL_COLUMN_SERIAL",
736
+ "value_type:js:number"
737
+ );
738
+ var BigSerialToken = ColumnTypeToken(
739
+ "SQL_COLUMN_BIGSERIAL",
740
+ "value_type:js:bigint"
741
+ );
742
+ var IntegerToken = ColumnTypeToken(
743
+ "SQL_COLUMN_INTEGER",
744
+ "value_type:js:number"
745
+ );
746
+ var BigIntegerToken = ColumnTypeToken(
747
+ "SQL_COLUMN_BIGINT",
748
+ "value_type:js:bigint"
749
+ );
750
+ var JSONBToken = {
751
+ type: "SQL_COLUMN_JSONB",
752
+ from: () => {
753
+ return {
754
+ sqlTokenType: "SQL_COLUMN_JSONB",
755
+ ["SQL_COLUMN_JSONB"]: true
756
+ };
757
+ },
758
+ check: (token) => SQLToken.check(token) && token.sqlTokenType === "SQL_COLUMN_JSONB"
894
759
  };
895
- var executeInNewConnection = async (handle, options) => {
896
- const connection = await options.connection();
897
- try {
898
- return await handle(connection);
899
- } finally {
900
- await connection.close();
901
- }
760
+ var TimestampToken = ColumnTypeToken(
761
+ "SQL_COLUMN_TIMESTAMP",
762
+ "value_type:js:date"
763
+ );
764
+ var TimestamptzToken = ColumnTypeToken(
765
+ "SQL_COLUMN_TIMESTAMPTZ",
766
+ "value_type:js:date"
767
+ );
768
+ var VarcharToken = ColumnTypeToken(
769
+ "SQL_COLUMN_VARCHAR",
770
+ "value_type:js:string",
771
+ (length) => ({
772
+ length: length ?? "max",
773
+ jsTypeName: "value_type:js:string"
774
+ })
775
+ );
776
+ var AutoIncrementSQLColumnToken = ColumnTypeToken(
777
+ "SQL_COLUMN_AUTO_INCREMENT",
778
+ "value_type:js:bigint"
779
+ );
780
+ var SQLColumnTypeTokens = {
781
+ AutoIncrement: AutoIncrementSQLColumnToken,
782
+ BigInteger: BigIntegerToken,
783
+ BigSerial: BigSerialToken,
784
+ Integer: IntegerToken,
785
+ JSONB: JSONBToken,
786
+ Serial: SerialToken,
787
+ Timestamp: TimestampToken,
788
+ Timestamptz: TimestamptzToken,
789
+ Varchar: VarcharToken
902
790
  };
903
- var executeInAmbientConnection = async (handle, options) => {
904
- const connection = await options.connection();
905
- try {
906
- return await handle(connection);
907
- } finally {
908
- }
791
+ var SQLColumnTypeTokensFactory = {
792
+ AutoIncrement: AutoIncrementSQLColumnToken.from,
793
+ BigInteger: BigIntegerToken.from(),
794
+ BigSerial: BigSerialToken.from(),
795
+ Integer: IntegerToken.from(),
796
+ JSONB: JSONBToken.from,
797
+ Serial: SerialToken.from(),
798
+ Timestamp: TimestampToken.from(),
799
+ Timestamptz: TimestamptzToken.from(),
800
+ Varchar: VarcharToken.from
909
801
  };
802
+ var SQLColumnToken = SQLToken("SQL_COLUMN");
910
803
 
911
- // src/core/connections/transaction.ts
912
- var toTransactionResult = (transactionResult) => transactionResult !== void 0 && transactionResult !== null && typeof transactionResult === "object" && "success" in transactionResult ? transactionResult : { success: true, result: transactionResult };
913
- var executeInTransaction = async (transaction, handle) => {
914
- await transaction.begin();
915
- try {
916
- const { success, result } = toTransactionResult(await handle(transaction));
917
- if (success) await transaction.commit();
918
- else await transaction.rollback();
919
- return result;
920
- } catch (e) {
921
- await transaction.rollback();
922
- throw e;
923
- }
924
- };
925
- var transactionFactoryWithDbClient = (connect, initTransaction) => {
926
- let currentTransaction = void 0;
927
- const getOrInitCurrentTransaction = (options) => currentTransaction ?? (currentTransaction = initTransaction(connect(), {
928
- close: () => {
929
- currentTransaction = void 0;
930
- return Promise.resolve();
931
- },
932
- ...options ?? {}
933
- }));
934
- return {
935
- transaction: getOrInitCurrentTransaction,
936
- withTransaction: (handle, options) => executeInTransaction(getOrInitCurrentTransaction(options), handle)
937
- };
938
- };
939
- var wrapInConnectionClosure = async (connection, handle) => {
940
- try {
941
- return await handle();
942
- } finally {
943
- await connection.close();
804
+ // src/core/sql/processors/sqlProcessor.ts
805
+ var SQLProcessor = (options) => options;
806
+
807
+ // src/core/sql/processors/defaultProcessors.ts
808
+ var ExpandArrayProcessor = SQLProcessor({
809
+ canHandle: "SQL_ARRAY",
810
+ handle: (token, { builder, serializer, mapper }) => {
811
+ if (token.value.length === 0) {
812
+ throw new Error(
813
+ "Empty arrays are not supported. If you're using it with SELECT IN statement Use SQL.in(column, array) helper instead."
814
+ );
815
+ }
816
+ builder.addParams(mapper.mapValue(token.value, serializer));
944
817
  }
945
- };
946
- var transactionFactoryWithNewConnection = (connect) => ({
947
- transaction: (options) => {
948
- const connection = connect();
949
- const transaction = connection.transaction(options);
950
- return {
951
- ...transaction,
952
- commit: () => wrapInConnectionClosure(connection, () => transaction.commit()),
953
- rollback: () => wrapInConnectionClosure(connection, () => transaction.rollback())
954
- };
955
- },
956
- withTransaction: (handle, options) => {
957
- const connection = connect();
958
- return wrapInConnectionClosure(
959
- connection,
960
- () => connection.withTransaction(handle, options)
961
- );
818
+ });
819
+ var ExpandSQLInProcessor = SQLProcessor({
820
+ canHandle: "SQL_IN",
821
+ handle: (token, context) => {
822
+ const { builder, mapper, processorsRegistry, serializer } = context;
823
+ const { values: inValues, column } = token;
824
+ if (inValues.value.length === 0) {
825
+ builder.addParam(mapper.mapValue(false, serializer));
826
+ return;
827
+ }
828
+ builder.addSQL(mapper.mapValue(column.value, serializer));
829
+ builder.addSQL(` IN (`);
830
+ const arrayProcessor = processorsRegistry.get(SQLArray.type);
831
+ if (!arrayProcessor) {
832
+ throw new Error(
833
+ "No sql processor registered for an array. Cannot expand IN statement"
834
+ );
835
+ }
836
+ arrayProcessor.handle(inValues, {
837
+ builder,
838
+ mapper,
839
+ processorsRegistry,
840
+ serializer
841
+ });
842
+ builder.addSQL(`)`);
962
843
  }
963
844
  });
964
- var transactionFactoryWithAmbientConnection = (connect) => ({
965
- transaction: (options) => {
966
- const connection = connect();
967
- const transaction = connection.transaction(options);
968
- return {
969
- ...transaction,
970
- commit: () => transaction.commit(),
971
- rollback: () => transaction.rollback()
972
- };
973
- },
974
- withTransaction: (handle, options) => {
975
- const connection = connect();
976
- return connection.withTransaction(handle, options);
845
+ var FormatIdentifierProcessor = SQLProcessor({
846
+ canHandle: "SQL_IDENTIFIER",
847
+ handle: (token, { builder, mapper, serializer }) => {
848
+ builder.addSQL(mapper.mapValue(token, serializer));
977
849
  }
978
850
  });
851
+ var MapLiteralProcessor = SQLProcessor({
852
+ canHandle: "SQL_LITERAL",
853
+ handle: (token, { builder, mapper, serializer }) => builder.addParam(mapper.mapValue(token.value, serializer))
854
+ });
979
855
 
980
- // src/core/connections/connection.ts
981
- var createAmbientConnection = (options) => {
982
- const { driverType, client, executor, initTransaction } = options;
983
- const clientPromise = Promise.resolve(client);
984
- const closePromise = Promise.resolve();
985
- const open = () => clientPromise;
986
- const close = () => closePromise;
987
- const connection = {
988
- driverType,
989
- open,
990
- close,
991
- ...transactionFactoryWithDbClient(
992
- open,
993
- initTransaction(() => typedConnection)
994
- ),
995
- execute: sqlExecutor(executor(), { connect: open })
996
- };
997
- const typedConnection = connection;
998
- return typedConnection;
999
- };
1000
- var createSingletonConnection = (options) => {
1001
- const { driverType, connect, close, initTransaction, executor } = options;
1002
- let client = null;
1003
- let connectPromise = null;
1004
- const getClient = async () => {
1005
- if (client) return client;
1006
- if (!connectPromise) {
1007
- connectPromise = connect().then((c) => {
1008
- client = c;
1009
- return c;
1010
- });
856
+ // src/core/sql/processors/sqlProcessorRegistry.ts
857
+ var SQLProcessorsRegistry = (options) => {
858
+ const processors = options ? new Map(options.from.all()) : /* @__PURE__ */ new Map();
859
+ function register(...args) {
860
+ if (args.length === 1 && typeof args[0] === "object" && !Array.isArray(args[0])) {
861
+ Object.entries(args[0]).forEach(
862
+ ([_, processor]) => {
863
+ processors.set(processor.canHandle, processor);
864
+ }
865
+ );
866
+ } else {
867
+ args.forEach(
868
+ (p) => processors.set(p.canHandle, p)
869
+ );
1011
870
  }
1012
- return connectPromise;
871
+ return registry;
872
+ }
873
+ const registry = {
874
+ register,
875
+ get: (tokenType) => {
876
+ return processors.get(tokenType) ?? null;
877
+ },
878
+ all: () => processors
1013
879
  };
1014
- const connection = {
1015
- driverType,
1016
- open: getClient,
1017
- close: () => client ? close(client) : Promise.resolve(),
1018
- ...transactionFactoryWithDbClient(
1019
- getClient,
1020
- initTransaction(() => typedConnection)
1021
- ),
1022
- execute: sqlExecutor(executor(), { connect: getClient })
1023
- };
1024
- const typedConnection = connection;
1025
- return typedConnection;
1026
- };
1027
- var createTransientConnection = (options) => {
1028
- const { driverType, open, close, initTransaction, executor } = options;
1029
- const connection = {
1030
- driverType,
1031
- open,
1032
- close,
1033
- ...transactionFactoryWithDbClient(
1034
- open,
1035
- initTransaction(() => typedConnection)
1036
- ),
1037
- execute: sqlExecutor(executor(), { connect: open })
1038
- };
1039
- const typedConnection = connection;
1040
- return typedConnection;
1041
- };
1042
- var createConnection = (options) => {
1043
- const { driverType, connect, close, initTransaction, executor } = options;
1044
- let client = null;
1045
- let connectPromise = null;
1046
- const getClient = async () => {
1047
- if (client) return client;
1048
- if (!connectPromise) {
1049
- connectPromise = connect().then((c) => {
1050
- client = c;
1051
- return c;
1052
- });
1053
- }
1054
- return connectPromise;
1055
- };
1056
- const connection = {
1057
- driverType,
1058
- open: getClient,
1059
- close: () => client ? close(client) : Promise.resolve(),
1060
- ...transactionFactoryWithDbClient(
1061
- getClient,
1062
- initTransaction(() => typedConnection)
1063
- ),
1064
- execute: sqlExecutor(executor(), { connect: getClient })
1065
- };
1066
- const typedConnection = connection;
1067
- return typedConnection;
880
+ return registry;
1068
881
  };
1069
882
 
1070
- // src/core/connections/pool.ts
1071
- var createAmbientConnectionPool = (options) => {
1072
- const { driverType, connection } = options;
1073
- return createConnectionPool({
1074
- driverType,
1075
- getConnection: () => connection,
1076
- execute: connection.execute,
1077
- transaction: (options2) => connection.transaction(options2),
1078
- withTransaction: (handle, options2) => connection.withTransaction(handle, options2)
1079
- });
1080
- };
1081
- var createSingletonConnectionPool = (options) => {
1082
- const { driverType, getConnection } = options;
1083
- let connection = null;
1084
- const getExistingOrNewConnection = () => connection ?? (connection = getConnection());
1085
- const getExistingOrNewConnectionAsync = () => Promise.resolve(getExistingOrNewConnection());
1086
- const result = {
1087
- driverType,
1088
- connection: getExistingOrNewConnectionAsync,
1089
- execute: sqlExecutorInAmbientConnection({
1090
- driverType,
1091
- connection: getExistingOrNewConnectionAsync
1092
- }),
1093
- withConnection: (handle) => executeInAmbientConnection(handle, {
1094
- connection: getExistingOrNewConnectionAsync
1095
- }),
1096
- ...transactionFactoryWithAmbientConnection(getExistingOrNewConnection),
1097
- close: () => {
1098
- return connection !== null ? connection.close() : Promise.resolve();
883
+ // src/core/sql/processors/columnProcessors.ts
884
+ var mapDefaultSQLColumnProcessors = (mapColumnType) => ({
885
+ AutoIncrement: SQLProcessor({
886
+ canHandle: "SQL_COLUMN_AUTO_INCREMENT",
887
+ handle: (token, context) => {
888
+ mapColumnType(token, context);
1099
889
  }
1100
- };
1101
- return result;
1102
- };
1103
- var createSingletonClientPool = (options) => {
1104
- const { driverType, dbClient } = options;
1105
- return createSingletonConnectionPool({
1106
- getConnection: () => options.connectionFactory({ dbClient }),
1107
- driverType
1108
- });
1109
- };
1110
- var createAlwaysNewConnectionPool = (options) => {
1111
- const { driverType, getConnection, connectionOptions } = options;
1112
- return createConnectionPool({
1113
- driverType,
1114
- getConnection: () => connectionOptions ? getConnection(connectionOptions) : getConnection()
1115
- });
1116
- };
1117
- var createConnectionPool = (pool) => {
1118
- const { driverType, getConnection } = pool;
1119
- const connection = "connection" in pool ? pool.connection : () => Promise.resolve(getConnection());
1120
- const withConnection = "withConnection" in pool ? pool.withConnection : (handle) => executeInNewConnection(handle, {
1121
- connection
1122
- });
1123
- const close = "close" in pool ? pool.close : () => Promise.resolve();
1124
- const execute = "execute" in pool ? pool.execute : sqlExecutorInNewConnection({
1125
- driverType,
1126
- connection
1127
- });
1128
- const transaction = "transaction" in pool && "withTransaction" in pool ? {
1129
- transaction: pool.transaction,
1130
- withTransaction: pool.withTransaction
1131
- } : transactionFactoryWithNewConnection(getConnection);
1132
- const result = {
1133
- driverType,
1134
- connection,
1135
- withConnection,
1136
- close,
1137
- execute,
1138
- ...transaction
1139
- };
1140
- return result;
1141
- };
1142
-
1143
- // src/core/schema/sqlMigration.ts
1144
- var sqlMigration = (name, sqls) => ({
1145
- name,
1146
- sqls
890
+ }),
891
+ BigInteger: SQLProcessor({
892
+ canHandle: "SQL_COLUMN_BIGINT",
893
+ handle: (token, context) => mapColumnType(token, context)
894
+ }),
895
+ BigSerial: SQLProcessor({
896
+ canHandle: "SQL_COLUMN_BIGSERIAL",
897
+ handle: (token, context) => mapColumnType(token, context)
898
+ }),
899
+ Serial: SQLProcessor({
900
+ canHandle: "SQL_COLUMN_SERIAL",
901
+ handle: (token, context) => mapColumnType(token, context)
902
+ }),
903
+ Integer: SQLProcessor({
904
+ canHandle: "SQL_COLUMN_INTEGER",
905
+ handle: (token, context) => mapColumnType(token, context)
906
+ }),
907
+ JSONB: SQLProcessor({
908
+ canHandle: "SQL_COLUMN_JSONB",
909
+ handle: (token, context) => mapColumnType(token, context)
910
+ }),
911
+ Timestamp: SQLProcessor({
912
+ canHandle: "SQL_COLUMN_TIMESTAMP",
913
+ handle: (token, context) => mapColumnType(token, context)
914
+ }),
915
+ Timestamptz: SQLProcessor({
916
+ canHandle: "SQL_COLUMN_TIMESTAMPTZ",
917
+ handle: (token, context) => mapColumnType(token, context)
918
+ }),
919
+ Varchar: SQLProcessor({
920
+ canHandle: "SQL_COLUMN_VARCHAR",
921
+ handle: (token, context) => mapColumnType(token, context)
922
+ })
1147
923
  });
1148
924
 
1149
- // src/core/schema/schemaComponent.ts
1150
- var schemaComponent = (key, options) => {
1151
- const componentsMap = new Map(
1152
- options.components?.map((comp) => [comp.schemaComponentKey, comp])
1153
- );
1154
- const migrations = [...options.migrations ?? []];
925
+ // src/core/sql/processors/index.ts
926
+ var defaultProcessorsRegistry = globalThis.defaultProcessorsRegistry = globalThis.defaultProcessorsRegistry ?? SQLProcessorsRegistry().register(
927
+ FormatIdentifierProcessor,
928
+ MapLiteralProcessor,
929
+ ExpandArrayProcessor,
930
+ ExpandSQLInProcessor
931
+ );
932
+
933
+ // src/core/sql/tokenizedSQL/tokenizedSQL.ts
934
+ var TokenizedSQLBuilder = () => {
935
+ const sqlChunks = [];
936
+ const sqlTokens = [];
1155
937
  return {
1156
- schemaComponentKey: key,
1157
- components: componentsMap,
1158
- get migrations() {
1159
- return [
1160
- ...migrations,
1161
- ...Array.from(componentsMap.values()).flatMap((c) => c.migrations)
1162
- ];
938
+ addSQL(str) {
939
+ sqlChunks.push(str);
1163
940
  },
1164
- addComponent: (component) => {
1165
- componentsMap.set(component.schemaComponentKey, component);
1166
- migrations.push(...component.migrations);
1167
- return component;
941
+ addSQLs(str) {
942
+ sqlChunks.push(...str);
1168
943
  },
1169
- addMigration: (migration) => {
1170
- migrations.push(migration);
944
+ addToken(value) {
945
+ sqlTokens.push(value);
946
+ },
947
+ addTokens(vals) {
948
+ sqlTokens.push(...vals);
949
+ },
950
+ build() {
951
+ return sqlChunks.length > 0 ? {
952
+ __brand: "tokenized-sql",
953
+ sqlChunks,
954
+ sqlTokens
955
+ } : TokenizedSQL.empty;
1171
956
  }
1172
957
  };
1173
958
  };
1174
- var isSchemaComponentOfType = (component, prefix) => component.schemaComponentKey.startsWith(prefix);
1175
- var filterSchemaComponentsOfType = (components, prefix) => mapSchemaComponentsOfType(components, prefix);
1176
- var mapSchemaComponentsOfType = (components, prefix, keyMapper) => new Map(
1177
- Array.from(components.entries()).filter(([urn]) => urn.startsWith(prefix)).map(([urn, component]) => [
1178
- keyMapper ? keyMapper(component) : urn,
1179
- component
1180
- ])
1181
- );
1182
- var findSchemaComponentsOfType = (root, prefix) => {
1183
- const results = [];
1184
- const traverse = (component) => {
1185
- if (component.schemaComponentKey.startsWith(prefix)) {
1186
- results.push(component);
1187
- }
1188
- for (const child of component.components.values()) {
1189
- traverse(child);
959
+ var TokenizedSQL = (strings, values) => {
960
+ const builder = TokenizedSQLBuilder();
961
+ for (let i = 0; i < strings.length; i++) {
962
+ if (strings[i] !== "") builder.addSQL(strings[i]);
963
+ if (i >= values.length) break;
964
+ const value = values[i];
965
+ if (isTokenizedSQL(value)) {
966
+ builder.addSQLs(value.sqlChunks);
967
+ builder.addTokens(value.sqlTokens);
968
+ } else if (SQLPlain.check(value)) {
969
+ builder.addSQL(value.value);
970
+ } else {
971
+ builder.addSQL(TokenizedSQL.paramPlaceholder);
972
+ builder.addToken(
973
+ SQLToken.check(value) ? value : Array.isArray(value) ? SQLArray.from(value) : SQLLiteral.from(value)
974
+ );
1190
975
  }
1191
- };
1192
- traverse(root);
1193
- return results;
976
+ }
977
+ return builder.build();
978
+ };
979
+ var isTokenizedSQL = (value) => {
980
+ return value !== null && typeof value === "object" && "__brand" in value && value.__brand === "tokenized-sql";
981
+ };
982
+ TokenizedSQL.paramPlaceholder = `__P__`;
983
+ TokenizedSQL.empty = {
984
+ __brand: "tokenized-sql",
985
+ sqlChunks: [""],
986
+ sqlTokens: []
1194
987
  };
1195
988
 
1196
- // src/core/schema/components/columnSchemaComponent.ts
1197
- var ColumnURNType = "sc:dumbo:column";
1198
- var ColumnURN = ({
1199
- name
1200
- }) => `${ColumnURNType}:${name}`;
1201
- var columnSchemaComponent = (params) => {
1202
- const {
1203
- columnName,
1204
- type,
1205
- notNull,
1206
- unique,
1207
- primaryKey,
1208
- default: defaultValue,
1209
- ...schemaOptions
1210
- } = params;
1211
- const sc = schemaComponent(ColumnURN({ name: columnName }), schemaOptions);
1212
- const result = {
1213
- ...sc,
1214
- columnName,
1215
- notNull,
1216
- unique,
1217
- primaryKey,
1218
- defaultValue,
1219
- sqlTokenType: "SQL_COLUMN",
1220
- name: columnName,
1221
- type
989
+ // src/core/sql/valueMappers/reservedSqlWords.ts
990
+ var ansiSqlReservedMap = {
991
+ ALL: true,
992
+ AND: true,
993
+ ANY: true,
994
+ ARRAY: true,
995
+ AS: true,
996
+ ASC: true,
997
+ AUTHORIZATION: true,
998
+ BETWEEN: true,
999
+ BINARY: true,
1000
+ BOTH: true,
1001
+ CASE: true,
1002
+ CAST: true,
1003
+ CHECK: true,
1004
+ COLLATE: true,
1005
+ COLUMN: true,
1006
+ CONSTRAINT: true,
1007
+ CREATE: true,
1008
+ CROSS: true,
1009
+ CURRENT_DATE: true,
1010
+ CURRENT_TIME: true,
1011
+ CURRENT_TIMESTAMP: true,
1012
+ CURRENT_USER: true,
1013
+ DEFAULT: true,
1014
+ DEFERRABLE: true,
1015
+ DESC: true,
1016
+ DISTINCT: true,
1017
+ DO: true,
1018
+ ELSE: true,
1019
+ END: true,
1020
+ EXCEPT: true,
1021
+ FALSE: true,
1022
+ FOR: true,
1023
+ FOREIGN: true,
1024
+ FROM: true,
1025
+ FULL: true,
1026
+ GRANT: true,
1027
+ GROUP: true,
1028
+ HAVING: true,
1029
+ IN: true,
1030
+ INITIALLY: true,
1031
+ INNER: true,
1032
+ INTERSECT: true,
1033
+ INTO: true,
1034
+ IS: true,
1035
+ JOIN: true,
1036
+ LEADING: true,
1037
+ LEFT: true,
1038
+ LIKE: true,
1039
+ LOCALTIME: true,
1040
+ LOCALTIMESTAMP: true,
1041
+ NATURAL: true,
1042
+ NEW: true,
1043
+ NOT: true,
1044
+ NULL: true,
1045
+ NULLS: true,
1046
+ OLD: true,
1047
+ ON: true,
1048
+ ONLY: true,
1049
+ OPEN: true,
1050
+ OR: true,
1051
+ ORDER: true,
1052
+ OUTER: true,
1053
+ OVERLAPS: true,
1054
+ PARTITION: true,
1055
+ PLACING: true,
1056
+ PRIMARY: true,
1057
+ REFERENCES: true,
1058
+ RIGHT: true,
1059
+ SELECT: true,
1060
+ SESSION_USER: true,
1061
+ SIMILAR: true,
1062
+ SOME: true,
1063
+ TABLE: true,
1064
+ THEN: true,
1065
+ TO: true,
1066
+ TRAILING: true,
1067
+ TRUE: true,
1068
+ UNION: true,
1069
+ UNIQUE: true,
1070
+ USER: true,
1071
+ USING: true,
1072
+ WHEN: true,
1073
+ WHERE: true,
1074
+ WITH: true,
1075
+ WITHOUT: true,
1076
+ ADD: true,
1077
+ ALTER: true,
1078
+ ARE: true,
1079
+ AT: true,
1080
+ BEGIN: true,
1081
+ BY: true,
1082
+ CASCADE: true,
1083
+ CLOSE: true,
1084
+ COMMIT: true,
1085
+ CONNECT: true,
1086
+ CONTINUE: true,
1087
+ CORRESPONDING: true,
1088
+ CURSOR: true,
1089
+ DEALLOCATE: true,
1090
+ DECLARE: true,
1091
+ DELETE: true,
1092
+ DESCRIBE: true,
1093
+ DISCONNECT: true,
1094
+ DROP: true,
1095
+ ESCAPE: true,
1096
+ EXECUTE: true,
1097
+ EXISTS: true,
1098
+ FETCH: true,
1099
+ FIRST: true,
1100
+ FLOAT: true,
1101
+ GET: true,
1102
+ GLOBAL: true,
1103
+ GO: true,
1104
+ GOTO: true,
1105
+ HOUR: true,
1106
+ IMMEDIATE: true,
1107
+ INDICATOR: true,
1108
+ INPUT: true,
1109
+ INSERT: true,
1110
+ INT: true,
1111
+ INTEGER: true,
1112
+ INTERVAL: true,
1113
+ LANGUAGE: true,
1114
+ LAST: true,
1115
+ LOCAL: true,
1116
+ MATCH: true,
1117
+ MINUTE: true,
1118
+ MODULE: true,
1119
+ MONTH: true,
1120
+ NATIONAL: true,
1121
+ NEXT: true,
1122
+ NO: true,
1123
+ OF: true,
1124
+ OUTPUT: true,
1125
+ PARTIAL: true,
1126
+ PREPARE: true,
1127
+ PRESERVE: true,
1128
+ PRIOR: true,
1129
+ PRIVILEGES: true,
1130
+ PROCEDURE: true,
1131
+ PUBLIC: true,
1132
+ READ: true,
1133
+ REAL: true,
1134
+ RESTRICT: true,
1135
+ REVOKE: true,
1136
+ ROLLBACK: true,
1137
+ ROWS: true,
1138
+ SCHEMA: true,
1139
+ SCROLL: true,
1140
+ SECOND: true,
1141
+ SECTION: true,
1142
+ SET: true,
1143
+ SIZE: true,
1144
+ SMALLINT: true,
1145
+ SQL: true,
1146
+ SQLCODE: true,
1147
+ SQLERROR: true,
1148
+ SQLSTATE: true,
1149
+ TEMPORARY: true,
1150
+ TIMEZONE_HOUR: true,
1151
+ TIMEZONE_MINUTE: true,
1152
+ TRANSACTION: true,
1153
+ TRANSLATE: true,
1154
+ TRANSLATION: true,
1155
+ UNKNOWN: true,
1156
+ UPDATE: true,
1157
+ VALUE: true,
1158
+ VALUES: true,
1159
+ VARCHAR: true,
1160
+ VARYING: true,
1161
+ VIEW: true,
1162
+ WHENEVER: true,
1163
+ WORK: true,
1164
+ WRITE: true,
1165
+ YEAR: true,
1166
+ ZONE: true
1167
+ };
1168
+
1169
+ // src/core/sql/valueMappers/sqlValueMapper.ts
1170
+ var ANSISQLParamPlaceholder = "?";
1171
+ var ANSISQLIdentifierQuote = '"';
1172
+ var mapANSISQLParamPlaceholder = () => ANSISQLParamPlaceholder;
1173
+ var isReserved = (value, reserved) => !!reserved[value.toUpperCase()];
1174
+ var mapSQLIdentifier = (value, options) => {
1175
+ if (value === void 0 || value === null) {
1176
+ throw new Error("SQL identifier cannot be null or undefined");
1177
+ }
1178
+ const ident = value.toString().slice(0);
1179
+ const quoteSign = options?.quote ?? ANSISQLIdentifierQuote;
1180
+ if (/^[a-z_][a-z0-9_$]*$/.test(ident) && !isReserved(ident, options?.reservedWords ?? ansiSqlReservedMap)) {
1181
+ return ident;
1182
+ }
1183
+ let quoted = quoteSign;
1184
+ for (let i = 0; i < ident.length; i++) {
1185
+ const c = ident[i];
1186
+ quoted += c === quoteSign ? c + c : c;
1187
+ }
1188
+ quoted += quoteSign;
1189
+ return quoted;
1190
+ };
1191
+ var DefaultMapSQLParamValueOptions = {
1192
+ mapPlaceholder: mapANSISQLParamPlaceholder,
1193
+ mapIdentifier: mapSQLIdentifier
1194
+ };
1195
+ var SQLValueMapper = (options) => {
1196
+ const mapSQLParamValueOptions = {
1197
+ ...DefaultMapSQLParamValueOptions,
1198
+ ...options ?? {}
1222
1199
  };
1223
- return result;
1200
+ const resultMapper = {
1201
+ mapValue: (value, serializer, mapOptions) => mapSQLParamValue(value, serializer, {
1202
+ ...mapSQLParamValueOptions,
1203
+ ...mapOptions
1204
+ }),
1205
+ mapPlaceholder: mapSQLParamValueOptions.mapPlaceholder,
1206
+ mapIdentifier: mapSQLParamValueOptions.mapIdentifier
1207
+ };
1208
+ return resultMapper;
1224
1209
  };
1210
+ function mapSQLParamValue(value, serializer, options) {
1211
+ if (value === null || value === void 0) {
1212
+ return null;
1213
+ } else if (typeof value === "number") {
1214
+ return value;
1215
+ } else if (typeof value === "string") {
1216
+ return value;
1217
+ } else if (Array.isArray(value)) {
1218
+ const mapValue = options?.mapValue ?? mapSQLParamValue;
1219
+ return options?.mapArray ? options.mapArray(value, mapValue) : value.map((item) => mapValue(item, serializer, options));
1220
+ } else if (typeof value === "boolean") {
1221
+ return options?.mapBoolean ? options.mapBoolean(value) : value;
1222
+ } else if (typeof value === "bigint") {
1223
+ return options?.mapBigInt ? options.mapBigInt(value) : value.toString();
1224
+ } else if (value instanceof Date) {
1225
+ return options?.mapDate ? options.mapDate(value) : value.toISOString();
1226
+ } else if (SQL.check.isIdentifier(value)) {
1227
+ return (options?.mapIdentifier ?? mapSQLIdentifier)(value.value);
1228
+ } else if (typeof value === "object") {
1229
+ return options?.mapObject ? options.mapObject(value) : `${serializer.serialize(value).replace(/'/g, "''")}`;
1230
+ } else {
1231
+ return serializer.serialize(value);
1232
+ }
1233
+ }
1225
1234
 
1226
- // src/core/schema/components/indexSchemaComponent.ts
1227
- var IndexURNType = "sc:dumbo:index";
1228
- var IndexURN = ({ name }) => `${IndexURNType}:${name}`;
1229
- var indexSchemaComponent = ({
1230
- indexName,
1231
- columnNames,
1232
- isUnique,
1233
- ...migrationsOrComponents
1235
+ // src/core/sql/formatters/sqlFormatter.ts
1236
+ var SQLFormatter = ({
1237
+ format,
1238
+ describe,
1239
+ valueMapper: valueMapperOptions,
1240
+ processorsRegistry
1234
1241
  }) => {
1235
- const sc = schemaComponent(IndexURN({ name: indexName }), {
1236
- migrations: migrationsOrComponents.migrations ?? [],
1237
- components: [...migrationsOrComponents.components ?? []]
1242
+ const valueMapper = SQLValueMapper(valueMapperOptions);
1243
+ const options = {
1244
+ builder: ParametrizedSQLBuilder({
1245
+ mapParamPlaceholder: valueMapper.mapPlaceholder
1246
+ }),
1247
+ mapper: valueMapper,
1248
+ processorsRegistry: processorsRegistry ?? defaultProcessorsRegistry
1249
+ };
1250
+ const resultFormatter = {
1251
+ format: format ?? ((sql, methodOptions) => formatSQL(
1252
+ sql,
1253
+ resultFormatter,
1254
+ methodOptions?.serializer ?? JSONSerializer,
1255
+ {
1256
+ ...options,
1257
+ ...methodOptions ?? {}
1258
+ }
1259
+ )),
1260
+ describe: describe ?? ((sql, methodOptions) => describeSQL(
1261
+ sql,
1262
+ resultFormatter,
1263
+ methodOptions?.serializer ?? JSONSerializer,
1264
+ {
1265
+ ...options,
1266
+ ...methodOptions ?? {}
1267
+ }
1268
+ )),
1269
+ valueMapper
1270
+ };
1271
+ return resultFormatter;
1272
+ };
1273
+ var dumboSQLFormatters = globalThis.dumboSQLFormatters = globalThis.dumboSQLFormatters ?? {};
1274
+ var registerFormatter = (dialect, formatter) => {
1275
+ dumboSQLFormatters[dialect] = formatter;
1276
+ };
1277
+ var getFormatter = (dialect) => {
1278
+ const formatterKey = dialect;
1279
+ if (!dumboSQLFormatters[formatterKey]) {
1280
+ throw new Error(`No SQL formatter registered for dialect: ${dialect}`);
1281
+ }
1282
+ return dumboSQLFormatters[formatterKey];
1283
+ };
1284
+ function formatSQL(sql, formatter, serializer, context) {
1285
+ const mapper = context?.mapper == void 0 ? formatter.valueMapper : {
1286
+ ...formatter.valueMapper,
1287
+ ...context.mapper
1288
+ };
1289
+ const processorsRegistry = context?.processorsRegistry ?? defaultProcessorsRegistry;
1290
+ const merged = Array.isArray(sql) ? SQL.merge(sql, "\n") : sql;
1291
+ if (!isTokenizedSQL(merged)) {
1292
+ throw new Error("Expected TokenizedSQL, got string-based SQL");
1293
+ }
1294
+ const builder = ParametrizedSQLBuilder({
1295
+ mapParamPlaceholder: mapper.mapPlaceholder
1238
1296
  });
1297
+ let paramIndex = 0;
1298
+ for (let i = 0; i < merged.sqlChunks.length; i++) {
1299
+ const sqlChunk = merged.sqlChunks[i];
1300
+ if (sqlChunk !== TokenizedSQL.paramPlaceholder) {
1301
+ builder.addSQL(sqlChunk);
1302
+ continue;
1303
+ }
1304
+ const token = merged.sqlTokens[paramIndex++];
1305
+ const processor = processorsRegistry.get(token.sqlTokenType);
1306
+ if (!processor) {
1307
+ throw new Error(
1308
+ `No SQL processor registered for token type: ${token.sqlTokenType}`
1309
+ );
1310
+ }
1311
+ processor.handle(token, {
1312
+ builder,
1313
+ processorsRegistry,
1314
+ serializer,
1315
+ mapper
1316
+ });
1317
+ }
1318
+ return builder.build();
1319
+ }
1320
+ var describeSQL = (sql, formatter, serializer, options) => formatSQL(sql, formatter, serializer, {
1321
+ ...options ?? {},
1322
+ mapper: {
1323
+ mapPlaceholder: (_, value) => serializer.serialize(value)
1324
+ }
1325
+ }).query;
1326
+
1327
+ // src/core/sql/sql.ts
1328
+ function SQL(strings, ...values) {
1329
+ const parametrized = TokenizedSQL(strings, values);
1330
+ return parametrized;
1331
+ }
1332
+ function RawSQL(strings, ...values) {
1333
+ let result = "";
1334
+ for (let i = 0; i < strings.length; i++) {
1335
+ result += strings[i];
1336
+ if (i < values.length) {
1337
+ result += String(values[i]);
1338
+ }
1339
+ }
1239
1340
  return {
1240
- ...sc,
1241
- indexName,
1242
- get columnNames() {
1243
- return columnNames;
1244
- },
1245
- addColumn: (column) => columnNames.push(typeof column === "string" ? column : column.columnName),
1246
- isUnique
1341
+ __brand: "tokenized-sql",
1342
+ sqlChunks: [result],
1343
+ sqlTokens: []
1247
1344
  };
1345
+ }
1346
+ var isSQL = (value) => {
1347
+ if (value === void 0 || value === null) {
1348
+ return false;
1349
+ }
1350
+ return isTokenizedSQL(value);
1351
+ };
1352
+ var emptySQL = {
1353
+ __brand: "tokenized-sql",
1354
+ sqlChunks: [""],
1355
+ sqlTokens: []
1356
+ };
1357
+ var mergeSQL = (sqls, separator = " ") => {
1358
+ const parametrized = sqls.filter((sql) => !isEmpty(sql)).map((sql) => sql);
1359
+ const params = parametrized.flatMap((p) => p.sqlTokens);
1360
+ const sqlChunks = parametrized.flatMap(
1361
+ (p, i) => i == parametrized.length - 1 || separator === "" ? p.sqlChunks : [...p.sqlChunks, separator]
1362
+ );
1363
+ const merged = sqlChunks.length > 0 ? {
1364
+ __brand: "tokenized-sql",
1365
+ sqlChunks,
1366
+ sqlTokens: params
1367
+ } : TokenizedSQL.empty;
1368
+ return merged;
1369
+ };
1370
+ var concatSQL = (...sqls) => mergeSQL(sqls, "");
1371
+ var isEmpty = (sql) => {
1372
+ if (isTokenizedSQL(sql)) {
1373
+ const parametrized = sql;
1374
+ return parametrized.sqlChunks.every((chunk) => chunk.trim() === "") && parametrized.sqlTokens.length === 0;
1375
+ }
1376
+ return false;
1377
+ };
1378
+ SQL.EMPTY = emptySQL;
1379
+ SQL.concat = concatSQL;
1380
+ SQL.merge = mergeSQL;
1381
+ SQL.format = (sql, formatter, options) => formatSQL(sql, formatter, options?.serializer ?? JSONSerializer, options);
1382
+ SQL.describe = (sql, formatter, options) => describeSQL(sql, formatter, options?.serializer ?? JSONSerializer, options);
1383
+ SQL.in = (column, values, options) => options?.mode ? SQLIn.from({ column, values, mode: options.mode }) : SQLIn.from({ column, values });
1384
+ SQL.array = (values, options) => SQLArray.from(options?.mode ? { value: values, mode: options.mode } : values);
1385
+ SQL.identifier = SQLIdentifier.from;
1386
+ SQL.plain = SQLPlain.from;
1387
+ SQL.check = {
1388
+ isSQL,
1389
+ isTokenizedSQL: (value) => isTokenizedSQL(value),
1390
+ isEmpty,
1391
+ isIdentifier: SQLIdentifier.check,
1392
+ isPlain: SQLPlain.check,
1393
+ isSQLIn: SQLIn.check
1248
1394
  };
1395
+ var columnFactory = SQLColumnToken.from;
1396
+ columnFactory.type = SQLColumnTypeTokensFactory;
1397
+ SQL.column = columnFactory;
1249
1398
 
1250
- // src/core/schema/components/tableSchemaComponent.ts
1251
- var TableURNType = "sc:dumbo:table";
1252
- var TableURN = ({ name }) => `${TableURNType}:${name}`;
1253
- var tableSchemaComponent = ({
1254
- tableName,
1255
- columns,
1256
- primaryKey,
1257
- relationships,
1258
- ...migrationsOrComponents
1259
- }) => {
1260
- columns ??= {};
1261
- relationships ??= {};
1262
- const base = schemaComponent(TableURN({ name: tableName }), {
1263
- migrations: migrationsOrComponents.migrations ?? [],
1264
- components: [
1265
- ...migrationsOrComponents.components ?? [],
1266
- ...Object.values(columns)
1267
- ]
1268
- });
1269
- return {
1270
- ...base,
1271
- tableName,
1272
- primaryKey: primaryKey ?? [],
1273
- relationships,
1274
- get columns() {
1275
- const columnsMap = mapSchemaComponentsOfType(
1276
- base.components,
1277
- ColumnURNType,
1278
- (c) => c.columnName
1279
- );
1280
- return Object.assign(columnsMap, columns);
1281
- },
1282
- get indexes() {
1283
- return mapSchemaComponentsOfType(
1284
- base.components,
1285
- IndexURNType,
1286
- (c) => c.indexName
1287
- );
1288
- },
1289
- addColumn: (column) => base.addComponent(column),
1290
- addIndex: (index) => base.addComponent(index)
1399
+ // src/core/tracing/printing/color.ts
1400
+ import ansis from "ansis";
1401
+ var enableColors = true;
1402
+ var color = {
1403
+ set level(value) {
1404
+ enableColors = value === 1;
1405
+ },
1406
+ hex: (value) => (text) => enableColors ? ansis.hex(value)(text) : text,
1407
+ red: (value) => enableColors ? ansis.red(value) : value,
1408
+ green: (value) => enableColors ? ansis.green(value) : value,
1409
+ blue: (value) => enableColors ? ansis.blue(value) : value,
1410
+ cyan: (value) => enableColors ? ansis.cyan(value) : value,
1411
+ yellow: (value) => enableColors ? ansis.yellow(value) : value
1412
+ };
1413
+ var color_default = color;
1414
+
1415
+ // src/core/tracing/printing/pretty.ts
1416
+ var TWO_SPACES = " ";
1417
+ var COLOR_STRING = color_default.hex("#98c379");
1418
+ var COLOR_KEY = color_default.hex("#61afef");
1419
+ var COLOR_NUMBER_OR_DATE = color_default.hex("#d19a66");
1420
+ var COLOR_BOOLEAN = color_default.hex("#c678dd");
1421
+ var COLOR_NULL_OR_UNDEFINED = color_default.hex("#c678dd");
1422
+ var COLOR_BRACKETS = color_default.hex("#abb2bf");
1423
+ var processString = (str, indent, handleMultiline) => {
1424
+ if (handleMultiline && str.includes("\n")) {
1425
+ const lines = str.split("\n");
1426
+ const indentedLines = lines.map(
1427
+ (line) => indent + TWO_SPACES + COLOR_STRING(line)
1428
+ );
1429
+ return COLOR_STRING('"') + "\n" + indentedLines.join("\n") + "\n" + indent + COLOR_STRING('"');
1430
+ }
1431
+ return COLOR_STRING(`"${str}"`);
1432
+ };
1433
+ var shouldPrint = (obj) => typeof obj !== "function" && typeof obj !== "symbol";
1434
+ var formatJson = (obj, indentLevel = 0, handleMultiline = false) => {
1435
+ const indent = TWO_SPACES.repeat(indentLevel);
1436
+ if (obj === null) return COLOR_NULL_OR_UNDEFINED("null");
1437
+ if (obj === void 0) return COLOR_NULL_OR_UNDEFINED("undefined");
1438
+ if (typeof obj === "string")
1439
+ return processString(obj, indent, handleMultiline);
1440
+ if (typeof obj === "number" || typeof obj === "bigint" || obj instanceof Date)
1441
+ return COLOR_NUMBER_OR_DATE(String(obj));
1442
+ if (typeof obj === "boolean") return COLOR_BOOLEAN(String(obj));
1443
+ if (obj instanceof Error) {
1444
+ const errorObj = {};
1445
+ const propNames = Object.getOwnPropertyNames(obj);
1446
+ propNames.forEach((key) => {
1447
+ errorObj[key] = obj[key];
1448
+ });
1449
+ return formatJson(errorObj, indentLevel, handleMultiline);
1450
+ }
1451
+ if (obj instanceof Promise) {
1452
+ return COLOR_STRING("Promise {pending}");
1453
+ }
1454
+ if (Array.isArray(obj)) {
1455
+ const arrayItems = obj.map(
1456
+ (item) => formatJson(item, indentLevel + 1, handleMultiline)
1457
+ );
1458
+ return `${COLOR_BRACKETS("[")}
1459
+ ${indent} ${arrayItems.join(
1460
+ `,
1461
+ ${indent} `
1462
+ )}
1463
+ ${indent}${COLOR_BRACKETS("]")}`;
1464
+ }
1465
+ const entries = Object.entries(obj).filter(([_, value]) => shouldPrint(value)).map(
1466
+ ([key, value]) => `${COLOR_KEY(`"${key}"`)}: ${formatJson(
1467
+ value,
1468
+ indentLevel + 1,
1469
+ handleMultiline
1470
+ )}`
1471
+ );
1472
+ return `${COLOR_BRACKETS("{")}
1473
+ ${indent} ${entries.join(
1474
+ `,
1475
+ ${indent} `
1476
+ )}
1477
+ ${indent}${COLOR_BRACKETS("}")}`;
1478
+ };
1479
+ var prettyJson = (obj, options) => formatJson(obj, 0, options?.handleMultiline);
1480
+
1481
+ // src/core/tracing/index.ts
1482
+ var tracer = () => {
1483
+ };
1484
+ var LogLevel = {
1485
+ DISABLED: "DISABLED",
1486
+ INFO: "INFO",
1487
+ LOG: "LOG",
1488
+ WARN: "WARN",
1489
+ ERROR: "ERROR"
1490
+ };
1491
+ var LogStyle = {
1492
+ RAW: "RAW",
1493
+ PRETTY: "PRETTY"
1494
+ };
1495
+ var getEnvVariable = (name) => {
1496
+ try {
1497
+ if (typeof process !== "undefined" && process.env) {
1498
+ return process.env[name];
1499
+ }
1500
+ return void 0;
1501
+ } catch {
1502
+ return void 0;
1503
+ }
1504
+ };
1505
+ var shouldLog = (logLevel) => {
1506
+ const definedLogLevel = getEnvVariable("DUMBO_LOG_LEVEL") ?? LogLevel.ERROR;
1507
+ if (definedLogLevel === LogLevel.ERROR && logLevel === LogLevel.ERROR)
1508
+ return true;
1509
+ if (definedLogLevel === LogLevel.WARN && [LogLevel.ERROR, LogLevel.WARN].includes(logLevel))
1510
+ return true;
1511
+ if (definedLogLevel === LogLevel.LOG && [LogLevel.ERROR, LogLevel.WARN, LogLevel.LOG].includes(logLevel))
1512
+ return true;
1513
+ if (definedLogLevel === LogLevel.INFO && [LogLevel.ERROR, LogLevel.WARN, LogLevel.LOG, LogLevel.INFO].includes(
1514
+ logLevel
1515
+ ))
1516
+ return true;
1517
+ return false;
1518
+ };
1519
+ var nulloTraceEventRecorder = () => {
1520
+ };
1521
+ var getTraceEventFormatter = (logStyle, serializer = JSONSerializer) => (event) => {
1522
+ switch (logStyle) {
1523
+ case "RAW":
1524
+ return serializer.serialize(event);
1525
+ case "PRETTY":
1526
+ return prettyJson(event, { handleMultiline: true });
1527
+ }
1528
+ };
1529
+ var getTraceEventRecorder = (logLevel, logStyle) => {
1530
+ const format = getTraceEventFormatter(logStyle);
1531
+ switch (logLevel) {
1532
+ case "DISABLED":
1533
+ return nulloTraceEventRecorder;
1534
+ case "INFO":
1535
+ return (event) => console.info(format(event));
1536
+ case "LOG":
1537
+ return (event) => console.log(format(event));
1538
+ case "WARN":
1539
+ return (event) => console.warn(format(event));
1540
+ case "ERROR":
1541
+ return (event) => console.error(format(event));
1542
+ }
1543
+ };
1544
+ var recordTraceEvent = (logLevel, eventName, attributes) => {
1545
+ if (!shouldLog(LogLevel.LOG)) return;
1546
+ const event = {
1547
+ name: eventName,
1548
+ timestamp: (/* @__PURE__ */ new Date()).getTime(),
1549
+ ...attributes
1291
1550
  };
1551
+ const record = getTraceEventRecorder(
1552
+ logLevel,
1553
+ getEnvVariable("DUMBO_LOG_STYLE") ?? "RAW"
1554
+ );
1555
+ record(event);
1292
1556
  };
1557
+ tracer.info = (eventName, attributes) => recordTraceEvent(LogLevel.INFO, eventName, attributes);
1558
+ tracer.warn = (eventName, attributes) => recordTraceEvent(LogLevel.WARN, eventName, attributes);
1559
+ tracer.log = (eventName, attributes) => recordTraceEvent(LogLevel.LOG, eventName, attributes);
1560
+ tracer.error = (eventName, attributes) => recordTraceEvent(LogLevel.ERROR, eventName, attributes);
1293
1561
 
1294
- // src/core/schema/components/databaseSchemaSchemaComponent.ts
1295
- var DatabaseSchemaURNType = "sc:dumbo:database_schema";
1296
- var DatabaseSchemaURN = ({
1297
- name
1298
- }) => `${DatabaseSchemaURNType}:${name}`;
1299
- var databaseSchemaSchemaComponent = ({
1300
- schemaName,
1301
- tables,
1302
- ...migrationsOrComponents
1303
- }) => {
1304
- const base = schemaComponent(DatabaseSchemaURN({ name: schemaName }), {
1305
- migrations: migrationsOrComponents.migrations ?? [],
1306
- components: [
1307
- ...migrationsOrComponents.components ?? [],
1308
- ...Object.values(tables ?? {})
1309
- ]
1310
- });
1311
- return {
1312
- ...base,
1313
- schemaName,
1314
- get tables() {
1315
- const tablesMap = mapSchemaComponentsOfType(
1316
- base.components,
1317
- TableURNType,
1318
- (c) => c.tableName
1319
- );
1320
- return Object.assign(tablesMap, tables);
1321
- },
1322
- addTable: (table) => base.addComponent(
1323
- typeof table === "string" ? tableSchemaComponent({ tableName: table }) : table
1324
- )
1325
- };
1562
+ // src/core/schema/sqlMigration.ts
1563
+ var sqlMigration = (name, sqls) => ({
1564
+ name,
1565
+ sqls
1566
+ });
1567
+
1568
+ // src/core/errors/index.ts
1569
+ var isNumber = (val) => typeof val === "number" && val === val;
1570
+ var isString = (val) => typeof val === "string";
1571
+ var DumboError = class _DumboError extends Error {
1572
+ static ErrorCode = 500;
1573
+ static ErrorType = "DumboError";
1574
+ errorCode;
1575
+ errorType;
1576
+ innerError;
1577
+ constructor(options) {
1578
+ const errorCode = options && typeof options === "object" && "errorCode" in options ? options.errorCode : isNumber(options) ? options : _DumboError.ErrorCode;
1579
+ const errorType = options && typeof options === "object" && "errorType" in options ? options.errorType ?? _DumboError.ErrorType : _DumboError.ErrorType;
1580
+ const message = options && typeof options === "object" && "message" in options ? options.message : isString(options) ? options : `Error with status code '${errorCode}' ocurred during DumboError processing`;
1581
+ const innerError = options && typeof options === "object" && "innerError" in options ? options.innerError : void 0;
1582
+ super(message, { cause: innerError });
1583
+ this.errorCode = errorCode;
1584
+ this.errorType = errorType;
1585
+ this.innerError = innerError;
1586
+ Object.setPrototypeOf(this, _DumboError.prototype);
1587
+ }
1588
+ static isInstanceOf(error, options) {
1589
+ if (typeof error !== "object" || error === null || !("errorCode" in error) || !isNumber(error.errorCode) || !("errorType" in error) || !isString(error.errorType))
1590
+ return false;
1591
+ if (!options) return true;
1592
+ if (options.errorCode !== void 0 && error.errorCode !== options.errorCode)
1593
+ return false;
1594
+ if (options.errorType !== void 0 && error.errorType !== options.errorType)
1595
+ return false;
1596
+ return true;
1597
+ }
1598
+ };
1599
+ var ConcurrencyError = class _ConcurrencyError extends DumboError {
1600
+ static ErrorCode = 412;
1601
+ static ErrorType = "ConcurrencyError";
1602
+ constructor(message, innerError) {
1603
+ super({
1604
+ errorCode: _ConcurrencyError.ErrorCode,
1605
+ errorType: _ConcurrencyError.ErrorType,
1606
+ message: message ?? `Expected document state does not match current one!`,
1607
+ innerError
1608
+ });
1609
+ Object.setPrototypeOf(this, _ConcurrencyError.prototype);
1610
+ }
1611
+ };
1612
+ var TransientDatabaseError = class _TransientDatabaseError extends DumboError {
1613
+ static ErrorCode = 503;
1614
+ static ErrorType = "TransientDatabaseError";
1615
+ constructor(message, innerError) {
1616
+ super({
1617
+ errorCode: _TransientDatabaseError.ErrorCode,
1618
+ errorType: _TransientDatabaseError.ErrorType,
1619
+ message: message ?? `A transient error occurred during database operation. Retrying the operation might succeed.`,
1620
+ innerError
1621
+ });
1622
+ Object.setPrototypeOf(this, _TransientDatabaseError.prototype);
1623
+ }
1624
+ };
1625
+ var ConnectionError = class _ConnectionError extends TransientDatabaseError {
1626
+ static ErrorCode = 503;
1627
+ static ErrorType = "ConnectionError";
1628
+ constructor(message, innerError) {
1629
+ super(
1630
+ message ?? `A connection error occurred during database operation.`,
1631
+ innerError
1632
+ );
1633
+ this.errorType = _ConnectionError.ErrorType;
1634
+ Object.setPrototypeOf(this, _ConnectionError.prototype);
1635
+ }
1636
+ };
1637
+ var SerializationError = class _SerializationError extends TransientDatabaseError {
1638
+ static ErrorCode = 503;
1639
+ static ErrorType = "SerializationError";
1640
+ constructor(message, innerError) {
1641
+ super(
1642
+ message ?? `A serialization failure occurred. The transaction can be retried.`,
1643
+ innerError
1644
+ );
1645
+ this.errorType = _SerializationError.ErrorType;
1646
+ Object.setPrototypeOf(this, _SerializationError.prototype);
1647
+ }
1648
+ };
1649
+ var DeadlockError = class _DeadlockError extends TransientDatabaseError {
1650
+ static ErrorCode = 503;
1651
+ static ErrorType = "DeadlockError";
1652
+ constructor(message, innerError) {
1653
+ super(
1654
+ message ?? `A deadlock was detected. The transaction can be retried.`,
1655
+ innerError
1656
+ );
1657
+ this.errorType = _DeadlockError.ErrorType;
1658
+ Object.setPrototypeOf(this, _DeadlockError.prototype);
1659
+ }
1660
+ };
1661
+ var LockNotAvailableError = class _LockNotAvailableError extends TransientDatabaseError {
1662
+ static ErrorCode = 503;
1663
+ static ErrorType = "LockNotAvailableError";
1664
+ constructor(message, innerError) {
1665
+ super(message ?? `The requested lock is not available.`, innerError);
1666
+ this.errorType = _LockNotAvailableError.ErrorType;
1667
+ Object.setPrototypeOf(this, _LockNotAvailableError.prototype);
1668
+ }
1669
+ };
1670
+ var InsufficientResourcesError = class _InsufficientResourcesError extends TransientDatabaseError {
1671
+ static ErrorCode = 503;
1672
+ static ErrorType = "InsufficientResourcesError";
1673
+ constructor(message, innerError) {
1674
+ super(
1675
+ message ?? `Insufficient resources to complete the database operation (e.g. disk full, out of memory, too many connections).`,
1676
+ innerError
1677
+ );
1678
+ this.errorType = _InsufficientResourcesError.ErrorType;
1679
+ Object.setPrototypeOf(this, _InsufficientResourcesError.prototype);
1680
+ }
1681
+ };
1682
+ var SystemError = class _SystemError extends TransientDatabaseError {
1683
+ static ErrorCode = 503;
1684
+ static ErrorType = "SystemError";
1685
+ constructor(message, innerError) {
1686
+ super(
1687
+ message ?? `A system-level error occurred (e.g. I/O error).`,
1688
+ innerError
1689
+ );
1690
+ this.errorType = _SystemError.ErrorType;
1691
+ Object.setPrototypeOf(this, _SystemError.prototype);
1692
+ }
1693
+ };
1694
+ var AdminShutdownError = class _AdminShutdownError extends TransientDatabaseError {
1695
+ static ErrorCode = 503;
1696
+ static ErrorType = "AdminShutdownError";
1697
+ constructor(message, innerError) {
1698
+ super(
1699
+ message ?? `The database server is shutting down or restarting.`,
1700
+ innerError
1701
+ );
1702
+ this.errorType = _AdminShutdownError.ErrorType;
1703
+ Object.setPrototypeOf(this, _AdminShutdownError.prototype);
1704
+ }
1705
+ };
1706
+ var QueryCanceledError = class _QueryCanceledError extends TransientDatabaseError {
1707
+ static ErrorCode = 503;
1708
+ static ErrorType = "QueryCanceledError";
1709
+ constructor(message, innerError) {
1710
+ super(
1711
+ message ?? `The query was canceled, e.g. due to statement timeout or user request.`,
1712
+ innerError
1713
+ );
1714
+ this.errorType = _QueryCanceledError.ErrorType;
1715
+ Object.setPrototypeOf(this, _QueryCanceledError.prototype);
1716
+ }
1717
+ };
1718
+ var IntegrityConstraintViolationError = class _IntegrityConstraintViolationError extends DumboError {
1719
+ static ErrorCode = 409;
1720
+ static ErrorType = "IntegrityConstraintViolationError";
1721
+ constructor(message, innerError) {
1722
+ super({
1723
+ errorCode: _IntegrityConstraintViolationError.ErrorCode,
1724
+ errorType: _IntegrityConstraintViolationError.ErrorType,
1725
+ message: message ?? `An integrity constraint violation occurred!`,
1726
+ innerError
1727
+ });
1728
+ Object.setPrototypeOf(this, _IntegrityConstraintViolationError.prototype);
1729
+ }
1730
+ };
1731
+ var UniqueConstraintError = class _UniqueConstraintError extends IntegrityConstraintViolationError {
1732
+ static ErrorCode = 409;
1733
+ static ErrorType = "UniqueConstraintError";
1734
+ constructor(message, innerError) {
1735
+ super(message ?? `Unique constraint violation occurred!`, innerError);
1736
+ this.errorType = _UniqueConstraintError.ErrorType;
1737
+ Object.setPrototypeOf(this, _UniqueConstraintError.prototype);
1738
+ }
1739
+ };
1740
+ var ForeignKeyViolationError = class _ForeignKeyViolationError extends IntegrityConstraintViolationError {
1741
+ static ErrorCode = 409;
1742
+ static ErrorType = "ForeignKeyViolationError";
1743
+ constructor(message, innerError) {
1744
+ super(message ?? `Foreign key constraint violation occurred!`, innerError);
1745
+ this.errorType = _ForeignKeyViolationError.ErrorType;
1746
+ Object.setPrototypeOf(this, _ForeignKeyViolationError.prototype);
1747
+ }
1748
+ };
1749
+ var NotNullViolationError = class _NotNullViolationError extends IntegrityConstraintViolationError {
1750
+ static ErrorCode = 409;
1751
+ static ErrorType = "NotNullViolationError";
1752
+ constructor(message, innerError) {
1753
+ super(message ?? `NOT NULL constraint violation occurred!`, innerError);
1754
+ this.errorType = _NotNullViolationError.ErrorType;
1755
+ Object.setPrototypeOf(this, _NotNullViolationError.prototype);
1756
+ }
1757
+ };
1758
+ var CheckViolationError = class _CheckViolationError extends IntegrityConstraintViolationError {
1759
+ static ErrorCode = 409;
1760
+ static ErrorType = "CheckViolationError";
1761
+ constructor(message, innerError) {
1762
+ super(message ?? `CHECK constraint violation occurred!`, innerError);
1763
+ this.errorType = _CheckViolationError.ErrorType;
1764
+ Object.setPrototypeOf(this, _CheckViolationError.prototype);
1765
+ }
1766
+ };
1767
+ var ExclusionViolationError = class _ExclusionViolationError extends IntegrityConstraintViolationError {
1768
+ static ErrorCode = 409;
1769
+ static ErrorType = "ExclusionViolationError";
1770
+ constructor(message, innerError) {
1771
+ super(message ?? `Exclusion constraint violation occurred!`, innerError);
1772
+ this.errorType = _ExclusionViolationError.ErrorType;
1773
+ Object.setPrototypeOf(this, _ExclusionViolationError.prototype);
1774
+ }
1775
+ };
1776
+ var DataError = class _DataError extends DumboError {
1777
+ static ErrorCode = 400;
1778
+ static ErrorType = "DataError";
1779
+ constructor(message, innerError) {
1780
+ super({
1781
+ errorCode: _DataError.ErrorCode,
1782
+ errorType: _DataError.ErrorType,
1783
+ message: message ?? `A data error occurred (e.g. invalid value, type mismatch).`,
1784
+ innerError
1785
+ });
1786
+ Object.setPrototypeOf(this, _DataError.prototype);
1787
+ }
1788
+ };
1789
+ var InvalidOperationError = class _InvalidOperationError extends DumboError {
1790
+ static ErrorCode = 400;
1791
+ static ErrorType = "InvalidOperationError";
1792
+ constructor(message, innerError) {
1793
+ super({
1794
+ errorCode: _InvalidOperationError.ErrorCode,
1795
+ errorType: _InvalidOperationError.ErrorType,
1796
+ message: message ?? `Invalid operation (e.g. syntax error, insufficient privileges, undefined table).`,
1797
+ innerError
1798
+ });
1799
+ Object.setPrototypeOf(this, _InvalidOperationError.prototype);
1800
+ }
1326
1801
  };
1327
1802
 
1328
- // src/core/schema/components/databaseSchemaComponent.ts
1329
- var DatabaseURNType = "sc:dumbo:database";
1330
- var DatabaseURN = ({ name }) => `${DatabaseURNType}:${name}`;
1331
- var databaseSchemaComponent = ({
1332
- databaseName,
1333
- schemas,
1334
- ...migrationsOrComponents
1335
- }) => {
1336
- schemas ??= {};
1337
- const base = schemaComponent(DatabaseURN({ name: databaseName }), {
1338
- migrations: migrationsOrComponents.migrations ?? [],
1339
- components: [
1340
- ...migrationsOrComponents.components ?? [],
1341
- ...Object.values(schemas)
1342
- ]
1343
- });
1344
- return {
1345
- ...base,
1346
- databaseName,
1347
- get schemas() {
1348
- const schemasMap = mapSchemaComponentsOfType(
1349
- base.components,
1350
- DatabaseSchemaURNType,
1351
- (c) => c.schemaName
1352
- );
1353
- return Object.assign(schemasMap, schemas);
1354
- },
1355
- addSchema: (schema) => base.addComponent(
1356
- typeof schema === "string" ? databaseSchemaSchemaComponent({ schemaName: schema }) : schema
1357
- )
1803
+ // src/core/execute/execute.ts
1804
+ var mapColumnToJSON = (column, serializer, options) => ({
1805
+ [column]: (value) => {
1806
+ if (typeof value === "string") {
1807
+ try {
1808
+ return serializer.deserialize(value, options);
1809
+ } catch {
1810
+ }
1811
+ }
1812
+ return value;
1813
+ }
1814
+ });
1815
+ var mapColumnToBigint = (column) => ({
1816
+ [column]: (value) => {
1817
+ if (typeof value === "number" || typeof value === "string") {
1818
+ return BigInt(value);
1819
+ }
1820
+ return value;
1821
+ }
1822
+ });
1823
+ var mapColumnToDate = (column) => ({
1824
+ [column]: (value) => {
1825
+ if (typeof value === "number" || typeof value === "string") {
1826
+ return new Date(value);
1827
+ }
1828
+ return value;
1829
+ }
1830
+ });
1831
+ var mapSQLQueryResult = (result, mapping) => {
1832
+ if (typeof result !== "object" || result === null) return result;
1833
+ const mappedResult = {
1834
+ ...result
1358
1835
  };
1836
+ for (const column of Object.keys(mapping)) {
1837
+ if (column in mappedResult) {
1838
+ mappedResult[column] = mapping[column](mappedResult[column]);
1839
+ }
1840
+ }
1841
+ return mappedResult;
1842
+ };
1843
+ var BatchCommandNoChangesError = class _BatchCommandNoChangesError extends DumboError {
1844
+ statementIndex;
1845
+ constructor(statementIndex) {
1846
+ super({
1847
+ errorCode: 409,
1848
+ message: `Batch command at index ${statementIndex} affected no rows`
1849
+ });
1850
+ this.name = "BatchCommandNoChangesError";
1851
+ this.statementIndex = statementIndex;
1852
+ Object.setPrototypeOf(this, _BatchCommandNoChangesError.prototype);
1853
+ }
1854
+ };
1855
+ var sqlExecutor = (sqlExecutor2, options) => ({
1856
+ query: (sql, queryOptions) => executeInNewDbClient(
1857
+ (client) => sqlExecutor2.query(client, sql, queryOptions),
1858
+ options
1859
+ ),
1860
+ batchQuery: (sqls, queryOptions) => executeInNewDbClient(
1861
+ (client) => sqlExecutor2.batchQuery(client, sqls, queryOptions),
1862
+ options
1863
+ ),
1864
+ command: (sql, commandOptions) => executeInNewDbClient(
1865
+ (client) => sqlExecutor2.command(client, sql, commandOptions),
1866
+ options
1867
+ ),
1868
+ batchCommand: (sqls, commandOptions) => executeInNewDbClient(
1869
+ (client) => sqlExecutor2.batchCommand(client, sqls, commandOptions),
1870
+ options
1871
+ )
1872
+ });
1873
+ var sqlExecutorInNewConnection = (options) => ({
1874
+ query: (sql, queryOptions) => executeInNewConnection(
1875
+ (connection) => connection.execute.query(sql, queryOptions),
1876
+ options
1877
+ ),
1878
+ batchQuery: (sqls, queryOptions) => executeInNewConnection(
1879
+ (connection) => connection.execute.batchQuery(sqls, queryOptions),
1880
+ options
1881
+ ),
1882
+ command: (sql, commandOptions) => executeInNewConnection(
1883
+ (connection) => connection.execute.command(sql, commandOptions),
1884
+ options
1885
+ ),
1886
+ batchCommand: (sqls, commandOptions) => executeInNewConnection(
1887
+ (connection) => connection.execute.batchCommand(sqls, commandOptions),
1888
+ options
1889
+ )
1890
+ });
1891
+ var sqlExecutorInAmbientConnection = (options) => ({
1892
+ query: (sql, queryOptions) => executeInAmbientConnection(
1893
+ (connection) => connection.execute.query(sql, queryOptions),
1894
+ options
1895
+ ),
1896
+ batchQuery: (sqls, queryOptions) => executeInAmbientConnection(
1897
+ (connection) => connection.execute.batchQuery(sqls, queryOptions),
1898
+ options
1899
+ ),
1900
+ command: (sql, commandOptions) => executeInAmbientConnection(
1901
+ (connection) => connection.execute.command(sql, commandOptions),
1902
+ options
1903
+ ),
1904
+ batchCommand: (sqls, commandOptions) => executeInAmbientConnection(
1905
+ (connection) => connection.execute.batchCommand(sqls, commandOptions),
1906
+ options
1907
+ )
1908
+ });
1909
+ var executeInNewDbClient = async (handle, options) => {
1910
+ const { connect, close } = options;
1911
+ const client = await connect();
1912
+ try {
1913
+ return await handle(client);
1914
+ } catch (error) {
1915
+ if (close) await close(client, error);
1916
+ throw error;
1917
+ }
1918
+ };
1919
+ var executeInNewConnection = async (handle, options) => {
1920
+ const connection = await options.connection();
1921
+ try {
1922
+ return await handle(connection);
1923
+ } finally {
1924
+ await connection.close();
1925
+ }
1926
+ };
1927
+ var executeInAmbientConnection = async (handle, options) => {
1928
+ const connection = await options.connection();
1929
+ try {
1930
+ return await handle(connection);
1931
+ } finally {
1932
+ }
1359
1933
  };
1360
1934
 
1361
- // src/core/schema/components/relationships/relationshipTypes.ts
1362
- var relationship = (columns, references, type) => {
1935
+ // src/core/connections/transaction.ts
1936
+ var toTransactionResult = (transactionResult) => transactionResult !== void 0 && transactionResult !== null && typeof transactionResult === "object" && "success" in transactionResult ? transactionResult : { success: true, result: transactionResult };
1937
+ var executeInTransaction = async (transaction, handle) => {
1938
+ await transaction.begin();
1939
+ try {
1940
+ const { success, result } = toTransactionResult(await handle(transaction));
1941
+ if (success) await transaction.commit();
1942
+ else await transaction.rollback();
1943
+ return result;
1944
+ } catch (e) {
1945
+ await transaction.rollback();
1946
+ throw e;
1947
+ }
1948
+ };
1949
+ var transactionFactoryWithDbClient = (connect, initTransaction) => {
1950
+ let currentTransaction = void 0;
1951
+ const getOrInitCurrentTransaction = (options) => currentTransaction ?? (currentTransaction = initTransaction(connect(), {
1952
+ close: () => {
1953
+ currentTransaction = void 0;
1954
+ return Promise.resolve();
1955
+ },
1956
+ ...options ?? {}
1957
+ }));
1363
1958
  return {
1364
- columns,
1365
- references,
1366
- type
1959
+ transaction: getOrInitCurrentTransaction,
1960
+ withTransaction: (handle, options) => executeInTransaction(getOrInitCurrentTransaction(options), handle)
1367
1961
  };
1368
1962
  };
1369
-
1370
- // src/core/schema/components/index.ts
1371
- var schemaComponentURN = {
1372
- database: DatabaseURN,
1373
- schema: DatabaseSchemaURN,
1374
- table: TableURN,
1375
- column: ColumnURN,
1376
- index: IndexURN,
1377
- extractName: (urn) => {
1378
- const parts = urn.split(":");
1379
- return parts[parts.length - 1] || "";
1963
+ var wrapInConnectionClosure = async (connection, handle) => {
1964
+ try {
1965
+ return await handle();
1966
+ } finally {
1967
+ await connection.close();
1380
1968
  }
1381
1969
  };
1382
-
1383
- // src/core/schema/dumboSchema/dumboSchema.ts
1384
- var DEFAULT_DATABASE_NAME = "__default_database__";
1385
- var DEFAULT_DATABASE_SCHEMA_NAME = "__default_database_schema__";
1386
- var dumboColumn = (name, type, options) => columnSchemaComponent({
1387
- columnName: name,
1388
- type,
1389
- ...options
1970
+ var transactionFactoryWithNewConnection = (connect) => ({
1971
+ transaction: (options) => {
1972
+ const connection = connect();
1973
+ const transaction = connection.transaction(
1974
+ options
1975
+ );
1976
+ return {
1977
+ ...transaction,
1978
+ commit: () => wrapInConnectionClosure(connection, () => transaction.commit()),
1979
+ rollback: () => wrapInConnectionClosure(connection, () => transaction.rollback())
1980
+ };
1981
+ },
1982
+ withTransaction: (handle, options) => {
1983
+ const connection = connect();
1984
+ const withTx = connection.withTransaction;
1985
+ return wrapInConnectionClosure(connection, () => withTx(handle, options));
1986
+ }
1390
1987
  });
1391
- var dumboIndex = (name, columnNames, options) => indexSchemaComponent({
1392
- indexName: name,
1393
- columnNames,
1394
- isUnique: options?.unique ?? false,
1395
- ...options
1988
+ var transactionFactoryWithAmbientConnection = (connect) => ({
1989
+ transaction: (options) => {
1990
+ const connection = connect();
1991
+ const transaction = connection.transaction(options);
1992
+ return {
1993
+ ...transaction,
1994
+ commit: () => transaction.commit(),
1995
+ rollback: () => transaction.rollback()
1996
+ };
1997
+ },
1998
+ withTransaction: (handle, options) => {
1999
+ const connection = connect();
2000
+ const withTx = connection.withTransaction;
2001
+ return withTx(handle, options);
2002
+ }
1396
2003
  });
1397
- var dumboTable = (name, definition) => {
1398
- const { columns, indexes, primaryKey, relationships, ...options } = definition;
1399
- const components = [...indexes ? Object.values(indexes) : []];
1400
- return tableSchemaComponent({
1401
- tableName: name,
1402
- columns: columns ?? {},
1403
- primaryKey: primaryKey ?? [],
1404
- ...relationships !== void 0 ? { relationships } : {},
1405
- components,
1406
- ...options
1407
- });
1408
- };
1409
- function dumboDatabaseSchema(nameOrTables, tables, options) {
1410
- const schemaName = typeof nameOrTables === "string" ? nameOrTables : DEFAULT_DATABASE_SCHEMA_NAME;
1411
- const tablesMap = (typeof nameOrTables === "string" ? tables : nameOrTables) ?? {};
1412
- return databaseSchemaSchemaComponent({
1413
- schemaName,
1414
- tables: tablesMap,
1415
- ...options
1416
- });
1417
- }
1418
- dumboDatabaseSchema.from = (schemaName, tableNames) => {
1419
- const tables = tableNames.reduce(
1420
- (acc, tableName) => {
1421
- acc[tableName] = dumboTable(tableName, {});
1422
- return acc;
1423
- },
1424
- {}
1425
- );
1426
- return schemaName ? dumboDatabaseSchema(schemaName, tables) : dumboDatabaseSchema(tables);
1427
- };
1428
- function dumboDatabase(nameOrSchemas, schemasOrOptions, options) {
1429
- const databaseName = typeof nameOrSchemas === "string" ? nameOrSchemas : DEFAULT_DATABASE_NAME;
1430
- const schemasOrSchema = typeof nameOrSchemas === "string" ? schemasOrOptions ?? {} : nameOrSchemas;
1431
- const schemaMap = "schemaComponentKey" in schemasOrSchema && isSchemaComponentOfType(
1432
- schemasOrSchema,
1433
- "sc:dumbo:database_schema"
1434
- ) ? {
1435
- [DEFAULT_DATABASE_SCHEMA_NAME]: schemasOrSchema
1436
- } : schemasOrSchema;
1437
- const dbOptions = typeof nameOrSchemas === "string" ? options : schemasOrOptions;
1438
- return databaseSchemaComponent({
1439
- databaseName,
1440
- schemas: schemaMap,
1441
- ...dbOptions
1442
- });
1443
- }
1444
- dumboDatabase.from = (databaseName, schemaNames) => {
1445
- const schemas = schemaNames.reduce(
1446
- (acc, schemaName) => {
1447
- acc[schemaName] = dumboDatabaseSchema(
1448
- schemaName,
1449
- {}
1450
- );
1451
- return acc;
2004
+ var transactionFactoryWithAsyncAmbientConnection = (driverType, connect, close) => {
2005
+ close ??= () => Promise.resolve();
2006
+ return {
2007
+ transaction: (options) => {
2008
+ let conn = null;
2009
+ let innerTx = null;
2010
+ let connectingPromise = null;
2011
+ const ensureConnection = async () => {
2012
+ if (conn) return innerTx;
2013
+ if (!connectingPromise) {
2014
+ connectingPromise = (async () => {
2015
+ conn = await connect();
2016
+ innerTx = conn.transaction(options);
2017
+ })();
2018
+ }
2019
+ await connectingPromise;
2020
+ return innerTx;
2021
+ };
2022
+ const tx = {
2023
+ driverType,
2024
+ get connection() {
2025
+ if (!conn) {
2026
+ throw new Error("Transaction not started - call begin() first");
2027
+ }
2028
+ return conn;
2029
+ },
2030
+ execute: {
2031
+ query: async (sql, queryOptions) => {
2032
+ const tx2 = await ensureConnection();
2033
+ return tx2.execute.query(sql, queryOptions);
2034
+ },
2035
+ batchQuery: async (sqls, queryOptions) => {
2036
+ const tx2 = await ensureConnection();
2037
+ return tx2.execute.batchQuery(sqls, queryOptions);
2038
+ },
2039
+ command: async (sql, commandOptions) => {
2040
+ const tx2 = await ensureConnection();
2041
+ return tx2.execute.command(sql, commandOptions);
2042
+ },
2043
+ batchCommand: async (sqls, commandOptions) => {
2044
+ const tx2 = await ensureConnection();
2045
+ return tx2.execute.batchCommand(sqls, commandOptions);
2046
+ }
2047
+ },
2048
+ begin: async () => {
2049
+ const tx2 = await ensureConnection();
2050
+ return tx2.begin();
2051
+ },
2052
+ commit: async () => {
2053
+ if (!innerTx) {
2054
+ throw new Error("Transaction not started");
2055
+ }
2056
+ try {
2057
+ return await innerTx.commit();
2058
+ } finally {
2059
+ if (conn) await close(conn);
2060
+ }
2061
+ },
2062
+ rollback: async (error) => {
2063
+ if (!innerTx) {
2064
+ if (conn) await close(conn);
2065
+ return;
2066
+ }
2067
+ try {
2068
+ return await innerTx.rollback(error);
2069
+ } finally {
2070
+ if (conn) await close(conn);
2071
+ }
2072
+ },
2073
+ _transactionOptions: void 0
2074
+ };
2075
+ return tx;
1452
2076
  },
1453
- {}
1454
- );
1455
- return databaseName ? dumboDatabase(databaseName, schemas) : dumboDatabase(schemas);
1456
- };
1457
- dumboDatabase.defaultName = DEFAULT_DATABASE_NAME;
1458
- dumboDatabaseSchema.defaultName = DEFAULT_DATABASE_SCHEMA_NAME;
1459
- var dumboSchema = {
1460
- database: dumboDatabase,
1461
- schema: dumboDatabaseSchema,
1462
- table: dumboTable,
1463
- column: dumboColumn,
1464
- index: dumboIndex
1465
- };
1466
-
1467
- // src/core/locks/databaseLock.ts
1468
- var defaultDatabaseLockOptions = {
1469
- timeoutMs: 1e4
1470
- };
1471
- var NoDatabaseLock = {
1472
- acquire: () => Promise.resolve(),
1473
- tryAcquire: () => Promise.resolve(true),
1474
- release: () => Promise.resolve(true),
1475
- withAcquire: (_execute, handle, _options) => handle()
1476
- };
1477
-
1478
- // src/core/query/mappers.ts
1479
- var mapRows = async (getResult, map) => {
1480
- const result = await getResult;
1481
- return result.rows.map(map);
1482
- };
1483
- var toCamelCase = (snakeStr) => snakeStr.replace(/_([a-z])/g, (g) => g[1]?.toUpperCase() ?? "");
1484
- var mapToCamelCase = (obj) => {
1485
- const newObj = {};
1486
- for (const key in obj) {
1487
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
1488
- newObj[toCamelCase(key)] = obj[key];
2077
+ withTransaction: async (handle, options) => {
2078
+ const conn = await connect();
2079
+ try {
2080
+ const withTx = conn.withTransaction;
2081
+ return await withTx(handle, options);
2082
+ } finally {
2083
+ await close(conn);
2084
+ }
1489
2085
  }
1490
- }
1491
- return newObj;
2086
+ };
1492
2087
  };
1493
2088
 
1494
- // src/core/query/selectors.ts
1495
- var firstOrNull = async (getResult) => {
1496
- const result = await getResult;
1497
- return result.rows.length > 0 ? result.rows[0] ?? null : null;
1498
- };
1499
- var first = async (getResult) => {
1500
- const result = await getResult;
1501
- if (result.rows.length === 0)
1502
- throw new Error("Query didn't return any result");
1503
- return result.rows[0];
1504
- };
1505
- var singleOrNull = async (getResult) => {
1506
- const result = await getResult;
1507
- if (result.rows.length > 1) throw new Error("Query had more than one result");
1508
- return result.rows.length > 0 ? result.rows[0] ?? null : null;
1509
- };
1510
- var single = async (getResult) => {
1511
- const result = await getResult;
1512
- if (result.rows.length === 0)
1513
- throw new Error("Query didn't return any result");
1514
- if (result.rows.length > 1) throw new Error("Query had more than one result");
1515
- return result.rows[0];
2089
+ // src/core/connections/connection.ts
2090
+ var createAmbientConnection = (options) => {
2091
+ const { driverType, client, executor, initTransaction, serializer } = options;
2092
+ const clientPromise = Promise.resolve(client);
2093
+ const closePromise = Promise.resolve();
2094
+ const open = () => clientPromise;
2095
+ const close = () => closePromise;
2096
+ const connection = {
2097
+ driverType,
2098
+ open,
2099
+ close,
2100
+ ...transactionFactoryWithDbClient(
2101
+ open,
2102
+ initTransaction(() => typedConnection)
2103
+ ),
2104
+ execute: sqlExecutor(executor({ serializer }), { connect: open }),
2105
+ _transactionType: void 0
2106
+ };
2107
+ const typedConnection = connection;
2108
+ return typedConnection;
1516
2109
  };
1517
- var count = async (getResult) => {
1518
- const result = await single(getResult);
1519
- return Number(result.count);
2110
+ var createSingletonConnection = (options) => {
2111
+ const { driverType, connect, close, initTransaction, executor, serializer } = options;
2112
+ let client = null;
2113
+ let connectPromise = null;
2114
+ const getClient = async () => {
2115
+ if (client) return client;
2116
+ if (!connectPromise) {
2117
+ connectPromise = connect().then((c) => {
2118
+ client = c;
2119
+ return c;
2120
+ });
2121
+ }
2122
+ return connectPromise;
2123
+ };
2124
+ const connection = {
2125
+ driverType,
2126
+ open: getClient,
2127
+ close: () => client ? close(client) : Promise.resolve(),
2128
+ ...transactionFactoryWithDbClient(
2129
+ getClient,
2130
+ initTransaction(() => typedConnection)
2131
+ ),
2132
+ execute: sqlExecutor(executor({ serializer }), { connect: getClient }),
2133
+ _transactionType: void 0
2134
+ };
2135
+ const typedConnection = connection;
2136
+ return typedConnection;
1520
2137
  };
1521
- var exists = async (getResult) => {
1522
- const result = await single(getResult);
1523
- return result.exists === true || result.exists === 1;
2138
+ var createTransientConnection = (options) => {
2139
+ const { driverType, open, close, initTransaction, executor, serializer } = options;
2140
+ const connection = {
2141
+ driverType,
2142
+ open,
2143
+ close,
2144
+ ...transactionFactoryWithDbClient(
2145
+ open,
2146
+ initTransaction(() => typedConnection)
2147
+ ),
2148
+ execute: sqlExecutor(executor({ serializer }), { connect: open }),
2149
+ _transactionType: void 0
2150
+ };
2151
+ const typedConnection = connection;
2152
+ return typedConnection;
1524
2153
  };
1525
-
1526
- // src/core/tracing/printing/color.ts
1527
- import ansis from "ansis";
1528
- var enableColors = true;
1529
- var color = {
1530
- set level(value) {
1531
- enableColors = value === 1;
1532
- },
1533
- hex: (value) => (text) => enableColors ? ansis.hex(value)(text) : text,
1534
- red: (value) => enableColors ? ansis.red(value) : value,
1535
- green: (value) => enableColors ? ansis.green(value) : value,
1536
- blue: (value) => enableColors ? ansis.blue(value) : value,
1537
- cyan: (value) => enableColors ? ansis.cyan(value) : value,
1538
- yellow: (value) => enableColors ? ansis.yellow(value) : value
2154
+ var createConnection = (options) => {
2155
+ const { driverType, connect, close, initTransaction, executor, serializer } = options;
2156
+ let client = null;
2157
+ let connectPromise = null;
2158
+ const getClient = async () => {
2159
+ if (client) return client;
2160
+ if (!connectPromise) {
2161
+ connectPromise = connect().then((c) => {
2162
+ client = c;
2163
+ return c;
2164
+ });
2165
+ }
2166
+ return connectPromise;
2167
+ };
2168
+ const connection = {
2169
+ driverType,
2170
+ open: getClient,
2171
+ close: () => client ? close(client) : Promise.resolve(),
2172
+ ...transactionFactoryWithDbClient(
2173
+ getClient,
2174
+ initTransaction(() => typedConnection)
2175
+ ),
2176
+ execute: sqlExecutor(executor({ serializer }), { connect: getClient }),
2177
+ _transactionType: void 0
2178
+ };
2179
+ const typedConnection = connection;
2180
+ return typedConnection;
1539
2181
  };
1540
- var color_default = color;
1541
2182
 
1542
- // src/core/tracing/printing/pretty.ts
1543
- var TWO_SPACES = " ";
1544
- var COLOR_STRING = color_default.hex("#98c379");
1545
- var COLOR_KEY = color_default.hex("#61afef");
1546
- var COLOR_NUMBER_OR_DATE = color_default.hex("#d19a66");
1547
- var COLOR_BOOLEAN = color_default.hex("#c678dd");
1548
- var COLOR_NULL_OR_UNDEFINED = color_default.hex("#c678dd");
1549
- var COLOR_BRACKETS = color_default.hex("#abb2bf");
1550
- var processString = (str, indent, handleMultiline) => {
1551
- if (handleMultiline && str.includes("\n")) {
1552
- const lines = str.split("\n");
1553
- const indentedLines = lines.map(
1554
- (line) => indent + TWO_SPACES + COLOR_STRING(line)
1555
- );
1556
- return COLOR_STRING('"') + "\n" + indentedLines.join("\n") + "\n" + indent + COLOR_STRING('"');
2183
+ // src/core/taskProcessing/taskProcessor.ts
2184
+ var TaskProcessor = class {
2185
+ queue = [];
2186
+ isProcessing = false;
2187
+ activeTasks = 0;
2188
+ activeGroups = /* @__PURE__ */ new Set();
2189
+ options;
2190
+ constructor(options) {
2191
+ this.options = options;
1557
2192
  }
1558
- return COLOR_STRING(`"${str}"`);
1559
- };
1560
- var shouldPrint = (obj) => typeof obj !== "function" && typeof obj !== "symbol";
1561
- var formatJson = (obj, indentLevel = 0, handleMultiline = false) => {
1562
- const indent = TWO_SPACES.repeat(indentLevel);
1563
- if (obj === null) return COLOR_NULL_OR_UNDEFINED("null");
1564
- if (obj === void 0) return COLOR_NULL_OR_UNDEFINED("undefined");
1565
- if (typeof obj === "string")
1566
- return processString(obj, indent, handleMultiline);
1567
- if (typeof obj === "number" || typeof obj === "bigint" || obj instanceof Date)
1568
- return COLOR_NUMBER_OR_DATE(String(obj));
1569
- if (typeof obj === "boolean") return COLOR_BOOLEAN(String(obj));
1570
- if (obj instanceof Error) {
1571
- const errorObj = {};
1572
- const propNames = Object.getOwnPropertyNames(obj);
1573
- propNames.forEach((key) => {
1574
- errorObj[key] = obj[key];
1575
- });
1576
- return formatJson(errorObj, indentLevel, handleMultiline);
2193
+ enqueue(task, options) {
2194
+ if (this.queue.length >= this.options.maxQueueSize) {
2195
+ return Promise.reject(
2196
+ new TransientDatabaseError(
2197
+ "Too many pending connections. Please try again later."
2198
+ )
2199
+ );
2200
+ }
2201
+ return this.schedule(task, options);
1577
2202
  }
1578
- if (obj instanceof Promise) {
1579
- return COLOR_STRING("Promise {pending}");
2203
+ waitForEndOfProcessing() {
2204
+ return this.schedule(({ ack }) => Promise.resolve(ack()));
1580
2205
  }
1581
- if (Array.isArray(obj)) {
1582
- const arrayItems = obj.map(
1583
- (item) => formatJson(item, indentLevel + 1, handleMultiline)
2206
+ schedule(task, options) {
2207
+ return promiseWithDeadline(
2208
+ (resolve, reject) => {
2209
+ const taskWithContext = () => {
2210
+ return new Promise((resolveTask, failTask) => {
2211
+ const taskPromise = task({
2212
+ ack: resolveTask
2213
+ });
2214
+ taskPromise.then(resolve).catch((err) => {
2215
+ failTask(err);
2216
+ reject(err);
2217
+ });
2218
+ });
2219
+ };
2220
+ this.queue.push({ task: taskWithContext, options });
2221
+ if (!this.isProcessing) {
2222
+ this.ensureProcessing();
2223
+ }
2224
+ },
2225
+ { deadline: this.options.maxTaskIdleTime }
1584
2226
  );
1585
- return `${COLOR_BRACKETS("[")}
1586
- ${indent} ${arrayItems.join(
1587
- `,
1588
- ${indent} `
1589
- )}
1590
- ${indent}${COLOR_BRACKETS("]")}`;
1591
2227
  }
1592
- const entries = Object.entries(obj).filter(([_, value]) => shouldPrint(value)).map(
1593
- ([key, value]) => `${COLOR_KEY(`"${key}"`)}: ${formatJson(
1594
- value,
1595
- indentLevel + 1,
1596
- handleMultiline
1597
- )}`
1598
- );
1599
- return `${COLOR_BRACKETS("{")}
1600
- ${indent} ${entries.join(
1601
- `,
1602
- ${indent} `
1603
- )}
1604
- ${indent}${COLOR_BRACKETS("}")}`;
1605
- };
1606
- var prettyJson = (obj, options) => formatJson(obj, 0, options?.handleMultiline);
1607
-
1608
- // src/core/tracing/index.ts
1609
- var tracer = () => {
1610
- };
1611
- var LogLevel = {
1612
- DISABLED: "DISABLED",
1613
- INFO: "INFO",
1614
- LOG: "LOG",
1615
- WARN: "WARN",
1616
- ERROR: "ERROR"
1617
- };
1618
- var LogStyle = {
1619
- RAW: "RAW",
1620
- PRETTY: "PRETTY"
1621
- };
1622
- var shouldLog = (logLevel) => {
1623
- const definedLogLevel = process.env.DUMBO_LOG_LEVEL ?? LogLevel.DISABLED;
1624
- if (definedLogLevel === LogLevel.ERROR && logLevel === LogLevel.ERROR)
1625
- return true;
1626
- if (definedLogLevel === LogLevel.WARN && [LogLevel.ERROR, LogLevel.WARN].includes(logLevel))
1627
- return true;
1628
- if (definedLogLevel === LogLevel.LOG && [LogLevel.ERROR, LogLevel.WARN, LogLevel.LOG].includes(logLevel))
1629
- return true;
1630
- if (definedLogLevel === LogLevel.INFO && [LogLevel.ERROR, LogLevel.WARN, LogLevel.LOG, LogLevel.INFO].includes(
1631
- logLevel
1632
- ))
1633
- return true;
1634
- return false;
1635
- };
1636
- var nulloTraceEventRecorder = () => {
1637
- };
1638
- var getTraceEventFormatter = (logStyle) => (event) => {
1639
- switch (logStyle) {
1640
- case "RAW":
1641
- return JSONSerializer.serialize(event);
1642
- case "PRETTY":
1643
- return prettyJson(event, { handleMultiline: true });
2228
+ ensureProcessing() {
2229
+ if (this.isProcessing) return;
2230
+ this.isProcessing = true;
2231
+ this.processQueue();
1644
2232
  }
1645
- };
1646
- var getTraceEventRecorder = (logLevel, logStyle) => {
1647
- const format = getTraceEventFormatter(logStyle);
1648
- switch (logLevel) {
1649
- case "DISABLED":
1650
- return nulloTraceEventRecorder;
1651
- case "INFO":
1652
- return (event) => console.info(format(event));
1653
- case "LOG":
1654
- return (event) => console.log(format(event));
1655
- case "WARN":
1656
- return (event) => console.warn(format(event));
1657
- case "ERROR":
1658
- return (event) => console.error(format(event));
2233
+ processQueue() {
2234
+ try {
2235
+ while (this.activeTasks < this.options.maxActiveTasks && this.queue.length > 0) {
2236
+ const item = this.takeFirstAvailableItem();
2237
+ if (item === null) return;
2238
+ const groupId = item.options?.taskGroupId;
2239
+ if (groupId) {
2240
+ this.activeGroups.add(groupId);
2241
+ }
2242
+ this.activeTasks++;
2243
+ void this.executeItem(item);
2244
+ }
2245
+ } catch (error) {
2246
+ console.error(error);
2247
+ throw error;
2248
+ } finally {
2249
+ this.isProcessing = false;
2250
+ if (this.hasItemsToProcess() && this.activeTasks < this.options.maxActiveTasks) {
2251
+ this.ensureProcessing();
2252
+ }
2253
+ }
1659
2254
  }
1660
- };
1661
- var recordTraceEvent = (logLevel, eventName, attributes) => {
1662
- if (!shouldLog(LogLevel.LOG)) return;
1663
- const event = {
1664
- name: eventName,
1665
- timestamp: (/* @__PURE__ */ new Date()).getTime(),
1666
- ...attributes
2255
+ async executeItem({ task, options }) {
2256
+ try {
2257
+ await task();
2258
+ } finally {
2259
+ this.activeTasks--;
2260
+ if (options && options.taskGroupId) {
2261
+ this.activeGroups.delete(options.taskGroupId);
2262
+ }
2263
+ this.ensureProcessing();
2264
+ }
2265
+ }
2266
+ takeFirstAvailableItem = () => {
2267
+ const taskIndex = this.queue.findIndex(
2268
+ (item2) => !item2.options?.taskGroupId || !this.activeGroups.has(item2.options.taskGroupId)
2269
+ );
2270
+ if (taskIndex === -1) {
2271
+ return null;
2272
+ }
2273
+ const [item] = this.queue.splice(taskIndex, 1);
2274
+ return item ?? null;
1667
2275
  };
1668
- const record = getTraceEventRecorder(
1669
- logLevel,
1670
- process.env.DUMBO_LOG_STYLE ?? "RAW"
1671
- );
1672
- record(event);
2276
+ hasItemsToProcess = () => this.queue.findIndex(
2277
+ (item) => !item.options?.taskGroupId || !this.activeGroups.has(item.options.taskGroupId)
2278
+ ) !== -1;
2279
+ };
2280
+ var DEFAULT_PROMISE_DEADLINE = 2147483647;
2281
+ var promiseWithDeadline = (executor, options) => {
2282
+ return new Promise((resolve, reject) => {
2283
+ let taskStarted = false;
2284
+ const maxWaitingTime = options.deadline || DEFAULT_PROMISE_DEADLINE;
2285
+ let timeoutId = setTimeout(() => {
2286
+ if (!taskStarted) {
2287
+ reject(
2288
+ new Error("Task was not started within the maximum waiting time")
2289
+ );
2290
+ }
2291
+ }, maxWaitingTime);
2292
+ executor((value) => {
2293
+ taskStarted = true;
2294
+ if (timeoutId) {
2295
+ clearTimeout(timeoutId);
2296
+ }
2297
+ timeoutId = null;
2298
+ resolve(value);
2299
+ }, reject);
2300
+ });
1673
2301
  };
1674
- tracer.info = (eventName, attributes) => recordTraceEvent(LogLevel.INFO, eventName, attributes);
1675
- tracer.warn = (eventName, attributes) => recordTraceEvent(LogLevel.WARN, eventName, attributes);
1676
- tracer.log = (eventName, attributes) => recordTraceEvent(LogLevel.LOG, eventName, attributes);
1677
- tracer.error = (eventName, attributes) => recordTraceEvent(LogLevel.ERROR, eventName, attributes);
1678
2302
 
1679
- // src/core/schema/migrators/schemaComponentMigrator.ts
1680
- var { AutoIncrement, Varchar, Timestamp } = SQL.column.type;
1681
- var migrationTableSQL = SQL`
1682
- CREATE TABLE IF NOT EXISTS migrations (
1683
- id ${AutoIncrement({ primaryKey: true })},
1684
- name ${Varchar(255)} NOT NULL UNIQUE,
1685
- application ${Varchar(255)} NOT NULL DEFAULT 'default',
1686
- sql_hash ${Varchar(64)} NOT NULL,
1687
- timestamp ${Timestamp} NOT NULL DEFAULT CURRENT_TIMESTAMP
1688
- );
1689
- `;
1690
- var migrationTableSchemaComponent = schemaComponent(
1691
- "dumbo:schema-component:migrations-table",
1692
- {
1693
- migrations: [sqlMigration("dumbo:migrationTable:001", [migrationTableSQL])]
1694
- }
1695
- );
1696
- var SchemaComponentMigrator = (component, dumbo) => {
1697
- const completedMigrations = [];
2303
+ // src/core/connections/pool.ts
2304
+ var wrapPooledConnection = (conn, onClose) => ({ ...conn, close: onClose });
2305
+ var createAmbientConnectionPool = (options) => {
2306
+ const { driverType, connection } = options;
2307
+ return createConnectionPool({
2308
+ driverType,
2309
+ getConnection: () => connection,
2310
+ execute: connection.execute,
2311
+ transaction: (options2) => connection.transaction(
2312
+ options2
2313
+ ),
2314
+ withConnection: (handle, _options) => handle(connection),
2315
+ withTransaction: (handle, options2) => {
2316
+ const withTx = connection.withTransaction;
2317
+ return withTx(handle, options2);
2318
+ }
2319
+ });
2320
+ };
2321
+ var createSingletonConnectionPool = (options) => {
2322
+ const { driverType, getConnection } = options;
2323
+ let connectionPromise = null;
2324
+ const getExistingOrNewConnection = () => {
2325
+ if (!connectionPromise) {
2326
+ connectionPromise ??= Promise.resolve(getConnection());
2327
+ }
2328
+ return connectionPromise;
2329
+ };
2330
+ const result = {
2331
+ driverType,
2332
+ connection: () => getExistingOrNewConnection().then(
2333
+ (conn) => wrapPooledConnection(conn, () => Promise.resolve())
2334
+ ),
2335
+ execute: sqlExecutorInAmbientConnection({
2336
+ driverType,
2337
+ connection: getExistingOrNewConnection
2338
+ }),
2339
+ withConnection: (handle, _options) => executeInAmbientConnection(handle, {
2340
+ connection: getExistingOrNewConnection
2341
+ }),
2342
+ ...transactionFactoryWithAsyncAmbientConnection(
2343
+ options.driverType,
2344
+ getExistingOrNewConnection,
2345
+ options.closeConnection
2346
+ ),
2347
+ close: async () => {
2348
+ if (!connectionPromise) return;
2349
+ const connection = await connectionPromise;
2350
+ await connection.close();
2351
+ }
2352
+ };
2353
+ return result;
2354
+ };
2355
+ var memoizeConnection = (fn) => {
2356
+ let promise = null;
2357
+ return () => {
2358
+ if (!promise) {
2359
+ promise = Promise.resolve(fn()).catch((err) => {
2360
+ promise = null;
2361
+ throw err;
2362
+ });
2363
+ }
2364
+ return promise;
2365
+ };
2366
+ };
2367
+ var createBoundedConnectionPool = (options) => {
2368
+ const { driverType, maxConnections } = options;
2369
+ const getConnection = memoizeConnection(options.getConnection);
2370
+ const pool = [];
2371
+ const allConnections = /* @__PURE__ */ new Set();
2372
+ const taskProcessor = new TaskProcessor({
2373
+ maxActiveTasks: maxConnections,
2374
+ maxQueueSize: 1e3
2375
+ });
2376
+ const ackCallbacks = /* @__PURE__ */ new Map();
2377
+ let closed = false;
2378
+ const acquire = async () => {
2379
+ if (closed) throw new DumboError("Connection pool is closed");
2380
+ return taskProcessor.enqueue(async ({ ack }) => {
2381
+ try {
2382
+ let conn = pool.pop();
2383
+ if (!conn) {
2384
+ conn = await getConnection();
2385
+ allConnections.add(conn);
2386
+ }
2387
+ ackCallbacks.set(conn, ack);
2388
+ return conn;
2389
+ } catch (e) {
2390
+ ack();
2391
+ throw e;
2392
+ }
2393
+ });
2394
+ };
2395
+ const release = (conn) => {
2396
+ const ack = ackCallbacks.get(conn);
2397
+ if (ack) {
2398
+ ackCallbacks.delete(conn);
2399
+ pool.push(conn);
2400
+ ack();
2401
+ }
2402
+ };
2403
+ const executeWithPooling = async (operation) => {
2404
+ const conn = await acquire();
2405
+ try {
2406
+ return await operation(conn);
2407
+ } finally {
2408
+ release(conn);
2409
+ }
2410
+ };
1698
2411
  return {
1699
- component,
1700
- run: async (options) => {
1701
- const pendingMigrations = component.migrations.filter(
1702
- (m) => !completedMigrations.includes(
1703
- `${component.schemaComponentKey}:${m.name}`
1704
- )
1705
- );
1706
- if (pendingMigrations.length === 0) return;
1707
- await runSQLMigrations(dumbo, pendingMigrations, options);
1708
- completedMigrations.push(
1709
- ...pendingMigrations.map(
1710
- (m) => `${component.schemaComponentKey}:${m.name}`
1711
- )
1712
- );
2412
+ driverType,
2413
+ connection: async () => {
2414
+ const conn = await acquire();
2415
+ return wrapPooledConnection(conn, () => Promise.resolve(release(conn)));
2416
+ },
2417
+ execute: {
2418
+ query: (sql, opts) => executeWithPooling((c) => c.execute.query(sql, opts)),
2419
+ batchQuery: (sqls, opts) => executeWithPooling((c) => c.execute.batchQuery(sqls, opts)),
2420
+ command: (sql, opts) => executeWithPooling((c) => c.execute.command(sql, opts)),
2421
+ batchCommand: (sqls, opts) => executeWithPooling((c) => c.execute.batchCommand(sqls, opts))
2422
+ },
2423
+ withConnection: executeWithPooling,
2424
+ ...transactionFactoryWithAsyncAmbientConnection(
2425
+ driverType,
2426
+ acquire,
2427
+ release
2428
+ ),
2429
+ close: async () => {
2430
+ if (closed) return;
2431
+ closed = true;
2432
+ for (const ack of ackCallbacks.values()) ack();
2433
+ ackCallbacks.clear();
2434
+ const connections = [...allConnections];
2435
+ allConnections.clear();
2436
+ pool.length = 0;
2437
+ await Promise.all(connections.map((conn) => conn.close()));
1713
2438
  }
1714
2439
  };
1715
2440
  };
2441
+ var createSingletonClientConnectionPool = (options) => {
2442
+ const { driverType, dbClient } = options;
2443
+ return createSingletonConnectionPool({
2444
+ getConnection: () => options.connectionFactory({ dbClient }),
2445
+ driverType
2446
+ });
2447
+ };
2448
+ var createAlwaysNewConnectionPool = (options) => {
2449
+ const { driverType, getConnection, connectionOptions } = options;
2450
+ return createConnectionPool({
2451
+ driverType,
2452
+ getConnection: () => connectionOptions ? getConnection(connectionOptions) : getConnection()
2453
+ });
2454
+ };
2455
+ var createConnectionPool = (pool) => {
2456
+ const { driverType, getConnection } = pool;
2457
+ const connection = "connection" in pool ? pool.connection : () => Promise.resolve(getConnection());
2458
+ const withConnection = "withConnection" in pool ? pool.withConnection : (handle, _options) => executeInNewConnection(handle, {
2459
+ connection
2460
+ });
2461
+ const close = "close" in pool ? pool.close : () => Promise.resolve();
2462
+ const execute = "execute" in pool ? pool.execute : sqlExecutorInNewConnection({
2463
+ driverType,
2464
+ connection
2465
+ });
2466
+ const transaction = "transaction" in pool && "withTransaction" in pool ? {
2467
+ transaction: pool.transaction,
2468
+ withTransaction: pool.withTransaction
2469
+ } : transactionFactoryWithNewConnection(getConnection);
2470
+ const result = {
2471
+ driverType,
2472
+ connection,
2473
+ withConnection,
2474
+ close,
2475
+ execute,
2476
+ ...transaction
2477
+ };
2478
+ return result;
2479
+ };
2480
+
2481
+ // src/core/index.ts
2482
+ SQL.columnN = Object.assign(dumboSchema.column, {
2483
+ type: SQLColumnTypeTokensFactory
2484
+ });
1716
2485
 
1717
2486
  // src/core/schema/migrators/migrator.ts
1718
2487
  var MIGRATIONS_LOCK_ID = 999956789;
@@ -1748,7 +2517,9 @@ var runSQLMigrations = (pool, migrations, partialOptions) => pool.withTransactio
1748
2517
  ...partialOptions?.lock?.options
1749
2518
  }
1750
2519
  },
1751
- dryRun: defaultOptions.dryRun ?? partialOptions?.dryRun
2520
+ dryRun: defaultOptions.dryRun ?? partialOptions?.dryRun,
2521
+ ignoreMigrationHashMismatch: defaultOptions.ignoreMigrationHashMismatch ?? partialOptions?.ignoreMigrationHashMismatch,
2522
+ migrationTimeoutMs: defaultOptions.migrationTimeoutMs ?? partialOptions?.migrationTimeoutMs
1752
2523
  };
1753
2524
  const { databaseLock: _, ...rest } = options.lock ?? {};
1754
2525
  const databaseLock = options.lock?.databaseLock ?? NoDatabaseLock;
@@ -1758,21 +2529,37 @@ var runSQLMigrations = (pool, migrations, partialOptions) => pool.withTransactio
1758
2529
  };
1759
2530
  const migrationTable = options.schema?.migrationTable ?? migrationTableSchemaComponent;
1760
2531
  const coreMigrations = migrationTable.migrations;
2532
+ const result = { applied: [], skipped: [] };
1761
2533
  await databaseLock.withAcquire(
1762
2534
  execute,
1763
2535
  async () => {
1764
2536
  for (const migration of coreMigrations) {
1765
- await execute.batchCommand(migration.sqls);
2537
+ await execute.batchCommand(migration.sqls, {
2538
+ timeoutMs: options.migrationTimeoutMs
2539
+ });
1766
2540
  }
1767
2541
  for (const migration of migrations) {
1768
- await runSQLMigration(databaseType, execute, migration);
2542
+ const wasApplied = await runSQLMigration(
2543
+ databaseType,
2544
+ execute,
2545
+ migration,
2546
+ {
2547
+ ignoreMigrationHashMismatch: options.ignoreMigrationHashMismatch ?? false,
2548
+ migrationTimeoutMs: options.migrationTimeoutMs
2549
+ }
2550
+ );
2551
+ if (wasApplied) {
2552
+ result.applied.push(migration);
2553
+ } else {
2554
+ result.skipped.push(migration);
2555
+ }
1769
2556
  }
1770
2557
  },
1771
2558
  lockOptions
1772
2559
  );
1773
- return { success: options.dryRun ? false : true, result: void 0 };
2560
+ return { success: options.dryRun ? false : true, result };
1774
2561
  });
1775
- var runSQLMigration = async (databaseType, execute, migration) => {
2562
+ var runSQLMigration = async (databaseType, execute, migration, options) => {
1776
2563
  const sqls = combineMigrations(migration);
1777
2564
  const sqlHash = await getMigrationHash(migration, getFormatter(databaseType));
1778
2565
  try {
@@ -1780,13 +2567,34 @@ var runSQLMigration = async (databaseType, execute, migration) => {
1780
2567
  name: migration.name,
1781
2568
  sqlHash
1782
2569
  };
1783
- const wasMigrationApplied = await ensureMigrationWasNotAppliedYet(
2570
+ const checkResult = await ensureMigrationWasNotAppliedYet(
1784
2571
  execute,
1785
2572
  newMigration
1786
2573
  );
1787
- if (wasMigrationApplied) return;
1788
- await execute.batchCommand(sqls);
2574
+ if (checkResult.exists === true) {
2575
+ if (checkResult.hashesMatch === true) {
2576
+ tracer.info("migration-already-applied", {
2577
+ migrationName: migration.name
2578
+ });
2579
+ return false;
2580
+ }
2581
+ if (options?.ignoreMigrationHashMismatch !== true)
2582
+ throw new Error(
2583
+ `Migration hash mismatch for "${migration.name}". Aborting migration.`
2584
+ );
2585
+ tracer.warn("migration-hash-mismatch", {
2586
+ migrationName: migration.name,
2587
+ expectedHash: sqlHash,
2588
+ actualHash: checkResult.hashFromDB
2589
+ });
2590
+ await updateMigrationHash(execute, newMigration);
2591
+ return false;
2592
+ }
2593
+ await execute.batchCommand(sqls, {
2594
+ timeoutMs: options?.migrationTimeoutMs
2595
+ });
1789
2596
  await recordMigration(execute, newMigration);
2597
+ return true;
1790
2598
  } catch (error) {
1791
2599
  tracer.error("migration-error", {
1792
2600
  migationName: migration.name,
@@ -1796,7 +2604,9 @@ var runSQLMigration = async (databaseType, execute, migration) => {
1796
2604
  }
1797
2605
  };
1798
2606
  var getMigrationHash = async (sqlMigration2, sqlFormatter) => {
1799
- const content = sqlFormatter.describe(sqlMigration2.sqls);
2607
+ const content = sqlFormatter.describe(sqlMigration2.sqls, {
2608
+ serializer: JSONSerializer
2609
+ });
1800
2610
  const encoder = new TextEncoder();
1801
2611
  const data = encoder.encode(content);
1802
2612
  const hashBuffer = await crypto.subtle.digest("SHA-256", data);
@@ -1807,76 +2617,95 @@ var combineMigrations = (...migration) => migration.flatMap((m) => m.sqls);
1807
2617
  var ensureMigrationWasNotAppliedYet = async (execute, migration) => {
1808
2618
  const result = await singleOrNull(
1809
2619
  execute.query(
1810
- SQL`SELECT sql_hash FROM migrations WHERE name = ${migration.name}`
2620
+ SQL`SELECT sql_hash as "sqlHash" FROM dmb_migrations WHERE name = ${migration.name}`
1811
2621
  )
1812
2622
  );
1813
- if (result === null) return false;
1814
- const { sqlHash } = mapToCamelCase(result);
1815
- if (sqlHash !== migration.sqlHash) {
1816
- throw new Error(
1817
- `Migration hash mismatch for "${migration.name}". Aborting migration.`
1818
- );
1819
- }
1820
- return true;
2623
+ if (result === null) return { exists: false };
2624
+ const { sqlHash } = result;
2625
+ return {
2626
+ exists: true,
2627
+ hashesMatch: sqlHash === migration.sqlHash,
2628
+ hashFromDB: sqlHash
2629
+ };
1821
2630
  };
1822
2631
  var recordMigration = async (execute, migration) => {
1823
2632
  await execute.command(
1824
2633
  SQL`
1825
- INSERT INTO migrations (name, sql_hash)
2634
+ INSERT INTO dmb_migrations (name, sql_hash)
1826
2635
  VALUES (${migration.name}, ${migration.sqlHash})`
1827
2636
  );
1828
2637
  };
1829
-
1830
- // src/core/index.ts
1831
- SQL.columnN = Object.assign(dumboSchema.column, {
1832
- type: SQLColumnTypeTokensFactory
1833
- });
1834
-
1835
- // src/core/drivers/databaseDriver.ts
1836
- var canHandleDriverWithConnectionString = (driver, tryParseConnectionString) => (options) => {
1837
- if ("driverType" in options) return options.driverType === driver;
1838
- if ("connectionString" in options && typeof options.connectionString === "string")
1839
- return tryParseConnectionString(options.connectionString) !== null;
1840
- return false;
2638
+ var updateMigrationHash = async (execute, migration) => {
2639
+ await execute.command(
2640
+ SQL`
2641
+ UPDATE dmb_migrations
2642
+ SET sql_hash = ${migration.sqlHash}, timestamp = ${/* @__PURE__ */ new Date()}
2643
+ WHERE name = ${migration.name}
2644
+ `
2645
+ );
1841
2646
  };
1842
- var DumboDatabaseDriverRegistry = () => {
1843
- const drivers = /* @__PURE__ */ new Map();
1844
- const register = (driverType, plugin) => {
1845
- const entry = drivers.get(driverType);
1846
- if (entry && (typeof entry !== "function" || typeof plugin === "function")) {
1847
- return;
1848
- }
1849
- drivers.set(driverType, plugin);
1850
- };
1851
- const getDriver = (options) => options.driverType ? drivers.get(options.driverType) : [...drivers.values()].find(
1852
- (d) => typeof d !== "function" && d.canHandle(options)
2647
+
2648
+ // src/core/schema/migrators/schemaComponentMigrator.ts
2649
+ var { AutoIncrement, Varchar, Timestamp } = SQL.column.type;
2650
+ var migrationTableSQL = SQL`
2651
+ CREATE TABLE IF NOT EXISTS dmb_migrations (
2652
+ id ${AutoIncrement({ primaryKey: true })},
2653
+ name ${Varchar(255)} NOT NULL UNIQUE,
2654
+ application ${Varchar(255)} NOT NULL DEFAULT 'default',
2655
+ sql_hash ${Varchar(64)} NOT NULL,
2656
+ timestamp ${Timestamp} NOT NULL DEFAULT CURRENT_TIMESTAMP
1853
2657
  );
1854
- const tryResolve = async (options) => {
1855
- const driver = getDriver(options);
1856
- if (!driver) return null;
1857
- if (typeof driver !== "function") return driver;
1858
- const plugin = await driver();
1859
- register(plugin.driverType, plugin);
1860
- return plugin;
1861
- };
1862
- const tryGet = (options) => {
1863
- const driver = getDriver(options);
1864
- return driver && typeof driver !== "function" ? driver : null;
1865
- };
1866
- const has = (driverType) => drivers.has(driverType);
2658
+ `;
2659
+ var migrationTableSchemaComponent = schemaComponent(
2660
+ "dumbo:schema-component:migrations-table",
2661
+ {
2662
+ migrations: [sqlMigration("dumbo:migrationTable:001", [migrationTableSQL])]
2663
+ }
2664
+ );
2665
+ var SchemaComponentMigrator = (component, dumbo) => {
2666
+ const completedMigrations = [];
1867
2667
  return {
1868
- register,
1869
- tryResolve,
1870
- tryGet,
1871
- has,
1872
- get databaseDriverTypes() {
1873
- return Array.from(drivers.keys());
2668
+ component,
2669
+ run: async (options) => {
2670
+ const pendingMigrations = component.migrations.filter(
2671
+ (m) => !completedMigrations.includes(
2672
+ `${component.schemaComponentKey}:${m.name}`
2673
+ )
2674
+ );
2675
+ if (pendingMigrations.length === 0) return;
2676
+ await runSQLMigrations(dumbo, pendingMigrations, options);
2677
+ completedMigrations.push(
2678
+ ...pendingMigrations.map(
2679
+ (m) => `${component.schemaComponentKey}:${m.name}`
2680
+ )
2681
+ );
1874
2682
  }
1875
2683
  };
1876
2684
  };
1877
- var dumboDatabaseDriverRegistry = globalThis.dumboDatabaseDriverRegistry = globalThis.dumboDatabaseDriverRegistry ?? DumboDatabaseDriverRegistry();
1878
2685
 
1879
2686
  export {
2687
+ schemaComponent,
2688
+ isSchemaComponentOfType,
2689
+ filterSchemaComponentsOfType,
2690
+ mapSchemaComponentsOfType,
2691
+ findSchemaComponentsOfType,
2692
+ ColumnURNType,
2693
+ ColumnURN,
2694
+ columnSchemaComponent,
2695
+ IndexURNType,
2696
+ IndexURN,
2697
+ indexSchemaComponent,
2698
+ TableURNType,
2699
+ TableURN,
2700
+ tableSchemaComponent,
2701
+ DatabaseSchemaURNType,
2702
+ DatabaseSchemaURN,
2703
+ databaseSchemaSchemaComponent,
2704
+ DatabaseURNType,
2705
+ DatabaseURN,
2706
+ databaseSchemaComponent,
2707
+ relationship,
2708
+ schemaComponentURN,
1880
2709
  canHandleDriverWithConnectionString,
1881
2710
  DumboDatabaseDriverRegistry,
1882
2711
  dumboDatabaseDriverRegistry,
@@ -1884,6 +2713,24 @@ export {
1884
2713
  fromDatabaseDriverType,
1885
2714
  getDatabaseDriverName,
1886
2715
  getDatabaseType,
2716
+ DumboDatabaseMetadataRegistry,
2717
+ dumboDatabaseMetadataRegistry,
2718
+ getDatabaseMetadata,
2719
+ resolveDatabaseMetadata,
2720
+ getDefaultDatabase,
2721
+ getDefaultDatabaseAsync,
2722
+ dumboSchema,
2723
+ defaultDatabaseLockOptions,
2724
+ NoDatabaseLock,
2725
+ mapRows,
2726
+ toCamelCase,
2727
+ mapToCamelCase,
2728
+ firstOrNull,
2729
+ first,
2730
+ singleOrNull,
2731
+ single,
2732
+ count,
2733
+ exists,
1887
2734
  composeJSONReplacers,
1888
2735
  composeJSONRevivers,
1889
2736
  JSONReplacer,
@@ -1892,7 +2739,7 @@ export {
1892
2739
  JSONRevivers,
1893
2740
  jsonSerializer,
1894
2741
  JSONSerializer,
1895
- RawJSONSerializer,
2742
+ JSONCodec,
1896
2743
  ParametrizedSQLBuilder,
1897
2744
  SQLToken,
1898
2745
  SQLIdentifier,
@@ -1924,6 +2771,7 @@ export {
1924
2771
  TokenizedSQL,
1925
2772
  isTokenizedSQL,
1926
2773
  SQL,
2774
+ RawSQL,
1927
2775
  isSQL,
1928
2776
  ansiSqlReservedMap,
1929
2777
  ANSISQLParamPlaceholder,
@@ -1933,14 +2781,48 @@ export {
1933
2781
  DefaultMapSQLParamValueOptions,
1934
2782
  SQLValueMapper,
1935
2783
  mapSQLParamValue,
1936
- SQLFormatter2 as SQLFormatter,
2784
+ SQLFormatter,
1937
2785
  registerFormatter,
1938
2786
  getFormatter,
1939
2787
  formatSQL,
1940
2788
  describeSQL,
2789
+ color,
2790
+ prettyJson,
2791
+ tracer,
2792
+ LogLevel,
2793
+ LogStyle,
2794
+ sqlMigration,
2795
+ migrationTableSchemaComponent,
2796
+ SchemaComponentMigrator,
2797
+ MIGRATIONS_LOCK_ID,
2798
+ registerDefaultMigratorOptions,
2799
+ getDefaultMigratorOptionsFromRegistry,
2800
+ runSQLMigrations,
2801
+ combineMigrations,
2802
+ DumboError,
2803
+ ConcurrencyError,
2804
+ TransientDatabaseError,
2805
+ ConnectionError,
2806
+ SerializationError,
2807
+ DeadlockError,
2808
+ LockNotAvailableError,
2809
+ InsufficientResourcesError,
2810
+ SystemError,
2811
+ AdminShutdownError,
2812
+ QueryCanceledError,
2813
+ IntegrityConstraintViolationError,
2814
+ UniqueConstraintError,
2815
+ ForeignKeyViolationError,
2816
+ NotNullViolationError,
2817
+ CheckViolationError,
2818
+ ExclusionViolationError,
2819
+ DataError,
2820
+ InvalidOperationError,
1941
2821
  mapColumnToJSON,
1942
2822
  mapColumnToBigint,
2823
+ mapColumnToDate,
1943
2824
  mapSQLQueryResult,
2825
+ BatchCommandNoChangesError,
1944
2826
  sqlExecutor,
1945
2827
  sqlExecutorInNewConnection,
1946
2828
  sqlExecutorInAmbientConnection,
@@ -1951,61 +2833,17 @@ export {
1951
2833
  transactionFactoryWithDbClient,
1952
2834
  transactionFactoryWithNewConnection,
1953
2835
  transactionFactoryWithAmbientConnection,
2836
+ transactionFactoryWithAsyncAmbientConnection,
1954
2837
  createAmbientConnection,
1955
2838
  createSingletonConnection,
1956
2839
  createTransientConnection,
1957
2840
  createConnection,
2841
+ TaskProcessor,
1958
2842
  createAmbientConnectionPool,
1959
2843
  createSingletonConnectionPool,
1960
- createSingletonClientPool,
2844
+ createBoundedConnectionPool,
2845
+ createSingletonClientConnectionPool,
1961
2846
  createAlwaysNewConnectionPool,
1962
- createConnectionPool,
1963
- sqlMigration,
1964
- schemaComponent,
1965
- isSchemaComponentOfType,
1966
- filterSchemaComponentsOfType,
1967
- mapSchemaComponentsOfType,
1968
- findSchemaComponentsOfType,
1969
- ColumnURNType,
1970
- ColumnURN,
1971
- columnSchemaComponent,
1972
- IndexURNType,
1973
- IndexURN,
1974
- indexSchemaComponent,
1975
- TableURNType,
1976
- TableURN,
1977
- tableSchemaComponent,
1978
- DatabaseSchemaURNType,
1979
- DatabaseSchemaURN,
1980
- databaseSchemaSchemaComponent,
1981
- DatabaseURNType,
1982
- DatabaseURN,
1983
- databaseSchemaComponent,
1984
- relationship,
1985
- schemaComponentURN,
1986
- dumboSchema,
1987
- defaultDatabaseLockOptions,
1988
- NoDatabaseLock,
1989
- mapRows,
1990
- toCamelCase,
1991
- mapToCamelCase,
1992
- firstOrNull,
1993
- first,
1994
- singleOrNull,
1995
- single,
1996
- count,
1997
- exists,
1998
- color,
1999
- prettyJson,
2000
- tracer,
2001
- LogLevel,
2002
- LogStyle,
2003
- migrationTableSchemaComponent,
2004
- SchemaComponentMigrator,
2005
- MIGRATIONS_LOCK_ID,
2006
- registerDefaultMigratorOptions,
2007
- getDefaultMigratorOptionsFromRegistry,
2008
- runSQLMigrations,
2009
- combineMigrations
2847
+ createConnectionPool
2010
2848
  };
2011
- //# sourceMappingURL=chunk-N7RWT46K.js.map
2849
+ //# sourceMappingURL=chunk-JKE6SULM.js.map