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