@event-driven-io/dumbo 0.13.0-beta.40 → 0.13.0-beta.42
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cloudflare.cjs +4 -3
- package/dist/cloudflare.d.cts +3 -3
- package/dist/cloudflare.d.ts +3 -3
- package/dist/cloudflare.js +4 -4
- package/dist/{core-D-smW7cm.cjs → core-BPSzA-lq.cjs} +2091 -2075
- package/dist/core-BPSzA-lq.cjs.map +1 -0
- package/dist/{core-DXCRR5A9.cjs → core-BuSVyamf.cjs} +33 -3
- package/dist/core-BuSVyamf.cjs.map +1 -0
- package/dist/{core-BchvTX3G.js → core-C3xoqqDs.js} +28 -4
- package/dist/core-C3xoqqDs.js.map +1 -0
- package/dist/{core-DlV8ua1P.js → core-CHw8vO17.js} +9 -4
- package/dist/core-CHw8vO17.js.map +1 -0
- package/dist/{core-CWZb0zOY.cjs → core-CUGYxOEQ.cjs} +14 -3
- package/dist/core-CUGYxOEQ.cjs.map +1 -0
- package/dist/{core-BG__WVn6.js → core-IV7or0Mj.js} +2086 -2070
- package/dist/core-IV7or0Mj.js.map +1 -0
- package/dist/{index-N2ly5shv.d.cts → index-BJC_v03L.d.ts} +9 -3
- package/dist/{index-BDSQvDH2.d.cts → index-CfH0u2y_.d.cts} +260 -163
- package/dist/{index-BgFHGsuP.d.ts → index-DP9b7v4e.d.cts} +9 -3
- package/dist/{index-zkszkJqP.d.ts → index-QWEAqtHF.d.ts} +260 -163
- package/dist/{index-BdWFmDhJ.d.cts → index-qxECrBHo.d.ts} +10 -3
- package/dist/{index-cxtbLiju.d.ts → index-tS9lpLPz.d.cts} +10 -3
- package/dist/index.cjs +24 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -3
- package/dist/index.d.ts +2 -3
- package/dist/index.js +24 -13
- package/dist/index.js.map +1 -1
- package/dist/pg.cjs +4 -3
- package/dist/pg.d.cts +3 -3
- package/dist/pg.d.ts +3 -3
- package/dist/pg.js +4 -4
- package/dist/{postgreSQLMetadata-WGXySO7a.cjs → postgreSQLMetadata-CCsCJ-eH.cjs} +2 -2
- package/dist/{postgreSQLMetadata-WGXySO7a.cjs.map → postgreSQLMetadata-CCsCJ-eH.cjs.map} +1 -1
- package/dist/{postgreSQLMetadata-BTz6vdwE.js → postgreSQLMetadata-bCBDGz1f.js} +2 -2
- package/dist/{postgreSQLMetadata-BTz6vdwE.js.map → postgreSQLMetadata-bCBDGz1f.js.map} +1 -1
- package/dist/postgresql.cjs +3 -2
- package/dist/postgresql.d.cts +3 -3
- package/dist/postgresql.d.ts +3 -3
- package/dist/postgresql.js +3 -3
- package/dist/sqlite.cjs +3 -2
- package/dist/sqlite.d.cts +3 -3
- package/dist/sqlite.d.ts +3 -3
- package/dist/sqlite.js +3 -3
- package/dist/sqlite3.cjs +4 -3
- package/dist/sqlite3.d.cts +3 -3
- package/dist/sqlite3.d.ts +3 -3
- package/dist/sqlite3.js +4 -4
- package/dist/{sqliteMetadata-PJTRPIZ1.cjs → sqliteMetadata-Cc7Z03lm.cjs} +2 -2
- package/dist/{sqliteMetadata-PJTRPIZ1.cjs.map → sqliteMetadata-Cc7Z03lm.cjs.map} +1 -1
- package/dist/{sqliteMetadata-7qBjsMBN.js → sqliteMetadata-CvvEc1-v.js} +2 -2
- package/dist/{sqliteMetadata-7qBjsMBN.js.map → sqliteMetadata-CvvEc1-v.js.map} +1 -1
- package/package.json +1 -1
- package/dist/core-BG__WVn6.js.map +0 -1
- package/dist/core-BchvTX3G.js.map +0 -1
- package/dist/core-CWZb0zOY.cjs.map +0 -1
- package/dist/core-D-smW7cm.cjs.map +0 -1
- package/dist/core-DXCRR5A9.cjs.map +0 -1
- package/dist/core-DlV8ua1P.js.map +0 -1
- package/dist/index-DaP2fTEX.d.ts +0 -67
- package/dist/index-S_wp0Eaf.d.cts +0 -67
|
@@ -1,2262 +1,2278 @@
|
|
|
1
|
-
import ansis from "ansis";
|
|
2
1
|
import { v7 } from "uuid";
|
|
2
|
+
import ansis from "ansis";
|
|
3
3
|
|
|
4
|
-
//#region src/core/
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
4
|
+
//#region src/core/errors/index.ts
|
|
5
|
+
const isNumber = (val) => typeof val === "number" && val === val;
|
|
6
|
+
const isString = (val) => typeof val === "string";
|
|
7
|
+
var DumboError = class DumboError extends Error {
|
|
8
|
+
static ErrorCode = 500;
|
|
9
|
+
static ErrorType = "DumboError";
|
|
10
|
+
errorCode;
|
|
11
|
+
errorType;
|
|
12
|
+
innerError;
|
|
13
|
+
constructor(options) {
|
|
14
|
+
const errorCode = options && typeof options === "object" && "errorCode" in options ? options.errorCode : isNumber(options) ? options : DumboError.ErrorCode;
|
|
15
|
+
const errorType = options && typeof options === "object" && "errorType" in options ? options.errorType ?? DumboError.ErrorType : DumboError.ErrorType;
|
|
16
|
+
const message = options && typeof options === "object" && "message" in options ? options.message : isString(options) ? options : `Error with status code '${errorCode}' ocurred during DumboError processing`;
|
|
17
|
+
const innerError = options && typeof options === "object" && "innerError" in options ? options.innerError : void 0;
|
|
18
|
+
super(message, { cause: innerError });
|
|
19
|
+
this.errorCode = errorCode;
|
|
20
|
+
this.errorType = errorType;
|
|
21
|
+
this.innerError = innerError;
|
|
22
|
+
Object.setPrototypeOf(this, DumboError.prototype);
|
|
23
|
+
}
|
|
24
|
+
static isInstanceOf(error, options) {
|
|
25
|
+
if (typeof error !== "object" || error === null || !("errorCode" in error) || !isNumber(error.errorCode) || !("errorType" in error) || !isString(error.errorType)) return false;
|
|
26
|
+
if (!options) return true;
|
|
27
|
+
if (options.errorCode !== void 0 && error.errorCode !== options.errorCode) return false;
|
|
28
|
+
if (options.errorType !== void 0 && error.errorType !== options.errorType) return false;
|
|
29
|
+
return true;
|
|
30
|
+
}
|
|
23
31
|
};
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
var ConcurrencyError = class ConcurrencyError extends DumboError {
|
|
33
|
+
static ErrorCode = 412;
|
|
34
|
+
static ErrorType = "ConcurrencyError";
|
|
35
|
+
constructor(message, innerError) {
|
|
36
|
+
super({
|
|
37
|
+
errorCode: ConcurrencyError.ErrorCode,
|
|
38
|
+
errorType: ConcurrencyError.ErrorType,
|
|
39
|
+
message: message ?? `Expected document state does not match current one!`,
|
|
40
|
+
innerError
|
|
41
|
+
});
|
|
42
|
+
Object.setPrototypeOf(this, ConcurrencyError.prototype);
|
|
43
|
+
}
|
|
35
44
|
};
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
primaryKey,
|
|
49
|
-
defaultValue,
|
|
50
|
-
sqlTokenType: "SQL_COLUMN",
|
|
51
|
-
name: columnName,
|
|
52
|
-
type
|
|
53
|
-
};
|
|
45
|
+
var TransientDatabaseError = class TransientDatabaseError extends DumboError {
|
|
46
|
+
static ErrorCode = 503;
|
|
47
|
+
static ErrorType = "TransientDatabaseError";
|
|
48
|
+
constructor(message, innerError) {
|
|
49
|
+
super({
|
|
50
|
+
errorCode: TransientDatabaseError.ErrorCode,
|
|
51
|
+
errorType: TransientDatabaseError.ErrorType,
|
|
52
|
+
message: message ?? `A transient error occurred during database operation. Retrying the operation might succeed.`,
|
|
53
|
+
innerError
|
|
54
|
+
});
|
|
55
|
+
Object.setPrototypeOf(this, TransientDatabaseError.prototype);
|
|
56
|
+
}
|
|
54
57
|
};
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
migrations: migrationsOrComponents.migrations ?? [],
|
|
64
|
-
components: [...migrationsOrComponents.components ?? []]
|
|
65
|
-
}),
|
|
66
|
-
indexName,
|
|
67
|
-
get columnNames() {
|
|
68
|
-
return columnNames;
|
|
69
|
-
},
|
|
70
|
-
addColumn: (column) => columnNames.push(typeof column === "string" ? column : column.columnName),
|
|
71
|
-
isUnique
|
|
72
|
-
};
|
|
58
|
+
var ConnectionError = class ConnectionError extends TransientDatabaseError {
|
|
59
|
+
static ErrorCode = 503;
|
|
60
|
+
static ErrorType = "ConnectionError";
|
|
61
|
+
constructor(message, innerError) {
|
|
62
|
+
super(message ?? `A connection error occurred during database operation.`, innerError);
|
|
63
|
+
this.errorType = ConnectionError.ErrorType;
|
|
64
|
+
Object.setPrototypeOf(this, ConnectionError.prototype);
|
|
65
|
+
}
|
|
73
66
|
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const base = schemaComponent(TableURN({ name: tableName }), {
|
|
83
|
-
migrations: migrationsOrComponents.migrations ?? [],
|
|
84
|
-
components: [...migrationsOrComponents.components ?? [], ...Object.values(columns)]
|
|
85
|
-
});
|
|
86
|
-
return {
|
|
87
|
-
...base,
|
|
88
|
-
tableName,
|
|
89
|
-
primaryKey: primaryKey ?? [],
|
|
90
|
-
relationships,
|
|
91
|
-
get columns() {
|
|
92
|
-
const columnsMap = mapSchemaComponentsOfType(base.components, ColumnURNType, (c) => c.columnName);
|
|
93
|
-
return Object.assign(columnsMap, columns);
|
|
94
|
-
},
|
|
95
|
-
get indexes() {
|
|
96
|
-
return mapSchemaComponentsOfType(base.components, IndexURNType, (c) => c.indexName);
|
|
97
|
-
},
|
|
98
|
-
addColumn: (column) => base.addComponent(column),
|
|
99
|
-
addIndex: (index) => base.addComponent(index)
|
|
100
|
-
};
|
|
67
|
+
var SerializationError = class SerializationError extends TransientDatabaseError {
|
|
68
|
+
static ErrorCode = 503;
|
|
69
|
+
static ErrorType = "SerializationError";
|
|
70
|
+
constructor(message, innerError) {
|
|
71
|
+
super(message ?? `A serialization failure occurred. The transaction can be retried.`, innerError);
|
|
72
|
+
this.errorType = SerializationError.ErrorType;
|
|
73
|
+
Object.setPrototypeOf(this, SerializationError.prototype);
|
|
74
|
+
}
|
|
101
75
|
};
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
components: [...migrationsOrComponents.components ?? [], ...Object.values(tables ?? {})]
|
|
111
|
-
});
|
|
112
|
-
return {
|
|
113
|
-
...base,
|
|
114
|
-
schemaName,
|
|
115
|
-
get tables() {
|
|
116
|
-
const tablesMap = mapSchemaComponentsOfType(base.components, TableURNType, (c) => c.tableName);
|
|
117
|
-
return Object.assign(tablesMap, tables);
|
|
118
|
-
},
|
|
119
|
-
addTable: (table) => base.addComponent(typeof table === "string" ? tableSchemaComponent({ tableName: table }) : table)
|
|
120
|
-
};
|
|
76
|
+
var DeadlockError = class DeadlockError extends TransientDatabaseError {
|
|
77
|
+
static ErrorCode = 503;
|
|
78
|
+
static ErrorType = "DeadlockError";
|
|
79
|
+
constructor(message, innerError) {
|
|
80
|
+
super(message ?? `A deadlock was detected. The transaction can be retried.`, innerError);
|
|
81
|
+
this.errorType = DeadlockError.ErrorType;
|
|
82
|
+
Object.setPrototypeOf(this, DeadlockError.prototype);
|
|
83
|
+
}
|
|
121
84
|
};
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
migrations: migrationsOrComponents.migrations ?? [],
|
|
131
|
-
components: [...migrationsOrComponents.components ?? [], ...Object.values(schemas)]
|
|
132
|
-
});
|
|
133
|
-
return {
|
|
134
|
-
...base,
|
|
135
|
-
databaseName,
|
|
136
|
-
get schemas() {
|
|
137
|
-
const schemasMap = mapSchemaComponentsOfType(base.components, DatabaseSchemaURNType, (c) => c.schemaName);
|
|
138
|
-
return Object.assign(schemasMap, schemas);
|
|
139
|
-
},
|
|
140
|
-
addSchema: (schema) => base.addComponent(typeof schema === "string" ? databaseSchemaSchemaComponent({ schemaName: schema }) : schema)
|
|
141
|
-
};
|
|
85
|
+
var LockNotAvailableError = class LockNotAvailableError extends TransientDatabaseError {
|
|
86
|
+
static ErrorCode = 503;
|
|
87
|
+
static ErrorType = "LockNotAvailableError";
|
|
88
|
+
constructor(message, innerError) {
|
|
89
|
+
super(message ?? `The requested lock is not available.`, innerError);
|
|
90
|
+
this.errorType = LockNotAvailableError.ErrorType;
|
|
91
|
+
Object.setPrototypeOf(this, LockNotAvailableError.prototype);
|
|
92
|
+
}
|
|
142
93
|
};
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
column: ColumnURN,
|
|
151
|
-
index: IndexURN,
|
|
152
|
-
extractName: (urn) => {
|
|
153
|
-
const parts = urn.split(":");
|
|
154
|
-
return parts[parts.length - 1] || "";
|
|
94
|
+
var InsufficientResourcesError = class InsufficientResourcesError extends TransientDatabaseError {
|
|
95
|
+
static ErrorCode = 503;
|
|
96
|
+
static ErrorType = "InsufficientResourcesError";
|
|
97
|
+
constructor(message, innerError) {
|
|
98
|
+
super(message ?? `Insufficient resources to complete the database operation (e.g. disk full, out of memory, too many connections).`, innerError);
|
|
99
|
+
this.errorType = InsufficientResourcesError.ErrorType;
|
|
100
|
+
Object.setPrototypeOf(this, InsufficientResourcesError.prototype);
|
|
155
101
|
}
|
|
156
102
|
};
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
103
|
+
var SystemError = class SystemError extends TransientDatabaseError {
|
|
104
|
+
static ErrorCode = 503;
|
|
105
|
+
static ErrorType = "SystemError";
|
|
106
|
+
constructor(message, innerError) {
|
|
107
|
+
super(message ?? `A system-level error occurred (e.g. I/O error).`, innerError);
|
|
108
|
+
this.errorType = SystemError.ErrorType;
|
|
109
|
+
Object.setPrototypeOf(this, SystemError.prototype);
|
|
110
|
+
}
|
|
164
111
|
};
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
const tryResolve = async (options) => {
|
|
174
|
-
const driver = getDriver(options);
|
|
175
|
-
if (!driver) return null;
|
|
176
|
-
if (typeof driver !== "function") return driver;
|
|
177
|
-
const plugin = await driver();
|
|
178
|
-
register(plugin.driverType, plugin);
|
|
179
|
-
return plugin;
|
|
180
|
-
};
|
|
181
|
-
const tryGet = (options) => {
|
|
182
|
-
const driver = getDriver(options);
|
|
183
|
-
return driver && typeof driver !== "function" ? driver : null;
|
|
184
|
-
};
|
|
185
|
-
const has = (driverType) => drivers.has(driverType);
|
|
186
|
-
return {
|
|
187
|
-
register,
|
|
188
|
-
tryResolve,
|
|
189
|
-
tryGet,
|
|
190
|
-
has,
|
|
191
|
-
get databaseDriverTypes() {
|
|
192
|
-
return Array.from(drivers.keys());
|
|
193
|
-
}
|
|
194
|
-
};
|
|
195
|
-
};
|
|
196
|
-
const dumboDatabaseDriverRegistry = globalThis.dumboDatabaseDriverRegistry = globalThis.dumboDatabaseDriverRegistry ?? DumboDatabaseDriverRegistry();
|
|
197
|
-
|
|
198
|
-
//#endregion
|
|
199
|
-
//#region src/core/drivers/index.ts
|
|
200
|
-
/**
|
|
201
|
-
* Accepts a `databaseType` (e.g. PostgreSQL, SQLite) and a `driverName`
|
|
202
|
-
* (the library name, e.g. pg, sqlite3) and combines them to a singular
|
|
203
|
-
* `databaseDriverType` which can be used in database handling.
|
|
204
|
-
*/
|
|
205
|
-
function toDatabaseDriverType(databaseType, driverName) {
|
|
206
|
-
return `${databaseType}:${driverName}`;
|
|
207
|
-
}
|
|
208
|
-
/**
|
|
209
|
-
* Accepts a fully formatted `driverType` and returns the broken down
|
|
210
|
-
* `databaseType` and `driverName`.
|
|
211
|
-
*/
|
|
212
|
-
function fromDatabaseDriverType(databaseDriverType) {
|
|
213
|
-
const parts = databaseDriverType.split(":");
|
|
214
|
-
return {
|
|
215
|
-
databaseType: parts[0],
|
|
216
|
-
driverName: parts[1]
|
|
217
|
-
};
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* Accepts a fully formatted `databaseDriverType` and returns the `driverName`.
|
|
221
|
-
*/
|
|
222
|
-
function getDatabaseDriverName(databaseDriverType) {
|
|
223
|
-
const { driverName } = fromDatabaseDriverType(databaseDriverType);
|
|
224
|
-
return driverName;
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Accepts a fully formatted `databaseDriverType` and returns the `databaseType`.
|
|
228
|
-
*/
|
|
229
|
-
function getDatabaseType(databaseDriverType) {
|
|
230
|
-
const { databaseType } = fromDatabaseDriverType(databaseDriverType);
|
|
231
|
-
return databaseType;
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
//#endregion
|
|
235
|
-
//#region src/core/schema/databaseMetadata/databaseMetadata.ts
|
|
236
|
-
const DumboDatabaseMetadataRegistry = () => {
|
|
237
|
-
const infos = /* @__PURE__ */ new Map();
|
|
238
|
-
const register = (databaseType, info) => {
|
|
239
|
-
const entry = infos.get(databaseType);
|
|
240
|
-
if (entry && (typeof entry !== "function" || typeof info === "function")) return;
|
|
241
|
-
infos.set(databaseType, info);
|
|
242
|
-
};
|
|
243
|
-
const tryResolve = async (databaseType) => {
|
|
244
|
-
const entry = infos.get(databaseType);
|
|
245
|
-
if (!entry) return null;
|
|
246
|
-
if (typeof entry !== "function") return entry;
|
|
247
|
-
const resolved = await entry();
|
|
248
|
-
register(databaseType, resolved);
|
|
249
|
-
return resolved;
|
|
250
|
-
};
|
|
251
|
-
const tryGet = (databaseType) => {
|
|
252
|
-
const entry = infos.get(databaseType);
|
|
253
|
-
return entry && typeof entry !== "function" ? entry : null;
|
|
254
|
-
};
|
|
255
|
-
const has = (databaseType) => infos.has(databaseType);
|
|
256
|
-
return {
|
|
257
|
-
register,
|
|
258
|
-
tryResolve,
|
|
259
|
-
tryGet,
|
|
260
|
-
has,
|
|
261
|
-
get databaseTypes() {
|
|
262
|
-
return Array.from(infos.keys());
|
|
263
|
-
}
|
|
264
|
-
};
|
|
112
|
+
var AdminShutdownError = class AdminShutdownError extends TransientDatabaseError {
|
|
113
|
+
static ErrorCode = 503;
|
|
114
|
+
static ErrorType = "AdminShutdownError";
|
|
115
|
+
constructor(message, innerError) {
|
|
116
|
+
super(message ?? `The database server is shutting down or restarting.`, innerError);
|
|
117
|
+
this.errorType = AdminShutdownError.ErrorType;
|
|
118
|
+
Object.setPrototypeOf(this, AdminShutdownError.prototype);
|
|
119
|
+
}
|
|
265
120
|
};
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
121
|
+
var QueryCanceledError = class QueryCanceledError extends TransientDatabaseError {
|
|
122
|
+
static ErrorCode = 503;
|
|
123
|
+
static ErrorType = "QueryCanceledError";
|
|
124
|
+
constructor(message, innerError) {
|
|
125
|
+
super(message ?? `The query was canceled, e.g. due to statement timeout or user request.`, innerError);
|
|
126
|
+
this.errorType = QueryCanceledError.ErrorType;
|
|
127
|
+
Object.setPrototypeOf(this, QueryCanceledError.prototype);
|
|
128
|
+
}
|
|
270
129
|
};
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
130
|
+
var IntegrityConstraintViolationError = class IntegrityConstraintViolationError extends DumboError {
|
|
131
|
+
static ErrorCode = 409;
|
|
132
|
+
static ErrorType = "IntegrityConstraintViolationError";
|
|
133
|
+
constructor(message, innerError) {
|
|
134
|
+
super({
|
|
135
|
+
errorCode: IntegrityConstraintViolationError.ErrorCode,
|
|
136
|
+
errorType: IntegrityConstraintViolationError.ErrorType,
|
|
137
|
+
message: message ?? `An integrity constraint violation occurred!`,
|
|
138
|
+
innerError
|
|
139
|
+
});
|
|
140
|
+
Object.setPrototypeOf(this, IntegrityConstraintViolationError.prototype);
|
|
141
|
+
}
|
|
275
142
|
};
|
|
276
|
-
|
|
277
|
-
|
|
143
|
+
var UniqueConstraintError = class UniqueConstraintError extends IntegrityConstraintViolationError {
|
|
144
|
+
static ErrorCode = 409;
|
|
145
|
+
static ErrorType = "UniqueConstraintError";
|
|
146
|
+
constructor(message, innerError) {
|
|
147
|
+
super(message ?? `Unique constraint violation occurred!`, innerError);
|
|
148
|
+
this.errorType = UniqueConstraintError.ErrorType;
|
|
149
|
+
Object.setPrototypeOf(this, UniqueConstraintError.prototype);
|
|
150
|
+
}
|
|
278
151
|
};
|
|
279
|
-
|
|
280
|
-
|
|
152
|
+
var ForeignKeyViolationError = class ForeignKeyViolationError extends IntegrityConstraintViolationError {
|
|
153
|
+
static ErrorCode = 409;
|
|
154
|
+
static ErrorType = "ForeignKeyViolationError";
|
|
155
|
+
constructor(message, innerError) {
|
|
156
|
+
super(message ?? `Foreign key constraint violation occurred!`, innerError);
|
|
157
|
+
this.errorType = ForeignKeyViolationError.ErrorType;
|
|
158
|
+
Object.setPrototypeOf(this, ForeignKeyViolationError.prototype);
|
|
159
|
+
}
|
|
281
160
|
};
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
...options
|
|
291
|
-
});
|
|
292
|
-
const dumboIndex = (name, columnNames, options) => indexSchemaComponent({
|
|
293
|
-
indexName: name,
|
|
294
|
-
columnNames,
|
|
295
|
-
isUnique: options?.unique ?? false,
|
|
296
|
-
...options
|
|
297
|
-
});
|
|
298
|
-
const dumboTable = (name, definition) => {
|
|
299
|
-
const { columns, indexes, primaryKey, relationships, ...options } = definition;
|
|
300
|
-
const components = [...indexes ? Object.values(indexes) : []];
|
|
301
|
-
return tableSchemaComponent({
|
|
302
|
-
tableName: name,
|
|
303
|
-
columns: columns ?? {},
|
|
304
|
-
primaryKey: primaryKey ?? [],
|
|
305
|
-
...relationships !== void 0 ? { relationships } : {},
|
|
306
|
-
components,
|
|
307
|
-
...options
|
|
308
|
-
});
|
|
161
|
+
var NotNullViolationError = class NotNullViolationError extends IntegrityConstraintViolationError {
|
|
162
|
+
static ErrorCode = 409;
|
|
163
|
+
static ErrorType = "NotNullViolationError";
|
|
164
|
+
constructor(message, innerError) {
|
|
165
|
+
super(message ?? `NOT NULL constraint violation occurred!`, innerError);
|
|
166
|
+
this.errorType = NotNullViolationError.ErrorType;
|
|
167
|
+
Object.setPrototypeOf(this, NotNullViolationError.prototype);
|
|
168
|
+
}
|
|
309
169
|
};
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
const tables = tableNames.reduce((acc, tableName) => {
|
|
319
|
-
acc[tableName] = dumboTable(tableName, {});
|
|
320
|
-
return acc;
|
|
321
|
-
}, {});
|
|
322
|
-
return schemaName ? dumboDatabaseSchema(schemaName, tables) : dumboDatabaseSchema(tables);
|
|
170
|
+
var CheckViolationError = class CheckViolationError extends IntegrityConstraintViolationError {
|
|
171
|
+
static ErrorCode = 409;
|
|
172
|
+
static ErrorType = "CheckViolationError";
|
|
173
|
+
constructor(message, innerError) {
|
|
174
|
+
super(message ?? `CHECK constraint violation occurred!`, innerError);
|
|
175
|
+
this.errorType = CheckViolationError.ErrorType;
|
|
176
|
+
Object.setPrototypeOf(this, CheckViolationError.prototype);
|
|
177
|
+
}
|
|
323
178
|
};
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
dumboDatabase.from = (databaseName, schemaNames) => {
|
|
334
|
-
const schemas = schemaNames.reduce((acc, schemaName) => {
|
|
335
|
-
acc[schemaName] = dumboDatabaseSchema(schemaName, {});
|
|
336
|
-
return acc;
|
|
337
|
-
}, {});
|
|
338
|
-
return databaseName ? dumboDatabase(databaseName, schemas) : dumboDatabase(schemas);
|
|
179
|
+
var ExclusionViolationError = class ExclusionViolationError extends IntegrityConstraintViolationError {
|
|
180
|
+
static ErrorCode = 409;
|
|
181
|
+
static ErrorType = "ExclusionViolationError";
|
|
182
|
+
constructor(message, innerError) {
|
|
183
|
+
super(message ?? `Exclusion constraint violation occurred!`, innerError);
|
|
184
|
+
this.errorType = ExclusionViolationError.ErrorType;
|
|
185
|
+
Object.setPrototypeOf(this, ExclusionViolationError.prototype);
|
|
186
|
+
}
|
|
339
187
|
};
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
188
|
+
var DataError = class DataError extends DumboError {
|
|
189
|
+
static ErrorCode = 400;
|
|
190
|
+
static ErrorType = "DataError";
|
|
191
|
+
constructor(message, innerError) {
|
|
192
|
+
super({
|
|
193
|
+
errorCode: DataError.ErrorCode,
|
|
194
|
+
errorType: DataError.ErrorType,
|
|
195
|
+
message: message ?? `A data error occurred (e.g. invalid value, type mismatch).`,
|
|
196
|
+
innerError
|
|
197
|
+
});
|
|
198
|
+
Object.setPrototypeOf(this, DataError.prototype);
|
|
199
|
+
}
|
|
348
200
|
};
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
201
|
+
var InvalidOperationError = class InvalidOperationError extends DumboError {
|
|
202
|
+
static ErrorCode = 400;
|
|
203
|
+
static ErrorType = "InvalidOperationError";
|
|
204
|
+
constructor(message, innerError) {
|
|
205
|
+
super({
|
|
206
|
+
errorCode: InvalidOperationError.ErrorCode,
|
|
207
|
+
errorType: InvalidOperationError.ErrorType,
|
|
208
|
+
message: message ?? `Invalid operation (e.g. syntax error, insufficient privileges, undefined table).`,
|
|
209
|
+
innerError
|
|
210
|
+
});
|
|
211
|
+
Object.setPrototypeOf(this, InvalidOperationError.prototype);
|
|
212
|
+
}
|
|
358
213
|
};
|
|
359
214
|
|
|
360
215
|
//#endregion
|
|
361
|
-
//#region src/core/
|
|
362
|
-
const
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
return
|
|
216
|
+
//#region src/core/execute/execute.ts
|
|
217
|
+
const mapColumnToJSON = (column, serializer, options) => ({ [column]: (value) => {
|
|
218
|
+
if (typeof value === "string") try {
|
|
219
|
+
return serializer.deserialize(value, options);
|
|
220
|
+
} catch {}
|
|
221
|
+
return value;
|
|
222
|
+
} });
|
|
223
|
+
const mapColumnToBigint = (column) => ({ [column]: (value) => {
|
|
224
|
+
if (typeof value === "number" || typeof value === "string") return BigInt(value);
|
|
225
|
+
return value;
|
|
226
|
+
} });
|
|
227
|
+
const mapColumnToDate = (column) => ({ [column]: (value) => {
|
|
228
|
+
if (typeof value === "number" || typeof value === "string") return new Date(value);
|
|
229
|
+
return value;
|
|
230
|
+
} });
|
|
231
|
+
const mapSQLQueryResult = (result, mapping) => {
|
|
232
|
+
if (typeof result !== "object" || result === null) return result;
|
|
233
|
+
const mappedResult = { ...result };
|
|
234
|
+
for (const column of Object.keys(mapping)) if (column in mappedResult) mappedResult[column] = mapping[column](mappedResult[column]);
|
|
235
|
+
return mappedResult;
|
|
370
236
|
};
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
237
|
+
var BatchCommandNoChangesError = class BatchCommandNoChangesError extends DumboError {
|
|
238
|
+
static ErrorCode = 409;
|
|
239
|
+
static ErrorType = "BatchCommandNoChangesError";
|
|
240
|
+
statementIndex;
|
|
241
|
+
constructor(statementIndex) {
|
|
242
|
+
super({
|
|
243
|
+
errorCode: BatchCommandNoChangesError.ErrorCode,
|
|
244
|
+
errorType: BatchCommandNoChangesError.ErrorType,
|
|
245
|
+
message: `Batch command at index ${statementIndex} affected no rows`
|
|
246
|
+
});
|
|
247
|
+
this.name = "BatchCommandNoChangesError";
|
|
248
|
+
this.statementIndex = statementIndex;
|
|
249
|
+
Object.setPrototypeOf(this, BatchCommandNoChangesError.prototype);
|
|
250
|
+
}
|
|
375
251
|
};
|
|
376
|
-
const
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
252
|
+
const sqlExecutor = (sqlExecutor, options) => ({
|
|
253
|
+
query: (sql, queryOptions) => executeInNewDbClient((client) => sqlExecutor.query(client, sql, queryOptions), options),
|
|
254
|
+
batchQuery: (sqls, queryOptions) => executeInNewDbClient((client) => sqlExecutor.batchQuery(client, sqls, queryOptions), options),
|
|
255
|
+
command: (sql, commandOptions) => executeInNewDbClient((client) => sqlExecutor.command(client, sql, commandOptions), options),
|
|
256
|
+
batchCommand: (sqls, commandOptions) => executeInNewDbClient((client) => sqlExecutor.batchCommand(client, sqls, commandOptions), options)
|
|
257
|
+
});
|
|
258
|
+
const sqlExecutorInNewConnection = (options) => ({
|
|
259
|
+
query: (sql, queryOptions) => executeInNewConnection((connection) => connection.execute.query(sql, queryOptions), options),
|
|
260
|
+
batchQuery: (sqls, queryOptions) => executeInNewConnection((connection) => connection.execute.batchQuery(sqls, queryOptions), options),
|
|
261
|
+
command: (sql, commandOptions) => executeInNewConnection((connection) => connection.execute.command(sql, commandOptions), options),
|
|
262
|
+
batchCommand: (sqls, commandOptions) => executeInNewConnection((connection) => connection.execute.batchCommand(sqls, commandOptions), options)
|
|
263
|
+
});
|
|
264
|
+
const sqlExecutorInAmbientConnection = (options) => ({
|
|
265
|
+
query: (sql, queryOptions) => executeInAmbientConnection((connection) => connection.execute.query(sql, queryOptions), options),
|
|
266
|
+
batchQuery: (sqls, queryOptions) => executeInAmbientConnection((connection) => connection.execute.batchQuery(sqls, queryOptions), options),
|
|
267
|
+
command: (sql, commandOptions) => executeInAmbientConnection((connection) => connection.execute.command(sql, commandOptions), options),
|
|
268
|
+
batchCommand: (sqls, commandOptions) => executeInAmbientConnection((connection) => connection.execute.batchCommand(sqls, commandOptions), options)
|
|
269
|
+
});
|
|
270
|
+
const executeInNewDbClient = async (handle, options) => {
|
|
271
|
+
const { connect, close } = options;
|
|
272
|
+
const client = await connect();
|
|
273
|
+
try {
|
|
274
|
+
return await handle(client);
|
|
275
|
+
} catch (error) {
|
|
276
|
+
if (close) await close(client, error);
|
|
277
|
+
throw error;
|
|
278
|
+
}
|
|
381
279
|
};
|
|
382
|
-
const
|
|
383
|
-
const
|
|
384
|
-
|
|
280
|
+
const executeInNewConnection = async (handle, options) => {
|
|
281
|
+
const connection = await options.connection();
|
|
282
|
+
try {
|
|
283
|
+
return await handle(connection);
|
|
284
|
+
} finally {
|
|
285
|
+
await connection.close();
|
|
286
|
+
}
|
|
385
287
|
};
|
|
386
|
-
const
|
|
387
|
-
const
|
|
388
|
-
|
|
288
|
+
const executeInAmbientConnection = async (handle, options) => {
|
|
289
|
+
const connection = await options.connection();
|
|
290
|
+
try {
|
|
291
|
+
return await handle(connection);
|
|
292
|
+
} finally {}
|
|
389
293
|
};
|
|
390
294
|
|
|
391
295
|
//#endregion
|
|
392
|
-
//#region src/core/
|
|
393
|
-
const
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
const dateReplacer = (_key, value) => {
|
|
397
|
-
return value instanceof Date ? value.toISOString() : value;
|
|
398
|
-
};
|
|
399
|
-
const isFirstLetterNumeric = (str) => {
|
|
400
|
-
const c = str.charCodeAt(0);
|
|
401
|
-
return c >= 48 && c <= 57;
|
|
402
|
-
};
|
|
403
|
-
const isFirstLetterNumericOrMinus = (str) => {
|
|
404
|
-
const c = str.charCodeAt(0);
|
|
405
|
-
return c >= 48 && c <= 57 || c === 45;
|
|
406
|
-
};
|
|
407
|
-
const bigIntReviver = (_key, value, context) => {
|
|
408
|
-
if (typeof value === "number" && Number.isInteger(value) && !Number.isSafeInteger(value)) try {
|
|
409
|
-
return BigInt(context?.source ?? value.toString());
|
|
410
|
-
} catch {
|
|
411
|
-
return value;
|
|
412
|
-
}
|
|
413
|
-
if (typeof value === "string" && value.length > 15) {
|
|
414
|
-
if (isFirstLetterNumericOrMinus(value)) {
|
|
415
|
-
const num = Number(value);
|
|
416
|
-
if (Number.isFinite(num) && !Number.isSafeInteger(num)) try {
|
|
417
|
-
return BigInt(value);
|
|
418
|
-
} catch {}
|
|
419
|
-
}
|
|
420
|
-
}
|
|
421
|
-
return value;
|
|
296
|
+
//#region src/core/connections/transaction.ts
|
|
297
|
+
const toTransactionResult = (transactionResult) => transactionResult !== void 0 && transactionResult !== null && typeof transactionResult === "object" && "success" in transactionResult ? transactionResult : {
|
|
298
|
+
success: true,
|
|
299
|
+
result: transactionResult
|
|
422
300
|
};
|
|
423
|
-
const
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
301
|
+
const executeInTransaction = async (transaction, handle) => {
|
|
302
|
+
await transaction.begin();
|
|
303
|
+
try {
|
|
304
|
+
const { success, result } = toTransactionResult(await handle(transaction));
|
|
305
|
+
if (success) await transaction.commit();
|
|
306
|
+
else await transaction.rollback();
|
|
307
|
+
return result;
|
|
308
|
+
} catch (e) {
|
|
309
|
+
await transaction.rollback();
|
|
310
|
+
throw e;
|
|
427
311
|
}
|
|
428
|
-
return value;
|
|
429
|
-
};
|
|
430
|
-
const composeJSONReplacers = (...replacers) => {
|
|
431
|
-
const filteredReplacers = replacers.filter((r) => r !== void 0);
|
|
432
|
-
if (filteredReplacers.length === 0) return void 0;
|
|
433
|
-
return (key, value) => filteredReplacers.reduce((accValue, replacer) => replacer(key, accValue), value);
|
|
434
|
-
};
|
|
435
|
-
const composeJSONRevivers = (...revivers) => {
|
|
436
|
-
const filteredRevivers = revivers.filter((r) => r !== void 0);
|
|
437
|
-
if (filteredRevivers.length === 0) return void 0;
|
|
438
|
-
return (key, value, context) => filteredRevivers.reduce((accValue, reviver) => reviver(key, accValue, context), value);
|
|
439
|
-
};
|
|
440
|
-
const JSONReplacer = (opts) => composeJSONReplacers(opts?.replacer, opts?.failOnBigIntSerialization !== true ? JSONReplacers.bigInt : void 0, opts?.useDefaultDateSerialization !== true ? JSONReplacers.date : void 0);
|
|
441
|
-
const JSONReviver = (opts) => composeJSONRevivers(opts?.reviver, opts?.parseBigInts === true ? JSONRevivers.bigInt : void 0, opts?.parseDates === true ? JSONRevivers.date : void 0);
|
|
442
|
-
const JSONReplacers = {
|
|
443
|
-
bigInt: bigIntReplacer,
|
|
444
|
-
date: dateReplacer
|
|
445
|
-
};
|
|
446
|
-
const JSONRevivers = {
|
|
447
|
-
bigInt: bigIntReviver,
|
|
448
|
-
date: dateReviver
|
|
449
312
|
};
|
|
450
|
-
const
|
|
451
|
-
|
|
452
|
-
const
|
|
313
|
+
const transactionFactoryWithDbClient = (connect, initTransaction) => {
|
|
314
|
+
let currentTransaction = void 0;
|
|
315
|
+
const getOrInitCurrentTransaction = (options) => currentTransaction ?? (currentTransaction = initTransaction(connect(), {
|
|
316
|
+
close: () => {
|
|
317
|
+
currentTransaction = void 0;
|
|
318
|
+
return Promise.resolve();
|
|
319
|
+
},
|
|
320
|
+
...options ?? {}
|
|
321
|
+
}));
|
|
453
322
|
return {
|
|
454
|
-
|
|
455
|
-
|
|
323
|
+
transaction: getOrInitCurrentTransaction,
|
|
324
|
+
withTransaction: (handle, options) => executeInTransaction(getOrInitCurrentTransaction(options), handle)
|
|
456
325
|
};
|
|
457
326
|
};
|
|
458
|
-
const
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
decode: (payload, decodeOptions) => {
|
|
465
|
-
return upcast(decodeOptions ? serializer.deserialize(payload, decodeOptions) : serializer.deserialize(payload));
|
|
466
|
-
},
|
|
467
|
-
encode: (object, encodeOptions) => {
|
|
468
|
-
const downcasted = downcast(object);
|
|
469
|
-
return encodeOptions ? serializer.serialize(downcasted, encodeOptions) : serializer.serialize(downcasted);
|
|
470
|
-
}
|
|
471
|
-
};
|
|
327
|
+
const wrapInConnectionClosure = async (connection, handle) => {
|
|
328
|
+
try {
|
|
329
|
+
return await handle();
|
|
330
|
+
} finally {
|
|
331
|
+
await connection.close();
|
|
332
|
+
}
|
|
472
333
|
};
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
const
|
|
477
|
-
|
|
478
|
-
|
|
334
|
+
const transactionFactoryWithNewConnection = (connect) => ({
|
|
335
|
+
transaction: (options) => {
|
|
336
|
+
const connection = connect();
|
|
337
|
+
const transaction = connection.transaction(options);
|
|
338
|
+
return {
|
|
339
|
+
...transaction,
|
|
340
|
+
commit: () => wrapInConnectionClosure(connection, () => transaction.commit()),
|
|
341
|
+
rollback: () => wrapInConnectionClosure(connection, () => transaction.rollback())
|
|
342
|
+
};
|
|
343
|
+
},
|
|
344
|
+
withTransaction: (handle, options) => {
|
|
345
|
+
const connection = connect();
|
|
346
|
+
const withTx = connection.withTransaction;
|
|
347
|
+
return wrapInConnectionClosure(connection, () => withTx(handle, options));
|
|
348
|
+
}
|
|
349
|
+
});
|
|
350
|
+
const transactionFactoryWithAmbientConnection = (connect) => ({
|
|
351
|
+
transaction: (options) => {
|
|
352
|
+
const transaction = connect().transaction(options);
|
|
353
|
+
return {
|
|
354
|
+
...transaction,
|
|
355
|
+
commit: () => transaction.commit(),
|
|
356
|
+
rollback: () => transaction.rollback()
|
|
357
|
+
};
|
|
358
|
+
},
|
|
359
|
+
withTransaction: (handle, options) => {
|
|
360
|
+
const withTx = connect().withTransaction;
|
|
361
|
+
return withTx(handle, options);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
const transactionFactoryWithAsyncAmbientConnection = (driverType, connect, close) => {
|
|
365
|
+
close ??= () => Promise.resolve();
|
|
479
366
|
return {
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
return this;
|
|
494
|
-
},
|
|
495
|
-
build() {
|
|
367
|
+
transaction: (options) => {
|
|
368
|
+
let conn = null;
|
|
369
|
+
let innerTx = null;
|
|
370
|
+
let connectingPromise = null;
|
|
371
|
+
const ensureConnection = async () => {
|
|
372
|
+
if (conn) return innerTx;
|
|
373
|
+
if (!connectingPromise) connectingPromise = (async () => {
|
|
374
|
+
conn = await connect();
|
|
375
|
+
innerTx = conn.transaction(options);
|
|
376
|
+
})();
|
|
377
|
+
await connectingPromise;
|
|
378
|
+
return innerTx;
|
|
379
|
+
};
|
|
496
380
|
return {
|
|
497
|
-
|
|
498
|
-
|
|
381
|
+
driverType,
|
|
382
|
+
get connection() {
|
|
383
|
+
if (!conn) throw new Error("Transaction not started - call begin() first");
|
|
384
|
+
return conn;
|
|
385
|
+
},
|
|
386
|
+
execute: {
|
|
387
|
+
query: async (sql, queryOptions) => {
|
|
388
|
+
return (await ensureConnection()).execute.query(sql, queryOptions);
|
|
389
|
+
},
|
|
390
|
+
batchQuery: async (sqls, queryOptions) => {
|
|
391
|
+
return (await ensureConnection()).execute.batchQuery(sqls, queryOptions);
|
|
392
|
+
},
|
|
393
|
+
command: async (sql, commandOptions) => {
|
|
394
|
+
return (await ensureConnection()).execute.command(sql, commandOptions);
|
|
395
|
+
},
|
|
396
|
+
batchCommand: async (sqls, commandOptions) => {
|
|
397
|
+
return (await ensureConnection()).execute.batchCommand(sqls, commandOptions);
|
|
398
|
+
}
|
|
399
|
+
},
|
|
400
|
+
begin: async () => {
|
|
401
|
+
return (await ensureConnection()).begin();
|
|
402
|
+
},
|
|
403
|
+
commit: async () => {
|
|
404
|
+
if (!innerTx) throw new Error("Transaction not started");
|
|
405
|
+
try {
|
|
406
|
+
return await innerTx.commit();
|
|
407
|
+
} finally {
|
|
408
|
+
if (conn) await close(conn);
|
|
409
|
+
}
|
|
410
|
+
},
|
|
411
|
+
rollback: async (error) => {
|
|
412
|
+
if (!innerTx) {
|
|
413
|
+
if (conn) await close(conn);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
try {
|
|
417
|
+
return await innerTx.rollback(error);
|
|
418
|
+
} finally {
|
|
419
|
+
if (conn) await close(conn);
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
_transactionOptions: void 0
|
|
499
423
|
};
|
|
424
|
+
},
|
|
425
|
+
withTransaction: async (handle, options) => {
|
|
426
|
+
const conn = await connect();
|
|
427
|
+
try {
|
|
428
|
+
const withTx = conn.withTransaction;
|
|
429
|
+
return await withTx(handle, options);
|
|
430
|
+
} finally {
|
|
431
|
+
await close(conn);
|
|
432
|
+
}
|
|
500
433
|
}
|
|
501
434
|
};
|
|
502
435
|
};
|
|
503
436
|
|
|
504
437
|
//#endregion
|
|
505
|
-
//#region src/core/
|
|
506
|
-
const
|
|
507
|
-
const
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
const check = (token) => SQLToken.check(token) && token.sqlTokenType === sqlTokenType;
|
|
520
|
-
return {
|
|
521
|
-
from: factory,
|
|
522
|
-
check,
|
|
523
|
-
type: sqlTokenType
|
|
438
|
+
//#region src/core/connections/connection.ts
|
|
439
|
+
const createAmbientConnection = (options) => {
|
|
440
|
+
const { driverType, client, executor, initTransaction, serializer } = options;
|
|
441
|
+
const clientPromise = Promise.resolve(client);
|
|
442
|
+
const closePromise = Promise.resolve();
|
|
443
|
+
const open = () => clientPromise;
|
|
444
|
+
const close = () => closePromise;
|
|
445
|
+
const typedConnection = {
|
|
446
|
+
driverType,
|
|
447
|
+
open,
|
|
448
|
+
close,
|
|
449
|
+
...transactionFactoryWithDbClient(open, initTransaction(() => typedConnection)),
|
|
450
|
+
execute: sqlExecutor(executor({ serializer }), { connect: open }),
|
|
451
|
+
_transactionType: void 0
|
|
524
452
|
};
|
|
453
|
+
return typedConnection;
|
|
525
454
|
};
|
|
526
|
-
|
|
527
|
-
const
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
const
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
const SQLIn = SQLToken("SQL_IN", ({ column, values, mode }) => mode !== void 0 ? {
|
|
538
|
-
column: SQLIdentifier.from(column),
|
|
539
|
-
values: SQLArray.from(values),
|
|
540
|
-
mode
|
|
541
|
-
} : {
|
|
542
|
-
column: SQLIdentifier.from(column),
|
|
543
|
-
values: SQLArray.from(values)
|
|
544
|
-
});
|
|
545
|
-
|
|
546
|
-
//#endregion
|
|
547
|
-
//#region src/core/sql/tokens/columnTokens.ts
|
|
548
|
-
const ColumnTypeToken = (sqlTokenType, jsTypeName, map) => {
|
|
549
|
-
const factory = (input) => {
|
|
550
|
-
let props;
|
|
551
|
-
if (map !== void 0) props = map(input);
|
|
552
|
-
else if (input === void 0 || input === null) props = {};
|
|
553
|
-
else if (typeof input === "object" && !Array.isArray(input)) props = input;
|
|
554
|
-
else throw new Error(`Cannot create SQLToken of type ${sqlTokenType} with input: ${input}`);
|
|
555
|
-
return {
|
|
556
|
-
sqlTokenType,
|
|
557
|
-
[sqlTokenType]: true,
|
|
558
|
-
jsTypeName,
|
|
559
|
-
...props
|
|
560
|
-
};
|
|
455
|
+
const createSingletonConnection = (options) => {
|
|
456
|
+
const { driverType, connect, close, initTransaction, executor, serializer } = options;
|
|
457
|
+
let client = null;
|
|
458
|
+
let connectPromise = null;
|
|
459
|
+
const getClient = async () => {
|
|
460
|
+
if (client) return client;
|
|
461
|
+
if (!connectPromise) connectPromise = connect().then((c) => {
|
|
462
|
+
client = c;
|
|
463
|
+
return c;
|
|
464
|
+
});
|
|
465
|
+
return connectPromise;
|
|
561
466
|
};
|
|
562
|
-
const
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
467
|
+
const typedConnection = {
|
|
468
|
+
driverType,
|
|
469
|
+
open: getClient,
|
|
470
|
+
close: () => client ? close(client) : Promise.resolve(),
|
|
471
|
+
...transactionFactoryWithDbClient(getClient, initTransaction(() => typedConnection)),
|
|
472
|
+
execute: sqlExecutor(executor({ serializer }), { connect: getClient }),
|
|
473
|
+
_transactionType: void 0
|
|
567
474
|
};
|
|
475
|
+
return typedConnection;
|
|
568
476
|
};
|
|
569
|
-
const
|
|
570
|
-
const
|
|
571
|
-
const
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
},
|
|
581
|
-
check: (token) => SQLToken.check(token) && token.sqlTokenType === "SQL_COLUMN_JSONB"
|
|
582
|
-
};
|
|
583
|
-
const TimestampToken = ColumnTypeToken("SQL_COLUMN_TIMESTAMP", "value_type:js:date");
|
|
584
|
-
const TimestamptzToken = ColumnTypeToken("SQL_COLUMN_TIMESTAMPTZ", "value_type:js:date");
|
|
585
|
-
const VarcharToken = ColumnTypeToken("SQL_COLUMN_VARCHAR", "value_type:js:string", (length) => ({
|
|
586
|
-
length: length ?? "max",
|
|
587
|
-
jsTypeName: "value_type:js:string"
|
|
588
|
-
}));
|
|
589
|
-
const AutoIncrementSQLColumnToken = ColumnTypeToken("SQL_COLUMN_AUTO_INCREMENT", "value_type:js:bigint");
|
|
590
|
-
const SQLColumnTypeTokens = {
|
|
591
|
-
AutoIncrement: AutoIncrementSQLColumnToken,
|
|
592
|
-
BigInteger: BigIntegerToken,
|
|
593
|
-
BigSerial: BigSerialToken,
|
|
594
|
-
Integer: IntegerToken,
|
|
595
|
-
JSONB: JSONBToken,
|
|
596
|
-
Serial: SerialToken,
|
|
597
|
-
Timestamp: TimestampToken,
|
|
598
|
-
Timestamptz: TimestamptzToken,
|
|
599
|
-
Varchar: VarcharToken
|
|
477
|
+
const createTransientConnection = (options) => {
|
|
478
|
+
const { driverType, open, close, initTransaction, executor, serializer } = options;
|
|
479
|
+
const typedConnection = {
|
|
480
|
+
driverType,
|
|
481
|
+
open,
|
|
482
|
+
close,
|
|
483
|
+
...transactionFactoryWithDbClient(open, initTransaction(() => typedConnection)),
|
|
484
|
+
execute: sqlExecutor(executor({ serializer }), { connect: open }),
|
|
485
|
+
_transactionType: void 0
|
|
486
|
+
};
|
|
487
|
+
return typedConnection;
|
|
600
488
|
};
|
|
601
|
-
const
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
489
|
+
const createConnection = (options) => {
|
|
490
|
+
const { driverType, connect, close, initTransaction, executor, serializer } = options;
|
|
491
|
+
let client = null;
|
|
492
|
+
let connectPromise = null;
|
|
493
|
+
const getClient = async () => {
|
|
494
|
+
if (client) return client;
|
|
495
|
+
if (!connectPromise) connectPromise = connect().then((c) => {
|
|
496
|
+
client = c;
|
|
497
|
+
return c;
|
|
498
|
+
});
|
|
499
|
+
return connectPromise;
|
|
500
|
+
};
|
|
501
|
+
const typedConnection = {
|
|
502
|
+
driverType,
|
|
503
|
+
open: getClient,
|
|
504
|
+
close: () => client ? close(client) : Promise.resolve(),
|
|
505
|
+
...transactionFactoryWithDbClient(getClient, initTransaction(() => typedConnection)),
|
|
506
|
+
execute: sqlExecutor(executor({ serializer }), { connect: getClient }),
|
|
507
|
+
_transactionType: void 0
|
|
508
|
+
};
|
|
509
|
+
return typedConnection;
|
|
611
510
|
};
|
|
612
|
-
const SQLColumnToken = SQLToken("SQL_COLUMN");
|
|
613
|
-
|
|
614
|
-
//#endregion
|
|
615
|
-
//#region src/core/sql/processors/sqlProcessor.ts
|
|
616
|
-
const SQLProcessor = (options) => options;
|
|
617
511
|
|
|
618
512
|
//#endregion
|
|
619
|
-
//#region src/core/
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
handle: (token, context) => {
|
|
630
|
-
const { builder, mapper, processorsRegistry, serializer } = context;
|
|
631
|
-
const { values: inValues, column } = token;
|
|
632
|
-
if (inValues.value.length === 0) {
|
|
633
|
-
builder.addParam(mapper.mapValue(false, serializer));
|
|
634
|
-
return;
|
|
635
|
-
}
|
|
636
|
-
builder.addSQL(mapper.mapValue(column.value, serializer));
|
|
637
|
-
builder.addSQL(` IN (`);
|
|
638
|
-
const arrayProcessor = processorsRegistry.get(SQLArray.type);
|
|
639
|
-
if (!arrayProcessor) throw new Error("No sql processor registered for an array. Cannot expand IN statement");
|
|
640
|
-
arrayProcessor.handle(inValues, {
|
|
641
|
-
builder,
|
|
642
|
-
mapper,
|
|
643
|
-
processorsRegistry,
|
|
644
|
-
serializer
|
|
645
|
-
});
|
|
646
|
-
builder.addSQL(`)`);
|
|
513
|
+
//#region src/core/taskProcessing/taskProcessor.ts
|
|
514
|
+
var TaskProcessor = class {
|
|
515
|
+
queue = [];
|
|
516
|
+
isProcessing = false;
|
|
517
|
+
activeTasks = 0;
|
|
518
|
+
activeGroups = /* @__PURE__ */ new Set();
|
|
519
|
+
options;
|
|
520
|
+
stopped = false;
|
|
521
|
+
constructor(options) {
|
|
522
|
+
this.options = options;
|
|
647
523
|
}
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
builder.addSQL(mapper.mapValue(token, serializer));
|
|
524
|
+
enqueue(task, options) {
|
|
525
|
+
if (this.stopped) return Promise.reject(new DumboError("TaskProcessor has been stopped"));
|
|
526
|
+
if (this.queue.length >= this.options.maxQueueSize) return Promise.reject(new TransientDatabaseError("Too many pending connections. Please try again later."));
|
|
527
|
+
return this.schedule(task, options);
|
|
653
528
|
}
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
canHandle: "SQL_LITERAL",
|
|
657
|
-
handle: (token, { builder, mapper, serializer }) => builder.addParam(mapper.mapValue(token.value, serializer))
|
|
658
|
-
});
|
|
659
|
-
|
|
660
|
-
//#endregion
|
|
661
|
-
//#region src/core/sql/processors/sqlProcessorRegistry.ts
|
|
662
|
-
const SQLProcessorsRegistry = (options) => {
|
|
663
|
-
const processors = options ? new Map(options.from.all()) : /* @__PURE__ */ new Map();
|
|
664
|
-
function register(...args) {
|
|
665
|
-
if (args.length === 1 && typeof args[0] === "object" && !Array.isArray(args[0])) Object.entries(args[0]).forEach(([_, processor]) => {
|
|
666
|
-
processors.set(processor.canHandle, processor);
|
|
667
|
-
});
|
|
668
|
-
else args.forEach((p) => processors.set(p.canHandle, p));
|
|
669
|
-
return registry;
|
|
529
|
+
waitForEndOfProcessing() {
|
|
530
|
+
return this.schedule(({ ack }) => Promise.resolve(ack()));
|
|
670
531
|
}
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
handle: (token, context) => mapColumnType(token, context)
|
|
717
|
-
}),
|
|
718
|
-
Varchar: SQLProcessor({
|
|
719
|
-
canHandle: "SQL_COLUMN_VARCHAR",
|
|
720
|
-
handle: (token, context) => mapColumnType(token, context)
|
|
721
|
-
})
|
|
722
|
-
});
|
|
723
|
-
|
|
724
|
-
//#endregion
|
|
725
|
-
//#region src/core/sql/processors/index.ts
|
|
726
|
-
const defaultProcessorsRegistry = globalThis.defaultProcessorsRegistry = globalThis.defaultProcessorsRegistry ?? SQLProcessorsRegistry().register(FormatIdentifierProcessor, MapLiteralProcessor, ExpandArrayProcessor, ExpandSQLInProcessor);
|
|
727
|
-
|
|
728
|
-
//#endregion
|
|
729
|
-
//#region src/core/sql/tokenizedSQL/tokenizedSQL.ts
|
|
730
|
-
const TokenizedSQLBuilder = () => {
|
|
731
|
-
const sqlChunks = [];
|
|
732
|
-
const sqlTokens = [];
|
|
733
|
-
return {
|
|
734
|
-
addSQL(str) {
|
|
735
|
-
sqlChunks.push(str);
|
|
736
|
-
},
|
|
737
|
-
addSQLs(str) {
|
|
738
|
-
sqlChunks.push(...str);
|
|
739
|
-
},
|
|
740
|
-
addToken(value) {
|
|
741
|
-
sqlTokens.push(value);
|
|
742
|
-
},
|
|
743
|
-
addTokens(vals) {
|
|
744
|
-
sqlTokens.push(...vals);
|
|
745
|
-
},
|
|
746
|
-
build() {
|
|
747
|
-
return sqlChunks.length > 0 ? {
|
|
748
|
-
__brand: "tokenized-sql",
|
|
749
|
-
sqlChunks,
|
|
750
|
-
sqlTokens
|
|
751
|
-
} : TokenizedSQL.empty;
|
|
532
|
+
async stop(options) {
|
|
533
|
+
if (this.stopped) return;
|
|
534
|
+
this.stopped = true;
|
|
535
|
+
this.queue.length = 0;
|
|
536
|
+
this.activeGroups.clear();
|
|
537
|
+
if (!options?.force) await this.waitForEndOfProcessing();
|
|
538
|
+
}
|
|
539
|
+
schedule(task, options) {
|
|
540
|
+
return promiseWithDeadline((resolve, reject) => {
|
|
541
|
+
const taskWithContext = () => {
|
|
542
|
+
return new Promise((resolveTask, failTask) => {
|
|
543
|
+
task({ ack: resolveTask }).then(resolve).catch((err) => {
|
|
544
|
+
failTask(err);
|
|
545
|
+
reject(err);
|
|
546
|
+
});
|
|
547
|
+
});
|
|
548
|
+
};
|
|
549
|
+
this.queue.push({
|
|
550
|
+
task: taskWithContext,
|
|
551
|
+
options
|
|
552
|
+
});
|
|
553
|
+
if (!this.isProcessing) this.ensureProcessing();
|
|
554
|
+
}, { deadline: this.options.maxTaskIdleTime });
|
|
555
|
+
}
|
|
556
|
+
ensureProcessing() {
|
|
557
|
+
if (this.isProcessing) return;
|
|
558
|
+
this.isProcessing = true;
|
|
559
|
+
this.processQueue();
|
|
560
|
+
}
|
|
561
|
+
processQueue() {
|
|
562
|
+
try {
|
|
563
|
+
while (this.activeTasks < this.options.maxActiveTasks && this.queue.length > 0) {
|
|
564
|
+
const item = this.takeFirstAvailableItem();
|
|
565
|
+
if (item === null) return;
|
|
566
|
+
const groupId = item.options?.taskGroupId;
|
|
567
|
+
if (groupId) this.activeGroups.add(groupId);
|
|
568
|
+
this.activeTasks++;
|
|
569
|
+
this.executeItem(item);
|
|
570
|
+
}
|
|
571
|
+
} catch (error) {
|
|
572
|
+
console.error(error);
|
|
573
|
+
throw error;
|
|
574
|
+
} finally {
|
|
575
|
+
this.isProcessing = false;
|
|
576
|
+
if (this.hasItemsToProcess() && this.activeTasks < this.options.maxActiveTasks) this.ensureProcessing();
|
|
752
577
|
}
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
if (isTokenizedSQL(value)) {
|
|
762
|
-
builder.addSQLs(value.sqlChunks);
|
|
763
|
-
builder.addTokens(value.sqlTokens);
|
|
764
|
-
} else if (SQLPlain.check(value)) builder.addSQL(value.value);
|
|
765
|
-
else {
|
|
766
|
-
builder.addSQL(TokenizedSQL.paramPlaceholder);
|
|
767
|
-
builder.addToken(SQLToken.check(value) ? value : Array.isArray(value) ? SQLArray.from(value) : SQLLiteral.from(value));
|
|
578
|
+
}
|
|
579
|
+
async executeItem({ task, options }) {
|
|
580
|
+
try {
|
|
581
|
+
await task();
|
|
582
|
+
} finally {
|
|
583
|
+
this.activeTasks--;
|
|
584
|
+
if (options && options.taskGroupId) this.activeGroups.delete(options.taskGroupId);
|
|
585
|
+
this.ensureProcessing();
|
|
768
586
|
}
|
|
769
587
|
}
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
588
|
+
takeFirstAvailableItem = () => {
|
|
589
|
+
const taskIndex = this.queue.findIndex((item) => !item.options?.taskGroupId || !this.activeGroups.has(item.options.taskGroupId));
|
|
590
|
+
if (taskIndex === -1) return null;
|
|
591
|
+
const [item] = this.queue.splice(taskIndex, 1);
|
|
592
|
+
return item ?? null;
|
|
593
|
+
};
|
|
594
|
+
hasItemsToProcess = () => this.queue.findIndex((item) => !item.options?.taskGroupId || !this.activeGroups.has(item.options.taskGroupId)) !== -1;
|
|
774
595
|
};
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
596
|
+
const DEFAULT_PROMISE_DEADLINE = 2147483647;
|
|
597
|
+
const promiseWithDeadline = (executor, options) => {
|
|
598
|
+
return new Promise((resolve, reject) => {
|
|
599
|
+
let taskStarted = false;
|
|
600
|
+
let timeoutId = null;
|
|
601
|
+
const deadline = options.deadline ?? DEFAULT_PROMISE_DEADLINE;
|
|
602
|
+
timeoutId = setTimeout(() => {
|
|
603
|
+
if (!taskStarted) reject(/* @__PURE__ */ new Error("Task was not started within the maximum waiting time"));
|
|
604
|
+
}, deadline);
|
|
605
|
+
timeoutId.unref();
|
|
606
|
+
executor((value) => {
|
|
607
|
+
taskStarted = true;
|
|
608
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
609
|
+
timeoutId = null;
|
|
610
|
+
resolve(value);
|
|
611
|
+
}, (reason) => {
|
|
612
|
+
if (timeoutId) clearTimeout(timeoutId);
|
|
613
|
+
timeoutId = null;
|
|
614
|
+
reject(reason);
|
|
615
|
+
});
|
|
616
|
+
});
|
|
780
617
|
};
|
|
781
618
|
|
|
782
619
|
//#endregion
|
|
783
|
-
//#region src/core/
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
620
|
+
//#region src/core/taskProcessing/executionGuards.ts
|
|
621
|
+
const guardBoundedAccess = (getResource, options) => {
|
|
622
|
+
let isStopped = false;
|
|
623
|
+
const taskProcessor = new TaskProcessor({
|
|
624
|
+
maxActiveTasks: options.maxResources,
|
|
625
|
+
maxQueueSize: options.maxQueueSize ?? 1e3
|
|
626
|
+
});
|
|
627
|
+
const resourcePool = [];
|
|
628
|
+
const allResources = /* @__PURE__ */ new Set();
|
|
629
|
+
const ackCallbacks = /* @__PURE__ */ new Map();
|
|
630
|
+
const acquire = async () => taskProcessor.enqueue(async ({ ack }) => {
|
|
631
|
+
try {
|
|
632
|
+
let resource;
|
|
633
|
+
if (options.reuseResources) resource = resourcePool.pop();
|
|
634
|
+
if (!resource) {
|
|
635
|
+
resource = await getResource();
|
|
636
|
+
allResources.add(resource);
|
|
637
|
+
}
|
|
638
|
+
ackCallbacks.set(resource, ack);
|
|
639
|
+
return resource;
|
|
640
|
+
} catch (e) {
|
|
641
|
+
ack();
|
|
642
|
+
throw e;
|
|
643
|
+
}
|
|
644
|
+
});
|
|
645
|
+
const release = (resource) => {
|
|
646
|
+
const ack = ackCallbacks.get(resource);
|
|
647
|
+
if (ack) {
|
|
648
|
+
ackCallbacks.delete(resource);
|
|
649
|
+
if (options.reuseResources) resourcePool.push(resource);
|
|
650
|
+
ack();
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
const execute = async (operation) => {
|
|
654
|
+
const resource = await acquire();
|
|
655
|
+
try {
|
|
656
|
+
return await operation(resource);
|
|
657
|
+
} finally {
|
|
658
|
+
release(resource);
|
|
659
|
+
}
|
|
660
|
+
};
|
|
661
|
+
return {
|
|
662
|
+
acquire,
|
|
663
|
+
release,
|
|
664
|
+
execute,
|
|
665
|
+
waitForIdle: () => taskProcessor.waitForEndOfProcessing(),
|
|
666
|
+
stop: async (stopOptions) => {
|
|
667
|
+
if (isStopped) return;
|
|
668
|
+
isStopped = true;
|
|
669
|
+
if (options?.closeResource) {
|
|
670
|
+
const resources = [...allResources];
|
|
671
|
+
allResources.clear();
|
|
672
|
+
resourcePool.length = 0;
|
|
673
|
+
await Promise.all(resources.map(async (resource) => await options.closeResource(resource)));
|
|
674
|
+
}
|
|
675
|
+
await taskProcessor.stop(stopOptions);
|
|
676
|
+
}
|
|
797
677
|
};
|
|
798
|
-
}
|
|
799
|
-
const isSQL = (value) => {
|
|
800
|
-
if (value === void 0 || value === null) return false;
|
|
801
|
-
return isTokenizedSQL(value);
|
|
802
678
|
};
|
|
803
|
-
const
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
679
|
+
const guardInitializedOnce = (initialize, options) => {
|
|
680
|
+
let initPromise = null;
|
|
681
|
+
const taskProcessor = new TaskProcessor({
|
|
682
|
+
maxActiveTasks: 1,
|
|
683
|
+
maxQueueSize: options?.maxQueueSize ?? 1e3
|
|
684
|
+
});
|
|
685
|
+
const ensureInitialized = async (retryCount = 0) => {
|
|
686
|
+
if (initPromise !== null) return initPromise;
|
|
687
|
+
return taskProcessor.enqueue(async ({ ack }) => {
|
|
688
|
+
if (initPromise !== null) {
|
|
689
|
+
ack();
|
|
690
|
+
return initPromise;
|
|
691
|
+
}
|
|
692
|
+
try {
|
|
693
|
+
const promise = initialize();
|
|
694
|
+
initPromise = promise;
|
|
695
|
+
const result = await promise;
|
|
696
|
+
ack();
|
|
697
|
+
return result;
|
|
698
|
+
} catch (error) {
|
|
699
|
+
initPromise = null;
|
|
700
|
+
ack();
|
|
701
|
+
if (retryCount < (options?.maxRetries ?? 3)) return ensureInitialized(retryCount + 1);
|
|
702
|
+
throw error;
|
|
703
|
+
}
|
|
704
|
+
}, { taskGroupId: v7() });
|
|
705
|
+
};
|
|
706
|
+
return {
|
|
707
|
+
ensureInitialized,
|
|
708
|
+
reset: () => {
|
|
709
|
+
initPromise = null;
|
|
710
|
+
},
|
|
711
|
+
stop: (options) => taskProcessor.stop(options)
|
|
712
|
+
};
|
|
807
713
|
};
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
}
|
|
714
|
+
|
|
715
|
+
//#endregion
|
|
716
|
+
//#region src/core/connections/pool.ts
|
|
717
|
+
const wrapPooledConnection = (conn, onClose) => ({
|
|
718
|
+
...conn,
|
|
719
|
+
close: onClose
|
|
720
|
+
});
|
|
721
|
+
const createAmbientConnectionPool = (options) => {
|
|
722
|
+
const { driverType, connection } = options;
|
|
723
|
+
return createConnectionPool({
|
|
724
|
+
driverType,
|
|
725
|
+
getConnection: () => connection,
|
|
726
|
+
execute: connection.execute,
|
|
727
|
+
transaction: (options) => connection.transaction(options),
|
|
728
|
+
withConnection: (handle, _options) => handle(connection),
|
|
729
|
+
withTransaction: (handle, options) => {
|
|
730
|
+
const withTx = connection.withTransaction;
|
|
731
|
+
return withTx(handle, options);
|
|
732
|
+
}
|
|
733
|
+
});
|
|
817
734
|
};
|
|
818
|
-
const
|
|
819
|
-
const
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
735
|
+
const createSingletonConnectionPool = (options) => {
|
|
736
|
+
const { driverType, getConnection } = options;
|
|
737
|
+
let connectionPromise = null;
|
|
738
|
+
const getExistingOrNewConnection = () => {
|
|
739
|
+
if (!connectionPromise) connectionPromise ??= Promise.resolve(getConnection());
|
|
740
|
+
return connectionPromise;
|
|
741
|
+
};
|
|
742
|
+
return {
|
|
743
|
+
driverType,
|
|
744
|
+
connection: () => getExistingOrNewConnection().then((conn) => wrapPooledConnection(conn, () => Promise.resolve())),
|
|
745
|
+
execute: sqlExecutorInAmbientConnection({
|
|
746
|
+
driverType,
|
|
747
|
+
connection: getExistingOrNewConnection
|
|
748
|
+
}),
|
|
749
|
+
withConnection: (handle, _options) => executeInAmbientConnection(handle, { connection: getExistingOrNewConnection }),
|
|
750
|
+
...transactionFactoryWithAsyncAmbientConnection(options.driverType, getExistingOrNewConnection, options.closeConnection),
|
|
751
|
+
close: async () => {
|
|
752
|
+
if (!connectionPromise) return;
|
|
753
|
+
await (await connectionPromise).close();
|
|
754
|
+
}
|
|
755
|
+
};
|
|
825
756
|
};
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
757
|
+
const createBoundedConnectionPool = (options) => {
|
|
758
|
+
const { driverType, maxConnections } = options;
|
|
759
|
+
const guardMaxConnections = guardBoundedAccess(options.getConnection, {
|
|
760
|
+
maxResources: maxConnections,
|
|
761
|
+
reuseResources: true
|
|
762
|
+
});
|
|
763
|
+
let closed = false;
|
|
764
|
+
const executeWithPooling = async (operation) => {
|
|
765
|
+
const conn = await guardMaxConnections.acquire();
|
|
766
|
+
try {
|
|
767
|
+
return await operation(conn);
|
|
768
|
+
} finally {
|
|
769
|
+
guardMaxConnections.release(conn);
|
|
770
|
+
}
|
|
771
|
+
};
|
|
772
|
+
return {
|
|
773
|
+
driverType,
|
|
774
|
+
connection: async () => {
|
|
775
|
+
const conn = await guardMaxConnections.acquire();
|
|
776
|
+
return wrapPooledConnection(conn, () => Promise.resolve(guardMaxConnections.release(conn)));
|
|
777
|
+
},
|
|
778
|
+
execute: {
|
|
779
|
+
query: (sql, opts) => executeWithPooling((c) => c.execute.query(sql, opts)),
|
|
780
|
+
batchQuery: (sqls, opts) => executeWithPooling((c) => c.execute.batchQuery(sqls, opts)),
|
|
781
|
+
command: (sql, opts) => executeWithPooling((c) => c.execute.command(sql, opts)),
|
|
782
|
+
batchCommand: (sqls, opts) => executeWithPooling((c) => c.execute.batchCommand(sqls, opts))
|
|
783
|
+
},
|
|
784
|
+
withConnection: executeWithPooling,
|
|
785
|
+
...transactionFactoryWithAsyncAmbientConnection(driverType, guardMaxConnections.acquire, guardMaxConnections.release),
|
|
786
|
+
close: async () => {
|
|
787
|
+
if (closed) return;
|
|
788
|
+
closed = true;
|
|
789
|
+
await guardMaxConnections.stop({ force: true });
|
|
790
|
+
}
|
|
791
|
+
};
|
|
792
|
+
};
|
|
793
|
+
const createSingletonClientConnectionPool = (options) => {
|
|
794
|
+
const { driverType, dbClient } = options;
|
|
795
|
+
return createSingletonConnectionPool({
|
|
796
|
+
getConnection: () => options.connectionFactory({ dbClient }),
|
|
797
|
+
driverType
|
|
798
|
+
});
|
|
799
|
+
};
|
|
800
|
+
const createAlwaysNewConnectionPool = (options) => {
|
|
801
|
+
const { driverType, getConnection, connectionOptions } = options;
|
|
802
|
+
return createConnectionPool({
|
|
803
|
+
driverType,
|
|
804
|
+
getConnection: () => connectionOptions ? getConnection(connectionOptions) : getConnection()
|
|
805
|
+
});
|
|
806
|
+
};
|
|
807
|
+
const createConnectionPool = (pool) => {
|
|
808
|
+
const { driverType, getConnection } = pool;
|
|
809
|
+
const connection = "connection" in pool ? pool.connection : () => Promise.resolve(getConnection());
|
|
810
|
+
return {
|
|
811
|
+
driverType,
|
|
812
|
+
connection,
|
|
813
|
+
withConnection: "withConnection" in pool ? pool.withConnection : (handle, _options) => executeInNewConnection(handle, { connection }),
|
|
814
|
+
close: "close" in pool ? pool.close : () => Promise.resolve(),
|
|
815
|
+
execute: "execute" in pool ? pool.execute : sqlExecutorInNewConnection({
|
|
816
|
+
driverType,
|
|
817
|
+
connection
|
|
818
|
+
}),
|
|
819
|
+
..."transaction" in pool && "withTransaction" in pool ? {
|
|
820
|
+
transaction: pool.transaction,
|
|
821
|
+
withTransaction: pool.withTransaction
|
|
822
|
+
} : transactionFactoryWithNewConnection(getConnection)
|
|
823
|
+
};
|
|
852
824
|
};
|
|
853
|
-
const columnFactory = SQLColumnToken.from;
|
|
854
|
-
columnFactory.type = SQLColumnTypeTokensFactory;
|
|
855
|
-
SQL.column = columnFactory;
|
|
856
825
|
|
|
857
826
|
//#endregion
|
|
858
|
-
//#region src/core/
|
|
859
|
-
const
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
ARRAY: true,
|
|
864
|
-
AS: true,
|
|
865
|
-
ASC: true,
|
|
866
|
-
AUTHORIZATION: true,
|
|
867
|
-
BETWEEN: true,
|
|
868
|
-
BINARY: true,
|
|
869
|
-
BOTH: true,
|
|
870
|
-
CASE: true,
|
|
871
|
-
CAST: true,
|
|
872
|
-
CHECK: true,
|
|
873
|
-
COLLATE: true,
|
|
874
|
-
COLUMN: true,
|
|
875
|
-
CONSTRAINT: true,
|
|
876
|
-
CREATE: true,
|
|
877
|
-
CROSS: true,
|
|
878
|
-
CURRENT_DATE: true,
|
|
879
|
-
CURRENT_TIME: true,
|
|
880
|
-
CURRENT_TIMESTAMP: true,
|
|
881
|
-
CURRENT_USER: true,
|
|
882
|
-
DEFAULT: true,
|
|
883
|
-
DEFERRABLE: true,
|
|
884
|
-
DESC: true,
|
|
885
|
-
DISTINCT: true,
|
|
886
|
-
DO: true,
|
|
887
|
-
ELSE: true,
|
|
888
|
-
END: true,
|
|
889
|
-
EXCEPT: true,
|
|
890
|
-
FALSE: true,
|
|
891
|
-
FOR: true,
|
|
892
|
-
FOREIGN: true,
|
|
893
|
-
FROM: true,
|
|
894
|
-
FULL: true,
|
|
895
|
-
GRANT: true,
|
|
896
|
-
GROUP: true,
|
|
897
|
-
HAVING: true,
|
|
898
|
-
IN: true,
|
|
899
|
-
INITIALLY: true,
|
|
900
|
-
INNER: true,
|
|
901
|
-
INTERSECT: true,
|
|
902
|
-
INTO: true,
|
|
903
|
-
IS: true,
|
|
904
|
-
JOIN: true,
|
|
905
|
-
LEADING: true,
|
|
906
|
-
LEFT: true,
|
|
907
|
-
LIKE: true,
|
|
908
|
-
LOCALTIME: true,
|
|
909
|
-
LOCALTIMESTAMP: true,
|
|
910
|
-
NATURAL: true,
|
|
911
|
-
NEW: true,
|
|
912
|
-
NOT: true,
|
|
913
|
-
NULL: true,
|
|
914
|
-
NULLS: true,
|
|
915
|
-
OLD: true,
|
|
916
|
-
ON: true,
|
|
917
|
-
ONLY: true,
|
|
918
|
-
OPEN: true,
|
|
919
|
-
OR: true,
|
|
920
|
-
ORDER: true,
|
|
921
|
-
OUTER: true,
|
|
922
|
-
OVERLAPS: true,
|
|
923
|
-
PARTITION: true,
|
|
924
|
-
PLACING: true,
|
|
925
|
-
PRIMARY: true,
|
|
926
|
-
REFERENCES: true,
|
|
927
|
-
RIGHT: true,
|
|
928
|
-
SELECT: true,
|
|
929
|
-
SESSION_USER: true,
|
|
930
|
-
SIMILAR: true,
|
|
931
|
-
SOME: true,
|
|
932
|
-
TABLE: true,
|
|
933
|
-
THEN: true,
|
|
934
|
-
TO: true,
|
|
935
|
-
TRAILING: true,
|
|
936
|
-
TRUE: true,
|
|
937
|
-
UNION: true,
|
|
938
|
-
UNIQUE: true,
|
|
939
|
-
USER: true,
|
|
940
|
-
USING: true,
|
|
941
|
-
WHEN: true,
|
|
942
|
-
WHERE: true,
|
|
943
|
-
WITH: true,
|
|
944
|
-
WITHOUT: true,
|
|
945
|
-
ADD: true,
|
|
946
|
-
ALTER: true,
|
|
947
|
-
ARE: true,
|
|
948
|
-
AT: true,
|
|
949
|
-
BEGIN: true,
|
|
950
|
-
BY: true,
|
|
951
|
-
CASCADE: true,
|
|
952
|
-
CLOSE: true,
|
|
953
|
-
COMMIT: true,
|
|
954
|
-
CONNECT: true,
|
|
955
|
-
CONTINUE: true,
|
|
956
|
-
CORRESPONDING: true,
|
|
957
|
-
CURSOR: true,
|
|
958
|
-
DEALLOCATE: true,
|
|
959
|
-
DECLARE: true,
|
|
960
|
-
DELETE: true,
|
|
961
|
-
DESCRIBE: true,
|
|
962
|
-
DISCONNECT: true,
|
|
963
|
-
DROP: true,
|
|
964
|
-
ESCAPE: true,
|
|
965
|
-
EXECUTE: true,
|
|
966
|
-
EXISTS: true,
|
|
967
|
-
FETCH: true,
|
|
968
|
-
FIRST: true,
|
|
969
|
-
FLOAT: true,
|
|
970
|
-
GET: true,
|
|
971
|
-
GLOBAL: true,
|
|
972
|
-
GO: true,
|
|
973
|
-
GOTO: true,
|
|
974
|
-
HOUR: true,
|
|
975
|
-
IMMEDIATE: true,
|
|
976
|
-
INDICATOR: true,
|
|
977
|
-
INPUT: true,
|
|
978
|
-
INSERT: true,
|
|
979
|
-
INT: true,
|
|
980
|
-
INTEGER: true,
|
|
981
|
-
INTERVAL: true,
|
|
982
|
-
LANGUAGE: true,
|
|
983
|
-
LAST: true,
|
|
984
|
-
LOCAL: true,
|
|
985
|
-
MATCH: true,
|
|
986
|
-
MINUTE: true,
|
|
987
|
-
MODULE: true,
|
|
988
|
-
MONTH: true,
|
|
989
|
-
NATIONAL: true,
|
|
990
|
-
NEXT: true,
|
|
991
|
-
NO: true,
|
|
992
|
-
OF: true,
|
|
993
|
-
OUTPUT: true,
|
|
994
|
-
PARTIAL: true,
|
|
995
|
-
PREPARE: true,
|
|
996
|
-
PRESERVE: true,
|
|
997
|
-
PRIOR: true,
|
|
998
|
-
PRIVILEGES: true,
|
|
999
|
-
PROCEDURE: true,
|
|
1000
|
-
PUBLIC: true,
|
|
1001
|
-
READ: true,
|
|
1002
|
-
REAL: true,
|
|
1003
|
-
RESTRICT: true,
|
|
1004
|
-
REVOKE: true,
|
|
1005
|
-
ROLLBACK: true,
|
|
1006
|
-
ROWS: true,
|
|
1007
|
-
SCHEMA: true,
|
|
1008
|
-
SCROLL: true,
|
|
1009
|
-
SECOND: true,
|
|
1010
|
-
SECTION: true,
|
|
1011
|
-
SET: true,
|
|
1012
|
-
SIZE: true,
|
|
1013
|
-
SMALLINT: true,
|
|
1014
|
-
SQL: true,
|
|
1015
|
-
SQLCODE: true,
|
|
1016
|
-
SQLERROR: true,
|
|
1017
|
-
SQLSTATE: true,
|
|
1018
|
-
TEMPORARY: true,
|
|
1019
|
-
TIMEZONE_HOUR: true,
|
|
1020
|
-
TIMEZONE_MINUTE: true,
|
|
1021
|
-
TRANSACTION: true,
|
|
1022
|
-
TRANSLATE: true,
|
|
1023
|
-
TRANSLATION: true,
|
|
1024
|
-
UNKNOWN: true,
|
|
1025
|
-
UPDATE: true,
|
|
1026
|
-
VALUE: true,
|
|
1027
|
-
VALUES: true,
|
|
1028
|
-
VARCHAR: true,
|
|
1029
|
-
VARYING: true,
|
|
1030
|
-
VIEW: true,
|
|
1031
|
-
WHENEVER: true,
|
|
1032
|
-
WORK: true,
|
|
1033
|
-
WRITE: true,
|
|
1034
|
-
YEAR: true,
|
|
1035
|
-
ZONE: true
|
|
1036
|
-
};
|
|
1037
|
-
|
|
1038
|
-
//#endregion
|
|
1039
|
-
//#region src/core/sql/valueMappers/sqlValueMapper.ts
|
|
1040
|
-
const ANSISQLParamPlaceholder = "?";
|
|
1041
|
-
const ANSISQLIdentifierQuote = "\"";
|
|
1042
|
-
const mapANSISQLParamPlaceholder = () => "?";
|
|
1043
|
-
const isReserved = (value, reserved) => !!reserved[value.toUpperCase()];
|
|
1044
|
-
const mapSQLIdentifier = (value, options) => {
|
|
1045
|
-
if (value === void 0 || value === null) throw new Error("SQL identifier cannot be null or undefined");
|
|
1046
|
-
const ident = value.toString().slice(0);
|
|
1047
|
-
const quoteSign = options?.quote ?? "\"";
|
|
1048
|
-
if (/^[a-z_][a-z0-9_$]*$/.test(ident) && !isReserved(ident, options?.reservedWords ?? ansiSqlReservedMap)) return ident;
|
|
1049
|
-
let quoted = quoteSign;
|
|
1050
|
-
for (let i = 0; i < ident.length; i++) {
|
|
1051
|
-
const c = ident[i];
|
|
1052
|
-
quoted += c === quoteSign ? c + c : c;
|
|
1053
|
-
}
|
|
1054
|
-
quoted += quoteSign;
|
|
1055
|
-
return quoted;
|
|
1056
|
-
};
|
|
1057
|
-
const DefaultMapSQLParamValueOptions = {
|
|
1058
|
-
mapPlaceholder: mapANSISQLParamPlaceholder,
|
|
1059
|
-
mapIdentifier: mapSQLIdentifier
|
|
827
|
+
//#region src/core/drivers/databaseDriver.ts
|
|
828
|
+
const canHandleDriverWithConnectionString = (driver, tryParseConnectionString) => (options) => {
|
|
829
|
+
if ("driverType" in options) return options.driverType === driver;
|
|
830
|
+
if ("connectionString" in options && typeof options.connectionString === "string") return tryParseConnectionString(options.connectionString) !== null;
|
|
831
|
+
return false;
|
|
1060
832
|
};
|
|
1061
|
-
const
|
|
1062
|
-
const
|
|
1063
|
-
|
|
1064
|
-
|
|
833
|
+
const DumboDatabaseDriverRegistry = () => {
|
|
834
|
+
const drivers = /* @__PURE__ */ new Map();
|
|
835
|
+
const register = (driverType, plugin) => {
|
|
836
|
+
const entry = drivers.get(driverType);
|
|
837
|
+
if (entry && (typeof entry !== "function" || typeof plugin === "function")) return;
|
|
838
|
+
drivers.set(driverType, plugin);
|
|
839
|
+
};
|
|
840
|
+
const getDriver = (options) => options.driverType ? drivers.get(options.driverType) : [...drivers.values()].find((d) => typeof d !== "function" && d.canHandle(options));
|
|
841
|
+
const tryResolve = async (options) => {
|
|
842
|
+
const driver = getDriver(options);
|
|
843
|
+
if (!driver) return null;
|
|
844
|
+
if (typeof driver !== "function") return driver;
|
|
845
|
+
const plugin = await driver();
|
|
846
|
+
register(plugin.driverType, plugin);
|
|
847
|
+
return plugin;
|
|
848
|
+
};
|
|
849
|
+
const tryGet = (options) => {
|
|
850
|
+
const driver = getDriver(options);
|
|
851
|
+
return driver && typeof driver !== "function" ? driver : null;
|
|
1065
852
|
};
|
|
853
|
+
const has = (driverType) => drivers.has(driverType);
|
|
1066
854
|
return {
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
855
|
+
register,
|
|
856
|
+
tryResolve,
|
|
857
|
+
tryGet,
|
|
858
|
+
has,
|
|
859
|
+
get databaseDriverTypes() {
|
|
860
|
+
return Array.from(drivers.keys());
|
|
861
|
+
}
|
|
1073
862
|
};
|
|
1074
863
|
};
|
|
1075
|
-
|
|
1076
|
-
if (value === null || value === void 0) return null;
|
|
1077
|
-
else if (typeof value === "number") return value;
|
|
1078
|
-
else if (typeof value === "string") return value;
|
|
1079
|
-
else if (Array.isArray(value)) {
|
|
1080
|
-
const mapValue = options?.mapValue ?? mapSQLParamValue;
|
|
1081
|
-
return options?.mapArray ? options.mapArray(value, mapValue) : value.map((item) => mapValue(item, serializer, options));
|
|
1082
|
-
} else if (typeof value === "boolean") return options?.mapBoolean ? options.mapBoolean(value) : value;
|
|
1083
|
-
else if (typeof value === "bigint") return options?.mapBigInt ? options.mapBigInt(value) : value.toString();
|
|
1084
|
-
else if (value instanceof Date) return options?.mapDate ? options.mapDate(value) : value.toISOString();
|
|
1085
|
-
else if (SQL.check.isIdentifier(value)) return (options?.mapIdentifier ?? mapSQLIdentifier)(value.value);
|
|
1086
|
-
else if (typeof value === "object") return options?.mapObject ? options.mapObject(value) : `${serializer.serialize(value).replace(/'/g, "''")}`;
|
|
1087
|
-
else return serializer.serialize(value);
|
|
1088
|
-
}
|
|
864
|
+
const dumboDatabaseDriverRegistry = globalThis.dumboDatabaseDriverRegistry = globalThis.dumboDatabaseDriverRegistry ?? DumboDatabaseDriverRegistry();
|
|
1089
865
|
|
|
1090
866
|
//#endregion
|
|
1091
|
-
//#region src/core/
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
867
|
+
//#region src/core/drivers/index.ts
|
|
868
|
+
/**
|
|
869
|
+
* Accepts a `databaseType` (e.g. PostgreSQL, SQLite) and a `driverName`
|
|
870
|
+
* (the library name, e.g. pg, sqlite3) and combines them to a singular
|
|
871
|
+
* `databaseDriverType` which can be used in database handling.
|
|
872
|
+
*/
|
|
873
|
+
function toDatabaseDriverType(databaseType, driverName) {
|
|
874
|
+
return `${databaseType}:${driverName}`;
|
|
875
|
+
}
|
|
876
|
+
/**
|
|
877
|
+
* Accepts a fully formatted `driverType` and returns the broken down
|
|
878
|
+
* `databaseType` and `driverName`.
|
|
879
|
+
*/
|
|
880
|
+
function fromDatabaseDriverType(databaseDriverType) {
|
|
881
|
+
const parts = databaseDriverType.split(":");
|
|
882
|
+
return {
|
|
883
|
+
databaseType: parts[0],
|
|
884
|
+
driverName: parts[1]
|
|
1098
885
|
};
|
|
1099
|
-
const resultFormatter = {
|
|
1100
|
-
format: format ?? ((sql, methodOptions) => formatSQL(sql, resultFormatter, methodOptions?.serializer ?? JSONSerializer, {
|
|
1101
|
-
...options,
|
|
1102
|
-
...methodOptions ?? {}
|
|
1103
|
-
})),
|
|
1104
|
-
describe: describe ?? ((sql, methodOptions) => describeSQL(sql, resultFormatter, methodOptions?.serializer ?? JSONSerializer, {
|
|
1105
|
-
...options,
|
|
1106
|
-
...methodOptions ?? {}
|
|
1107
|
-
})),
|
|
1108
|
-
valueMapper
|
|
1109
|
-
};
|
|
1110
|
-
return resultFormatter;
|
|
1111
|
-
};
|
|
1112
|
-
const dumboSQLFormatters = globalThis.dumboSQLFormatters = globalThis.dumboSQLFormatters ?? {};
|
|
1113
|
-
const registerFormatter = (dialect, formatter) => {
|
|
1114
|
-
dumboSQLFormatters[dialect] = formatter;
|
|
1115
|
-
};
|
|
1116
|
-
const getFormatter = (dialect) => {
|
|
1117
|
-
const formatterKey = dialect;
|
|
1118
|
-
if (!dumboSQLFormatters[formatterKey]) throw new Error(`No SQL formatter registered for dialect: ${dialect}`);
|
|
1119
|
-
return dumboSQLFormatters[formatterKey];
|
|
1120
|
-
};
|
|
1121
|
-
function formatSQL(sql, formatter, serializer, context) {
|
|
1122
|
-
const mapper = context?.mapper == void 0 ? formatter.valueMapper : {
|
|
1123
|
-
...formatter.valueMapper,
|
|
1124
|
-
...context.mapper
|
|
1125
|
-
};
|
|
1126
|
-
const processorsRegistry = context?.processorsRegistry ?? defaultProcessorsRegistry;
|
|
1127
|
-
const merged = Array.isArray(sql) ? SQL.merge(sql, "\n") : sql;
|
|
1128
|
-
if (!isTokenizedSQL(merged)) throw new Error("Expected TokenizedSQL, got string-based SQL");
|
|
1129
|
-
const builder = ParametrizedSQLBuilder({ mapParamPlaceholder: mapper.mapPlaceholder });
|
|
1130
|
-
let paramIndex = 0;
|
|
1131
|
-
for (let i = 0; i < merged.sqlChunks.length; i++) {
|
|
1132
|
-
const sqlChunk = merged.sqlChunks[i];
|
|
1133
|
-
if (sqlChunk !== TokenizedSQL.paramPlaceholder) {
|
|
1134
|
-
builder.addSQL(sqlChunk);
|
|
1135
|
-
continue;
|
|
1136
|
-
}
|
|
1137
|
-
const token = merged.sqlTokens[paramIndex++];
|
|
1138
|
-
const processor = processorsRegistry.get(token.sqlTokenType);
|
|
1139
|
-
if (!processor) throw new Error(`No SQL processor registered for token type: ${token.sqlTokenType}`);
|
|
1140
|
-
processor.handle(token, {
|
|
1141
|
-
builder,
|
|
1142
|
-
processorsRegistry,
|
|
1143
|
-
serializer,
|
|
1144
|
-
mapper
|
|
1145
|
-
});
|
|
1146
|
-
}
|
|
1147
|
-
return builder.build();
|
|
1148
886
|
}
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
green: (value) => enableColors ? ansis.green(value) : value,
|
|
1164
|
-
blue: (value) => enableColors ? ansis.blue(value) : value,
|
|
1165
|
-
cyan: (value) => enableColors ? ansis.cyan(value) : value,
|
|
1166
|
-
yellow: (value) => enableColors ? ansis.yellow(value) : value
|
|
1167
|
-
};
|
|
887
|
+
/**
|
|
888
|
+
* Accepts a fully formatted `databaseDriverType` and returns the `driverName`.
|
|
889
|
+
*/
|
|
890
|
+
function getDatabaseDriverName(databaseDriverType) {
|
|
891
|
+
const { driverName } = fromDatabaseDriverType(databaseDriverType);
|
|
892
|
+
return driverName;
|
|
893
|
+
}
|
|
894
|
+
/**
|
|
895
|
+
* Accepts a fully formatted `databaseDriverType` and returns the `databaseType`.
|
|
896
|
+
*/
|
|
897
|
+
function getDatabaseType(databaseDriverType) {
|
|
898
|
+
const { databaseType } = fromDatabaseDriverType(databaseDriverType);
|
|
899
|
+
return databaseType;
|
|
900
|
+
}
|
|
1168
901
|
|
|
1169
902
|
//#endregion
|
|
1170
|
-
//#region src/core/
|
|
1171
|
-
const
|
|
1172
|
-
const
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
const COLOR_BRACKETS = color.hex("#abb2bf");
|
|
1178
|
-
const processString = (str, indent, handleMultiline) => {
|
|
1179
|
-
if (handleMultiline && str.includes("\n")) {
|
|
1180
|
-
const indentedLines = str.split("\n").map((line) => indent + TWO_SPACES + COLOR_STRING(line));
|
|
1181
|
-
return COLOR_STRING("\"") + "\n" + indentedLines.join("\n") + "\n" + indent + COLOR_STRING("\"");
|
|
1182
|
-
}
|
|
1183
|
-
return COLOR_STRING(`"${str}"`);
|
|
1184
|
-
};
|
|
1185
|
-
const shouldPrint = (obj) => typeof obj !== "function" && typeof obj !== "symbol";
|
|
1186
|
-
const formatJson = (obj, indentLevel = 0, handleMultiline = false) => {
|
|
1187
|
-
const indent = TWO_SPACES.repeat(indentLevel);
|
|
1188
|
-
if (obj === null) return COLOR_NULL_OR_UNDEFINED("null");
|
|
1189
|
-
if (obj === void 0) return COLOR_NULL_OR_UNDEFINED("undefined");
|
|
1190
|
-
if (typeof obj === "string") return processString(obj, indent, handleMultiline);
|
|
1191
|
-
if (typeof obj === "number" || typeof obj === "bigint" || obj instanceof Date) return COLOR_NUMBER_OR_DATE(String(obj));
|
|
1192
|
-
if (typeof obj === "boolean") return COLOR_BOOLEAN(String(obj));
|
|
1193
|
-
if (obj instanceof Error) {
|
|
1194
|
-
const errorObj = {};
|
|
1195
|
-
Object.getOwnPropertyNames(obj).forEach((key) => {
|
|
1196
|
-
errorObj[key] = obj[key];
|
|
1197
|
-
});
|
|
1198
|
-
return formatJson(errorObj, indentLevel, handleMultiline);
|
|
1199
|
-
}
|
|
1200
|
-
if (obj instanceof Promise) return COLOR_STRING("Promise {pending}");
|
|
1201
|
-
if (Array.isArray(obj)) {
|
|
1202
|
-
const arrayItems = obj.map((item) => formatJson(item, indentLevel + 1, handleMultiline));
|
|
1203
|
-
return `${COLOR_BRACKETS("[")}\n${indent} ${arrayItems.join(`,\n${indent} `)}\n${indent}${COLOR_BRACKETS("]")}`;
|
|
1204
|
-
}
|
|
1205
|
-
const entries = Object.entries(obj).filter(([_, value]) => shouldPrint(value)).map(([key, value]) => `${COLOR_KEY(`"${key}"`)}: ${formatJson(value, indentLevel + 1, handleMultiline)}`);
|
|
1206
|
-
return `${COLOR_BRACKETS("{")}\n${indent} ${entries.join(`,\n${indent} `)}\n${indent}${COLOR_BRACKETS("}")}`;
|
|
903
|
+
//#region src/core/locks/databaseLock.ts
|
|
904
|
+
const defaultDatabaseLockOptions = { timeoutMs: 1e4 };
|
|
905
|
+
const NoDatabaseLock = {
|
|
906
|
+
acquire: () => Promise.resolve(),
|
|
907
|
+
tryAcquire: () => Promise.resolve(true),
|
|
908
|
+
release: () => Promise.resolve(true),
|
|
909
|
+
withAcquire: (_execute, handle, _options) => handle()
|
|
1207
910
|
};
|
|
1208
|
-
const prettyJson = (obj, options) => formatJson(obj, 0, options?.handleMultiline);
|
|
1209
911
|
|
|
1210
912
|
//#endregion
|
|
1211
|
-
//#region src/core/
|
|
1212
|
-
const
|
|
1213
|
-
const
|
|
1214
|
-
|
|
1215
|
-
INFO: "INFO",
|
|
1216
|
-
LOG: "LOG",
|
|
1217
|
-
WARN: "WARN",
|
|
1218
|
-
ERROR: "ERROR"
|
|
1219
|
-
};
|
|
1220
|
-
const LogStyle = {
|
|
1221
|
-
RAW: "RAW",
|
|
1222
|
-
PRETTY: "PRETTY"
|
|
913
|
+
//#region src/core/query/selectors.ts
|
|
914
|
+
const firstOrNull = async (getResult) => {
|
|
915
|
+
const result = await getResult;
|
|
916
|
+
return result.rows.length > 0 ? result.rows[0] ?? null : null;
|
|
1223
917
|
};
|
|
1224
|
-
const
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
} catch {
|
|
1229
|
-
return;
|
|
1230
|
-
}
|
|
918
|
+
const first = async (getResult) => {
|
|
919
|
+
const result = await getResult;
|
|
920
|
+
if (result.rows.length === 0) throw new Error("Query didn't return any result");
|
|
921
|
+
return result.rows[0];
|
|
1231
922
|
};
|
|
1232
|
-
const
|
|
1233
|
-
const
|
|
1234
|
-
if (
|
|
1235
|
-
|
|
1236
|
-
if (definedLogLevel === LogLevel.LOG && [
|
|
1237
|
-
LogLevel.ERROR,
|
|
1238
|
-
LogLevel.WARN,
|
|
1239
|
-
LogLevel.LOG
|
|
1240
|
-
].includes(logLevel)) return true;
|
|
1241
|
-
if (definedLogLevel === LogLevel.INFO && [
|
|
1242
|
-
LogLevel.ERROR,
|
|
1243
|
-
LogLevel.WARN,
|
|
1244
|
-
LogLevel.LOG,
|
|
1245
|
-
LogLevel.INFO
|
|
1246
|
-
].includes(logLevel)) return true;
|
|
1247
|
-
return false;
|
|
923
|
+
const singleOrNull = async (getResult) => {
|
|
924
|
+
const result = await getResult;
|
|
925
|
+
if (result.rows.length > 1) throw new Error("Query had more than one result");
|
|
926
|
+
return result.rows.length > 0 ? result.rows[0] ?? null : null;
|
|
1248
927
|
};
|
|
1249
|
-
const
|
|
1250
|
-
const
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
}
|
|
928
|
+
const single = async (getResult) => {
|
|
929
|
+
const result = await getResult;
|
|
930
|
+
if (result.rows.length === 0) throw new Error("Query didn't return any result");
|
|
931
|
+
if (result.rows.length > 1) throw new Error("Query had more than one result");
|
|
932
|
+
return result.rows[0];
|
|
1255
933
|
};
|
|
1256
|
-
const
|
|
1257
|
-
const
|
|
1258
|
-
|
|
1259
|
-
case "DISABLED": return nulloTraceEventRecorder;
|
|
1260
|
-
case "INFO": return (event) => console.info(format(event));
|
|
1261
|
-
case "LOG": return (event) => console.log(format(event));
|
|
1262
|
-
case "WARN": return (event) => console.warn(format(event));
|
|
1263
|
-
case "ERROR": return (event) => console.error(format(event));
|
|
1264
|
-
}
|
|
934
|
+
const count = async (getResult) => {
|
|
935
|
+
const result = await single(getResult);
|
|
936
|
+
return Number(result.count);
|
|
1265
937
|
};
|
|
1266
|
-
const
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
name: eventName,
|
|
1270
|
-
timestamp: (/* @__PURE__ */ new Date()).getTime(),
|
|
1271
|
-
...attributes
|
|
1272
|
-
};
|
|
1273
|
-
getTraceEventRecorder(logLevel, getEnvVariable("DUMBO_LOG_STYLE") ?? "RAW")(event);
|
|
938
|
+
const exists = async (getResult) => {
|
|
939
|
+
const result = await single(getResult);
|
|
940
|
+
return result.exists === true || result.exists === 1;
|
|
1274
941
|
};
|
|
1275
|
-
tracer.info = (eventName, attributes) => recordTraceEvent(LogLevel.INFO, eventName, attributes);
|
|
1276
|
-
tracer.warn = (eventName, attributes) => recordTraceEvent(LogLevel.WARN, eventName, attributes);
|
|
1277
|
-
tracer.log = (eventName, attributes) => recordTraceEvent(LogLevel.LOG, eventName, attributes);
|
|
1278
|
-
tracer.error = (eventName, attributes) => recordTraceEvent(LogLevel.ERROR, eventName, attributes);
|
|
1279
|
-
|
|
1280
|
-
//#endregion
|
|
1281
|
-
//#region src/core/schema/sqlMigration.ts
|
|
1282
|
-
const sqlMigration = (name, sqls) => ({
|
|
1283
|
-
name,
|
|
1284
|
-
sqls
|
|
1285
|
-
});
|
|
1286
942
|
|
|
1287
943
|
//#endregion
|
|
1288
|
-
//#region src/core/schema/
|
|
1289
|
-
const
|
|
1290
|
-
const
|
|
1291
|
-
|
|
1292
|
-
id ${AutoIncrement({ primaryKey: true })},
|
|
1293
|
-
name ${Varchar(255)} NOT NULL UNIQUE,
|
|
1294
|
-
application ${Varchar(255)} NOT NULL DEFAULT 'default',
|
|
1295
|
-
sql_hash ${Varchar(64)} NOT NULL,
|
|
1296
|
-
timestamp ${Timestamp} NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
1297
|
-
);
|
|
1298
|
-
`;
|
|
1299
|
-
const migrationTableSchemaComponent = schemaComponent("dumbo:schema-component:migrations-table", { migrations: [sqlMigration("dumbo:migrationTable:001", [migrationTableSQL])] });
|
|
1300
|
-
const SchemaComponentMigrator = (component, dumbo) => {
|
|
1301
|
-
const completedMigrations = [];
|
|
944
|
+
//#region src/core/schema/schemaComponent.ts
|
|
945
|
+
const schemaComponent = (key, options) => {
|
|
946
|
+
const componentsMap = new Map(options.components?.map((comp) => [comp.schemaComponentKey, comp]));
|
|
947
|
+
const migrations = [...options.migrations ?? []];
|
|
1302
948
|
return {
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
949
|
+
schemaComponentKey: key,
|
|
950
|
+
components: componentsMap,
|
|
951
|
+
get migrations() {
|
|
952
|
+
return [...migrations, ...Array.from(componentsMap.values()).flatMap((c) => c.migrations)];
|
|
953
|
+
},
|
|
954
|
+
addComponent: (component) => {
|
|
955
|
+
componentsMap.set(component.schemaComponentKey, component);
|
|
956
|
+
migrations.push(...component.migrations);
|
|
957
|
+
return component;
|
|
958
|
+
},
|
|
959
|
+
addMigration: (migration) => {
|
|
960
|
+
migrations.push(migration);
|
|
1309
961
|
}
|
|
1310
962
|
};
|
|
1311
963
|
};
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
const
|
|
1316
|
-
const
|
|
1317
|
-
const
|
|
1318
|
-
|
|
964
|
+
const isSchemaComponentOfType = (component, prefix) => component.schemaComponentKey.startsWith(prefix);
|
|
965
|
+
const filterSchemaComponentsOfType = (components, prefix) => mapSchemaComponentsOfType(components, prefix);
|
|
966
|
+
const mapSchemaComponentsOfType = (components, prefix, keyMapper) => new Map(Array.from(components.entries()).filter(([urn]) => urn.startsWith(prefix)).map(([urn, component]) => [keyMapper ? keyMapper(component) : urn, component]));
|
|
967
|
+
const findSchemaComponentsOfType = (root, prefix) => {
|
|
968
|
+
const results = [];
|
|
969
|
+
const traverse = (component) => {
|
|
970
|
+
if (component.schemaComponentKey.startsWith(prefix)) results.push(component);
|
|
971
|
+
for (const child of component.components.values()) traverse(child);
|
|
972
|
+
};
|
|
973
|
+
traverse(root);
|
|
974
|
+
return results;
|
|
1319
975
|
};
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
976
|
+
|
|
977
|
+
//#endregion
|
|
978
|
+
//#region src/core/schema/components/columnSchemaComponent.ts
|
|
979
|
+
const ColumnURNType = "sc:dumbo:column";
|
|
980
|
+
const ColumnURN = ({ name }) => `${ColumnURNType}:${name}`;
|
|
981
|
+
const columnSchemaComponent = (params) => {
|
|
982
|
+
const { columnName, type, notNull, unique, primaryKey, default: defaultValue, ...schemaOptions } = params;
|
|
983
|
+
return {
|
|
984
|
+
...schemaComponent(ColumnURN({ name: columnName }), schemaOptions),
|
|
985
|
+
columnName,
|
|
986
|
+
notNull,
|
|
987
|
+
unique,
|
|
988
|
+
primaryKey,
|
|
989
|
+
defaultValue,
|
|
990
|
+
sqlTokenType: "SQL_COLUMN",
|
|
991
|
+
name: columnName,
|
|
992
|
+
type
|
|
993
|
+
};
|
|
1323
994
|
};
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
...
|
|
1334
|
-
},
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
options: {
|
|
1339
|
-
lockId: MIGRATIONS_LOCK_ID,
|
|
1340
|
-
...defaultOptions.lock?.options,
|
|
1341
|
-
...partialOptions?.lock?.options
|
|
1342
|
-
}
|
|
995
|
+
|
|
996
|
+
//#endregion
|
|
997
|
+
//#region src/core/schema/components/indexSchemaComponent.ts
|
|
998
|
+
const IndexURNType = "sc:dumbo:index";
|
|
999
|
+
const IndexURN = ({ name }) => `${IndexURNType}:${name}`;
|
|
1000
|
+
const indexSchemaComponent = ({ indexName, columnNames, isUnique, ...migrationsOrComponents }) => {
|
|
1001
|
+
return {
|
|
1002
|
+
...schemaComponent(IndexURN({ name: indexName }), {
|
|
1003
|
+
migrations: migrationsOrComponents.migrations ?? [],
|
|
1004
|
+
components: [...migrationsOrComponents.components ?? []]
|
|
1005
|
+
}),
|
|
1006
|
+
indexName,
|
|
1007
|
+
get columnNames() {
|
|
1008
|
+
return columnNames;
|
|
1343
1009
|
},
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
migrationTimeoutMs: defaultOptions.migrationTimeoutMs ?? partialOptions?.migrationTimeoutMs
|
|
1347
|
-
};
|
|
1348
|
-
const { databaseLock: _, ...rest } = options.lock ?? {};
|
|
1349
|
-
const databaseLock = options.lock?.databaseLock ?? NoDatabaseLock;
|
|
1350
|
-
const lockOptions = {
|
|
1351
|
-
lockId: MIGRATIONS_LOCK_ID,
|
|
1352
|
-
...rest
|
|
1353
|
-
};
|
|
1354
|
-
const coreMigrations = (options.schema?.migrationTable ?? migrationTableSchemaComponent).migrations;
|
|
1355
|
-
const result = {
|
|
1356
|
-
applied: [],
|
|
1357
|
-
skipped: []
|
|
1010
|
+
addColumn: (column) => columnNames.push(typeof column === "string" ? column : column.columnName),
|
|
1011
|
+
isUnique
|
|
1358
1012
|
};
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
}
|
|
1013
|
+
};
|
|
1014
|
+
|
|
1015
|
+
//#endregion
|
|
1016
|
+
//#region src/core/schema/components/tableSchemaComponent.ts
|
|
1017
|
+
const TableURNType = "sc:dumbo:table";
|
|
1018
|
+
const TableURN = ({ name }) => `${TableURNType}:${name}`;
|
|
1019
|
+
const tableSchemaComponent = ({ tableName, columns, primaryKey, relationships, ...migrationsOrComponents }) => {
|
|
1020
|
+
columns ??= {};
|
|
1021
|
+
relationships ??= {};
|
|
1022
|
+
const base = schemaComponent(TableURN({ name: tableName }), {
|
|
1023
|
+
migrations: migrationsOrComponents.migrations ?? [],
|
|
1024
|
+
components: [...migrationsOrComponents.components ?? [], ...Object.values(columns)]
|
|
1025
|
+
});
|
|
1367
1026
|
return {
|
|
1368
|
-
|
|
1369
|
-
|
|
1027
|
+
...base,
|
|
1028
|
+
tableName,
|
|
1029
|
+
primaryKey: primaryKey ?? [],
|
|
1030
|
+
relationships,
|
|
1031
|
+
get columns() {
|
|
1032
|
+
const columnsMap = mapSchemaComponentsOfType(base.components, ColumnURNType, (c) => c.columnName);
|
|
1033
|
+
return Object.assign(columnsMap, columns);
|
|
1034
|
+
},
|
|
1035
|
+
get indexes() {
|
|
1036
|
+
return mapSchemaComponentsOfType(base.components, IndexURNType, (c) => c.indexName);
|
|
1037
|
+
},
|
|
1038
|
+
addColumn: (column) => base.addComponent(column),
|
|
1039
|
+
addIndex: (index) => base.addComponent(index)
|
|
1370
1040
|
};
|
|
1371
|
-
});
|
|
1372
|
-
const runSQLMigration = async (databaseType, execute, migration, options) => {
|
|
1373
|
-
const sqls = combineMigrations(migration);
|
|
1374
|
-
const sqlHash = await getMigrationHash(migration, getFormatter(databaseType));
|
|
1375
|
-
try {
|
|
1376
|
-
const newMigration = {
|
|
1377
|
-
name: migration.name,
|
|
1378
|
-
sqlHash
|
|
1379
|
-
};
|
|
1380
|
-
const checkResult = await ensureMigrationWasNotAppliedYet(execute, newMigration);
|
|
1381
|
-
if (checkResult.exists === true) {
|
|
1382
|
-
if (checkResult.hashesMatch === true) {
|
|
1383
|
-
tracer.info("migration-already-applied", { migrationName: migration.name });
|
|
1384
|
-
return false;
|
|
1385
|
-
}
|
|
1386
|
-
if (options?.ignoreMigrationHashMismatch !== true) throw new Error(`Migration hash mismatch for "${migration.name}". Aborting migration.`);
|
|
1387
|
-
tracer.warn("migration-hash-mismatch", {
|
|
1388
|
-
migrationName: migration.name,
|
|
1389
|
-
expectedHash: sqlHash,
|
|
1390
|
-
actualHash: checkResult.hashFromDB
|
|
1391
|
-
});
|
|
1392
|
-
await updateMigrationHash(execute, newMigration);
|
|
1393
|
-
return false;
|
|
1394
|
-
}
|
|
1395
|
-
await execute.batchCommand(sqls, { timeoutMs: options?.migrationTimeoutMs });
|
|
1396
|
-
await recordMigration(execute, newMigration);
|
|
1397
|
-
return true;
|
|
1398
|
-
} catch (error) {
|
|
1399
|
-
tracer.error("migration-error", {
|
|
1400
|
-
migationName: migration.name,
|
|
1401
|
-
error
|
|
1402
|
-
});
|
|
1403
|
-
throw error;
|
|
1404
|
-
}
|
|
1405
|
-
};
|
|
1406
|
-
const getMigrationHash = async (sqlMigration, sqlFormatter) => {
|
|
1407
|
-
const content = sqlFormatter.describe(sqlMigration.sqls, { serializer: JSONSerializer });
|
|
1408
|
-
const data = new TextEncoder().encode(content);
|
|
1409
|
-
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
1410
|
-
return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1411
1041
|
};
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1042
|
+
|
|
1043
|
+
//#endregion
|
|
1044
|
+
//#region src/core/schema/components/databaseSchemaSchemaComponent.ts
|
|
1045
|
+
const DatabaseSchemaURNType = "sc:dumbo:database_schema";
|
|
1046
|
+
const DatabaseSchemaURN = ({ name }) => `${DatabaseSchemaURNType}:${name}`;
|
|
1047
|
+
const databaseSchemaSchemaComponent = ({ schemaName, tables, ...migrationsOrComponents }) => {
|
|
1048
|
+
const base = schemaComponent(DatabaseSchemaURN({ name: schemaName }), {
|
|
1049
|
+
migrations: migrationsOrComponents.migrations ?? [],
|
|
1050
|
+
components: [...migrationsOrComponents.components ?? [], ...Object.values(tables ?? {})]
|
|
1051
|
+
});
|
|
1417
1052
|
return {
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1053
|
+
...base,
|
|
1054
|
+
schemaName,
|
|
1055
|
+
get tables() {
|
|
1056
|
+
const tablesMap = mapSchemaComponentsOfType(base.components, TableURNType, (c) => c.tableName);
|
|
1057
|
+
return Object.assign(tablesMap, tables);
|
|
1058
|
+
},
|
|
1059
|
+
addTable: (table) => base.addComponent(typeof table === "string" ? tableSchemaComponent({ tableName: table }) : table)
|
|
1421
1060
|
};
|
|
1422
1061
|
};
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
}
|
|
1428
|
-
const
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1062
|
+
|
|
1063
|
+
//#endregion
|
|
1064
|
+
//#region src/core/schema/components/databaseSchemaComponent.ts
|
|
1065
|
+
const DatabaseURNType = "sc:dumbo:database";
|
|
1066
|
+
const DatabaseURN = ({ name }) => `${DatabaseURNType}:${name}`;
|
|
1067
|
+
const databaseSchemaComponent = ({ databaseName, schemas, ...migrationsOrComponents }) => {
|
|
1068
|
+
schemas ??= {};
|
|
1069
|
+
const base = schemaComponent(DatabaseURN({ name: databaseName }), {
|
|
1070
|
+
migrations: migrationsOrComponents.migrations ?? [],
|
|
1071
|
+
components: [...migrationsOrComponents.components ?? [], ...Object.values(schemas)]
|
|
1072
|
+
});
|
|
1073
|
+
return {
|
|
1074
|
+
...base,
|
|
1075
|
+
databaseName,
|
|
1076
|
+
get schemas() {
|
|
1077
|
+
const schemasMap = mapSchemaComponentsOfType(base.components, DatabaseSchemaURNType, (c) => c.schemaName);
|
|
1078
|
+
return Object.assign(schemasMap, schemas);
|
|
1079
|
+
},
|
|
1080
|
+
addSchema: (schema) => base.addComponent(typeof schema === "string" ? databaseSchemaSchemaComponent({ schemaName: schema }) : schema)
|
|
1081
|
+
};
|
|
1434
1082
|
};
|
|
1435
1083
|
|
|
1436
1084
|
//#endregion
|
|
1437
|
-
//#region src/core/
|
|
1438
|
-
const
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
const errorCode = options && typeof options === "object" && "errorCode" in options ? options.errorCode : isNumber(options) ? options : DumboError.ErrorCode;
|
|
1448
|
-
const errorType = options && typeof options === "object" && "errorType" in options ? options.errorType ?? DumboError.ErrorType : DumboError.ErrorType;
|
|
1449
|
-
const message = options && typeof options === "object" && "message" in options ? options.message : isString(options) ? options : `Error with status code '${errorCode}' ocurred during DumboError processing`;
|
|
1450
|
-
const innerError = options && typeof options === "object" && "innerError" in options ? options.innerError : void 0;
|
|
1451
|
-
super(message, { cause: innerError });
|
|
1452
|
-
this.errorCode = errorCode;
|
|
1453
|
-
this.errorType = errorType;
|
|
1454
|
-
this.innerError = innerError;
|
|
1455
|
-
Object.setPrototypeOf(this, DumboError.prototype);
|
|
1456
|
-
}
|
|
1457
|
-
static isInstanceOf(error, options) {
|
|
1458
|
-
if (typeof error !== "object" || error === null || !("errorCode" in error) || !isNumber(error.errorCode) || !("errorType" in error) || !isString(error.errorType)) return false;
|
|
1459
|
-
if (!options) return true;
|
|
1460
|
-
if (options.errorCode !== void 0 && error.errorCode !== options.errorCode) return false;
|
|
1461
|
-
if (options.errorType !== void 0 && error.errorType !== options.errorType) return false;
|
|
1462
|
-
return true;
|
|
1085
|
+
//#region src/core/schema/components/index.ts
|
|
1086
|
+
const schemaComponentURN = {
|
|
1087
|
+
database: DatabaseURN,
|
|
1088
|
+
schema: DatabaseSchemaURN,
|
|
1089
|
+
table: TableURN,
|
|
1090
|
+
column: ColumnURN,
|
|
1091
|
+
index: IndexURN,
|
|
1092
|
+
extractName: (urn) => {
|
|
1093
|
+
const parts = urn.split(":");
|
|
1094
|
+
return parts[parts.length - 1] || "";
|
|
1463
1095
|
}
|
|
1464
1096
|
};
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1097
|
+
|
|
1098
|
+
//#endregion
|
|
1099
|
+
//#region src/core/schema/databaseMetadata/databaseMetadata.ts
|
|
1100
|
+
const DumboDatabaseMetadataRegistry = () => {
|
|
1101
|
+
const infos = /* @__PURE__ */ new Map();
|
|
1102
|
+
const register = (databaseType, info) => {
|
|
1103
|
+
const entry = infos.get(databaseType);
|
|
1104
|
+
if (entry && (typeof entry !== "function" || typeof info === "function")) return;
|
|
1105
|
+
infos.set(databaseType, info);
|
|
1106
|
+
};
|
|
1107
|
+
const tryResolve = async (databaseType) => {
|
|
1108
|
+
const entry = infos.get(databaseType);
|
|
1109
|
+
if (!entry) return null;
|
|
1110
|
+
if (typeof entry !== "function") return entry;
|
|
1111
|
+
const resolved = await entry();
|
|
1112
|
+
register(databaseType, resolved);
|
|
1113
|
+
return resolved;
|
|
1114
|
+
};
|
|
1115
|
+
const tryGet = (databaseType) => {
|
|
1116
|
+
const entry = infos.get(databaseType);
|
|
1117
|
+
return entry && typeof entry !== "function" ? entry : null;
|
|
1118
|
+
};
|
|
1119
|
+
const has = (databaseType) => infos.has(databaseType);
|
|
1120
|
+
return {
|
|
1121
|
+
register,
|
|
1122
|
+
tryResolve,
|
|
1123
|
+
tryGet,
|
|
1124
|
+
has,
|
|
1125
|
+
get databaseTypes() {
|
|
1126
|
+
return Array.from(infos.keys());
|
|
1127
|
+
}
|
|
1128
|
+
};
|
|
1477
1129
|
};
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
super({
|
|
1483
|
-
errorCode: TransientDatabaseError.ErrorCode,
|
|
1484
|
-
errorType: TransientDatabaseError.ErrorType,
|
|
1485
|
-
message: message ?? `A transient error occurred during database operation. Retrying the operation might succeed.`,
|
|
1486
|
-
innerError
|
|
1487
|
-
});
|
|
1488
|
-
Object.setPrototypeOf(this, TransientDatabaseError.prototype);
|
|
1489
|
-
}
|
|
1130
|
+
const dumboDatabaseMetadataRegistry = globalThis.dumboDatabaseMetadataRegistry = globalThis.dumboDatabaseMetadataRegistry ?? DumboDatabaseMetadataRegistry();
|
|
1131
|
+
const getDatabaseMetadata = (driverType) => {
|
|
1132
|
+
const { databaseType } = fromDatabaseDriverType(driverType);
|
|
1133
|
+
return dumboDatabaseMetadataRegistry.tryGet(databaseType);
|
|
1490
1134
|
};
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
super(message ?? `A connection error occurred during database operation.`, innerError);
|
|
1496
|
-
this.errorType = ConnectionError.ErrorType;
|
|
1497
|
-
Object.setPrototypeOf(this, ConnectionError.prototype);
|
|
1498
|
-
}
|
|
1135
|
+
const resolveDatabaseMetadata = async (driverType, driverOverride) => {
|
|
1136
|
+
if (driverOverride) return driverOverride;
|
|
1137
|
+
const { databaseType } = fromDatabaseDriverType(driverType);
|
|
1138
|
+
return dumboDatabaseMetadataRegistry.tryResolve(databaseType);
|
|
1499
1139
|
};
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
static ErrorType = "SerializationError";
|
|
1503
|
-
constructor(message, innerError) {
|
|
1504
|
-
super(message ?? `A serialization failure occurred. The transaction can be retried.`, innerError);
|
|
1505
|
-
this.errorType = SerializationError.ErrorType;
|
|
1506
|
-
Object.setPrototypeOf(this, SerializationError.prototype);
|
|
1507
|
-
}
|
|
1140
|
+
const getDefaultDatabase = (driverType) => {
|
|
1141
|
+
return getDatabaseMetadata(driverType)?.defaultDatabaseName;
|
|
1508
1142
|
};
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
static ErrorType = "DeadlockError";
|
|
1512
|
-
constructor(message, innerError) {
|
|
1513
|
-
super(message ?? `A deadlock was detected. The transaction can be retried.`, innerError);
|
|
1514
|
-
this.errorType = DeadlockError.ErrorType;
|
|
1515
|
-
Object.setPrototypeOf(this, DeadlockError.prototype);
|
|
1516
|
-
}
|
|
1143
|
+
const getDefaultDatabaseAsync = async (driverType) => {
|
|
1144
|
+
return (await resolveDatabaseMetadata(driverType))?.defaultDatabaseName;
|
|
1517
1145
|
};
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1146
|
+
|
|
1147
|
+
//#endregion
|
|
1148
|
+
//#region src/core/schema/dumboSchema/dumboSchema.ts
|
|
1149
|
+
const DEFAULT_DATABASE_NAME = "__default_database__";
|
|
1150
|
+
const DEFAULT_DATABASE_SCHEMA_NAME = "__default_database_schema__";
|
|
1151
|
+
const dumboColumn = (name, type, options) => columnSchemaComponent({
|
|
1152
|
+
columnName: name,
|
|
1153
|
+
type,
|
|
1154
|
+
...options
|
|
1155
|
+
});
|
|
1156
|
+
const dumboIndex = (name, columnNames, options) => indexSchemaComponent({
|
|
1157
|
+
indexName: name,
|
|
1158
|
+
columnNames,
|
|
1159
|
+
isUnique: options?.unique ?? false,
|
|
1160
|
+
...options
|
|
1161
|
+
});
|
|
1162
|
+
const dumboTable = (name, definition) => {
|
|
1163
|
+
const { columns, indexes, primaryKey, relationships, ...options } = definition;
|
|
1164
|
+
const components = [...indexes ? Object.values(indexes) : []];
|
|
1165
|
+
return tableSchemaComponent({
|
|
1166
|
+
tableName: name,
|
|
1167
|
+
columns: columns ?? {},
|
|
1168
|
+
primaryKey: primaryKey ?? [],
|
|
1169
|
+
...relationships !== void 0 ? { relationships } : {},
|
|
1170
|
+
components,
|
|
1171
|
+
...options
|
|
1172
|
+
});
|
|
1526
1173
|
};
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1174
|
+
function dumboDatabaseSchema(nameOrTables, tables, options) {
|
|
1175
|
+
return databaseSchemaSchemaComponent({
|
|
1176
|
+
schemaName: typeof nameOrTables === "string" ? nameOrTables : DEFAULT_DATABASE_SCHEMA_NAME,
|
|
1177
|
+
tables: (typeof nameOrTables === "string" ? tables : nameOrTables) ?? {},
|
|
1178
|
+
...options
|
|
1179
|
+
});
|
|
1180
|
+
}
|
|
1181
|
+
dumboDatabaseSchema.from = (schemaName, tableNames) => {
|
|
1182
|
+
const tables = tableNames.reduce((acc, tableName) => {
|
|
1183
|
+
acc[tableName] = dumboTable(tableName, {});
|
|
1184
|
+
return acc;
|
|
1185
|
+
}, {});
|
|
1186
|
+
return schemaName ? dumboDatabaseSchema(schemaName, tables) : dumboDatabaseSchema(tables);
|
|
1535
1187
|
};
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
}
|
|
1188
|
+
function dumboDatabase(nameOrSchemas, schemasOrOptions, options) {
|
|
1189
|
+
const databaseName = typeof nameOrSchemas === "string" ? nameOrSchemas : DEFAULT_DATABASE_NAME;
|
|
1190
|
+
const schemasOrSchema = typeof nameOrSchemas === "string" ? schemasOrOptions ?? {} : nameOrSchemas;
|
|
1191
|
+
return databaseSchemaComponent({
|
|
1192
|
+
databaseName,
|
|
1193
|
+
schemas: "schemaComponentKey" in schemasOrSchema && isSchemaComponentOfType(schemasOrSchema, "sc:dumbo:database_schema") ? { [DEFAULT_DATABASE_SCHEMA_NAME]: schemasOrSchema } : schemasOrSchema,
|
|
1194
|
+
...typeof nameOrSchemas === "string" ? options : schemasOrOptions
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
1197
|
+
dumboDatabase.from = (databaseName, schemaNames) => {
|
|
1198
|
+
const schemas = schemaNames.reduce((acc, schemaName) => {
|
|
1199
|
+
acc[schemaName] = dumboDatabaseSchema(schemaName, {});
|
|
1200
|
+
return acc;
|
|
1201
|
+
}, {});
|
|
1202
|
+
return databaseName ? dumboDatabase(databaseName, schemas) : dumboDatabase(schemas);
|
|
1544
1203
|
};
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1204
|
+
dumboDatabase.defaultName = DEFAULT_DATABASE_NAME;
|
|
1205
|
+
dumboDatabaseSchema.defaultName = DEFAULT_DATABASE_SCHEMA_NAME;
|
|
1206
|
+
const dumboSchema = {
|
|
1207
|
+
database: dumboDatabase,
|
|
1208
|
+
schema: dumboDatabaseSchema,
|
|
1209
|
+
table: dumboTable,
|
|
1210
|
+
column: dumboColumn,
|
|
1211
|
+
index: dumboIndex
|
|
1553
1212
|
};
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
this.errorType = QueryCanceledError.ErrorType;
|
|
1560
|
-
Object.setPrototypeOf(this, QueryCanceledError.prototype);
|
|
1561
|
-
}
|
|
1213
|
+
|
|
1214
|
+
//#endregion
|
|
1215
|
+
//#region src/core/serializer/json/index.ts
|
|
1216
|
+
const bigIntReplacer = (_key, value) => {
|
|
1217
|
+
return typeof value === "bigint" ? value.toString() : value;
|
|
1562
1218
|
};
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
static ErrorType = "IntegrityConstraintViolationError";
|
|
1566
|
-
constructor(message, innerError) {
|
|
1567
|
-
super({
|
|
1568
|
-
errorCode: IntegrityConstraintViolationError.ErrorCode,
|
|
1569
|
-
errorType: IntegrityConstraintViolationError.ErrorType,
|
|
1570
|
-
message: message ?? `An integrity constraint violation occurred!`,
|
|
1571
|
-
innerError
|
|
1572
|
-
});
|
|
1573
|
-
Object.setPrototypeOf(this, IntegrityConstraintViolationError.prototype);
|
|
1574
|
-
}
|
|
1219
|
+
const dateReplacer = (_key, value) => {
|
|
1220
|
+
return value instanceof Date ? value.toISOString() : value;
|
|
1575
1221
|
};
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
constructor(message, innerError) {
|
|
1580
|
-
super(message ?? `Unique constraint violation occurred!`, innerError);
|
|
1581
|
-
this.errorType = UniqueConstraintError.ErrorType;
|
|
1582
|
-
Object.setPrototypeOf(this, UniqueConstraintError.prototype);
|
|
1583
|
-
}
|
|
1222
|
+
const isFirstLetterNumeric = (str) => {
|
|
1223
|
+
const c = str.charCodeAt(0);
|
|
1224
|
+
return c >= 48 && c <= 57;
|
|
1584
1225
|
};
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
constructor(message, innerError) {
|
|
1589
|
-
super(message ?? `Foreign key constraint violation occurred!`, innerError);
|
|
1590
|
-
this.errorType = ForeignKeyViolationError.ErrorType;
|
|
1591
|
-
Object.setPrototypeOf(this, ForeignKeyViolationError.prototype);
|
|
1592
|
-
}
|
|
1226
|
+
const isFirstLetterNumericOrMinus = (str) => {
|
|
1227
|
+
const c = str.charCodeAt(0);
|
|
1228
|
+
return c >= 48 && c <= 57 || c === 45;
|
|
1593
1229
|
};
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1230
|
+
const bigIntReviver = (_key, value, context) => {
|
|
1231
|
+
if (typeof value === "number" && Number.isInteger(value) && !Number.isSafeInteger(value)) try {
|
|
1232
|
+
return BigInt(context?.source ?? value.toString());
|
|
1233
|
+
} catch {
|
|
1234
|
+
return value;
|
|
1235
|
+
}
|
|
1236
|
+
if (typeof value === "string" && value.length > 15) {
|
|
1237
|
+
if (isFirstLetterNumericOrMinus(value)) {
|
|
1238
|
+
const num = Number(value);
|
|
1239
|
+
if (Number.isFinite(num) && !Number.isSafeInteger(num)) try {
|
|
1240
|
+
return BigInt(value);
|
|
1241
|
+
} catch {}
|
|
1242
|
+
}
|
|
1601
1243
|
}
|
|
1244
|
+
return value;
|
|
1602
1245
|
};
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
super(message ?? `CHECK constraint violation occurred!`, innerError);
|
|
1608
|
-
this.errorType = CheckViolationError.ErrorType;
|
|
1609
|
-
Object.setPrototypeOf(this, CheckViolationError.prototype);
|
|
1610
|
-
}
|
|
1611
|
-
};
|
|
1612
|
-
var ExclusionViolationError = class ExclusionViolationError extends IntegrityConstraintViolationError {
|
|
1613
|
-
static ErrorCode = 409;
|
|
1614
|
-
static ErrorType = "ExclusionViolationError";
|
|
1615
|
-
constructor(message, innerError) {
|
|
1616
|
-
super(message ?? `Exclusion constraint violation occurred!`, innerError);
|
|
1617
|
-
this.errorType = ExclusionViolationError.ErrorType;
|
|
1618
|
-
Object.setPrototypeOf(this, ExclusionViolationError.prototype);
|
|
1619
|
-
}
|
|
1620
|
-
};
|
|
1621
|
-
var DataError = class DataError extends DumboError {
|
|
1622
|
-
static ErrorCode = 400;
|
|
1623
|
-
static ErrorType = "DataError";
|
|
1624
|
-
constructor(message, innerError) {
|
|
1625
|
-
super({
|
|
1626
|
-
errorCode: DataError.ErrorCode,
|
|
1627
|
-
errorType: DataError.ErrorType,
|
|
1628
|
-
message: message ?? `A data error occurred (e.g. invalid value, type mismatch).`,
|
|
1629
|
-
innerError
|
|
1630
|
-
});
|
|
1631
|
-
Object.setPrototypeOf(this, DataError.prototype);
|
|
1246
|
+
const dateReviver = (_key, value) => {
|
|
1247
|
+
if (typeof value === "string" && value.length === 24 && isFirstLetterNumeric(value) && value[10] === "T" && value[23] === "Z") {
|
|
1248
|
+
const date = new Date(value);
|
|
1249
|
+
if (!isNaN(date.getTime())) return date;
|
|
1632
1250
|
}
|
|
1251
|
+
return value;
|
|
1633
1252
|
};
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
super({
|
|
1639
|
-
errorCode: InvalidOperationError.ErrorCode,
|
|
1640
|
-
errorType: InvalidOperationError.ErrorType,
|
|
1641
|
-
message: message ?? `Invalid operation (e.g. syntax error, insufficient privileges, undefined table).`,
|
|
1642
|
-
innerError
|
|
1643
|
-
});
|
|
1644
|
-
Object.setPrototypeOf(this, InvalidOperationError.prototype);
|
|
1645
|
-
}
|
|
1253
|
+
const composeJSONReplacers = (...replacers) => {
|
|
1254
|
+
const filteredReplacers = replacers.filter((r) => r !== void 0);
|
|
1255
|
+
if (filteredReplacers.length === 0) return void 0;
|
|
1256
|
+
return (key, value) => filteredReplacers.reduce((accValue, replacer) => replacer(key, accValue), value);
|
|
1646
1257
|
};
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
if (typeof value === "string") try {
|
|
1652
|
-
return serializer.deserialize(value, options);
|
|
1653
|
-
} catch {}
|
|
1654
|
-
return value;
|
|
1655
|
-
} });
|
|
1656
|
-
const mapColumnToBigint = (column) => ({ [column]: (value) => {
|
|
1657
|
-
if (typeof value === "number" || typeof value === "string") return BigInt(value);
|
|
1658
|
-
return value;
|
|
1659
|
-
} });
|
|
1660
|
-
const mapColumnToDate = (column) => ({ [column]: (value) => {
|
|
1661
|
-
if (typeof value === "number" || typeof value === "string") return new Date(value);
|
|
1662
|
-
return value;
|
|
1663
|
-
} });
|
|
1664
|
-
const mapSQLQueryResult = (result, mapping) => {
|
|
1665
|
-
if (typeof result !== "object" || result === null) return result;
|
|
1666
|
-
const mappedResult = { ...result };
|
|
1667
|
-
for (const column of Object.keys(mapping)) if (column in mappedResult) mappedResult[column] = mapping[column](mappedResult[column]);
|
|
1668
|
-
return mappedResult;
|
|
1258
|
+
const composeJSONRevivers = (...revivers) => {
|
|
1259
|
+
const filteredRevivers = revivers.filter((r) => r !== void 0);
|
|
1260
|
+
if (filteredRevivers.length === 0) return void 0;
|
|
1261
|
+
return (key, value, context) => filteredRevivers.reduce((accValue, reviver) => reviver(key, accValue, context), value);
|
|
1669
1262
|
};
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
message: `Batch command at index ${statementIndex} affected no rows`
|
|
1676
|
-
});
|
|
1677
|
-
this.name = "BatchCommandNoChangesError";
|
|
1678
|
-
this.statementIndex = statementIndex;
|
|
1679
|
-
Object.setPrototypeOf(this, BatchCommandNoChangesError.prototype);
|
|
1680
|
-
}
|
|
1263
|
+
const JSONReplacer = (opts) => composeJSONReplacers(opts?.replacer, opts?.failOnBigIntSerialization !== true ? JSONReplacers.bigInt : void 0, opts?.useDefaultDateSerialization !== true ? JSONReplacers.date : void 0);
|
|
1264
|
+
const JSONReviver = (opts) => composeJSONRevivers(opts?.reviver, opts?.parseBigInts === true ? JSONRevivers.bigInt : void 0, opts?.parseDates === true ? JSONRevivers.date : void 0);
|
|
1265
|
+
const JSONReplacers = {
|
|
1266
|
+
bigInt: bigIntReplacer,
|
|
1267
|
+
date: dateReplacer
|
|
1681
1268
|
};
|
|
1682
|
-
const
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
command: (sql, commandOptions) => executeInNewDbClient((client) => sqlExecutor.command(client, sql, commandOptions), options),
|
|
1686
|
-
batchCommand: (sqls, commandOptions) => executeInNewDbClient((client) => sqlExecutor.batchCommand(client, sqls, commandOptions), options)
|
|
1687
|
-
});
|
|
1688
|
-
const sqlExecutorInNewConnection = (options) => ({
|
|
1689
|
-
query: (sql, queryOptions) => executeInNewConnection((connection) => connection.execute.query(sql, queryOptions), options),
|
|
1690
|
-
batchQuery: (sqls, queryOptions) => executeInNewConnection((connection) => connection.execute.batchQuery(sqls, queryOptions), options),
|
|
1691
|
-
command: (sql, commandOptions) => executeInNewConnection((connection) => connection.execute.command(sql, commandOptions), options),
|
|
1692
|
-
batchCommand: (sqls, commandOptions) => executeInNewConnection((connection) => connection.execute.batchCommand(sqls, commandOptions), options)
|
|
1693
|
-
});
|
|
1694
|
-
const sqlExecutorInAmbientConnection = (options) => ({
|
|
1695
|
-
query: (sql, queryOptions) => executeInAmbientConnection((connection) => connection.execute.query(sql, queryOptions), options),
|
|
1696
|
-
batchQuery: (sqls, queryOptions) => executeInAmbientConnection((connection) => connection.execute.batchQuery(sqls, queryOptions), options),
|
|
1697
|
-
command: (sql, commandOptions) => executeInAmbientConnection((connection) => connection.execute.command(sql, commandOptions), options),
|
|
1698
|
-
batchCommand: (sqls, commandOptions) => executeInAmbientConnection((connection) => connection.execute.batchCommand(sqls, commandOptions), options)
|
|
1699
|
-
});
|
|
1700
|
-
const executeInNewDbClient = async (handle, options) => {
|
|
1701
|
-
const { connect, close } = options;
|
|
1702
|
-
const client = await connect();
|
|
1703
|
-
try {
|
|
1704
|
-
return await handle(client);
|
|
1705
|
-
} catch (error) {
|
|
1706
|
-
if (close) await close(client, error);
|
|
1707
|
-
throw error;
|
|
1708
|
-
}
|
|
1269
|
+
const JSONRevivers = {
|
|
1270
|
+
bigInt: bigIntReviver,
|
|
1271
|
+
date: dateReviver
|
|
1709
1272
|
};
|
|
1710
|
-
const
|
|
1711
|
-
const
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
}
|
|
1273
|
+
const jsonSerializer = (options) => {
|
|
1274
|
+
const defaultReplacer = JSONReplacer(options);
|
|
1275
|
+
const defaultReviver = JSONReviver(options);
|
|
1276
|
+
return {
|
|
1277
|
+
serialize: (object, serializerOptions) => JSON.stringify(object, serializerOptions ? JSONReplacer(serializerOptions) : defaultReplacer),
|
|
1278
|
+
deserialize: (payload, deserializerOptions) => JSON.parse(payload, deserializerOptions ? JSONReviver(deserializerOptions) : defaultReviver)
|
|
1279
|
+
};
|
|
1717
1280
|
};
|
|
1718
|
-
const
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1281
|
+
const JSONSerializer = Object.assign(jsonSerializer(), { from: (options) => options?.serialization?.serializer ?? (options?.serialization?.options ? jsonSerializer(options?.serialization?.options) : JSONSerializer) });
|
|
1282
|
+
const JSONCodec = (options) => {
|
|
1283
|
+
const serializer = "serializer" in options ? options.serializer : jsonSerializer("serializerOptions" in options ? options.serializerOptions : void 0);
|
|
1284
|
+
const upcast = options.upcast ?? ((doc) => doc);
|
|
1285
|
+
const downcast = options.downcast ?? ((doc) => doc);
|
|
1286
|
+
return {
|
|
1287
|
+
decode: (payload, decodeOptions) => {
|
|
1288
|
+
return upcast(decodeOptions ? serializer.deserialize(payload, decodeOptions) : serializer.deserialize(payload));
|
|
1289
|
+
},
|
|
1290
|
+
encode: (object, encodeOptions) => {
|
|
1291
|
+
const downcasted = downcast(object);
|
|
1292
|
+
return encodeOptions ? serializer.serialize(downcasted, encodeOptions) : serializer.serialize(downcasted);
|
|
1293
|
+
}
|
|
1294
|
+
};
|
|
1723
1295
|
};
|
|
1724
1296
|
|
|
1725
1297
|
//#endregion
|
|
1726
|
-
//#region src/core/
|
|
1727
|
-
const
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
};
|
|
1731
|
-
const executeInTransaction = async (transaction, handle) => {
|
|
1732
|
-
await transaction.begin();
|
|
1733
|
-
try {
|
|
1734
|
-
const { success, result } = toTransactionResult(await handle(transaction));
|
|
1735
|
-
if (success) await transaction.commit();
|
|
1736
|
-
else await transaction.rollback();
|
|
1737
|
-
return result;
|
|
1738
|
-
} catch (e) {
|
|
1739
|
-
await transaction.rollback();
|
|
1740
|
-
throw e;
|
|
1741
|
-
}
|
|
1742
|
-
};
|
|
1743
|
-
const transactionFactoryWithDbClient = (connect, initTransaction) => {
|
|
1744
|
-
let currentTransaction = void 0;
|
|
1745
|
-
const getOrInitCurrentTransaction = (options) => currentTransaction ?? (currentTransaction = initTransaction(connect(), {
|
|
1746
|
-
close: () => {
|
|
1747
|
-
currentTransaction = void 0;
|
|
1748
|
-
return Promise.resolve();
|
|
1749
|
-
},
|
|
1750
|
-
...options ?? {}
|
|
1751
|
-
}));
|
|
1298
|
+
//#region src/core/sql/parametrizedSQL/parametrizedSQL.ts
|
|
1299
|
+
const ParametrizedSQLBuilder = ({ mapParamPlaceholder }) => {
|
|
1300
|
+
const sql = [];
|
|
1301
|
+
const params = [];
|
|
1752
1302
|
return {
|
|
1753
|
-
|
|
1754
|
-
|
|
1303
|
+
addSQL(str) {
|
|
1304
|
+
sql.push(str);
|
|
1305
|
+
return this;
|
|
1306
|
+
},
|
|
1307
|
+
addParam(value) {
|
|
1308
|
+
sql.push(mapParamPlaceholder(params.length, value));
|
|
1309
|
+
params.push(value);
|
|
1310
|
+
return this;
|
|
1311
|
+
},
|
|
1312
|
+
addParams(values) {
|
|
1313
|
+
const placeholders = values.map((value, i) => mapParamPlaceholder(params.length + i, value));
|
|
1314
|
+
this.addSQL(`${placeholders.join(", ")}`);
|
|
1315
|
+
params.push(...values);
|
|
1316
|
+
return this;
|
|
1317
|
+
},
|
|
1318
|
+
build() {
|
|
1319
|
+
return {
|
|
1320
|
+
query: sql.join(""),
|
|
1321
|
+
params
|
|
1322
|
+
};
|
|
1323
|
+
}
|
|
1755
1324
|
};
|
|
1756
1325
|
};
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
const transaction = connection.transaction(options);
|
|
1326
|
+
|
|
1327
|
+
//#endregion
|
|
1328
|
+
//#region src/core/sql/tokens/sqlToken.ts
|
|
1329
|
+
const SQLToken = (sqlTokenType, map) => {
|
|
1330
|
+
const factory = (input) => {
|
|
1331
|
+
let props;
|
|
1332
|
+
if (map !== void 0) props = map(input);
|
|
1333
|
+
else if (input === void 0 || input === null) props = {};
|
|
1334
|
+
else if (typeof input === "object" && !Array.isArray(input)) props = input;
|
|
1335
|
+
else throw new Error(`Cannot create SQLToken of type ${sqlTokenType} with input: ${input}`);
|
|
1768
1336
|
return {
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1337
|
+
sqlTokenType,
|
|
1338
|
+
[sqlTokenType]: true,
|
|
1339
|
+
...props
|
|
1772
1340
|
};
|
|
1773
|
-
}
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1341
|
+
};
|
|
1342
|
+
const check = (token) => SQLToken.check(token) && token.sqlTokenType === sqlTokenType;
|
|
1343
|
+
return {
|
|
1344
|
+
from: factory,
|
|
1345
|
+
check,
|
|
1346
|
+
type: sqlTokenType
|
|
1347
|
+
};
|
|
1348
|
+
};
|
|
1349
|
+
SQLToken.check = (token) => token !== null && typeof token === "object" && "sqlTokenType" in token;
|
|
1350
|
+
const SQLIdentifier = SQLToken("SQL_IDENTIFIER", (value) => ({ value }));
|
|
1351
|
+
const SQLPlain = SQLToken("SQL_RAW", (value) => ({ value }));
|
|
1352
|
+
const SQLLiteral = SQLToken("SQL_LITERAL", (value) => ({ value }));
|
|
1353
|
+
const SQLArray = SQLToken("SQL_ARRAY", (input) => {
|
|
1354
|
+
if (Array.isArray(input)) return { value: input };
|
|
1355
|
+
return input.mode !== void 0 ? {
|
|
1356
|
+
value: input.value,
|
|
1357
|
+
mode: input.mode
|
|
1358
|
+
} : { value: input.value };
|
|
1779
1359
|
});
|
|
1780
|
-
const
|
|
1781
|
-
|
|
1782
|
-
|
|
1360
|
+
const SQLIn = SQLToken("SQL_IN", ({ column, values, mode }) => mode !== void 0 ? {
|
|
1361
|
+
column: SQLIdentifier.from(column),
|
|
1362
|
+
values: SQLArray.from(values),
|
|
1363
|
+
mode
|
|
1364
|
+
} : {
|
|
1365
|
+
column: SQLIdentifier.from(column),
|
|
1366
|
+
values: SQLArray.from(values)
|
|
1367
|
+
});
|
|
1368
|
+
|
|
1369
|
+
//#endregion
|
|
1370
|
+
//#region src/core/sql/tokens/columnTokens.ts
|
|
1371
|
+
const ColumnTypeToken = (sqlTokenType, jsTypeName, map) => {
|
|
1372
|
+
const factory = (input) => {
|
|
1373
|
+
let props;
|
|
1374
|
+
if (map !== void 0) props = map(input);
|
|
1375
|
+
else if (input === void 0 || input === null) props = {};
|
|
1376
|
+
else if (typeof input === "object" && !Array.isArray(input)) props = input;
|
|
1377
|
+
else throw new Error(`Cannot create SQLToken of type ${sqlTokenType} with input: ${input}`);
|
|
1783
1378
|
return {
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1379
|
+
sqlTokenType,
|
|
1380
|
+
[sqlTokenType]: true,
|
|
1381
|
+
jsTypeName,
|
|
1382
|
+
...props
|
|
1383
|
+
};
|
|
1384
|
+
};
|
|
1385
|
+
const check = (token) => SQLToken.check(token) && token.sqlTokenType === sqlTokenType;
|
|
1386
|
+
return {
|
|
1387
|
+
from: factory,
|
|
1388
|
+
check,
|
|
1389
|
+
type: sqlTokenType
|
|
1390
|
+
};
|
|
1391
|
+
};
|
|
1392
|
+
const SerialToken = ColumnTypeToken("SQL_COLUMN_SERIAL", "value_type:js:number");
|
|
1393
|
+
const BigSerialToken = ColumnTypeToken("SQL_COLUMN_BIGSERIAL", "value_type:js:bigint");
|
|
1394
|
+
const IntegerToken = ColumnTypeToken("SQL_COLUMN_INTEGER", "value_type:js:number");
|
|
1395
|
+
const BigIntegerToken = ColumnTypeToken("SQL_COLUMN_BIGINT", "value_type:js:bigint");
|
|
1396
|
+
const JSONBToken = {
|
|
1397
|
+
type: "SQL_COLUMN_JSONB",
|
|
1398
|
+
from: () => {
|
|
1399
|
+
return {
|
|
1400
|
+
sqlTokenType: "SQL_COLUMN_JSONB",
|
|
1401
|
+
["SQL_COLUMN_JSONB"]: true
|
|
1787
1402
|
};
|
|
1788
1403
|
},
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1404
|
+
check: (token) => SQLToken.check(token) && token.sqlTokenType === "SQL_COLUMN_JSONB"
|
|
1405
|
+
};
|
|
1406
|
+
const TimestampToken = ColumnTypeToken("SQL_COLUMN_TIMESTAMP", "value_type:js:date");
|
|
1407
|
+
const TimestamptzToken = ColumnTypeToken("SQL_COLUMN_TIMESTAMPTZ", "value_type:js:date");
|
|
1408
|
+
const VarcharToken = ColumnTypeToken("SQL_COLUMN_VARCHAR", "value_type:js:string", (length) => ({
|
|
1409
|
+
length: length ?? "max",
|
|
1410
|
+
jsTypeName: "value_type:js:string"
|
|
1411
|
+
}));
|
|
1412
|
+
const AutoIncrementSQLColumnToken = ColumnTypeToken("SQL_COLUMN_AUTO_INCREMENT", "value_type:js:bigint");
|
|
1413
|
+
const SQLColumnTypeTokens = {
|
|
1414
|
+
AutoIncrement: AutoIncrementSQLColumnToken,
|
|
1415
|
+
BigInteger: BigIntegerToken,
|
|
1416
|
+
BigSerial: BigSerialToken,
|
|
1417
|
+
Integer: IntegerToken,
|
|
1418
|
+
JSONB: JSONBToken,
|
|
1419
|
+
Serial: SerialToken,
|
|
1420
|
+
Timestamp: TimestampToken,
|
|
1421
|
+
Timestamptz: TimestamptzToken,
|
|
1422
|
+
Varchar: VarcharToken
|
|
1423
|
+
};
|
|
1424
|
+
const SQLColumnTypeTokensFactory = {
|
|
1425
|
+
AutoIncrement: AutoIncrementSQLColumnToken.from,
|
|
1426
|
+
BigInteger: BigIntegerToken.from(),
|
|
1427
|
+
BigSerial: BigSerialToken.from(),
|
|
1428
|
+
Integer: IntegerToken.from(),
|
|
1429
|
+
JSONB: JSONBToken.from,
|
|
1430
|
+
Serial: SerialToken.from(),
|
|
1431
|
+
Timestamp: TimestampToken.from(),
|
|
1432
|
+
Timestamptz: TimestamptzToken.from(),
|
|
1433
|
+
Varchar: VarcharToken.from
|
|
1434
|
+
};
|
|
1435
|
+
const SQLColumnToken = SQLToken("SQL_COLUMN");
|
|
1436
|
+
|
|
1437
|
+
//#endregion
|
|
1438
|
+
//#region src/core/sql/processors/sqlProcessor.ts
|
|
1439
|
+
const SQLProcessor = (options) => options;
|
|
1440
|
+
|
|
1441
|
+
//#endregion
|
|
1442
|
+
//#region src/core/sql/processors/defaultProcessors.ts
|
|
1443
|
+
const ExpandArrayProcessor = SQLProcessor({
|
|
1444
|
+
canHandle: "SQL_ARRAY",
|
|
1445
|
+
handle: (token, { builder, serializer, mapper }) => {
|
|
1446
|
+
if (token.value.length === 0) throw new Error("Empty arrays are not supported. If you're using it with SELECT IN statement Use SQL.in(column, array) helper instead.");
|
|
1447
|
+
builder.addParams(mapper.mapValue(token.value, serializer));
|
|
1792
1448
|
}
|
|
1793
1449
|
});
|
|
1794
|
-
const
|
|
1795
|
-
|
|
1450
|
+
const ExpandSQLInProcessor = SQLProcessor({
|
|
1451
|
+
canHandle: "SQL_IN",
|
|
1452
|
+
handle: (token, context) => {
|
|
1453
|
+
const { builder, mapper, processorsRegistry, serializer } = context;
|
|
1454
|
+
const { values: inValues, column } = token;
|
|
1455
|
+
if (inValues.value.length === 0) {
|
|
1456
|
+
builder.addParam(mapper.mapValue(false, serializer));
|
|
1457
|
+
return;
|
|
1458
|
+
}
|
|
1459
|
+
builder.addSQL(mapper.mapValue(column.value, serializer));
|
|
1460
|
+
builder.addSQL(` IN (`);
|
|
1461
|
+
const arrayProcessor = processorsRegistry.get(SQLArray.type);
|
|
1462
|
+
if (!arrayProcessor) throw new Error("No sql processor registered for an array. Cannot expand IN statement");
|
|
1463
|
+
arrayProcessor.handle(inValues, {
|
|
1464
|
+
builder,
|
|
1465
|
+
mapper,
|
|
1466
|
+
processorsRegistry,
|
|
1467
|
+
serializer
|
|
1468
|
+
});
|
|
1469
|
+
builder.addSQL(`)`);
|
|
1470
|
+
}
|
|
1471
|
+
});
|
|
1472
|
+
const FormatIdentifierProcessor = SQLProcessor({
|
|
1473
|
+
canHandle: "SQL_IDENTIFIER",
|
|
1474
|
+
handle: (token, { builder, mapper, serializer }) => {
|
|
1475
|
+
builder.addSQL(mapper.mapValue(token, serializer));
|
|
1476
|
+
}
|
|
1477
|
+
});
|
|
1478
|
+
const MapLiteralProcessor = SQLProcessor({
|
|
1479
|
+
canHandle: "SQL_LITERAL",
|
|
1480
|
+
handle: (token, { builder, mapper, serializer }) => builder.addParam(mapper.mapValue(token.value, serializer))
|
|
1481
|
+
});
|
|
1482
|
+
|
|
1483
|
+
//#endregion
|
|
1484
|
+
//#region src/core/sql/processors/sqlProcessorRegistry.ts
|
|
1485
|
+
const SQLProcessorsRegistry = (options) => {
|
|
1486
|
+
const processors = options ? new Map(options.from.all()) : /* @__PURE__ */ new Map();
|
|
1487
|
+
function register(...args) {
|
|
1488
|
+
if (args.length === 1 && typeof args[0] === "object" && !Array.isArray(args[0])) Object.entries(args[0]).forEach(([_, processor]) => {
|
|
1489
|
+
processors.set(processor.canHandle, processor);
|
|
1490
|
+
});
|
|
1491
|
+
else args.forEach((p) => processors.set(p.canHandle, p));
|
|
1492
|
+
return registry;
|
|
1493
|
+
}
|
|
1494
|
+
const registry = {
|
|
1495
|
+
register,
|
|
1496
|
+
get: (tokenType) => {
|
|
1497
|
+
return processors.get(tokenType) ?? null;
|
|
1498
|
+
},
|
|
1499
|
+
all: () => processors
|
|
1500
|
+
};
|
|
1501
|
+
return registry;
|
|
1502
|
+
};
|
|
1503
|
+
|
|
1504
|
+
//#endregion
|
|
1505
|
+
//#region src/core/sql/processors/columnProcessors.ts
|
|
1506
|
+
const mapDefaultSQLColumnProcessors = (mapColumnType) => ({
|
|
1507
|
+
AutoIncrement: SQLProcessor({
|
|
1508
|
+
canHandle: "SQL_COLUMN_AUTO_INCREMENT",
|
|
1509
|
+
handle: (token, context) => {
|
|
1510
|
+
mapColumnType(token, context);
|
|
1511
|
+
}
|
|
1512
|
+
}),
|
|
1513
|
+
BigInteger: SQLProcessor({
|
|
1514
|
+
canHandle: "SQL_COLUMN_BIGINT",
|
|
1515
|
+
handle: (token, context) => mapColumnType(token, context)
|
|
1516
|
+
}),
|
|
1517
|
+
BigSerial: SQLProcessor({
|
|
1518
|
+
canHandle: "SQL_COLUMN_BIGSERIAL",
|
|
1519
|
+
handle: (token, context) => mapColumnType(token, context)
|
|
1520
|
+
}),
|
|
1521
|
+
Serial: SQLProcessor({
|
|
1522
|
+
canHandle: "SQL_COLUMN_SERIAL",
|
|
1523
|
+
handle: (token, context) => mapColumnType(token, context)
|
|
1524
|
+
}),
|
|
1525
|
+
Integer: SQLProcessor({
|
|
1526
|
+
canHandle: "SQL_COLUMN_INTEGER",
|
|
1527
|
+
handle: (token, context) => mapColumnType(token, context)
|
|
1528
|
+
}),
|
|
1529
|
+
JSONB: SQLProcessor({
|
|
1530
|
+
canHandle: "SQL_COLUMN_JSONB",
|
|
1531
|
+
handle: (token, context) => mapColumnType(token, context)
|
|
1532
|
+
}),
|
|
1533
|
+
Timestamp: SQLProcessor({
|
|
1534
|
+
canHandle: "SQL_COLUMN_TIMESTAMP",
|
|
1535
|
+
handle: (token, context) => mapColumnType(token, context)
|
|
1536
|
+
}),
|
|
1537
|
+
Timestamptz: SQLProcessor({
|
|
1538
|
+
canHandle: "SQL_COLUMN_TIMESTAMPTZ",
|
|
1539
|
+
handle: (token, context) => mapColumnType(token, context)
|
|
1540
|
+
}),
|
|
1541
|
+
Varchar: SQLProcessor({
|
|
1542
|
+
canHandle: "SQL_COLUMN_VARCHAR",
|
|
1543
|
+
handle: (token, context) => mapColumnType(token, context)
|
|
1544
|
+
})
|
|
1545
|
+
});
|
|
1546
|
+
|
|
1547
|
+
//#endregion
|
|
1548
|
+
//#region src/core/sql/processors/index.ts
|
|
1549
|
+
const defaultProcessorsRegistry = globalThis.defaultProcessorsRegistry = globalThis.defaultProcessorsRegistry ?? SQLProcessorsRegistry().register(FormatIdentifierProcessor, MapLiteralProcessor, ExpandArrayProcessor, ExpandSQLInProcessor);
|
|
1550
|
+
|
|
1551
|
+
//#endregion
|
|
1552
|
+
//#region src/core/sql/tokenizedSQL/tokenizedSQL.ts
|
|
1553
|
+
const TokenizedSQLBuilder = () => {
|
|
1554
|
+
const sqlChunks = [];
|
|
1555
|
+
const sqlTokens = [];
|
|
1796
1556
|
return {
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
let innerTx = null;
|
|
1800
|
-
let connectingPromise = null;
|
|
1801
|
-
const ensureConnection = async () => {
|
|
1802
|
-
if (conn) return innerTx;
|
|
1803
|
-
if (!connectingPromise) connectingPromise = (async () => {
|
|
1804
|
-
conn = await connect();
|
|
1805
|
-
innerTx = conn.transaction(options);
|
|
1806
|
-
})();
|
|
1807
|
-
await connectingPromise;
|
|
1808
|
-
return innerTx;
|
|
1809
|
-
};
|
|
1810
|
-
return {
|
|
1811
|
-
driverType,
|
|
1812
|
-
get connection() {
|
|
1813
|
-
if (!conn) throw new Error("Transaction not started - call begin() first");
|
|
1814
|
-
return conn;
|
|
1815
|
-
},
|
|
1816
|
-
execute: {
|
|
1817
|
-
query: async (sql, queryOptions) => {
|
|
1818
|
-
return (await ensureConnection()).execute.query(sql, queryOptions);
|
|
1819
|
-
},
|
|
1820
|
-
batchQuery: async (sqls, queryOptions) => {
|
|
1821
|
-
return (await ensureConnection()).execute.batchQuery(sqls, queryOptions);
|
|
1822
|
-
},
|
|
1823
|
-
command: async (sql, commandOptions) => {
|
|
1824
|
-
return (await ensureConnection()).execute.command(sql, commandOptions);
|
|
1825
|
-
},
|
|
1826
|
-
batchCommand: async (sqls, commandOptions) => {
|
|
1827
|
-
return (await ensureConnection()).execute.batchCommand(sqls, commandOptions);
|
|
1828
|
-
}
|
|
1829
|
-
},
|
|
1830
|
-
begin: async () => {
|
|
1831
|
-
return (await ensureConnection()).begin();
|
|
1832
|
-
},
|
|
1833
|
-
commit: async () => {
|
|
1834
|
-
if (!innerTx) throw new Error("Transaction not started");
|
|
1835
|
-
try {
|
|
1836
|
-
return await innerTx.commit();
|
|
1837
|
-
} finally {
|
|
1838
|
-
if (conn) await close(conn);
|
|
1839
|
-
}
|
|
1840
|
-
},
|
|
1841
|
-
rollback: async (error) => {
|
|
1842
|
-
if (!innerTx) {
|
|
1843
|
-
if (conn) await close(conn);
|
|
1844
|
-
return;
|
|
1845
|
-
}
|
|
1846
|
-
try {
|
|
1847
|
-
return await innerTx.rollback(error);
|
|
1848
|
-
} finally {
|
|
1849
|
-
if (conn) await close(conn);
|
|
1850
|
-
}
|
|
1851
|
-
},
|
|
1852
|
-
_transactionOptions: void 0
|
|
1853
|
-
};
|
|
1557
|
+
addSQL(str) {
|
|
1558
|
+
sqlChunks.push(str);
|
|
1854
1559
|
},
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1560
|
+
addSQLs(str) {
|
|
1561
|
+
sqlChunks.push(...str);
|
|
1562
|
+
},
|
|
1563
|
+
addToken(value) {
|
|
1564
|
+
sqlTokens.push(value);
|
|
1565
|
+
},
|
|
1566
|
+
addTokens(vals) {
|
|
1567
|
+
sqlTokens.push(...vals);
|
|
1568
|
+
},
|
|
1569
|
+
build() {
|
|
1570
|
+
return sqlChunks.length > 0 ? {
|
|
1571
|
+
__brand: "tokenized-sql",
|
|
1572
|
+
sqlChunks,
|
|
1573
|
+
sqlTokens
|
|
1574
|
+
} : TokenizedSQL.empty;
|
|
1863
1575
|
}
|
|
1864
1576
|
};
|
|
1865
1577
|
};
|
|
1578
|
+
const TokenizedSQL = (strings, values) => {
|
|
1579
|
+
const builder = TokenizedSQLBuilder();
|
|
1580
|
+
for (let i = 0; i < strings.length; i++) {
|
|
1581
|
+
if (strings[i] !== "") builder.addSQL(strings[i]);
|
|
1582
|
+
if (i >= values.length) break;
|
|
1583
|
+
const value = values[i];
|
|
1584
|
+
if (isTokenizedSQL(value)) {
|
|
1585
|
+
builder.addSQLs(value.sqlChunks);
|
|
1586
|
+
builder.addTokens(value.sqlTokens);
|
|
1587
|
+
} else if (SQLPlain.check(value)) builder.addSQL(value.value);
|
|
1588
|
+
else {
|
|
1589
|
+
builder.addSQL(TokenizedSQL.paramPlaceholder);
|
|
1590
|
+
builder.addToken(SQLToken.check(value) ? value : Array.isArray(value) ? SQLArray.from(value) : SQLLiteral.from(value));
|
|
1591
|
+
}
|
|
1592
|
+
}
|
|
1593
|
+
return builder.build();
|
|
1594
|
+
};
|
|
1595
|
+
const isTokenizedSQL = (value) => {
|
|
1596
|
+
return value !== null && typeof value === "object" && "__brand" in value && value.__brand === "tokenized-sql";
|
|
1597
|
+
};
|
|
1598
|
+
TokenizedSQL.paramPlaceholder = `__P__`;
|
|
1599
|
+
TokenizedSQL.empty = {
|
|
1600
|
+
__brand: "tokenized-sql",
|
|
1601
|
+
sqlChunks: [""],
|
|
1602
|
+
sqlTokens: []
|
|
1603
|
+
};
|
|
1604
|
+
|
|
1605
|
+
//#endregion
|
|
1606
|
+
//#region src/core/sql/sql.ts
|
|
1607
|
+
const createSQL = (strings, ...values) => {
|
|
1608
|
+
return TokenizedSQL(strings, values);
|
|
1609
|
+
};
|
|
1610
|
+
/**
|
|
1611
|
+
* Creates SQL by interpolating values directly into the statement.
|
|
1612
|
+
*
|
|
1613
|
+
* Prefer {@link SQL} for query execution. `RawSQL` is for trusted SQL text that
|
|
1614
|
+
* is already safe to inline.
|
|
1615
|
+
*/
|
|
1616
|
+
function RawSQL(strings, ...values) {
|
|
1617
|
+
let result = "";
|
|
1618
|
+
for (let i = 0; i < strings.length; i++) {
|
|
1619
|
+
result += strings[i];
|
|
1620
|
+
if (i < values.length) result += String(values[i]);
|
|
1621
|
+
}
|
|
1622
|
+
return {
|
|
1623
|
+
__brand: "tokenized-sql",
|
|
1624
|
+
sqlChunks: [result],
|
|
1625
|
+
sqlTokens: []
|
|
1626
|
+
};
|
|
1627
|
+
}
|
|
1628
|
+
/** Returns true when the value is a tokenized SQL statement. */
|
|
1629
|
+
const isSQL = (value) => {
|
|
1630
|
+
if (value === void 0 || value === null) return false;
|
|
1631
|
+
return isTokenizedSQL(value);
|
|
1632
|
+
};
|
|
1633
|
+
const emptySQL = {
|
|
1634
|
+
__brand: "tokenized-sql",
|
|
1635
|
+
sqlChunks: [""],
|
|
1636
|
+
sqlTokens: []
|
|
1637
|
+
};
|
|
1638
|
+
const mergeSQL = (sqls, separator = " ") => {
|
|
1639
|
+
const parametrized = sqls.filter((sql) => !isEmpty(sql)).map((sql) => sql);
|
|
1640
|
+
const params = parametrized.flatMap((p) => p.sqlTokens);
|
|
1641
|
+
const sqlChunks = parametrized.flatMap((p, i) => i == parametrized.length - 1 || separator === "" ? p.sqlChunks : [...p.sqlChunks, separator]);
|
|
1642
|
+
return sqlChunks.length > 0 ? {
|
|
1643
|
+
__brand: "tokenized-sql",
|
|
1644
|
+
sqlChunks,
|
|
1645
|
+
sqlTokens: params
|
|
1646
|
+
} : TokenizedSQL.empty;
|
|
1647
|
+
};
|
|
1648
|
+
const concatSQL = (...sqls) => mergeSQL(sqls, "");
|
|
1649
|
+
const literal = (value) => SQLPlain.from(`'${value.replace(/'/g, "''")}'`);
|
|
1650
|
+
const isEmpty = (sql) => {
|
|
1651
|
+
if (isTokenizedSQL(sql)) {
|
|
1652
|
+
const parametrized = sql;
|
|
1653
|
+
return parametrized.sqlChunks.every((chunk) => chunk.trim() === "") && parametrized.sqlTokens.length === 0;
|
|
1654
|
+
}
|
|
1655
|
+
return false;
|
|
1656
|
+
};
|
|
1657
|
+
const columnFactory = SQLColumnToken.from;
|
|
1658
|
+
columnFactory.type = SQLColumnTypeTokensFactory;
|
|
1659
|
+
const schemaColumnFactory = ((name, type, options) => columnSchemaComponent({
|
|
1660
|
+
columnName: name,
|
|
1661
|
+
type,
|
|
1662
|
+
...options
|
|
1663
|
+
}));
|
|
1664
|
+
const SQL = Object.assign(createSQL, {
|
|
1665
|
+
EMPTY: emptySQL,
|
|
1666
|
+
concat: concatSQL,
|
|
1667
|
+
merge: mergeSQL,
|
|
1668
|
+
format: (sql, formatter, options) => formatSQL(sql, formatter, options?.serializer ?? JSONSerializer, options),
|
|
1669
|
+
describe: (sql, formatter, options) => describeSQL(sql, formatter, options?.serializer ?? JSONSerializer, options),
|
|
1670
|
+
in: (column, values, options) => options?.mode ? SQLIn.from({
|
|
1671
|
+
column,
|
|
1672
|
+
values,
|
|
1673
|
+
mode: options.mode
|
|
1674
|
+
}) : SQLIn.from({
|
|
1675
|
+
column,
|
|
1676
|
+
values
|
|
1677
|
+
}),
|
|
1678
|
+
array: (values, options) => SQLArray.from(options?.mode ? {
|
|
1679
|
+
value: values,
|
|
1680
|
+
mode: options.mode
|
|
1681
|
+
} : values),
|
|
1682
|
+
identifier: SQLIdentifier.from,
|
|
1683
|
+
plain: SQLPlain.from,
|
|
1684
|
+
literal,
|
|
1685
|
+
check: {
|
|
1686
|
+
isSQL,
|
|
1687
|
+
isTokenizedSQL: (value) => isTokenizedSQL(value),
|
|
1688
|
+
isEmpty,
|
|
1689
|
+
isIdentifier: SQLIdentifier.check,
|
|
1690
|
+
isPlain: SQLPlain.check,
|
|
1691
|
+
isSQLIn: SQLIn.check
|
|
1692
|
+
},
|
|
1693
|
+
column: columnFactory,
|
|
1694
|
+
columnN: Object.assign(schemaColumnFactory, { type: SQLColumnTypeTokensFactory })
|
|
1695
|
+
});
|
|
1696
|
+
|
|
1697
|
+
//#endregion
|
|
1698
|
+
//#region src/core/sql/valueMappers/reservedSqlWords.ts
|
|
1699
|
+
const ansiSqlReservedMap = {
|
|
1700
|
+
ALL: true,
|
|
1701
|
+
AND: true,
|
|
1702
|
+
ANY: true,
|
|
1703
|
+
ARRAY: true,
|
|
1704
|
+
AS: true,
|
|
1705
|
+
ASC: true,
|
|
1706
|
+
AUTHORIZATION: true,
|
|
1707
|
+
BETWEEN: true,
|
|
1708
|
+
BINARY: true,
|
|
1709
|
+
BOTH: true,
|
|
1710
|
+
CASE: true,
|
|
1711
|
+
CAST: true,
|
|
1712
|
+
CHECK: true,
|
|
1713
|
+
COLLATE: true,
|
|
1714
|
+
COLUMN: true,
|
|
1715
|
+
CONSTRAINT: true,
|
|
1716
|
+
CREATE: true,
|
|
1717
|
+
CROSS: true,
|
|
1718
|
+
CURRENT_DATE: true,
|
|
1719
|
+
CURRENT_TIME: true,
|
|
1720
|
+
CURRENT_TIMESTAMP: true,
|
|
1721
|
+
CURRENT_USER: true,
|
|
1722
|
+
DEFAULT: true,
|
|
1723
|
+
DEFERRABLE: true,
|
|
1724
|
+
DESC: true,
|
|
1725
|
+
DISTINCT: true,
|
|
1726
|
+
DO: true,
|
|
1727
|
+
ELSE: true,
|
|
1728
|
+
END: true,
|
|
1729
|
+
EXCEPT: true,
|
|
1730
|
+
FALSE: true,
|
|
1731
|
+
FOR: true,
|
|
1732
|
+
FOREIGN: true,
|
|
1733
|
+
FROM: true,
|
|
1734
|
+
FULL: true,
|
|
1735
|
+
GRANT: true,
|
|
1736
|
+
GROUP: true,
|
|
1737
|
+
HAVING: true,
|
|
1738
|
+
IN: true,
|
|
1739
|
+
INITIALLY: true,
|
|
1740
|
+
INNER: true,
|
|
1741
|
+
INTERSECT: true,
|
|
1742
|
+
INTO: true,
|
|
1743
|
+
IS: true,
|
|
1744
|
+
JOIN: true,
|
|
1745
|
+
LEADING: true,
|
|
1746
|
+
LEFT: true,
|
|
1747
|
+
LIKE: true,
|
|
1748
|
+
LOCALTIME: true,
|
|
1749
|
+
LOCALTIMESTAMP: true,
|
|
1750
|
+
NATURAL: true,
|
|
1751
|
+
NEW: true,
|
|
1752
|
+
NOT: true,
|
|
1753
|
+
NULL: true,
|
|
1754
|
+
NULLS: true,
|
|
1755
|
+
OLD: true,
|
|
1756
|
+
ON: true,
|
|
1757
|
+
ONLY: true,
|
|
1758
|
+
OPEN: true,
|
|
1759
|
+
OR: true,
|
|
1760
|
+
ORDER: true,
|
|
1761
|
+
OUTER: true,
|
|
1762
|
+
OVERLAPS: true,
|
|
1763
|
+
PARTITION: true,
|
|
1764
|
+
PLACING: true,
|
|
1765
|
+
PRIMARY: true,
|
|
1766
|
+
REFERENCES: true,
|
|
1767
|
+
RIGHT: true,
|
|
1768
|
+
SELECT: true,
|
|
1769
|
+
SESSION_USER: true,
|
|
1770
|
+
SIMILAR: true,
|
|
1771
|
+
SOME: true,
|
|
1772
|
+
TABLE: true,
|
|
1773
|
+
THEN: true,
|
|
1774
|
+
TO: true,
|
|
1775
|
+
TRAILING: true,
|
|
1776
|
+
TRUE: true,
|
|
1777
|
+
UNION: true,
|
|
1778
|
+
UNIQUE: true,
|
|
1779
|
+
USER: true,
|
|
1780
|
+
USING: true,
|
|
1781
|
+
WHEN: true,
|
|
1782
|
+
WHERE: true,
|
|
1783
|
+
WITH: true,
|
|
1784
|
+
WITHOUT: true,
|
|
1785
|
+
ADD: true,
|
|
1786
|
+
ALTER: true,
|
|
1787
|
+
ARE: true,
|
|
1788
|
+
AT: true,
|
|
1789
|
+
BEGIN: true,
|
|
1790
|
+
BY: true,
|
|
1791
|
+
CASCADE: true,
|
|
1792
|
+
CLOSE: true,
|
|
1793
|
+
COMMIT: true,
|
|
1794
|
+
CONNECT: true,
|
|
1795
|
+
CONTINUE: true,
|
|
1796
|
+
CORRESPONDING: true,
|
|
1797
|
+
CURSOR: true,
|
|
1798
|
+
DEALLOCATE: true,
|
|
1799
|
+
DECLARE: true,
|
|
1800
|
+
DELETE: true,
|
|
1801
|
+
DESCRIBE: true,
|
|
1802
|
+
DISCONNECT: true,
|
|
1803
|
+
DROP: true,
|
|
1804
|
+
ESCAPE: true,
|
|
1805
|
+
EXECUTE: true,
|
|
1806
|
+
EXISTS: true,
|
|
1807
|
+
FETCH: true,
|
|
1808
|
+
FIRST: true,
|
|
1809
|
+
FLOAT: true,
|
|
1810
|
+
GET: true,
|
|
1811
|
+
GLOBAL: true,
|
|
1812
|
+
GO: true,
|
|
1813
|
+
GOTO: true,
|
|
1814
|
+
HOUR: true,
|
|
1815
|
+
IMMEDIATE: true,
|
|
1816
|
+
INDICATOR: true,
|
|
1817
|
+
INPUT: true,
|
|
1818
|
+
INSERT: true,
|
|
1819
|
+
INT: true,
|
|
1820
|
+
INTEGER: true,
|
|
1821
|
+
INTERVAL: true,
|
|
1822
|
+
LANGUAGE: true,
|
|
1823
|
+
LAST: true,
|
|
1824
|
+
LOCAL: true,
|
|
1825
|
+
MATCH: true,
|
|
1826
|
+
MINUTE: true,
|
|
1827
|
+
MODULE: true,
|
|
1828
|
+
MONTH: true,
|
|
1829
|
+
NATIONAL: true,
|
|
1830
|
+
NEXT: true,
|
|
1831
|
+
NO: true,
|
|
1832
|
+
OF: true,
|
|
1833
|
+
OUTPUT: true,
|
|
1834
|
+
PARTIAL: true,
|
|
1835
|
+
PREPARE: true,
|
|
1836
|
+
PRESERVE: true,
|
|
1837
|
+
PRIOR: true,
|
|
1838
|
+
PRIVILEGES: true,
|
|
1839
|
+
PROCEDURE: true,
|
|
1840
|
+
PUBLIC: true,
|
|
1841
|
+
READ: true,
|
|
1842
|
+
REAL: true,
|
|
1843
|
+
RESTRICT: true,
|
|
1844
|
+
REVOKE: true,
|
|
1845
|
+
ROLLBACK: true,
|
|
1846
|
+
ROWS: true,
|
|
1847
|
+
SCHEMA: true,
|
|
1848
|
+
SCROLL: true,
|
|
1849
|
+
SECOND: true,
|
|
1850
|
+
SECTION: true,
|
|
1851
|
+
SET: true,
|
|
1852
|
+
SIZE: true,
|
|
1853
|
+
SMALLINT: true,
|
|
1854
|
+
SQL: true,
|
|
1855
|
+
SQLCODE: true,
|
|
1856
|
+
SQLERROR: true,
|
|
1857
|
+
SQLSTATE: true,
|
|
1858
|
+
TEMPORARY: true,
|
|
1859
|
+
TIMEZONE_HOUR: true,
|
|
1860
|
+
TIMEZONE_MINUTE: true,
|
|
1861
|
+
TRANSACTION: true,
|
|
1862
|
+
TRANSLATE: true,
|
|
1863
|
+
TRANSLATION: true,
|
|
1864
|
+
UNKNOWN: true,
|
|
1865
|
+
UPDATE: true,
|
|
1866
|
+
VALUE: true,
|
|
1867
|
+
VALUES: true,
|
|
1868
|
+
VARCHAR: true,
|
|
1869
|
+
VARYING: true,
|
|
1870
|
+
VIEW: true,
|
|
1871
|
+
WHENEVER: true,
|
|
1872
|
+
WORK: true,
|
|
1873
|
+
WRITE: true,
|
|
1874
|
+
YEAR: true,
|
|
1875
|
+
ZONE: true
|
|
1876
|
+
};
|
|
1866
1877
|
|
|
1867
1878
|
//#endregion
|
|
1868
|
-
//#region src/core/
|
|
1869
|
-
const
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
const
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
}
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
const createSingletonConnection = (options) => {
|
|
1886
|
-
const { driverType, connect, close, initTransaction, executor, serializer } = options;
|
|
1887
|
-
let client = null;
|
|
1888
|
-
let connectPromise = null;
|
|
1889
|
-
const getClient = async () => {
|
|
1890
|
-
if (client) return client;
|
|
1891
|
-
if (!connectPromise) connectPromise = connect().then((c) => {
|
|
1892
|
-
client = c;
|
|
1893
|
-
return c;
|
|
1894
|
-
});
|
|
1895
|
-
return connectPromise;
|
|
1896
|
-
};
|
|
1897
|
-
const typedConnection = {
|
|
1898
|
-
driverType,
|
|
1899
|
-
open: getClient,
|
|
1900
|
-
close: () => client ? close(client) : Promise.resolve(),
|
|
1901
|
-
...transactionFactoryWithDbClient(getClient, initTransaction(() => typedConnection)),
|
|
1902
|
-
execute: sqlExecutor(executor({ serializer }), { connect: getClient }),
|
|
1903
|
-
_transactionType: void 0
|
|
1904
|
-
};
|
|
1905
|
-
return typedConnection;
|
|
1879
|
+
//#region src/core/sql/valueMappers/sqlValueMapper.ts
|
|
1880
|
+
const ANSISQLParamPlaceholder = "?";
|
|
1881
|
+
const ANSISQLIdentifierQuote = "\"";
|
|
1882
|
+
const mapANSISQLParamPlaceholder = () => "?";
|
|
1883
|
+
const isReserved = (value, reserved) => !!reserved[value.toUpperCase()];
|
|
1884
|
+
const mapSQLIdentifier = (value, options) => {
|
|
1885
|
+
if (value === void 0 || value === null) throw new Error("SQL identifier cannot be null or undefined");
|
|
1886
|
+
const ident = value.toString().slice(0);
|
|
1887
|
+
const quoteSign = options?.quote ?? "\"";
|
|
1888
|
+
if (/^[a-z_][a-z0-9_$]*$/.test(ident) && !isReserved(ident, options?.reservedWords ?? ansiSqlReservedMap)) return ident;
|
|
1889
|
+
let quoted = quoteSign;
|
|
1890
|
+
for (let i = 0; i < ident.length; i++) {
|
|
1891
|
+
const c = ident[i];
|
|
1892
|
+
quoted += c === quoteSign ? c + c : c;
|
|
1893
|
+
}
|
|
1894
|
+
quoted += quoteSign;
|
|
1895
|
+
return quoted;
|
|
1906
1896
|
};
|
|
1907
|
-
const
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
driverType,
|
|
1911
|
-
open,
|
|
1912
|
-
close,
|
|
1913
|
-
...transactionFactoryWithDbClient(open, initTransaction(() => typedConnection)),
|
|
1914
|
-
execute: sqlExecutor(executor({ serializer }), { connect: open }),
|
|
1915
|
-
_transactionType: void 0
|
|
1916
|
-
};
|
|
1917
|
-
return typedConnection;
|
|
1897
|
+
const DefaultMapSQLParamValueOptions = {
|
|
1898
|
+
mapPlaceholder: mapANSISQLParamPlaceholder,
|
|
1899
|
+
mapIdentifier: mapSQLIdentifier
|
|
1918
1900
|
};
|
|
1919
|
-
const
|
|
1920
|
-
const
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
const getClient = async () => {
|
|
1924
|
-
if (client) return client;
|
|
1925
|
-
if (!connectPromise) connectPromise = connect().then((c) => {
|
|
1926
|
-
client = c;
|
|
1927
|
-
return c;
|
|
1928
|
-
});
|
|
1929
|
-
return connectPromise;
|
|
1901
|
+
const SQLValueMapper = (options) => {
|
|
1902
|
+
const mapSQLParamValueOptions = {
|
|
1903
|
+
...DefaultMapSQLParamValueOptions,
|
|
1904
|
+
...options ?? {}
|
|
1930
1905
|
};
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1906
|
+
return {
|
|
1907
|
+
mapValue: (value, serializer, mapOptions) => mapSQLParamValue(value, serializer, {
|
|
1908
|
+
...mapSQLParamValueOptions,
|
|
1909
|
+
...mapOptions
|
|
1910
|
+
}),
|
|
1911
|
+
mapPlaceholder: mapSQLParamValueOptions.mapPlaceholder,
|
|
1912
|
+
mapIdentifier: mapSQLParamValueOptions.mapIdentifier
|
|
1938
1913
|
};
|
|
1939
|
-
return typedConnection;
|
|
1940
1914
|
};
|
|
1915
|
+
function mapSQLParamValue(value, serializer, options) {
|
|
1916
|
+
if (value === null || value === void 0) return null;
|
|
1917
|
+
else if (typeof value === "number") return value;
|
|
1918
|
+
else if (typeof value === "string") return value;
|
|
1919
|
+
else if (Array.isArray(value)) {
|
|
1920
|
+
const mapValue = options?.mapValue ?? mapSQLParamValue;
|
|
1921
|
+
return options?.mapArray ? options.mapArray(value, mapValue) : value.map((item) => mapValue(item, serializer, options));
|
|
1922
|
+
} else if (typeof value === "boolean") return options?.mapBoolean ? options.mapBoolean(value) : value;
|
|
1923
|
+
else if (typeof value === "bigint") return options?.mapBigInt ? options.mapBigInt(value) : value.toString();
|
|
1924
|
+
else if (value instanceof Date) return options?.mapDate ? options.mapDate(value) : value.toISOString();
|
|
1925
|
+
else if (SQL.check.isIdentifier(value)) return (options?.mapIdentifier ?? mapSQLIdentifier)(value.value);
|
|
1926
|
+
else if (typeof value === "object") return options?.mapObject ? options.mapObject(value) : serializer.serialize(value);
|
|
1927
|
+
else return serializer.serialize(value);
|
|
1928
|
+
}
|
|
1941
1929
|
|
|
1942
1930
|
//#endregion
|
|
1943
|
-
//#region src/core/
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
}
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
this.isProcessing = true;
|
|
1989
|
-
this.processQueue();
|
|
1990
|
-
}
|
|
1991
|
-
processQueue() {
|
|
1992
|
-
try {
|
|
1993
|
-
while (this.activeTasks < this.options.maxActiveTasks && this.queue.length > 0) {
|
|
1994
|
-
const item = this.takeFirstAvailableItem();
|
|
1995
|
-
if (item === null) return;
|
|
1996
|
-
const groupId = item.options?.taskGroupId;
|
|
1997
|
-
if (groupId) this.activeGroups.add(groupId);
|
|
1998
|
-
this.activeTasks++;
|
|
1999
|
-
this.executeItem(item);
|
|
2000
|
-
}
|
|
2001
|
-
} catch (error) {
|
|
2002
|
-
console.error(error);
|
|
2003
|
-
throw error;
|
|
2004
|
-
} finally {
|
|
2005
|
-
this.isProcessing = false;
|
|
2006
|
-
if (this.hasItemsToProcess() && this.activeTasks < this.options.maxActiveTasks) this.ensureProcessing();
|
|
1931
|
+
//#region src/core/sql/formatters/sqlFormatter.ts
|
|
1932
|
+
const SQLFormatter = ({ format, describe, valueMapper: valueMapperOptions, processorsRegistry }) => {
|
|
1933
|
+
const valueMapper = SQLValueMapper(valueMapperOptions);
|
|
1934
|
+
const options = {
|
|
1935
|
+
builder: ParametrizedSQLBuilder({ mapParamPlaceholder: valueMapper.mapPlaceholder }),
|
|
1936
|
+
mapper: valueMapper,
|
|
1937
|
+
processorsRegistry: processorsRegistry ?? defaultProcessorsRegistry
|
|
1938
|
+
};
|
|
1939
|
+
const resultFormatter = {
|
|
1940
|
+
format: format ?? ((sql, methodOptions) => formatSQL(sql, resultFormatter, methodOptions?.serializer ?? JSONSerializer, {
|
|
1941
|
+
...options,
|
|
1942
|
+
...methodOptions ?? {}
|
|
1943
|
+
})),
|
|
1944
|
+
describe: describe ?? ((sql, methodOptions) => describeSQL(sql, resultFormatter, methodOptions?.serializer ?? JSONSerializer, {
|
|
1945
|
+
...options,
|
|
1946
|
+
...methodOptions ?? {}
|
|
1947
|
+
})),
|
|
1948
|
+
valueMapper
|
|
1949
|
+
};
|
|
1950
|
+
return resultFormatter;
|
|
1951
|
+
};
|
|
1952
|
+
const dumboSQLFormatters = globalThis.dumboSQLFormatters = globalThis.dumboSQLFormatters ?? {};
|
|
1953
|
+
const registerFormatter = (dialect, formatter) => {
|
|
1954
|
+
dumboSQLFormatters[dialect] = formatter;
|
|
1955
|
+
};
|
|
1956
|
+
const getFormatter = (dialect) => {
|
|
1957
|
+
const formatterKey = dialect;
|
|
1958
|
+
if (!dumboSQLFormatters[formatterKey]) throw new Error(`No SQL formatter registered for dialect: ${dialect}`);
|
|
1959
|
+
return dumboSQLFormatters[formatterKey];
|
|
1960
|
+
};
|
|
1961
|
+
function formatSQL(sql, formatter, serializer, context) {
|
|
1962
|
+
const mapper = context?.mapper == void 0 ? formatter.valueMapper : {
|
|
1963
|
+
...formatter.valueMapper,
|
|
1964
|
+
...context.mapper
|
|
1965
|
+
};
|
|
1966
|
+
const processorsRegistry = context?.processorsRegistry ?? defaultProcessorsRegistry;
|
|
1967
|
+
const merged = Array.isArray(sql) ? SQL.merge(sql, "\n") : sql;
|
|
1968
|
+
if (!isTokenizedSQL(merged)) throw new Error("Expected TokenizedSQL, got string-based SQL");
|
|
1969
|
+
const builder = ParametrizedSQLBuilder({ mapParamPlaceholder: mapper.mapPlaceholder });
|
|
1970
|
+
let paramIndex = 0;
|
|
1971
|
+
for (let i = 0; i < merged.sqlChunks.length; i++) {
|
|
1972
|
+
const sqlChunk = merged.sqlChunks[i];
|
|
1973
|
+
if (sqlChunk !== TokenizedSQL.paramPlaceholder) {
|
|
1974
|
+
builder.addSQL(sqlChunk);
|
|
1975
|
+
continue;
|
|
2007
1976
|
}
|
|
1977
|
+
const token = merged.sqlTokens[paramIndex++];
|
|
1978
|
+
const processor = processorsRegistry.get(token.sqlTokenType);
|
|
1979
|
+
if (!processor) throw new Error(`No SQL processor registered for token type: ${token.sqlTokenType}`);
|
|
1980
|
+
processor.handle(token, {
|
|
1981
|
+
builder,
|
|
1982
|
+
processorsRegistry,
|
|
1983
|
+
serializer,
|
|
1984
|
+
mapper
|
|
1985
|
+
});
|
|
2008
1986
|
}
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
1987
|
+
return builder.build();
|
|
1988
|
+
}
|
|
1989
|
+
const describeSQL = (sql, formatter, serializer, options) => formatSQL(sql, formatter, serializer, {
|
|
1990
|
+
...options ?? {},
|
|
1991
|
+
mapper: { mapPlaceholder: (_, value) => serializer.serialize(value) }
|
|
1992
|
+
}).query;
|
|
1993
|
+
|
|
1994
|
+
//#endregion
|
|
1995
|
+
//#region src/core/tracing/printing/color.ts
|
|
1996
|
+
let enableColors = true;
|
|
1997
|
+
const color = {
|
|
1998
|
+
set level(value) {
|
|
1999
|
+
enableColors = value === 1;
|
|
2000
|
+
},
|
|
2001
|
+
hex: (value) => (text) => enableColors ? ansis.hex(value)(text) : text,
|
|
2002
|
+
red: (value) => enableColors ? ansis.red(value) : value,
|
|
2003
|
+
green: (value) => enableColors ? ansis.green(value) : value,
|
|
2004
|
+
blue: (value) => enableColors ? ansis.blue(value) : value,
|
|
2005
|
+
cyan: (value) => enableColors ? ansis.cyan(value) : value,
|
|
2006
|
+
yellow: (value) => enableColors ? ansis.yellow(value) : value
|
|
2007
|
+
};
|
|
2008
|
+
|
|
2009
|
+
//#endregion
|
|
2010
|
+
//#region src/core/tracing/printing/pretty.ts
|
|
2011
|
+
const TWO_SPACES = " ";
|
|
2012
|
+
const COLOR_STRING = color.hex("#98c379");
|
|
2013
|
+
const COLOR_KEY = color.hex("#61afef");
|
|
2014
|
+
const COLOR_NUMBER_OR_DATE = color.hex("#d19a66");
|
|
2015
|
+
const COLOR_BOOLEAN = color.hex("#c678dd");
|
|
2016
|
+
const COLOR_NULL_OR_UNDEFINED = color.hex("#c678dd");
|
|
2017
|
+
const COLOR_BRACKETS = color.hex("#abb2bf");
|
|
2018
|
+
const processString = (str, indent, handleMultiline) => {
|
|
2019
|
+
if (handleMultiline && str.includes("\n")) {
|
|
2020
|
+
const indentedLines = str.split("\n").map((line) => indent + TWO_SPACES + COLOR_STRING(line));
|
|
2021
|
+
return COLOR_STRING("\"") + "\n" + indentedLines.join("\n") + "\n" + indent + COLOR_STRING("\"");
|
|
2017
2022
|
}
|
|
2018
|
-
|
|
2019
|
-
const taskIndex = this.queue.findIndex((item) => !item.options?.taskGroupId || !this.activeGroups.has(item.options.taskGroupId));
|
|
2020
|
-
if (taskIndex === -1) return null;
|
|
2021
|
-
const [item] = this.queue.splice(taskIndex, 1);
|
|
2022
|
-
return item ?? null;
|
|
2023
|
-
};
|
|
2024
|
-
hasItemsToProcess = () => this.queue.findIndex((item) => !item.options?.taskGroupId || !this.activeGroups.has(item.options.taskGroupId)) !== -1;
|
|
2023
|
+
return COLOR_STRING(`"${str}"`);
|
|
2025
2024
|
};
|
|
2026
|
-
const
|
|
2027
|
-
const
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
2039
|
-
timeoutId = null;
|
|
2040
|
-
resolve(value);
|
|
2041
|
-
}, (reason) => {
|
|
2042
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
2043
|
-
timeoutId = null;
|
|
2044
|
-
reject(reason);
|
|
2025
|
+
const shouldPrint = (obj) => typeof obj !== "function" && typeof obj !== "symbol";
|
|
2026
|
+
const formatJson = (obj, indentLevel = 0, handleMultiline = false) => {
|
|
2027
|
+
const indent = TWO_SPACES.repeat(indentLevel);
|
|
2028
|
+
if (obj === null) return COLOR_NULL_OR_UNDEFINED("null");
|
|
2029
|
+
if (obj === void 0) return COLOR_NULL_OR_UNDEFINED("undefined");
|
|
2030
|
+
if (typeof obj === "string") return processString(obj, indent, handleMultiline);
|
|
2031
|
+
if (typeof obj === "number" || typeof obj === "bigint" || obj instanceof Date) return COLOR_NUMBER_OR_DATE(String(obj));
|
|
2032
|
+
if (typeof obj === "boolean") return COLOR_BOOLEAN(String(obj));
|
|
2033
|
+
if (obj instanceof Error) {
|
|
2034
|
+
const errorObj = {};
|
|
2035
|
+
Object.getOwnPropertyNames(obj).forEach((key) => {
|
|
2036
|
+
errorObj[key] = obj[key];
|
|
2045
2037
|
});
|
|
2046
|
-
|
|
2038
|
+
return formatJson(errorObj, indentLevel, handleMultiline);
|
|
2039
|
+
}
|
|
2040
|
+
if (obj instanceof Promise) return COLOR_STRING("Promise {pending}");
|
|
2041
|
+
if (Array.isArray(obj)) {
|
|
2042
|
+
const arrayItems = obj.map((item) => formatJson(item, indentLevel + 1, handleMultiline));
|
|
2043
|
+
return `${COLOR_BRACKETS("[")}\n${indent} ${arrayItems.join(`,\n${indent} `)}\n${indent}${COLOR_BRACKETS("]")}`;
|
|
2044
|
+
}
|
|
2045
|
+
const entries = Object.entries(obj).filter(([_, value]) => shouldPrint(value)).map(([key, value]) => `${COLOR_KEY(`"${key}"`)}: ${formatJson(value, indentLevel + 1, handleMultiline)}`);
|
|
2046
|
+
return `${COLOR_BRACKETS("{")}\n${indent} ${entries.join(`,\n${indent} `)}\n${indent}${COLOR_BRACKETS("}")}`;
|
|
2047
2047
|
};
|
|
2048
|
+
const prettyJson = (obj, options) => formatJson(obj, 0, options?.handleMultiline);
|
|
2048
2049
|
|
|
2049
2050
|
//#endregion
|
|
2050
|
-
//#region src/core/
|
|
2051
|
-
const
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
const allResources = /* @__PURE__ */ new Set();
|
|
2059
|
-
const ackCallbacks = /* @__PURE__ */ new Map();
|
|
2060
|
-
const acquire = async () => taskProcessor.enqueue(async ({ ack }) => {
|
|
2061
|
-
try {
|
|
2062
|
-
let resource;
|
|
2063
|
-
if (options.reuseResources) resource = resourcePool.pop();
|
|
2064
|
-
if (!resource) {
|
|
2065
|
-
resource = await getResource();
|
|
2066
|
-
allResources.add(resource);
|
|
2067
|
-
}
|
|
2068
|
-
ackCallbacks.set(resource, ack);
|
|
2069
|
-
return resource;
|
|
2070
|
-
} catch (e) {
|
|
2071
|
-
ack();
|
|
2072
|
-
throw e;
|
|
2073
|
-
}
|
|
2074
|
-
});
|
|
2075
|
-
const release = (resource) => {
|
|
2076
|
-
const ack = ackCallbacks.get(resource);
|
|
2077
|
-
if (ack) {
|
|
2078
|
-
ackCallbacks.delete(resource);
|
|
2079
|
-
if (options.reuseResources) resourcePool.push(resource);
|
|
2080
|
-
ack();
|
|
2081
|
-
}
|
|
2082
|
-
};
|
|
2083
|
-
const execute = async (operation) => {
|
|
2084
|
-
const resource = await acquire();
|
|
2085
|
-
try {
|
|
2086
|
-
return await operation(resource);
|
|
2087
|
-
} finally {
|
|
2088
|
-
release(resource);
|
|
2089
|
-
}
|
|
2090
|
-
};
|
|
2091
|
-
return {
|
|
2092
|
-
acquire,
|
|
2093
|
-
release,
|
|
2094
|
-
execute,
|
|
2095
|
-
waitForIdle: () => taskProcessor.waitForEndOfProcessing(),
|
|
2096
|
-
stop: async (stopOptions) => {
|
|
2097
|
-
if (isStopped) return;
|
|
2098
|
-
isStopped = true;
|
|
2099
|
-
if (options?.closeResource) {
|
|
2100
|
-
const resources = [...allResources];
|
|
2101
|
-
allResources.clear();
|
|
2102
|
-
resourcePool.length = 0;
|
|
2103
|
-
await Promise.all(resources.map(async (resource) => await options.closeResource(resource)));
|
|
2104
|
-
}
|
|
2105
|
-
await taskProcessor.stop(stopOptions);
|
|
2106
|
-
}
|
|
2107
|
-
};
|
|
2051
|
+
//#region src/core/tracing/index.ts
|
|
2052
|
+
const tracer = () => {};
|
|
2053
|
+
const LogLevel = {
|
|
2054
|
+
DISABLED: "DISABLED",
|
|
2055
|
+
INFO: "INFO",
|
|
2056
|
+
LOG: "LOG",
|
|
2057
|
+
WARN: "WARN",
|
|
2058
|
+
ERROR: "ERROR"
|
|
2108
2059
|
};
|
|
2109
|
-
const
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
|
|
2136
|
-
return
|
|
2137
|
-
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2060
|
+
const LogStyle = {
|
|
2061
|
+
RAW: "RAW",
|
|
2062
|
+
PRETTY: "PRETTY"
|
|
2063
|
+
};
|
|
2064
|
+
const getEnvVariable = (name) => {
|
|
2065
|
+
try {
|
|
2066
|
+
if (typeof process !== "undefined" && process.env) return process.env[name];
|
|
2067
|
+
return;
|
|
2068
|
+
} catch {
|
|
2069
|
+
return;
|
|
2070
|
+
}
|
|
2071
|
+
};
|
|
2072
|
+
const shouldLog = (logLevel) => {
|
|
2073
|
+
const definedLogLevel = getEnvVariable("DUMBO_LOG_LEVEL") ?? LogLevel.ERROR;
|
|
2074
|
+
if (definedLogLevel === LogLevel.ERROR && logLevel === LogLevel.ERROR) return true;
|
|
2075
|
+
if (definedLogLevel === LogLevel.WARN && [LogLevel.ERROR, LogLevel.WARN].includes(logLevel)) return true;
|
|
2076
|
+
if (definedLogLevel === LogLevel.LOG && [
|
|
2077
|
+
LogLevel.ERROR,
|
|
2078
|
+
LogLevel.WARN,
|
|
2079
|
+
LogLevel.LOG
|
|
2080
|
+
].includes(logLevel)) return true;
|
|
2081
|
+
if (definedLogLevel === LogLevel.INFO && [
|
|
2082
|
+
LogLevel.ERROR,
|
|
2083
|
+
LogLevel.WARN,
|
|
2084
|
+
LogLevel.LOG,
|
|
2085
|
+
LogLevel.INFO
|
|
2086
|
+
].includes(logLevel)) return true;
|
|
2087
|
+
return false;
|
|
2088
|
+
};
|
|
2089
|
+
const nulloTraceEventRecorder = () => {};
|
|
2090
|
+
const getTraceEventFormatter = (logStyle, serializer = JSONSerializer) => (event) => {
|
|
2091
|
+
switch (logStyle) {
|
|
2092
|
+
case "RAW": return serializer.serialize(event);
|
|
2093
|
+
case "PRETTY": return prettyJson(event, { handleMultiline: true });
|
|
2094
|
+
}
|
|
2095
|
+
};
|
|
2096
|
+
const getTraceEventRecorder = (logLevel, logStyle) => {
|
|
2097
|
+
const format = getTraceEventFormatter(logStyle);
|
|
2098
|
+
switch (logLevel) {
|
|
2099
|
+
case "DISABLED": return nulloTraceEventRecorder;
|
|
2100
|
+
case "INFO": return (event) => console.info(format(event));
|
|
2101
|
+
case "LOG": return (event) => console.log(format(event));
|
|
2102
|
+
case "WARN": return (event) => console.warn(format(event));
|
|
2103
|
+
case "ERROR": return (event) => console.error(format(event));
|
|
2104
|
+
}
|
|
2105
|
+
};
|
|
2106
|
+
const recordTraceEvent = (logLevel, eventName, attributes) => {
|
|
2107
|
+
if (!shouldLog(LogLevel.LOG)) return;
|
|
2108
|
+
const event = {
|
|
2109
|
+
name: eventName,
|
|
2110
|
+
timestamp: (/* @__PURE__ */ new Date()).getTime(),
|
|
2111
|
+
...attributes
|
|
2142
2112
|
};
|
|
2113
|
+
getTraceEventRecorder(logLevel, getEnvVariable("DUMBO_LOG_STYLE") ?? "RAW")(event);
|
|
2143
2114
|
};
|
|
2115
|
+
tracer.info = (eventName, attributes) => recordTraceEvent(LogLevel.INFO, eventName, attributes);
|
|
2116
|
+
tracer.warn = (eventName, attributes) => recordTraceEvent(LogLevel.WARN, eventName, attributes);
|
|
2117
|
+
tracer.log = (eventName, attributes) => recordTraceEvent(LogLevel.LOG, eventName, attributes);
|
|
2118
|
+
tracer.error = (eventName, attributes) => recordTraceEvent(LogLevel.ERROR, eventName, attributes);
|
|
2144
2119
|
|
|
2145
2120
|
//#endregion
|
|
2146
|
-
//#region src/core/
|
|
2147
|
-
const
|
|
2148
|
-
|
|
2149
|
-
|
|
2121
|
+
//#region src/core/schema/sqlMigration.ts
|
|
2122
|
+
const sqlMigration = (name, sqls) => ({
|
|
2123
|
+
name,
|
|
2124
|
+
sqls
|
|
2150
2125
|
});
|
|
2151
|
-
|
|
2152
|
-
|
|
2153
|
-
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
};
|
|
2165
|
-
const
|
|
2166
|
-
const
|
|
2167
|
-
let connectionPromise = null;
|
|
2168
|
-
const getExistingOrNewConnection = () => {
|
|
2169
|
-
if (!connectionPromise) connectionPromise ??= Promise.resolve(getConnection());
|
|
2170
|
-
return connectionPromise;
|
|
2171
|
-
};
|
|
2126
|
+
|
|
2127
|
+
//#endregion
|
|
2128
|
+
//#region src/core/schema/migrators/schemaComponentMigrator.ts
|
|
2129
|
+
const { AutoIncrement, Varchar, Timestamp } = SQL.column.type;
|
|
2130
|
+
const migrationTableSQL = SQL`
|
|
2131
|
+
CREATE TABLE IF NOT EXISTS dmb_migrations (
|
|
2132
|
+
id ${AutoIncrement({ primaryKey: true })},
|
|
2133
|
+
name ${Varchar(255)} NOT NULL UNIQUE,
|
|
2134
|
+
application ${Varchar(255)} NOT NULL DEFAULT 'default',
|
|
2135
|
+
sql_hash ${Varchar(64)} NOT NULL,
|
|
2136
|
+
timestamp ${Timestamp} NOT NULL DEFAULT CURRENT_TIMESTAMP
|
|
2137
|
+
);
|
|
2138
|
+
`;
|
|
2139
|
+
const migrationTableSchemaComponent = schemaComponent("dumbo:schema-component:migrations-table", { migrations: [sqlMigration("dumbo:migrationTable:001", [migrationTableSQL])] });
|
|
2140
|
+
const SchemaComponentMigrator = (component, dumbo) => {
|
|
2141
|
+
const completedMigrations = [];
|
|
2172
2142
|
return {
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
withConnection: (handle, _options) => executeInAmbientConnection(handle, { connection: getExistingOrNewConnection }),
|
|
2180
|
-
...transactionFactoryWithAsyncAmbientConnection(options.driverType, getExistingOrNewConnection, options.closeConnection),
|
|
2181
|
-
close: async () => {
|
|
2182
|
-
if (!connectionPromise) return;
|
|
2183
|
-
await (await connectionPromise).close();
|
|
2143
|
+
component,
|
|
2144
|
+
run: async (options) => {
|
|
2145
|
+
const pendingMigrations = component.migrations.filter((m) => !completedMigrations.includes(`${component.schemaComponentKey}:${m.name}`));
|
|
2146
|
+
if (pendingMigrations.length === 0) return;
|
|
2147
|
+
await runSQLMigrations(dumbo, pendingMigrations, options);
|
|
2148
|
+
completedMigrations.push(...pendingMigrations.map((m) => `${component.schemaComponentKey}:${m.name}`));
|
|
2184
2149
|
}
|
|
2185
2150
|
};
|
|
2186
2151
|
};
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
|
|
2201
|
-
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2152
|
+
|
|
2153
|
+
//#endregion
|
|
2154
|
+
//#region src/core/schema/migrators/migrator.ts
|
|
2155
|
+
const MIGRATIONS_LOCK_ID = 999956789;
|
|
2156
|
+
const defaultMigratorOptions = globalThis.defaultMigratorOptions = globalThis.defaultMigratorOptions ?? {};
|
|
2157
|
+
const registerDefaultMigratorOptions = (databaseType, options) => {
|
|
2158
|
+
defaultMigratorOptions[databaseType] = options;
|
|
2159
|
+
};
|
|
2160
|
+
const getDefaultMigratorOptionsFromRegistry = (databaseType) => {
|
|
2161
|
+
if (!defaultMigratorOptions[databaseType]) throw new Error(`No default migrator options registered for database type: ${databaseType}`);
|
|
2162
|
+
return defaultMigratorOptions[databaseType];
|
|
2163
|
+
};
|
|
2164
|
+
const runSQLMigrations = (pool, migrations, partialOptions) => pool.withTransaction(async ({ execute }) => {
|
|
2165
|
+
const databaseType = fromDatabaseDriverType(pool.driverType).databaseType;
|
|
2166
|
+
const defaultOptions = getDefaultMigratorOptionsFromRegistry(databaseType);
|
|
2167
|
+
partialOptions ??= {};
|
|
2168
|
+
const options = {
|
|
2169
|
+
...defaultOptions,
|
|
2170
|
+
...partialOptions,
|
|
2171
|
+
schema: {
|
|
2172
|
+
...defaultOptions.schema,
|
|
2173
|
+
...partialOptions?.schema ?? {}
|
|
2207
2174
|
},
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2175
|
+
lock: {
|
|
2176
|
+
...defaultOptions.lock,
|
|
2177
|
+
...partialOptions?.lock,
|
|
2178
|
+
options: {
|
|
2179
|
+
lockId: MIGRATIONS_LOCK_ID,
|
|
2180
|
+
...defaultOptions.lock?.options,
|
|
2181
|
+
...partialOptions?.lock?.options
|
|
2182
|
+
}
|
|
2213
2183
|
},
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
if (closed) return;
|
|
2218
|
-
closed = true;
|
|
2219
|
-
await guardMaxConnections.stop({ force: true });
|
|
2220
|
-
}
|
|
2184
|
+
dryRun: defaultOptions.dryRun ?? partialOptions?.dryRun,
|
|
2185
|
+
ignoreMigrationHashMismatch: defaultOptions.ignoreMigrationHashMismatch ?? partialOptions?.ignoreMigrationHashMismatch,
|
|
2186
|
+
migrationTimeoutMs: defaultOptions.migrationTimeoutMs ?? partialOptions?.migrationTimeoutMs
|
|
2221
2187
|
};
|
|
2188
|
+
const { databaseLock: _, ...rest } = options.lock ?? {};
|
|
2189
|
+
const databaseLock = options.lock?.databaseLock ?? NoDatabaseLock;
|
|
2190
|
+
const lockOptions = {
|
|
2191
|
+
lockId: MIGRATIONS_LOCK_ID,
|
|
2192
|
+
...rest
|
|
2193
|
+
};
|
|
2194
|
+
const coreMigrations = (options.schema?.migrationTable ?? migrationTableSchemaComponent).migrations;
|
|
2195
|
+
const result = {
|
|
2196
|
+
applied: [],
|
|
2197
|
+
skipped: []
|
|
2198
|
+
};
|
|
2199
|
+
await databaseLock.withAcquire(execute, async () => {
|
|
2200
|
+
for (const migration of coreMigrations) await execute.batchCommand(migration.sqls, { timeoutMs: options.migrationTimeoutMs });
|
|
2201
|
+
for (const migration of migrations) if (await runSQLMigration(databaseType, execute, migration, {
|
|
2202
|
+
ignoreMigrationHashMismatch: options.ignoreMigrationHashMismatch ?? false,
|
|
2203
|
+
migrationTimeoutMs: options.migrationTimeoutMs
|
|
2204
|
+
})) result.applied.push(migration);
|
|
2205
|
+
else result.skipped.push(migration);
|
|
2206
|
+
}, lockOptions);
|
|
2207
|
+
return {
|
|
2208
|
+
success: options.dryRun ? false : true,
|
|
2209
|
+
result
|
|
2210
|
+
};
|
|
2211
|
+
});
|
|
2212
|
+
const runSQLMigration = async (databaseType, execute, migration, options) => {
|
|
2213
|
+
const sqls = combineMigrations(migration);
|
|
2214
|
+
const sqlHash = await getMigrationHash(migration, getFormatter(databaseType));
|
|
2215
|
+
try {
|
|
2216
|
+
const newMigration = {
|
|
2217
|
+
name: migration.name,
|
|
2218
|
+
sqlHash
|
|
2219
|
+
};
|
|
2220
|
+
const checkResult = await ensureMigrationWasNotAppliedYet(execute, newMigration);
|
|
2221
|
+
if (checkResult.exists === true) {
|
|
2222
|
+
if (checkResult.hashesMatch === true) {
|
|
2223
|
+
tracer.info("migration-already-applied", { migrationName: migration.name });
|
|
2224
|
+
return false;
|
|
2225
|
+
}
|
|
2226
|
+
if (options?.ignoreMigrationHashMismatch !== true) throw new Error(`Migration hash mismatch for "${migration.name}". Aborting migration.`);
|
|
2227
|
+
tracer.warn("migration-hash-mismatch", {
|
|
2228
|
+
migrationName: migration.name,
|
|
2229
|
+
expectedHash: sqlHash,
|
|
2230
|
+
actualHash: checkResult.hashFromDB
|
|
2231
|
+
});
|
|
2232
|
+
await updateMigrationHash(execute, newMigration);
|
|
2233
|
+
return false;
|
|
2234
|
+
}
|
|
2235
|
+
await execute.batchCommand(sqls, { timeoutMs: options?.migrationTimeoutMs });
|
|
2236
|
+
await recordMigration(execute, newMigration);
|
|
2237
|
+
return true;
|
|
2238
|
+
} catch (error) {
|
|
2239
|
+
tracer.error("migration-error", {
|
|
2240
|
+
migationName: migration.name,
|
|
2241
|
+
error
|
|
2242
|
+
});
|
|
2243
|
+
throw error;
|
|
2244
|
+
}
|
|
2222
2245
|
};
|
|
2223
|
-
const
|
|
2224
|
-
const
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
});
|
|
2229
|
-
};
|
|
2230
|
-
const createAlwaysNewConnectionPool = (options) => {
|
|
2231
|
-
const { driverType, getConnection, connectionOptions } = options;
|
|
2232
|
-
return createConnectionPool({
|
|
2233
|
-
driverType,
|
|
2234
|
-
getConnection: () => connectionOptions ? getConnection(connectionOptions) : getConnection()
|
|
2235
|
-
});
|
|
2246
|
+
const getMigrationHash = async (sqlMigration, sqlFormatter) => {
|
|
2247
|
+
const content = sqlFormatter.describe(sqlMigration.sqls, { serializer: JSONSerializer });
|
|
2248
|
+
const data = new TextEncoder().encode(content);
|
|
2249
|
+
const hashBuffer = await crypto.subtle.digest("SHA-256", data);
|
|
2250
|
+
return Array.from(new Uint8Array(hashBuffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
2236
2251
|
};
|
|
2237
|
-
const
|
|
2238
|
-
|
|
2239
|
-
const
|
|
2252
|
+
const combineMigrations = (...migration) => migration.flatMap((m) => m.sqls);
|
|
2253
|
+
const ensureMigrationWasNotAppliedYet = async (execute, migration) => {
|
|
2254
|
+
const result = await singleOrNull(execute.query(SQL`SELECT sql_hash as "sqlHash" FROM dmb_migrations WHERE name = ${migration.name}`));
|
|
2255
|
+
if (result === null) return { exists: false };
|
|
2256
|
+
const { sqlHash } = result;
|
|
2240
2257
|
return {
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
close: "close" in pool ? pool.close : () => Promise.resolve(),
|
|
2245
|
-
execute: "execute" in pool ? pool.execute : sqlExecutorInNewConnection({
|
|
2246
|
-
driverType,
|
|
2247
|
-
connection
|
|
2248
|
-
}),
|
|
2249
|
-
..."transaction" in pool && "withTransaction" in pool ? {
|
|
2250
|
-
transaction: pool.transaction,
|
|
2251
|
-
withTransaction: pool.withTransaction
|
|
2252
|
-
} : transactionFactoryWithNewConnection(getConnection)
|
|
2258
|
+
exists: true,
|
|
2259
|
+
hashesMatch: sqlHash === migration.sqlHash,
|
|
2260
|
+
hashFromDB: sqlHash
|
|
2253
2261
|
};
|
|
2254
2262
|
};
|
|
2263
|
+
const recordMigration = async (execute, migration) => {
|
|
2264
|
+
await execute.command(SQL`
|
|
2265
|
+
INSERT INTO dmb_migrations (name, sql_hash)
|
|
2266
|
+
VALUES (${migration.name}, ${migration.sqlHash})`);
|
|
2267
|
+
};
|
|
2268
|
+
const updateMigrationHash = async (execute, migration) => {
|
|
2269
|
+
await execute.command(SQL`
|
|
2270
|
+
UPDATE dmb_migrations
|
|
2271
|
+
SET sql_hash = ${migration.sqlHash}, timestamp = ${/* @__PURE__ */ new Date()}
|
|
2272
|
+
WHERE name = ${migration.name}
|
|
2273
|
+
`);
|
|
2274
|
+
};
|
|
2255
2275
|
|
|
2256
2276
|
//#endregion
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
//#endregion
|
|
2261
|
-
export { SchemaComponentMigrator as $, JSONCodec as $t, CheckViolationError as A, schemaComponentURN as An, FormatIdentifierProcessor as At, InvalidOperationError as B, IndexURN as Bn, SQLColumnTypeTokens as Bt, mapColumnToDate as C, fromDatabaseDriverType as Cn, TokenizedSQL as Ct, sqlExecutorInAmbientConnection as D, DumboDatabaseDriverRegistry as Dn, SQLProcessorsRegistry as Dt, sqlExecutor as E, toDatabaseDriverType as En, mapDefaultSQLColumnProcessors as Et, DumboError as F, DatabaseSchemaURNType as Fn, BigSerialToken as Ft, SystemError as G, columnSchemaComponent as Gn, VarcharToken as Gt, NotNullViolationError as H, indexSchemaComponent as Hn, SerialToken as Ht, ExclusionViolationError as I, databaseSchemaSchemaComponent as In, ColumnTypeToken as It, MIGRATIONS_LOCK_ID as J, isSchemaComponentOfType as Jn, SQLIn as Jt, TransientDatabaseError as K, filterSchemaComponentsOfType as Kn, SQLArray as Kt, ForeignKeyViolationError as L, TableURN as Ln, IntegerToken as Lt, ConnectionError as M, DatabaseURNType as Mn, SQLProcessor as Mt, DataError as N, databaseSchemaComponent as Nn, AutoIncrementSQLColumnToken as Nt, sqlExecutorInNewConnection as O, canHandleDriverWithConnectionString as On, ExpandArrayProcessor as Ot, DeadlockError as P, DatabaseSchemaURN as Pn, BigIntegerToken as Pt, runSQLMigrations as Q, ParametrizedSQLBuilder as Qt, InsufficientResourcesError as R, TableURNType as Rn, JSONBToken as Rt, mapColumnToBigint as S, resolveDatabaseMetadata as Sn, isSQL as St, mapSQLQueryResult as T, getDatabaseType as Tn, defaultProcessorsRegistry as Tt, QueryCanceledError as U, ColumnURN as Un, TimestampToken as Ut, LockNotAvailableError as V, IndexURNType as Vn, SQLColumnTypeTokensFactory as Vt, SerializationError as W, ColumnURNType as Wn, TimestamptzToken as Wt, getDefaultMigratorOptionsFromRegistry as X, schemaComponent as Xn, SQLPlain as Xt, combineMigrations as Y, mapSchemaComponentsOfType as Yn, SQLLiteral as Yt, registerDefaultMigratorOptions as Z, SQLToken as Zt, transactionFactoryWithNewConnection as _, DumboDatabaseMetadataRegistry as _n, mapSQLIdentifier as _t, createSingletonClientConnectionPool as a, composeJSONReplacers as an, prettyJson as at, executeInNewConnection as b, getDefaultDatabase as bn, RawSQL as bt, TaskProcessor as c, count as cn, describeSQL as ct, createSingletonConnection as d, firstOrNull as dn, registerFormatter as dt, JSONReplacer as en, migrationTableSchemaComponent as et, createTransientConnection as f, single as fn, ANSISQLIdentifierQuote as ft, transactionFactoryWithDbClient as g, dumboSchema as gn, mapANSISQLParamPlaceholder as gt, transactionFactoryWithAsyncAmbientConnection as h, defaultDatabaseLockOptions as hn, SQLValueMapper as ht, createConnectionPool as i, JSONSerializer as in, tracer as it, ConcurrencyError as j, DatabaseURN as jn, MapLiteralProcessor as jt, AdminShutdownError as k, dumboDatabaseDriverRegistry as kn, ExpandSQLInProcessor as kt, createAmbientConnection as l, exists as ln, formatSQL as lt, transactionFactoryWithAmbientConnection as m, NoDatabaseLock as mn, DefaultMapSQLParamValueOptions as mt, createAmbientConnectionPool as n, JSONReviver as nn, LogLevel as nt, createSingletonConnectionPool as o, composeJSONRevivers as on, color as ot, executeInTransaction as p, singleOrNull as pn, ANSISQLParamPlaceholder as pt, UniqueConstraintError as q, findSchemaComponentsOfType as qn, SQLIdentifier as qt, createBoundedConnectionPool as r, JSONRevivers as rn, LogStyle as rt, guardInitializedOnce as s, jsonSerializer as sn, SQLFormatter as st, createAlwaysNewConnectionPool as t, JSONReplacers as tn, sqlMigration as tt, createConnection as u, first as un, getFormatter as ut, BatchCommandNoChangesError as v, dumboDatabaseMetadataRegistry as vn, mapSQLParamValue as vt, mapColumnToJSON as w, getDatabaseDriverName as wn, isTokenizedSQL as wt, executeInNewDbClient as x, getDefaultDatabaseAsync as xn, SQL as xt, executeInAmbientConnection as y, getDatabaseMetadata as yn, ansiSqlReservedMap as yt, IntegrityConstraintViolationError as z, tableSchemaComponent as zn, SQLColumnToken as zt };
|
|
2262
|
-
//# sourceMappingURL=core-BG__WVn6.js.map
|
|
2277
|
+
export { SQLArray as $, getDatabaseType as $t, TokenizedSQL as A, sqlExecutorInAmbientConnection as An, TableURNType as At, AutoIncrementSQLColumnToken as B, ForeignKeyViolationError as Bn, isSchemaComponentOfType as Bt, mapANSISQLParamPlaceholder as C, executeInNewConnection as Cn, DatabaseURN as Ct, RawSQL as D, mapColumnToJSON as Dn, DatabaseSchemaURNType as Dt, ansiSqlReservedMap as E, mapColumnToDate as En, DatabaseSchemaURN as Et, ExpandArrayProcessor as F, ConnectionError as Fn, ColumnURN as Ft, JSONBToken as G, NotNullViolationError as Gn, first as Gt, BigSerialToken as H, IntegrityConstraintViolationError as Hn, schemaComponent as Ht, ExpandSQLInProcessor as I, DataError as In, ColumnURNType as It, SQLColumnTypeTokensFactory as J, SystemError as Jn, singleOrNull as Jt, SQLColumnToken as K, QueryCanceledError as Kn, firstOrNull as Kt, FormatIdentifierProcessor as L, DeadlockError as Ln, columnSchemaComponent as Lt, defaultProcessorsRegistry as M, AdminShutdownError as Mn, IndexURN as Mt, mapDefaultSQLColumnProcessors as N, CheckViolationError as Nn, IndexURNType as Nt, SQL as O, mapSQLQueryResult as On, databaseSchemaSchemaComponent as Ot, SQLProcessorsRegistry as P, ConcurrencyError as Pn, indexSchemaComponent as Pt, VarcharToken as Q, getDatabaseDriverName as Qt, MapLiteralProcessor as R, DumboError as Rn, filterSchemaComponentsOfType as Rt, SQLValueMapper as S, executeInAmbientConnection as Sn, schemaComponentURN as St, mapSQLParamValue as T, mapColumnToBigint as Tn, databaseSchemaComponent as Tt, ColumnTypeToken as U, InvalidOperationError as Un, count as Ut, BigIntegerToken as V, InsufficientResourcesError as Vn, mapSchemaComponentsOfType as Vt, IntegerToken as W, LockNotAvailableError as Wn, exists as Wt, TimestampToken as X, UniqueConstraintError as Xn, defaultDatabaseLockOptions as Xt, SerialToken as Y, TransientDatabaseError as Yn, NoDatabaseLock as Yt, TimestamptzToken as Z, fromDatabaseDriverType as Zt, getFormatter as _, transactionFactoryWithAmbientConnection as _n, dumboDatabaseMetadataRegistry as _t, runSQLMigrations as a, createAmbientConnectionPool as an, ParametrizedSQLBuilder as at, ANSISQLParamPlaceholder as b, transactionFactoryWithNewConnection as bn, getDefaultDatabaseAsync as bt, sqlMigration as c, createSingletonClientConnectionPool as cn, JSONReplacers as ct, tracer as d, TaskProcessor as dn, JSONSerializer as dt, toDatabaseDriverType as en, SQLIdentifier as et, prettyJson as f, createAmbientConnection as fn, composeJSONReplacers as ft, formatSQL as g, executeInTransaction as gn, DumboDatabaseMetadataRegistry as gt, describeSQL as h, createTransientConnection as hn, dumboSchema as ht, registerDefaultMigratorOptions as i, createAlwaysNewConnectionPool as in, SQLToken as it, isTokenizedSQL as j, sqlExecutorInNewConnection as jn, tableSchemaComponent as jt, isSQL as k, sqlExecutor as kn, TableURN as kt, LogLevel as l, createSingletonConnectionPool as ln, JSONReviver as lt, SQLFormatter as m, createSingletonConnection as mn, jsonSerializer as mt, combineMigrations as n, canHandleDriverWithConnectionString as nn, SQLLiteral as nt, SchemaComponentMigrator as o, createBoundedConnectionPool as on, JSONCodec as ot, color as p, createConnection as pn, composeJSONRevivers as pt, SQLColumnTypeTokens as q, SerializationError as qn, single as qt, getDefaultMigratorOptionsFromRegistry as r, dumboDatabaseDriverRegistry as rn, SQLPlain as rt, migrationTableSchemaComponent as s, createConnectionPool as sn, JSONReplacer as st, MIGRATIONS_LOCK_ID as t, DumboDatabaseDriverRegistry as tn, SQLIn as tt, LogStyle as u, guardInitializedOnce as un, JSONRevivers as ut, registerFormatter as v, transactionFactoryWithAsyncAmbientConnection as vn, getDatabaseMetadata as vt, mapSQLIdentifier as w, executeInNewDbClient as wn, DatabaseURNType as wt, DefaultMapSQLParamValueOptions as x, BatchCommandNoChangesError as xn, resolveDatabaseMetadata as xt, ANSISQLIdentifierQuote as y, transactionFactoryWithDbClient as yn, getDefaultDatabase as yt, SQLProcessor as z, ExclusionViolationError as zn, findSchemaComponentsOfType as zt };
|
|
2278
|
+
//# sourceMappingURL=core-IV7or0Mj.js.map
|