@mlagie/sql-connector 3.0.3 → 3.1.0
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/README.md +985 -316
- package/docs/API.md +240 -0
- package/docs/DIALECTS.md +56 -0
- package/docs/MIGRATIONS.md +277 -0
- package/docs/QUERY.md +281 -0
- package/docs/README.md +20 -0
- package/docs/SCHEMA.md +167 -0
- package/docs/fr/README_FR.md +549 -305
- package/index.d.ts +2002 -137
- package/index.js +39 -9
- package/package.json +7 -6
- package/src/db/dialects.js +1 -1
- package/src/migration/BackupManager.js +42 -0
- package/src/migration/Migration.js +163 -0
- package/src/migration/MigrationPlan.js +62 -0
- package/src/migration/MigrationRunner.js +194 -0
- package/src/migration/MigrationStore.js +137 -0
- package/src/migration/SchemaDiffer.js +261 -0
- package/src/migration/SchemaInspector.js +44 -0
- package/src/migration/SchemaSnapshot.js +53 -0
- package/src/migration/crypto.js +79 -0
- package/src/migration/dialects/Dialect.js +112 -0
- package/src/migration/dialects/MySQLDialect.js +205 -0
- package/src/migration/dialects/PostgreSQLDialect.js +233 -0
- package/src/migration/dialects/index.js +21 -0
- package/src/migration/errors.js +28 -0
- package/src/migration/index.js +18 -0
- package/src/migration/utils.js +89 -0
- package/src/models/Model.js +8 -2
- package/src/models/Schema.js +20 -20
- package/src/utils/buildQuery/buildQuery.js +51 -11
- package/src/utils/sqlTypeMap.js +8 -0
package/index.d.ts
CHANGED
|
@@ -1,29 +1,96 @@
|
|
|
1
1
|
import { PoolOptions } from "mysql2";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* Supported SQL data types exposed by SQL Connector.
|
|
5
|
+
*
|
|
6
|
+
* SQL Connector uses a database-independent type vocabulary.
|
|
7
|
+
* The selected SQL dialect is responsible for translating these
|
|
8
|
+
* logical types into the native SQL type.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```ts
|
|
12
|
+
* const schema = new Schema({
|
|
13
|
+
* name: {
|
|
14
|
+
* type: "String",
|
|
15
|
+
* length: 255
|
|
16
|
+
* },
|
|
17
|
+
* age: {
|
|
18
|
+
* type: "Number"
|
|
19
|
+
* },
|
|
20
|
+
* active: {
|
|
21
|
+
* type: "Boolean"
|
|
22
|
+
* }
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
3
26
|
export type SqlType =
|
|
4
27
|
| "String"
|
|
28
|
+
| "Char"
|
|
5
29
|
| "Number"
|
|
30
|
+
| "SmallInt"
|
|
31
|
+
| "BigInt"
|
|
32
|
+
| "Decimal"
|
|
6
33
|
| "Boolean"
|
|
7
34
|
| "Date"
|
|
8
35
|
| "Object"
|
|
9
36
|
| "Array"
|
|
10
37
|
| "Now"
|
|
11
38
|
| "Float"
|
|
39
|
+
| "Double"
|
|
12
40
|
| "Text"
|
|
41
|
+
| "Blob"
|
|
42
|
+
| "Binary"
|
|
43
|
+
| "Uuid"
|
|
13
44
|
| "DateTime"
|
|
14
45
|
| "Timestamp"
|
|
15
46
|
| "CurrentTimestamp";
|
|
16
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Maps SQL Connector logical types to their TypeScript representation.
|
|
50
|
+
*
|
|
51
|
+
* Custom keys are supported for dialect-specific or user-defined types.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```ts
|
|
55
|
+
* const value: SqlTypeMap = {
|
|
56
|
+
* String: "varchar",
|
|
57
|
+
* Number: "integer",
|
|
58
|
+
* Date: "date"
|
|
59
|
+
* };
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
17
62
|
export interface SqlTypeMap {
|
|
18
63
|
String: string;
|
|
19
64
|
Number: string;
|
|
20
65
|
Date: string;
|
|
21
|
-
CurrentTimestamp: string;
|
|
22
|
-
|
|
66
|
+
CurrentTimestamp: string;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Allows additional SQL type mappings.
|
|
70
|
+
*/
|
|
71
|
+
[key: string]: any;
|
|
23
72
|
}
|
|
24
73
|
|
|
74
|
+
/**
|
|
75
|
+
* SQL type mapping used internally by the connector.
|
|
76
|
+
*/
|
|
25
77
|
export const sqlTypeMap: SqlTypeMap;
|
|
26
78
|
|
|
79
|
+
/**
|
|
80
|
+
* Native JavaScript constructors accepted as schema types.
|
|
81
|
+
*
|
|
82
|
+
* SQL Connector normalizes these constructors to its logical SQL types.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* const schema = new Schema({
|
|
87
|
+
* username: { type: String },
|
|
88
|
+
* age: { type: Number },
|
|
89
|
+
* active: { type: Boolean },
|
|
90
|
+
* createdAt: { type: Date }
|
|
91
|
+
* });
|
|
92
|
+
* ```
|
|
93
|
+
*/
|
|
27
94
|
export type SqlTypeConstructor =
|
|
28
95
|
| StringConstructor
|
|
29
96
|
| NumberConstructor
|
|
@@ -32,36 +99,369 @@ export type SqlTypeConstructor =
|
|
|
32
99
|
| ObjectConstructor
|
|
33
100
|
| ArrayConstructor;
|
|
34
101
|
|
|
35
|
-
|
|
102
|
+
/**
|
|
103
|
+
* Input accepted for a schema field type.
|
|
104
|
+
*
|
|
105
|
+
* A type can be specified using:
|
|
106
|
+
* - a SQL Connector type name;
|
|
107
|
+
* - a `{ name: ... }` descriptor;
|
|
108
|
+
* - a native JavaScript constructor.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* type: "String"
|
|
113
|
+
* ```
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* ```ts
|
|
117
|
+
* type: String
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* ```ts
|
|
122
|
+
* type: { name: "String" }
|
|
123
|
+
* ```
|
|
124
|
+
*/
|
|
125
|
+
export type SchemaTypeInput =
|
|
126
|
+
| SqlType
|
|
127
|
+
| { name: SqlType }
|
|
128
|
+
| SqlTypeConstructor;
|
|
36
129
|
|
|
130
|
+
/**
|
|
131
|
+
* Describes a column in a SQL Connector schema.
|
|
132
|
+
*
|
|
133
|
+
* Schema fields can define SQL types, constraints, defaults,
|
|
134
|
+
* indexes, foreign keys and migration metadata.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```ts
|
|
138
|
+
* const userSchema = new Schema({
|
|
139
|
+
* id: {
|
|
140
|
+
* type: "Uuid",
|
|
141
|
+
* primary_key: true
|
|
142
|
+
* },
|
|
143
|
+
*
|
|
144
|
+
* email: {
|
|
145
|
+
* type: "String",
|
|
146
|
+
* length: 320,
|
|
147
|
+
* required: true,
|
|
148
|
+
* unique: true
|
|
149
|
+
* },
|
|
150
|
+
*
|
|
151
|
+
* age: {
|
|
152
|
+
* type: "Number"
|
|
153
|
+
* }
|
|
154
|
+
* });
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
37
157
|
export interface SchemaField {
|
|
158
|
+
/**
|
|
159
|
+
* SQL Connector type used by the column.
|
|
160
|
+
*/
|
|
38
161
|
type: SchemaTypeInput;
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Maximum length of a character or binary field.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* { type: "String", length: 255 }
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
39
171
|
length?: number;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Total number of digits for numeric types such as DECIMAL.
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
* ```ts
|
|
178
|
+
* { type: "Decimal", precision: 12, scale: 2 }
|
|
179
|
+
* ```
|
|
180
|
+
*/
|
|
181
|
+
precision?: number;
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Number of digits stored after the decimal point.
|
|
185
|
+
*
|
|
186
|
+
* @example
|
|
187
|
+
* ```ts
|
|
188
|
+
* { type: "Decimal", precision: 12, scale: 2 }
|
|
189
|
+
* ```
|
|
190
|
+
*/
|
|
191
|
+
scale?: number;
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Marks the column as NOT NULL.
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* ```ts
|
|
198
|
+
* { type: "String", required: true }
|
|
199
|
+
* ```
|
|
200
|
+
*/
|
|
40
201
|
required?: boolean;
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Default value assigned by the database.
|
|
205
|
+
*
|
|
206
|
+
* `CurrentTimestamp` can be used for database-generated timestamps.
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* ```ts
|
|
210
|
+
* {
|
|
211
|
+
* type: "Timestamp",
|
|
212
|
+
* default: "CurrentTimestamp"
|
|
213
|
+
* }
|
|
214
|
+
* ```
|
|
215
|
+
*/
|
|
41
216
|
default?: any | SqlType | "CurrentTimestamp";
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Adds a UNIQUE constraint.
|
|
220
|
+
*/
|
|
42
221
|
unique?: boolean;
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Marks the column as auto-incrementing.
|
|
225
|
+
*/
|
|
43
226
|
auto_increment?: boolean;
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Legacy foreign-key declaration.
|
|
230
|
+
*
|
|
231
|
+
* Prefer the structured `references` declaration when available.
|
|
232
|
+
*
|
|
233
|
+
* @example
|
|
234
|
+
* ```ts
|
|
235
|
+
* {
|
|
236
|
+
* type: "Number",
|
|
237
|
+
* foreignKey: "users(id)"
|
|
238
|
+
* }
|
|
239
|
+
* ```
|
|
240
|
+
*/
|
|
44
241
|
foreignKey?: string;
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Allowed values for an enum-like column.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* ```ts
|
|
248
|
+
* {
|
|
249
|
+
* type: "String",
|
|
250
|
+
* enum: ["pending", "paid", "cancelled"]
|
|
251
|
+
* }
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
45
254
|
enum?: string[];
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Marks the column as the primary key.
|
|
258
|
+
*/
|
|
46
259
|
primary_key?: boolean;
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Previous column name used by migrations when a column is renamed.
|
|
263
|
+
*
|
|
264
|
+
* @example
|
|
265
|
+
* ```ts
|
|
266
|
+
* {
|
|
267
|
+
* type: "String",
|
|
268
|
+
* oldname: "username"
|
|
269
|
+
* }
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
oldname?: string;
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Allows custom SQL to be attached to the column definition.
|
|
276
|
+
*/
|
|
47
277
|
customize?: string;
|
|
48
278
|
}
|
|
49
279
|
|
|
280
|
+
/**
|
|
281
|
+
* Collection of schema fields indexed by column name.
|
|
282
|
+
*
|
|
283
|
+
* @example
|
|
284
|
+
* ```ts
|
|
285
|
+
* const schema: SchemaDict = {
|
|
286
|
+
* id: {
|
|
287
|
+
* type: "Uuid",
|
|
288
|
+
* primary_key: true
|
|
289
|
+
* },
|
|
290
|
+
* email: {
|
|
291
|
+
* type: "String",
|
|
292
|
+
* unique: true
|
|
293
|
+
* }
|
|
294
|
+
* };
|
|
295
|
+
* ```
|
|
296
|
+
*/
|
|
50
297
|
export interface SchemaDict {
|
|
51
298
|
[key: string]: SchemaField;
|
|
52
299
|
}
|
|
53
300
|
|
|
301
|
+
/**
|
|
302
|
+
* Describes an aggregate or calculated expression used in SELECT.
|
|
303
|
+
*
|
|
304
|
+
* Supported expressions include COUNT and SUM as well as column
|
|
305
|
+
* expressions and date formatting.
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```ts
|
|
309
|
+
* const users = await model.find({
|
|
310
|
+
* select: [
|
|
311
|
+
* "status",
|
|
312
|
+
* { count: "id", as: "total" }
|
|
313
|
+
* ]
|
|
314
|
+
* });
|
|
315
|
+
* ```
|
|
316
|
+
*
|
|
317
|
+
* @example
|
|
318
|
+
* ```ts
|
|
319
|
+
* const revenue = await model.find({
|
|
320
|
+
* select: [
|
|
321
|
+
* { sum: "amount", as: "revenue" }
|
|
322
|
+
* ]
|
|
323
|
+
* });
|
|
324
|
+
* ```
|
|
325
|
+
*/
|
|
54
326
|
export type SelectAggregation = {
|
|
327
|
+
/**
|
|
328
|
+
* Column used by the expression.
|
|
329
|
+
*/
|
|
55
330
|
col?: string;
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* Calculates SUM(column).
|
|
334
|
+
*/
|
|
56
335
|
sum?: string;
|
|
336
|
+
|
|
337
|
+
/**
|
|
338
|
+
* Selects a DISTINCT value/expression.
|
|
339
|
+
*/
|
|
57
340
|
distinct?: string;
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Formats a date expression.
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```ts
|
|
347
|
+
* { dateFormat: ["created_at", "%Y-%m"], as: "month" }
|
|
348
|
+
* ```
|
|
349
|
+
*/
|
|
58
350
|
dateFormat?: [string, string];
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Calculates COUNT(column).
|
|
354
|
+
*
|
|
355
|
+
* A string, list of strings or object may be supplied
|
|
356
|
+
* depending on the query builder expression.
|
|
357
|
+
*
|
|
358
|
+
* @example
|
|
359
|
+
* ```ts
|
|
360
|
+
* { count: "id", as: "total" }
|
|
361
|
+
* ```
|
|
362
|
+
*/
|
|
59
363
|
count?: string | string[] | Record<string, any>;
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Alias assigned to the resulting expression.
|
|
367
|
+
*/
|
|
60
368
|
as?: string;
|
|
61
369
|
};
|
|
62
370
|
|
|
371
|
+
/**
|
|
372
|
+
* Value accepted in the SELECT list.
|
|
373
|
+
*
|
|
374
|
+
* A SELECT item can either be a column name or an aggregate expression.
|
|
375
|
+
*
|
|
376
|
+
* @example
|
|
377
|
+
* ```ts
|
|
378
|
+
* select: [
|
|
379
|
+
* "status",
|
|
380
|
+
* { count: "id", as: "total" }
|
|
381
|
+
* ]
|
|
382
|
+
* ```
|
|
383
|
+
*/
|
|
63
384
|
export type SelectItem = string | SelectAggregation;
|
|
64
385
|
|
|
386
|
+
/**
|
|
387
|
+
* Describes an expression used by GROUP BY.
|
|
388
|
+
*
|
|
389
|
+
* @example
|
|
390
|
+
* ```ts
|
|
391
|
+
* groupBy: [
|
|
392
|
+
* "status"
|
|
393
|
+
* ]
|
|
394
|
+
* ```
|
|
395
|
+
*
|
|
396
|
+
* @example
|
|
397
|
+
* ```ts
|
|
398
|
+
* groupBy: [
|
|
399
|
+
* {
|
|
400
|
+
* col: "created_at",
|
|
401
|
+
* dateFormat: ["created_at", "%Y-%m"],
|
|
402
|
+
* as: "month"
|
|
403
|
+
* }
|
|
404
|
+
* ]
|
|
405
|
+
* ```
|
|
406
|
+
*/
|
|
407
|
+
export interface GroupAggregation {
|
|
408
|
+
/**
|
|
409
|
+
* Column used for grouping.
|
|
410
|
+
*/
|
|
411
|
+
col?: string;
|
|
412
|
+
|
|
413
|
+
/**
|
|
414
|
+
* Date formatting expression used before grouping.
|
|
415
|
+
*/
|
|
416
|
+
dateFormat?: [string, string];
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Alias assigned to the grouped expression.
|
|
420
|
+
*/
|
|
421
|
+
as?: string;
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
/**
|
|
425
|
+
* Defines a sort rule used by ORDER BY.
|
|
426
|
+
*
|
|
427
|
+
* @example
|
|
428
|
+
* ```ts
|
|
429
|
+
* orderBy: [
|
|
430
|
+
* {
|
|
431
|
+
* field: "created_at",
|
|
432
|
+
* direction: "DESC"
|
|
433
|
+
* }
|
|
434
|
+
* ]
|
|
435
|
+
* ```
|
|
436
|
+
*/
|
|
437
|
+
export interface OrderByOption {
|
|
438
|
+
/**
|
|
439
|
+
* Column or selected alias used for sorting.
|
|
440
|
+
*/
|
|
441
|
+
field: string;
|
|
442
|
+
|
|
443
|
+
/**
|
|
444
|
+
* Sort direction.
|
|
445
|
+
*
|
|
446
|
+
* Defaults to ASC when omitted.
|
|
447
|
+
*/
|
|
448
|
+
direction?: "ASC" | "DESC";
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* SQL operators supported by the SQL Connector condition builder.
|
|
453
|
+
*
|
|
454
|
+
* These operators are converted to parameterized SQL expressions.
|
|
455
|
+
*
|
|
456
|
+
* @example
|
|
457
|
+
* ```ts
|
|
458
|
+
* const where: WhereClause = {
|
|
459
|
+
* age: {
|
|
460
|
+
* ">=": 18
|
|
461
|
+
* }
|
|
462
|
+
* };
|
|
463
|
+
* ```
|
|
464
|
+
*/
|
|
65
465
|
export type WhereOperator =
|
|
66
466
|
| "="
|
|
67
467
|
| "!="
|
|
@@ -70,17 +470,142 @@ export type WhereOperator =
|
|
|
70
470
|
| ">="
|
|
71
471
|
| "<="
|
|
72
472
|
| "LIKE"
|
|
473
|
+
| "NOT LIKE"
|
|
474
|
+
| "ILIKE"
|
|
475
|
+
| "NOT ILIKE"
|
|
73
476
|
| "IN"
|
|
74
|
-
| "NOT IN"
|
|
477
|
+
| "NOT IN"
|
|
478
|
+
| "BETWEEN"
|
|
479
|
+
| "NOT BETWEEN";
|
|
75
480
|
|
|
481
|
+
/**
|
|
482
|
+
* Object containing a SQL comparison operator.
|
|
483
|
+
*
|
|
484
|
+
* @example
|
|
485
|
+
* ```ts
|
|
486
|
+
* {
|
|
487
|
+
* age: {
|
|
488
|
+
* ">=": 18
|
|
489
|
+
* }
|
|
490
|
+
* }
|
|
491
|
+
* ```
|
|
492
|
+
*
|
|
493
|
+
* @example
|
|
494
|
+
* ```ts
|
|
495
|
+
* {
|
|
496
|
+
* status: {
|
|
497
|
+
* IN: ["active", "pending"]
|
|
498
|
+
* }
|
|
499
|
+
* }
|
|
500
|
+
* ```
|
|
501
|
+
*/
|
|
76
502
|
export type WhereOperatorObject = {
|
|
77
503
|
[K in WhereOperator]?: any;
|
|
78
504
|
};
|
|
79
505
|
|
|
506
|
+
/**
|
|
507
|
+
* Represents a SQL WHERE or HAVING condition.
|
|
508
|
+
*
|
|
509
|
+
* Conditions can be combined recursively using AND, OR and NOT.
|
|
510
|
+
*
|
|
511
|
+
* A direct value represents an equality comparison.
|
|
512
|
+
*
|
|
513
|
+
* @example
|
|
514
|
+
* ```ts
|
|
515
|
+
* const where: WhereClause = {
|
|
516
|
+
* status: "active"
|
|
517
|
+
* };
|
|
518
|
+
* ```
|
|
519
|
+
*
|
|
520
|
+
* @example
|
|
521
|
+
* ```ts
|
|
522
|
+
* const where: WhereClause = {
|
|
523
|
+
* age: {
|
|
524
|
+
* ">=": 18,
|
|
525
|
+
* "<": 65
|
|
526
|
+
* }
|
|
527
|
+
* };
|
|
528
|
+
* ```
|
|
529
|
+
*
|
|
530
|
+
* @example
|
|
531
|
+
* ```ts
|
|
532
|
+
* const where: WhereClause = {
|
|
533
|
+
* status: {
|
|
534
|
+
* IN: ["active", "pending"]
|
|
535
|
+
* }
|
|
536
|
+
* };
|
|
537
|
+
* ```
|
|
538
|
+
*
|
|
539
|
+
* @example
|
|
540
|
+
* ```ts
|
|
541
|
+
* const where: WhereClause = {
|
|
542
|
+
* age: {
|
|
543
|
+
* BETWEEN: [18, 65]
|
|
544
|
+
* }
|
|
545
|
+
* };
|
|
546
|
+
* ```
|
|
547
|
+
*
|
|
548
|
+
* @example
|
|
549
|
+
* ```ts
|
|
550
|
+
* const where: WhereClause = {
|
|
551
|
+
* AND: [
|
|
552
|
+
* { active: true },
|
|
553
|
+
* {
|
|
554
|
+
* age: {
|
|
555
|
+
* ">=": 18
|
|
556
|
+
* }
|
|
557
|
+
* }
|
|
558
|
+
* ]
|
|
559
|
+
* };
|
|
560
|
+
* ```
|
|
561
|
+
*
|
|
562
|
+
* @example
|
|
563
|
+
* ```ts
|
|
564
|
+
* const where: WhereClause = {
|
|
565
|
+
* OR: [
|
|
566
|
+
* { status: "active" },
|
|
567
|
+
* { status: "pending" }
|
|
568
|
+
* ]
|
|
569
|
+
* };
|
|
570
|
+
* ```
|
|
571
|
+
*
|
|
572
|
+
* @example
|
|
573
|
+
* ```ts
|
|
574
|
+
* const where: WhereClause = {
|
|
575
|
+
* NOT: {
|
|
576
|
+
* status: "cancelled"
|
|
577
|
+
* }
|
|
578
|
+
* };
|
|
579
|
+
* ```
|
|
580
|
+
*
|
|
581
|
+
* `null` is translated to SQL NULL semantics.
|
|
582
|
+
*
|
|
583
|
+
* @example
|
|
584
|
+
* ```ts
|
|
585
|
+
* const where: WhereClause = {
|
|
586
|
+
* deleted_at: null
|
|
587
|
+
* };
|
|
588
|
+
* ```
|
|
589
|
+
*/
|
|
80
590
|
export interface WhereClause {
|
|
591
|
+
/**
|
|
592
|
+
* Combines several conditions with AND.
|
|
593
|
+
*/
|
|
81
594
|
AND?: WhereClause[];
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Combines several conditions with OR.
|
|
598
|
+
*/
|
|
82
599
|
OR?: WhereClause[];
|
|
83
600
|
|
|
601
|
+
/**
|
|
602
|
+
* Negates a condition.
|
|
603
|
+
*/
|
|
604
|
+
NOT?: WhereClause;
|
|
605
|
+
|
|
606
|
+
/**
|
|
607
|
+
* Column conditions.
|
|
608
|
+
*/
|
|
84
609
|
[key: string]:
|
|
85
610
|
| any
|
|
86
611
|
| WhereClause[]
|
|
@@ -88,6 +613,48 @@ export interface WhereClause {
|
|
|
88
613
|
| undefined;
|
|
89
614
|
}
|
|
90
615
|
|
|
616
|
+
/**
|
|
617
|
+
* Describes a SQL JOIN.
|
|
618
|
+
*
|
|
619
|
+
* @example
|
|
620
|
+
* ```ts
|
|
621
|
+
* const users = await model.find({
|
|
622
|
+
* join: {
|
|
623
|
+
* table: "companies",
|
|
624
|
+
* alias: "company",
|
|
625
|
+
* type: "LEFT",
|
|
626
|
+
* on: "users.company_id = company.id"
|
|
627
|
+
* }
|
|
628
|
+
* });
|
|
629
|
+
* ```
|
|
630
|
+
*/
|
|
631
|
+
export interface JoinOption {
|
|
632
|
+
/**
|
|
633
|
+
* Name of the table to join.
|
|
634
|
+
*/
|
|
635
|
+
table: string;
|
|
636
|
+
|
|
637
|
+
/**
|
|
638
|
+
* SQL join condition.
|
|
639
|
+
*
|
|
640
|
+
* @example
|
|
641
|
+
* ```ts
|
|
642
|
+
* on: "users.company_id = company.id"
|
|
643
|
+
* ```
|
|
644
|
+
*/
|
|
645
|
+
on: string;
|
|
646
|
+
|
|
647
|
+
/**
|
|
648
|
+
* Optional table alias.
|
|
649
|
+
*/
|
|
650
|
+
alias?: string;
|
|
651
|
+
|
|
652
|
+
/**
|
|
653
|
+
* Type of SQL JOIN.
|
|
654
|
+
*/
|
|
655
|
+
type?: "INNER" | "LEFT" | "RIGHT";
|
|
656
|
+
}
|
|
657
|
+
|
|
91
658
|
type NormalizeSqlType<T> =
|
|
92
659
|
T extends StringConstructor
|
|
93
660
|
? "String"
|
|
@@ -122,7 +689,8 @@ type InferSqlType<T> =
|
|
|
122
689
|
? unknown[]
|
|
123
690
|
: unknown;
|
|
124
691
|
|
|
125
|
-
type HasKey<T, K extends PropertyKey> =
|
|
692
|
+
type HasKey<T, K extends PropertyKey> =
|
|
693
|
+
K extends keyof T ? true : false;
|
|
126
694
|
|
|
127
695
|
type InferFieldValue<TField> =
|
|
128
696
|
InferSqlType<TField extends { type: infer T } ? T : TField>;
|
|
@@ -140,12 +708,56 @@ type InferFieldNullable<TField> =
|
|
|
140
708
|
? false
|
|
141
709
|
: true;
|
|
142
710
|
|
|
711
|
+
/**
|
|
712
|
+
* Infers the TypeScript representation of a SQL Connector schema.
|
|
713
|
+
*
|
|
714
|
+
* Nullable fields are automatically represented using `null`.
|
|
715
|
+
*
|
|
716
|
+
* @example
|
|
717
|
+
* ```ts
|
|
718
|
+
* const schema = {
|
|
719
|
+
* id: {
|
|
720
|
+
* type: "Number",
|
|
721
|
+
* primary_key: true
|
|
722
|
+
* },
|
|
723
|
+
* name: {
|
|
724
|
+
* type: "String",
|
|
725
|
+
* required: true
|
|
726
|
+
* },
|
|
727
|
+
* nickname: {
|
|
728
|
+
* type: "String"
|
|
729
|
+
* }
|
|
730
|
+
* } as const;
|
|
731
|
+
*
|
|
732
|
+
* type User = InferSchema<typeof schema>;
|
|
733
|
+
*
|
|
734
|
+
* // {
|
|
735
|
+
* // id: number;
|
|
736
|
+
* // name: string;
|
|
737
|
+
* // nickname: string | null;
|
|
738
|
+
* // }
|
|
739
|
+
* ```
|
|
740
|
+
*/
|
|
143
741
|
export type InferSchema<TSchema extends SchemaDict> = {
|
|
144
|
-
[K in keyof TSchema]:
|
|
742
|
+
[K in keyof TSchema]:
|
|
743
|
+
InferFieldNullable<TSchema[K]> extends true
|
|
145
744
|
? InferFieldValue<TSchema[K]> | null
|
|
146
745
|
: InferFieldValue<TSchema[K]>;
|
|
147
746
|
};
|
|
148
747
|
|
|
748
|
+
/**
|
|
749
|
+
* Represents either a Schema instance or a schema-compatible object.
|
|
750
|
+
*
|
|
751
|
+
* @example
|
|
752
|
+
* ```ts
|
|
753
|
+
* const schema = new Schema({
|
|
754
|
+
* id: {
|
|
755
|
+
* type: "Number",
|
|
756
|
+
* primary_key: true
|
|
757
|
+
* }
|
|
758
|
+
* });
|
|
759
|
+
* ```
|
|
760
|
+
*/
|
|
149
761
|
export type SchemaLike<TSchema extends SchemaDict = SchemaDict> =
|
|
150
762
|
| Schema<TSchema>
|
|
151
763
|
| {
|
|
@@ -153,212 +765,1465 @@ export type SchemaLike<TSchema extends SchemaDict = SchemaDict> =
|
|
|
153
765
|
schema?: TSchema;
|
|
154
766
|
};
|
|
155
767
|
|
|
156
|
-
|
|
768
|
+
/**
|
|
769
|
+
* Represents a database record together with ModelInstance methods.
|
|
770
|
+
*/
|
|
771
|
+
export type ModelRecord<
|
|
772
|
+
TData extends Record<string, any> = Record<string, any>
|
|
773
|
+
> = ModelInstance<TData> & TData;
|
|
157
774
|
|
|
158
775
|
/**
|
|
159
|
-
* Represents a database schema.
|
|
160
|
-
*
|
|
776
|
+
* Represents a database schema definition.
|
|
777
|
+
*
|
|
778
|
+
* A Schema is used by Model to describe table columns,
|
|
779
|
+
* constraints and migration metadata.
|
|
780
|
+
*
|
|
161
781
|
* @example
|
|
162
|
-
*
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
782
|
+
* ```ts
|
|
783
|
+
* const userSchema = new Schema({
|
|
784
|
+
* id: {
|
|
785
|
+
* type: "Uuid",
|
|
786
|
+
* primary_key: true
|
|
787
|
+
* },
|
|
788
|
+
* email: {
|
|
789
|
+
* type: "String",
|
|
790
|
+
* length: 320,
|
|
791
|
+
* required: true,
|
|
792
|
+
* unique: true
|
|
793
|
+
* }
|
|
171
794
|
* });
|
|
795
|
+
* ```
|
|
172
796
|
*/
|
|
173
797
|
export class Schema<TSchema extends SchemaDict = SchemaDict> {
|
|
798
|
+
/**
|
|
799
|
+
* Creates a schema definition.
|
|
800
|
+
*
|
|
801
|
+
* @param schemaDict Object describing the table columns.
|
|
802
|
+
*/
|
|
174
803
|
constructor(schemaDict: TSchema);
|
|
804
|
+
|
|
805
|
+
/**
|
|
806
|
+
* Original schema definition.
|
|
807
|
+
*/
|
|
175
808
|
schemaDict: TSchema;
|
|
809
|
+
|
|
810
|
+
/**
|
|
811
|
+
* Normalized schema definition.
|
|
812
|
+
*/
|
|
176
813
|
schema: TSchema;
|
|
177
814
|
}
|
|
178
815
|
|
|
179
816
|
/**
|
|
180
|
-
* Establishes a
|
|
181
|
-
*
|
|
182
|
-
* @param
|
|
183
|
-
* @
|
|
184
|
-
*
|
|
185
|
-
* @
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
*
|
|
190
|
-
*
|
|
191
|
-
*
|
|
192
|
-
*
|
|
193
|
-
*
|
|
194
|
-
*
|
|
195
|
-
* database: 'mydatabase'
|
|
196
|
-
* };
|
|
197
|
-
* await connect(config);
|
|
817
|
+
* Establishes a database connection.
|
|
818
|
+
*
|
|
819
|
+
* @param config MySQL/PostgreSQL connection pool configuration.
|
|
820
|
+
* @returns A promise resolved once the connection has been established.
|
|
821
|
+
*
|
|
822
|
+
* @example
|
|
823
|
+
* ```ts
|
|
824
|
+
* await connect({
|
|
825
|
+
* host: "localhost",
|
|
826
|
+
* port: 3306,
|
|
827
|
+
* user: "root",
|
|
828
|
+
* password: "password",
|
|
829
|
+
* database: "application"
|
|
830
|
+
* });
|
|
831
|
+
* ```
|
|
198
832
|
*/
|
|
199
833
|
export function connect(config: PoolOptions): Promise<void>;
|
|
200
834
|
|
|
201
835
|
/**
|
|
202
|
-
* Establishes a connection
|
|
203
|
-
*
|
|
204
|
-
* @param
|
|
205
|
-
* @param
|
|
206
|
-
*
|
|
207
|
-
* @
|
|
208
|
-
*
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
*
|
|
217
|
-
*
|
|
218
|
-
*
|
|
219
|
-
*
|
|
220
|
-
* await connect(config);
|
|
836
|
+
* Establishes a database connection using a specific SQL dialect.
|
|
837
|
+
*
|
|
838
|
+
* @param config Database connection pool configuration.
|
|
839
|
+
* @param dialect SQL dialect to use.
|
|
840
|
+
*
|
|
841
|
+
* @example
|
|
842
|
+
* ```ts
|
|
843
|
+
* await connect(
|
|
844
|
+
* {
|
|
845
|
+
* host: "localhost",
|
|
846
|
+
* port: 5432,
|
|
847
|
+
* user: "postgres",
|
|
848
|
+
* password: "password",
|
|
849
|
+
* database: "application"
|
|
850
|
+
* },
|
|
851
|
+
* "postgres"
|
|
852
|
+
* );
|
|
853
|
+
* ```
|
|
221
854
|
*/
|
|
222
|
-
export function connect(
|
|
855
|
+
export function connect(
|
|
856
|
+
config: PoolOptions,
|
|
857
|
+
dialect?: string
|
|
858
|
+
): Promise<void>;
|
|
223
859
|
|
|
224
860
|
/**
|
|
225
|
-
* Closes the database connection.
|
|
226
|
-
*
|
|
227
|
-
*
|
|
228
|
-
*
|
|
229
|
-
* @returns {Promise<void>} A promise that resolves when the connection is closed.
|
|
861
|
+
* Closes the active database connection.
|
|
862
|
+
*
|
|
863
|
+
* @returns A promise resolved after the connection has been closed.
|
|
230
864
|
*
|
|
231
865
|
* @example
|
|
866
|
+
* ```ts
|
|
232
867
|
* await logout();
|
|
868
|
+
* ```
|
|
233
869
|
*/
|
|
234
870
|
export function logout(): Promise<void>;
|
|
235
871
|
|
|
236
872
|
/**
|
|
237
|
-
* Represents a database model.
|
|
238
|
-
*
|
|
873
|
+
* Represents a database model and provides CRUD/query operations.
|
|
874
|
+
*
|
|
875
|
+
* A Model connects a logical model name to a Schema definition.
|
|
876
|
+
*
|
|
877
|
+
* @example
|
|
878
|
+
* ```ts
|
|
879
|
+
* const User = new Model(
|
|
880
|
+
* "users",
|
|
881
|
+
* new Schema({
|
|
882
|
+
* id: {
|
|
883
|
+
* type: "Uuid",
|
|
884
|
+
* primary_key: true
|
|
885
|
+
* },
|
|
886
|
+
* email: {
|
|
887
|
+
* type: "String",
|
|
888
|
+
* required: true
|
|
889
|
+
* }
|
|
890
|
+
* })
|
|
891
|
+
* );
|
|
892
|
+
* ```
|
|
239
893
|
*/
|
|
240
894
|
export class Model<TSchema extends SchemaDict = SchemaDict> {
|
|
895
|
+
/**
|
|
896
|
+
* SQL type mapping used by the model.
|
|
897
|
+
*/
|
|
241
898
|
static sqlTypeMap: Record<SqlType, string>;
|
|
899
|
+
|
|
900
|
+
/**
|
|
901
|
+
* Models waiting to be synchronized.
|
|
902
|
+
*/
|
|
242
903
|
static pendingModels: Model[];
|
|
904
|
+
|
|
905
|
+
/**
|
|
906
|
+
* Database table/model name.
|
|
907
|
+
*/
|
|
243
908
|
name: string;
|
|
909
|
+
|
|
910
|
+
/**
|
|
911
|
+
* Schema associated with the model.
|
|
912
|
+
*/
|
|
244
913
|
schema: SchemaLike<TSchema>;
|
|
245
|
-
|
|
914
|
+
|
|
246
915
|
/**
|
|
247
|
-
* Creates
|
|
248
|
-
*
|
|
916
|
+
* Creates a model.
|
|
917
|
+
*
|
|
918
|
+
* @param name Database table name.
|
|
919
|
+
* @param schema Schema describing the table.
|
|
920
|
+
*/
|
|
921
|
+
constructor(
|
|
922
|
+
name: string,
|
|
923
|
+
schema: SchemaLike<TSchema>
|
|
924
|
+
);
|
|
925
|
+
|
|
926
|
+
/**
|
|
927
|
+
* Creates all registered model tables in dependency order.
|
|
928
|
+
*
|
|
929
|
+
* Foreign-key dependencies are taken into account before creating tables.
|
|
930
|
+
*
|
|
931
|
+
* @example
|
|
932
|
+
* ```ts
|
|
933
|
+
* await Model.syncAllTables();
|
|
934
|
+
* ```
|
|
249
935
|
*/
|
|
250
936
|
static syncAllTables(): Promise<void>;
|
|
937
|
+
|
|
251
938
|
/**
|
|
252
|
-
*
|
|
253
|
-
*
|
|
254
|
-
* @
|
|
255
|
-
* @
|
|
939
|
+
* Inserts a new record into the model table.
|
|
940
|
+
*
|
|
941
|
+
* @param data Data to insert.
|
|
942
|
+
* @returns The inserted record/result.
|
|
943
|
+
*
|
|
944
|
+
* @example
|
|
945
|
+
* ```ts
|
|
946
|
+
* await userModel.save({
|
|
947
|
+
* email: "john@example.com",
|
|
948
|
+
* active: true
|
|
949
|
+
* });
|
|
950
|
+
* ```
|
|
256
951
|
*/
|
|
257
|
-
save(
|
|
952
|
+
save(
|
|
953
|
+
data: Partial<InferSchema<TSchema>>
|
|
954
|
+
): Promise<any>;
|
|
955
|
+
|
|
258
956
|
/**
|
|
259
|
-
* Retrieves
|
|
260
|
-
*
|
|
261
|
-
*
|
|
262
|
-
*
|
|
263
|
-
*
|
|
264
|
-
*
|
|
265
|
-
*
|
|
957
|
+
* Retrieves records from the model table.
|
|
958
|
+
*
|
|
959
|
+
* Supports filtering, selecting, aggregation, grouping, HAVING,
|
|
960
|
+
* ordering, JOINs, pagination and offsets.
|
|
961
|
+
*
|
|
962
|
+
* Query execution uses parameterized values for conditions.
|
|
963
|
+
*
|
|
964
|
+
* @param options Query options.
|
|
965
|
+
*
|
|
966
|
+
* @example Basic SELECT
|
|
967
|
+
* ```ts
|
|
968
|
+
* const users = await userModel.find({
|
|
969
|
+
* select: ["id", "email", "active"]
|
|
970
|
+
* });
|
|
971
|
+
* ```
|
|
972
|
+
*
|
|
973
|
+
* @example WHERE
|
|
974
|
+
* ```ts
|
|
975
|
+
* const users = await userModel.find({
|
|
976
|
+
* where: {
|
|
977
|
+
* active: true,
|
|
978
|
+
* age: {
|
|
979
|
+
* ">=": 18
|
|
980
|
+
* }
|
|
981
|
+
* }
|
|
982
|
+
* });
|
|
983
|
+
* ```
|
|
984
|
+
*
|
|
985
|
+
* @example IN / NOT IN
|
|
986
|
+
* ```ts
|
|
987
|
+
* const users = await userModel.find({
|
|
988
|
+
* where: {
|
|
989
|
+
* status: {
|
|
990
|
+
* IN: ["active", "pending"]
|
|
991
|
+
* }
|
|
992
|
+
* }
|
|
993
|
+
* });
|
|
994
|
+
* ```
|
|
995
|
+
*
|
|
996
|
+
* @example BETWEEN
|
|
997
|
+
* ```ts
|
|
998
|
+
* const users = await userModel.find({
|
|
999
|
+
* where: {
|
|
1000
|
+
* age: {
|
|
1001
|
+
* BETWEEN: [18, 65]
|
|
1002
|
+
* }
|
|
1003
|
+
* }
|
|
1004
|
+
* });
|
|
1005
|
+
* ```
|
|
1006
|
+
*
|
|
1007
|
+
* @example AND / OR / NOT
|
|
1008
|
+
* ```ts
|
|
1009
|
+
* const users = await userModel.find({
|
|
1010
|
+
* where: {
|
|
1011
|
+
* OR: [
|
|
1012
|
+
* { status: "active" },
|
|
1013
|
+
* {
|
|
1014
|
+
* AND: [
|
|
1015
|
+
* { status: "pending" },
|
|
1016
|
+
* { age: { ">=": 18 } }
|
|
1017
|
+
* ]
|
|
1018
|
+
* }
|
|
1019
|
+
* ]
|
|
1020
|
+
* }
|
|
1021
|
+
* });
|
|
1022
|
+
* ```
|
|
1023
|
+
*
|
|
1024
|
+
* @example Aggregation
|
|
1025
|
+
* ```ts
|
|
1026
|
+
* const stats = await userModel.find({
|
|
1027
|
+
* select: [
|
|
1028
|
+
* "status",
|
|
1029
|
+
* { count: "id", as: "total" }
|
|
1030
|
+
* ]
|
|
1031
|
+
* });
|
|
1032
|
+
* ```
|
|
1033
|
+
*
|
|
1034
|
+
* @example GROUP BY + HAVING + ORDER BY
|
|
1035
|
+
* ```ts
|
|
1036
|
+
* const stats = await userModel.find({
|
|
1037
|
+
* select: [
|
|
1038
|
+
* "status",
|
|
1039
|
+
* { count: "id", as: "total" },
|
|
1040
|
+
* { sum: "amount", as: "revenue" }
|
|
1041
|
+
* ],
|
|
1042
|
+
* where: {
|
|
1043
|
+
* active: true
|
|
1044
|
+
* },
|
|
1045
|
+
* groupBy: ["status"],
|
|
1046
|
+
* having: {
|
|
1047
|
+
* total: {
|
|
1048
|
+
* ">": 10
|
|
1049
|
+
* }
|
|
1050
|
+
* },
|
|
1051
|
+
* orderBy: [
|
|
1052
|
+
* {
|
|
1053
|
+
* field: "total",
|
|
1054
|
+
* direction: "DESC"
|
|
1055
|
+
* }
|
|
1056
|
+
* ]
|
|
1057
|
+
* });
|
|
1058
|
+
* ```
|
|
1059
|
+
*
|
|
1060
|
+
* @example JOIN
|
|
1061
|
+
* ```ts
|
|
1062
|
+
* const users = await userModel.find({
|
|
1063
|
+
* select: [
|
|
1064
|
+
* "users.id",
|
|
1065
|
+
* "company.name"
|
|
1066
|
+
* ],
|
|
1067
|
+
* join: {
|
|
1068
|
+
* table: "companies",
|
|
1069
|
+
* alias: "company",
|
|
1070
|
+
* type: "LEFT",
|
|
1071
|
+
* on: "users.company_id = company.id"
|
|
1072
|
+
* }
|
|
1073
|
+
* });
|
|
1074
|
+
* ```
|
|
1075
|
+
*
|
|
1076
|
+
* @example Pagination
|
|
1077
|
+
* ```ts
|
|
1078
|
+
* const users = await userModel.find({
|
|
1079
|
+
* limit: 20,
|
|
1080
|
+
* offset: 40
|
|
1081
|
+
* });
|
|
1082
|
+
* ```
|
|
266
1083
|
*/
|
|
267
1084
|
find(options?: {
|
|
1085
|
+
/**
|
|
1086
|
+
* Columns and aggregate expressions returned by SELECT.
|
|
1087
|
+
*
|
|
1088
|
+
* @example
|
|
1089
|
+
* ```ts
|
|
1090
|
+
* select: [
|
|
1091
|
+
* "status",
|
|
1092
|
+
* { count: "id", as: "total" }
|
|
1093
|
+
* ]
|
|
1094
|
+
* ```
|
|
1095
|
+
*/
|
|
268
1096
|
select?: SelectItem[];
|
|
269
|
-
|
|
270
|
-
|
|
1097
|
+
|
|
1098
|
+
/**
|
|
1099
|
+
* Filters applied before grouping.
|
|
1100
|
+
*
|
|
1101
|
+
* @example
|
|
1102
|
+
* ```ts
|
|
1103
|
+
* where: {
|
|
1104
|
+
* active: true,
|
|
1105
|
+
* age: { ">=": 18 }
|
|
1106
|
+
* }
|
|
1107
|
+
* ```
|
|
1108
|
+
*/
|
|
1109
|
+
where?: WhereClause;
|
|
1110
|
+
|
|
1111
|
+
/**
|
|
1112
|
+
* GROUP BY expressions.
|
|
1113
|
+
*
|
|
1114
|
+
* @example
|
|
1115
|
+
* ```ts
|
|
1116
|
+
* groupBy: ["status"]
|
|
1117
|
+
* ```
|
|
1118
|
+
*/
|
|
1119
|
+
groupBy?: Array<string | GroupAggregation>;
|
|
1120
|
+
|
|
1121
|
+
/**
|
|
1122
|
+
* Filters applied after GROUP BY and aggregation.
|
|
1123
|
+
*
|
|
1124
|
+
* @example
|
|
1125
|
+
* ```ts
|
|
1126
|
+
* having: {
|
|
1127
|
+
* total: { ">": 10 }
|
|
1128
|
+
* }
|
|
1129
|
+
* ```
|
|
1130
|
+
*/
|
|
1131
|
+
having?: WhereClause;
|
|
1132
|
+
|
|
1133
|
+
/**
|
|
1134
|
+
* ORDER BY rules.
|
|
1135
|
+
*
|
|
1136
|
+
* @example
|
|
1137
|
+
* ```ts
|
|
1138
|
+
* orderBy: [
|
|
1139
|
+
* { field: "total", direction: "DESC" }
|
|
1140
|
+
* ]
|
|
1141
|
+
* ```
|
|
1142
|
+
*/
|
|
1143
|
+
orderBy?: Array<string | OrderByOption>;
|
|
1144
|
+
|
|
1145
|
+
/**
|
|
1146
|
+
* JOIN definitions.
|
|
1147
|
+
*
|
|
1148
|
+
* @example
|
|
1149
|
+
* ```ts
|
|
1150
|
+
* join: {
|
|
1151
|
+
* table: "companies",
|
|
1152
|
+
* alias: "company",
|
|
1153
|
+
* type: "LEFT",
|
|
1154
|
+
* on: "users.company_id = company.id"
|
|
1155
|
+
* }
|
|
1156
|
+
* ```
|
|
1157
|
+
*/
|
|
1158
|
+
join?: JoinOption | JoinOption[];
|
|
1159
|
+
|
|
1160
|
+
/**
|
|
1161
|
+
* Maximum number of records returned.
|
|
1162
|
+
*
|
|
1163
|
+
* @example
|
|
1164
|
+
* ```ts
|
|
1165
|
+
* limit: 20
|
|
1166
|
+
* ```
|
|
1167
|
+
*/
|
|
271
1168
|
limit?: number;
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* Number of records skipped before returning results.
|
|
1172
|
+
*
|
|
1173
|
+
* @example
|
|
1174
|
+
* ```ts
|
|
1175
|
+
* offset: 40
|
|
1176
|
+
* ```
|
|
1177
|
+
*/
|
|
1178
|
+
offset?: number;
|
|
272
1179
|
}): Promise<Array<ModelRecord<InferSchema<TSchema>>>>;
|
|
1180
|
+
|
|
273
1181
|
/**
|
|
274
|
-
*
|
|
275
|
-
*
|
|
276
|
-
* @
|
|
1182
|
+
* Counts records matching the supplied filter.
|
|
1183
|
+
*
|
|
1184
|
+
* @param filter Optional equality/filter object.
|
|
1185
|
+
* @returns Number of matching records.
|
|
1186
|
+
*
|
|
1187
|
+
* @example
|
|
1188
|
+
* ```ts
|
|
1189
|
+
* const count = await userModel.count({
|
|
1190
|
+
* active: true
|
|
1191
|
+
* });
|
|
1192
|
+
* ```
|
|
277
1193
|
*/
|
|
278
|
-
count(
|
|
1194
|
+
count(
|
|
1195
|
+
filter?: Record<string, any> | Partial<InferSchema<TSchema>>
|
|
1196
|
+
): Promise<number>;
|
|
1197
|
+
|
|
279
1198
|
/**
|
|
280
|
-
*
|
|
281
|
-
*
|
|
282
|
-
*
|
|
283
|
-
*
|
|
1199
|
+
* Executes a custom SQL query.
|
|
1200
|
+
*
|
|
1201
|
+
* Use this method when a query cannot be represented by
|
|
1202
|
+
* the query builder.
|
|
1203
|
+
*
|
|
1204
|
+
* @param custom SQL query to execute.
|
|
1205
|
+
* @returns Query result.
|
|
1206
|
+
*
|
|
1207
|
+
* @example
|
|
1208
|
+
* ```ts
|
|
1209
|
+
* const users = await userModel.customRequest(
|
|
1210
|
+
* "SELECT * FROM users"
|
|
1211
|
+
* );
|
|
1212
|
+
* ```
|
|
284
1213
|
*/
|
|
285
|
-
customRequest<TResult extends Record<string, any> = InferSchema<TSchema>>(
|
|
1214
|
+
customRequest<TResult extends Record<string, any> = InferSchema<TSchema>>(
|
|
1215
|
+
custom: string
|
|
1216
|
+
): Promise<ModelRecord<TResult> | 0>;
|
|
1217
|
+
|
|
286
1218
|
/**
|
|
287
|
-
* Deletes
|
|
1219
|
+
* Deletes records matching the supplied filter.
|
|
288
1220
|
*
|
|
289
|
-
* @
|
|
290
|
-
* @
|
|
291
|
-
*
|
|
292
|
-
* @
|
|
293
|
-
*
|
|
294
|
-
*
|
|
1221
|
+
* @param filter Conditions identifying the records to delete.
|
|
1222
|
+
* @returns Number of deleted records.
|
|
1223
|
+
*
|
|
1224
|
+
* @example
|
|
1225
|
+
* ```ts
|
|
1226
|
+
* await userModel.delete({
|
|
1227
|
+
* status: "inactive"
|
|
1228
|
+
* });
|
|
1229
|
+
* ```
|
|
295
1230
|
*/
|
|
296
|
-
delete(
|
|
1231
|
+
delete(
|
|
1232
|
+
filter: Record<string, any> | Partial<InferSchema<TSchema>>
|
|
1233
|
+
): Promise<number>;
|
|
1234
|
+
|
|
297
1235
|
/**
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
* This function constructs a SQL_request query to drop a table with the name specified
|
|
301
|
-
* by the `this.name` property. It then executes the query using a promise-based
|
|
302
|
-
* approach. If the query is successful, the result is logged to the console.
|
|
303
|
-
* If an error occurs during the execution of the query, an error message is logged.
|
|
1236
|
+
* Drops the database table represented by this model.
|
|
304
1237
|
*
|
|
305
|
-
* @
|
|
1238
|
+
* @example
|
|
1239
|
+
* ```ts
|
|
1240
|
+
* await userModel.dropTable();
|
|
1241
|
+
* ```
|
|
306
1242
|
*/
|
|
307
1243
|
dropTable(): Promise<void>;
|
|
1244
|
+
|
|
1245
|
+
/**
|
|
1246
|
+
* Generates a unique UUID for the model.
|
|
1247
|
+
*
|
|
1248
|
+
* @param var_uuid Optional UUID value to validate.
|
|
1249
|
+
* @returns A unique UUID or null if generation fails.
|
|
1250
|
+
*
|
|
1251
|
+
* @example
|
|
1252
|
+
* ```ts
|
|
1253
|
+
* const id = await userModel.generate_uuid();
|
|
1254
|
+
*
|
|
1255
|
+
* if (id) {
|
|
1256
|
+
* console.log(id);
|
|
1257
|
+
* }
|
|
1258
|
+
* ```
|
|
1259
|
+
*/
|
|
1260
|
+
generate_uuid(var_uuid?: string): Promise<string | null>;
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
/**
|
|
1264
|
+
* Defines a SQL JOIN operation.
|
|
1265
|
+
*
|
|
1266
|
+
* @example
|
|
1267
|
+
* ```ts
|
|
1268
|
+
* const join: JoinOption = {
|
|
1269
|
+
* table: "companies",
|
|
1270
|
+
* alias: "company",
|
|
1271
|
+
* type: "LEFT",
|
|
1272
|
+
* on: "users.company_id = company.id"
|
|
1273
|
+
* };
|
|
1274
|
+
* ```
|
|
1275
|
+
*/
|
|
1276
|
+
export interface JoinOption {
|
|
1277
|
+
table: string;
|
|
1278
|
+
on: string;
|
|
1279
|
+
alias?: string;
|
|
1280
|
+
type?: "INNER" | "LEFT" | "RIGHT";
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
/**
|
|
1284
|
+
* Configuration used by the migration system.
|
|
1285
|
+
*
|
|
1286
|
+
* Migration options control schema inspection, diff generation,
|
|
1287
|
+
* migration storage, backups, encryption and destructive changes.
|
|
1288
|
+
*
|
|
1289
|
+
* @example
|
|
1290
|
+
* ```ts
|
|
1291
|
+
* const options: MigrationOptions = {
|
|
1292
|
+
* dialect: "mysql",
|
|
1293
|
+
* models: [UserModel],
|
|
1294
|
+
* directory: "./migrations",
|
|
1295
|
+
* backupDirectory: "./backups",
|
|
1296
|
+
* allowDestructiveChanges: false
|
|
1297
|
+
* };
|
|
1298
|
+
* ```
|
|
1299
|
+
*/
|
|
1300
|
+
export interface MigrationOptions {
|
|
1301
|
+
/**
|
|
1302
|
+
* Database connection used by the migration system.
|
|
1303
|
+
*/
|
|
1304
|
+
connection?: any;
|
|
1305
|
+
|
|
1306
|
+
/**
|
|
1307
|
+
* SQL dialect.
|
|
1308
|
+
*
|
|
1309
|
+
* Supported built-in dialects include `mysql` and `postgres`.
|
|
1310
|
+
*/
|
|
1311
|
+
dialect?: string | any;
|
|
1312
|
+
|
|
1313
|
+
/**
|
|
1314
|
+
* Models whose schemas should be compared against the database.
|
|
1315
|
+
*/
|
|
1316
|
+
models?: Array<Model<any>>;
|
|
1317
|
+
|
|
1318
|
+
/**
|
|
1319
|
+
* Directory containing generated migration files.
|
|
1320
|
+
*
|
|
1321
|
+
* Defaults to the configured migration directory.
|
|
1322
|
+
*/
|
|
1323
|
+
directory?: string;
|
|
1324
|
+
|
|
308
1325
|
/**
|
|
309
|
-
*
|
|
1326
|
+
* Directory used to store database/schema backups.
|
|
1327
|
+
*/
|
|
1328
|
+
backupDirectory?: string;
|
|
1329
|
+
|
|
1330
|
+
/**
|
|
1331
|
+
* Encryption key used to protect migration files.
|
|
1332
|
+
*/
|
|
1333
|
+
encryptionKey?: string;
|
|
1334
|
+
|
|
1335
|
+
/**
|
|
1336
|
+
* Retention policy for migration backups.
|
|
1337
|
+
*
|
|
1338
|
+
* Can be expressed in milliseconds or using duration strings.
|
|
1339
|
+
*
|
|
1340
|
+
* @example
|
|
1341
|
+
* ```ts
|
|
1342
|
+
* retention: "7d"
|
|
1343
|
+
* ```
|
|
1344
|
+
*/
|
|
1345
|
+
retention?: number | string | null | false;
|
|
1346
|
+
|
|
1347
|
+
/**
|
|
1348
|
+
* Allows operations that can modify or remove existing data/schema.
|
|
1349
|
+
*
|
|
1350
|
+
* Keep disabled unless destructive changes are explicitly intended.
|
|
1351
|
+
*/
|
|
1352
|
+
allowDestructiveChanges?: boolean;
|
|
1353
|
+
|
|
1354
|
+
/**
|
|
1355
|
+
* Allows table deletion during schema synchronization.
|
|
310
1356
|
*
|
|
311
|
-
* This
|
|
312
|
-
|
|
313
|
-
|
|
1357
|
+
* This should normally remain disabled.
|
|
1358
|
+
*/
|
|
1359
|
+
allowDropTables?: boolean;
|
|
1360
|
+
}
|
|
1361
|
+
|
|
1362
|
+
/**
|
|
1363
|
+
* Serializable representation of a migration plan.
|
|
1364
|
+
*
|
|
1365
|
+
* This structure can be used for logs, inspection and migration tooling.
|
|
1366
|
+
*/
|
|
1367
|
+
export interface MigrationPlanJSON {
|
|
1368
|
+
/**
|
|
1369
|
+
* Migration identifier.
|
|
1370
|
+
*/
|
|
1371
|
+
id: string;
|
|
1372
|
+
|
|
1373
|
+
/**
|
|
1374
|
+
* SQL dialect used by the migration.
|
|
1375
|
+
*/
|
|
1376
|
+
dialect: string;
|
|
1377
|
+
|
|
1378
|
+
/**
|
|
1379
|
+
* SHA-256 checksum identifying the migration content.
|
|
1380
|
+
*/
|
|
1381
|
+
checksum: string;
|
|
1382
|
+
|
|
1383
|
+
/**
|
|
1384
|
+
* Schema operations contained in the plan.
|
|
1385
|
+
*/
|
|
1386
|
+
operations: any[];
|
|
1387
|
+
|
|
1388
|
+
/**
|
|
1389
|
+
* Generated SQL.
|
|
1390
|
+
*/
|
|
1391
|
+
sql: string;
|
|
1392
|
+
|
|
1393
|
+
/**
|
|
1394
|
+
* Indicates whether the schema differs from the desired state.
|
|
1395
|
+
*/
|
|
1396
|
+
hasChanges: boolean;
|
|
1397
|
+
|
|
1398
|
+
/**
|
|
1399
|
+
* Indicates whether destructive operations are present.
|
|
1400
|
+
*/
|
|
1401
|
+
destructive: boolean;
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
/**
|
|
1405
|
+
* Represents a generated schema migration plan.
|
|
1406
|
+
*
|
|
1407
|
+
* A MigrationPlan is created by comparing the desired model schema
|
|
1408
|
+
* with the current database schema.
|
|
1409
|
+
*
|
|
1410
|
+
* @example
|
|
1411
|
+
* ```ts
|
|
1412
|
+
* const plan = await Migration.plan({
|
|
1413
|
+
* models: [UserModel],
|
|
1414
|
+
* dialect: "mysql"
|
|
1415
|
+
* });
|
|
1416
|
+
*
|
|
1417
|
+
* if (plan.hasChanges()) {
|
|
1418
|
+
* console.log(plan.sql);
|
|
1419
|
+
* }
|
|
1420
|
+
* ```
|
|
1421
|
+
*
|
|
1422
|
+
* @example Approving destructive changes
|
|
1423
|
+
* ```ts
|
|
1424
|
+
* const plan = await Migration.plan({
|
|
1425
|
+
* models: [UserModel]
|
|
1426
|
+
* });
|
|
1427
|
+
*
|
|
1428
|
+
* if (plan.hasDestructiveChanges()) {
|
|
1429
|
+
* plan.approve();
|
|
1430
|
+
* }
|
|
1431
|
+
*
|
|
1432
|
+
* await plan.execute({
|
|
1433
|
+
* allowDestructiveChanges: true
|
|
1434
|
+
* });
|
|
1435
|
+
* ```
|
|
1436
|
+
*/
|
|
1437
|
+
export class MigrationPlan {
|
|
1438
|
+
/**
|
|
1439
|
+
* Unique migration identifier.
|
|
1440
|
+
*/
|
|
1441
|
+
id: string;
|
|
1442
|
+
|
|
1443
|
+
/**
|
|
1444
|
+
* Schema operations generated by the differ.
|
|
1445
|
+
*/
|
|
1446
|
+
operations: any[];
|
|
1447
|
+
|
|
1448
|
+
/**
|
|
1449
|
+
* SQL generated for this migration.
|
|
1450
|
+
*/
|
|
1451
|
+
sql: string;
|
|
1452
|
+
|
|
1453
|
+
/**
|
|
1454
|
+
* Current desired schema snapshot.
|
|
1455
|
+
*/
|
|
1456
|
+
snapshot: any;
|
|
1457
|
+
|
|
1458
|
+
/**
|
|
1459
|
+
* Previous database schema snapshot.
|
|
1460
|
+
*/
|
|
1461
|
+
previousSnapshot: any;
|
|
1462
|
+
|
|
1463
|
+
/**
|
|
1464
|
+
* SQL dialect used by this plan.
|
|
1465
|
+
*/
|
|
1466
|
+
dialect: string;
|
|
1467
|
+
|
|
1468
|
+
/**
|
|
1469
|
+
* SHA-256 checksum of the migration.
|
|
1470
|
+
*/
|
|
1471
|
+
checksum: string;
|
|
1472
|
+
|
|
1473
|
+
/**
|
|
1474
|
+
* Indicates whether the migration has been explicitly approved.
|
|
1475
|
+
*/
|
|
1476
|
+
approved: boolean;
|
|
1477
|
+
|
|
1478
|
+
/**
|
|
1479
|
+
* Indicates whether the plan contains schema changes.
|
|
314
1480
|
*
|
|
315
|
-
* @
|
|
1481
|
+
* @example
|
|
1482
|
+
* ```ts
|
|
1483
|
+
* if (plan.hasChanges()) {
|
|
1484
|
+
* console.log(plan.sql);
|
|
1485
|
+
* }
|
|
1486
|
+
* ```
|
|
1487
|
+
*/
|
|
1488
|
+
hasChanges(): boolean;
|
|
1489
|
+
|
|
1490
|
+
/**
|
|
1491
|
+
* Indicates whether the migration contains destructive operations.
|
|
316
1492
|
*
|
|
317
1493
|
* @example
|
|
318
|
-
*
|
|
319
|
-
* if (
|
|
320
|
-
*
|
|
321
|
-
* } else {
|
|
322
|
-
* console.log('Failed to generate a unique UUID.');
|
|
1494
|
+
* ```ts
|
|
1495
|
+
* if (plan.hasDestructiveChanges()) {
|
|
1496
|
+
* console.warn("Manual approval required");
|
|
323
1497
|
* }
|
|
1498
|
+
* ```
|
|
1499
|
+
*/
|
|
1500
|
+
hasDestructiveChanges(): boolean;
|
|
1501
|
+
|
|
1502
|
+
/**
|
|
1503
|
+
* Returns the destructive operations contained in the plan.
|
|
324
1504
|
*
|
|
325
|
-
* @
|
|
1505
|
+
* @example
|
|
1506
|
+
* ```ts
|
|
1507
|
+
* console.table(plan.destructiveChanges());
|
|
1508
|
+
* ```
|
|
326
1509
|
*/
|
|
327
|
-
|
|
1510
|
+
destructiveChanges(): any[];
|
|
1511
|
+
|
|
1512
|
+
/**
|
|
1513
|
+
* Explicitly approves the migration plan.
|
|
1514
|
+
*
|
|
1515
|
+
* @returns The current migration plan.
|
|
1516
|
+
*
|
|
1517
|
+
* @example
|
|
1518
|
+
* ```ts
|
|
1519
|
+
* plan.approve();
|
|
1520
|
+
* ```
|
|
1521
|
+
*/
|
|
1522
|
+
approve(): this;
|
|
1523
|
+
|
|
1524
|
+
/**
|
|
1525
|
+
* Executes the migration plan.
|
|
1526
|
+
*
|
|
1527
|
+
* Destructive migrations can require explicit approval.
|
|
1528
|
+
*
|
|
1529
|
+
* @param options Execution options.
|
|
1530
|
+
*
|
|
1531
|
+
* @example
|
|
1532
|
+
* ```ts
|
|
1533
|
+
* await plan.execute();
|
|
1534
|
+
* ```
|
|
1535
|
+
*
|
|
1536
|
+
* @example
|
|
1537
|
+
* ```ts
|
|
1538
|
+
* plan.approve();
|
|
1539
|
+
*
|
|
1540
|
+
* await plan.execute({
|
|
1541
|
+
* requireApproval: true,
|
|
1542
|
+
* allowDestructiveChanges: true
|
|
1543
|
+
* });
|
|
1544
|
+
* ```
|
|
1545
|
+
*/
|
|
1546
|
+
execute(options?: {
|
|
1547
|
+
requireApproval?: boolean;
|
|
1548
|
+
allowDestructiveChanges?: boolean;
|
|
1549
|
+
}): Promise<any>;
|
|
1550
|
+
|
|
1551
|
+
/**
|
|
1552
|
+
* Converts the migration plan to a serializable JSON object.
|
|
1553
|
+
*
|
|
1554
|
+
* @example
|
|
1555
|
+
* ```ts
|
|
1556
|
+
* const json = plan.toJSON();
|
|
1557
|
+
* console.log(json.checksum);
|
|
1558
|
+
* ```
|
|
1559
|
+
*/
|
|
1560
|
+
toJSON(): MigrationPlanJSON;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
/**
|
|
1564
|
+
* Stores migrations, snapshots and backups on disk.
|
|
1565
|
+
*
|
|
1566
|
+
* MigrationStore is responsible for migration persistence,
|
|
1567
|
+
* checksum validation and cleanup according to the retention policy.
|
|
1568
|
+
*
|
|
1569
|
+
* @example
|
|
1570
|
+
* ```ts
|
|
1571
|
+
* const store = new MigrationStore({
|
|
1572
|
+
* directory: "./migrations",
|
|
1573
|
+
* backupDirectory: "./backups",
|
|
1574
|
+
* retention: "7d"
|
|
1575
|
+
* });
|
|
1576
|
+
* ```
|
|
1577
|
+
*/
|
|
1578
|
+
export class MigrationStore {
|
|
1579
|
+
/**
|
|
1580
|
+
* Directory containing migration files.
|
|
1581
|
+
*/
|
|
1582
|
+
directory: string;
|
|
1583
|
+
|
|
1584
|
+
/**
|
|
1585
|
+
* Directory containing backups.
|
|
1586
|
+
*/
|
|
1587
|
+
backupDirectory: string;
|
|
1588
|
+
|
|
1589
|
+
/**
|
|
1590
|
+
* Optional encryption key.
|
|
1591
|
+
*/
|
|
1592
|
+
encryptionKey?: string;
|
|
1593
|
+
|
|
1594
|
+
/**
|
|
1595
|
+
* Normalized retention duration in milliseconds.
|
|
1596
|
+
*/
|
|
1597
|
+
retention: number | null;
|
|
1598
|
+
|
|
1599
|
+
/**
|
|
1600
|
+
* Creates a migration store.
|
|
1601
|
+
*
|
|
1602
|
+
* @param options Storage configuration.
|
|
1603
|
+
*/
|
|
1604
|
+
constructor(options?: {
|
|
1605
|
+
directory?: string;
|
|
1606
|
+
backupDirectory?: string;
|
|
1607
|
+
encryptionKey?: string;
|
|
1608
|
+
retention?: number | string | null | false;
|
|
1609
|
+
});
|
|
1610
|
+
|
|
1611
|
+
/**
|
|
1612
|
+
* Creates the migration and backup directories if required.
|
|
1613
|
+
*/
|
|
1614
|
+
ensureDirectories(): Promise<void>;
|
|
1615
|
+
|
|
1616
|
+
/**
|
|
1617
|
+
* Writes a migration plan to persistent storage.
|
|
1618
|
+
*
|
|
1619
|
+
* @param plan Migration plan to persist.
|
|
1620
|
+
* @returns Path of the created migration file.
|
|
1621
|
+
*/
|
|
1622
|
+
writeMigration(plan: MigrationPlan): Promise<string>;
|
|
1623
|
+
|
|
1624
|
+
/** Reads encrypted rollback metadata for a migration. */
|
|
1625
|
+
readMigration(id: string): Promise<any | null>;
|
|
1626
|
+
|
|
1627
|
+
/** Reads an encrypted backup for a migration. */
|
|
1628
|
+
readBackup(id: string): Promise<any | null>;
|
|
1629
|
+
|
|
1630
|
+
/**
|
|
1631
|
+
* Writes a backup to disk.
|
|
1632
|
+
*
|
|
1633
|
+
* @param name Backup file name.
|
|
1634
|
+
* @param content Backup content.
|
|
1635
|
+
* @returns Backup path, or null when no backup is created.
|
|
1636
|
+
*/
|
|
1637
|
+
writeBackup(
|
|
1638
|
+
name: string,
|
|
1639
|
+
content: any
|
|
1640
|
+
): Promise<string | null>;
|
|
1641
|
+
|
|
1642
|
+
/**
|
|
1643
|
+
* Removes migration/backup files that exceed the configured retention period.
|
|
1644
|
+
*
|
|
1645
|
+
* @returns Number of removed files.
|
|
1646
|
+
*
|
|
1647
|
+
* @example
|
|
1648
|
+
* ```ts
|
|
1649
|
+
* const removed = await store.cleanup();
|
|
1650
|
+
* console.log(`Removed ${removed} old files`);
|
|
1651
|
+
* ```
|
|
1652
|
+
*/
|
|
1653
|
+
cleanup(): Promise<number>;
|
|
1654
|
+
|
|
1655
|
+
/**
|
|
1656
|
+
* Writes the current schema snapshot.
|
|
1657
|
+
*
|
|
1658
|
+
* @param snapshot Schema snapshot.
|
|
1659
|
+
* @returns Path of the snapshot file.
|
|
1660
|
+
*/
|
|
1661
|
+
writeSnapshot(snapshot: any): Promise<string>;
|
|
1662
|
+
|
|
1663
|
+
/**
|
|
1664
|
+
* Reads the latest stored schema snapshot.
|
|
1665
|
+
*
|
|
1666
|
+
* @returns Snapshot or null when none exists.
|
|
1667
|
+
*/
|
|
1668
|
+
readSnapshot(): Promise<any | null>;
|
|
1669
|
+
|
|
1670
|
+
/**
|
|
1671
|
+
* Lists persisted migration files.
|
|
1672
|
+
*
|
|
1673
|
+
* @returns Migration file paths.
|
|
1674
|
+
*/
|
|
1675
|
+
listMigrationFiles(): Promise<string[]>;
|
|
1676
|
+
|
|
1677
|
+
/**
|
|
1678
|
+
* Validates a migration checksum.
|
|
1679
|
+
*
|
|
1680
|
+
* @throws MigrationChecksumError when the checksum does not match.
|
|
1681
|
+
*
|
|
1682
|
+
* @example
|
|
1683
|
+
* ```ts
|
|
1684
|
+
* store.validateChecksum(actual, expected);
|
|
1685
|
+
* ```
|
|
1686
|
+
*/
|
|
1687
|
+
validateChecksum(
|
|
1688
|
+
actual: string,
|
|
1689
|
+
expected: string
|
|
1690
|
+
): void;
|
|
1691
|
+
}
|
|
1692
|
+
|
|
1693
|
+
/**
|
|
1694
|
+
* Executes migration plans against a database.
|
|
1695
|
+
*
|
|
1696
|
+
* MigrationRunner manages migration history, execution and
|
|
1697
|
+
* SQL generation for individual schema operations.
|
|
1698
|
+
*
|
|
1699
|
+
* @example
|
|
1700
|
+
* ```ts
|
|
1701
|
+
* const runner = new MigrationRunner({
|
|
1702
|
+
* connection,
|
|
1703
|
+
* dialect,
|
|
1704
|
+
* store,
|
|
1705
|
+
* backupManager
|
|
1706
|
+
* });
|
|
1707
|
+
*
|
|
1708
|
+
* await runner.execute(plan);
|
|
1709
|
+
* ```
|
|
1710
|
+
*/
|
|
1711
|
+
export class MigrationRunner {
|
|
1712
|
+
/**
|
|
1713
|
+
* Creates a migration runner.
|
|
1714
|
+
*
|
|
1715
|
+
* @param options Runner dependencies.
|
|
1716
|
+
*/
|
|
1717
|
+
constructor(options: {
|
|
1718
|
+
connection: any;
|
|
1719
|
+
dialect: any;
|
|
1720
|
+
store: MigrationStore;
|
|
1721
|
+
backupManager: any;
|
|
1722
|
+
});
|
|
1723
|
+
|
|
1724
|
+
/**
|
|
1725
|
+
* Creates the migration history table if necessary.
|
|
1726
|
+
*/
|
|
1727
|
+
ensureMigrationTable(): Promise<void>;
|
|
1728
|
+
|
|
1729
|
+
/**
|
|
1730
|
+
* Returns migrations already applied to the database.
|
|
1731
|
+
*/
|
|
1732
|
+
applied(): Promise<any[]>;
|
|
1733
|
+
|
|
1734
|
+
/**
|
|
1735
|
+
* Executes a migration plan and records it as applied.
|
|
1736
|
+
*
|
|
1737
|
+
* @param plan Migration plan.
|
|
1738
|
+
* @param options Execution and safety options.
|
|
1739
|
+
*
|
|
1740
|
+
* @example
|
|
1741
|
+
* ```ts
|
|
1742
|
+
* await runner.execute(plan, {
|
|
1743
|
+
* requireApproval: true
|
|
1744
|
+
* });
|
|
1745
|
+
* ```
|
|
1746
|
+
*/
|
|
1747
|
+
execute(
|
|
1748
|
+
plan: MigrationPlan,
|
|
1749
|
+
options?: {
|
|
1750
|
+
requireApproval?: boolean;
|
|
1751
|
+
allowDestructiveChanges?: boolean;
|
|
1752
|
+
}
|
|
1753
|
+
): Promise<any>;
|
|
1754
|
+
|
|
1755
|
+
/** Rolls back the latest applied migration and restores its backup. */
|
|
1756
|
+
rollback(id: string, options?: { allowOutOfOrder?: boolean }): Promise<any>;
|
|
1757
|
+
|
|
1758
|
+
/**
|
|
1759
|
+
* Generates SQL for a single schema operation.
|
|
1760
|
+
*
|
|
1761
|
+
* @param operation Schema operation.
|
|
1762
|
+
* @returns SQL statement.
|
|
1763
|
+
*/
|
|
1764
|
+
sqlForOperation(operation: any): string;
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
/**
|
|
1768
|
+
* Compares the desired schema with the current schema.
|
|
1769
|
+
*
|
|
1770
|
+
* SchemaDiffer generates a list of operations required to transform
|
|
1771
|
+
* the current database structure into the desired model structure.
|
|
1772
|
+
*
|
|
1773
|
+
* @example
|
|
1774
|
+
* ```ts
|
|
1775
|
+
* const differ = new SchemaDiffer({
|
|
1776
|
+
* allowDestructiveChanges: false
|
|
1777
|
+
* });
|
|
1778
|
+
*
|
|
1779
|
+
* const operations = differ.diff(
|
|
1780
|
+
* desiredSchema,
|
|
1781
|
+
* currentSchema
|
|
1782
|
+
* );
|
|
1783
|
+
* ```
|
|
1784
|
+
*/
|
|
1785
|
+
export class SchemaDiffer {
|
|
1786
|
+
/**
|
|
1787
|
+
* Creates a schema differ.
|
|
1788
|
+
*
|
|
1789
|
+
* @param options Controls destructive schema changes.
|
|
1790
|
+
*/
|
|
1791
|
+
constructor(options?: {
|
|
1792
|
+
allowDestructiveChanges?: boolean;
|
|
1793
|
+
allowDropTables?: boolean;
|
|
1794
|
+
});
|
|
1795
|
+
|
|
1796
|
+
/**
|
|
1797
|
+
* Calculates schema differences.
|
|
1798
|
+
*
|
|
1799
|
+
* @param desired Desired schema.
|
|
1800
|
+
* @param current Current database schema.
|
|
1801
|
+
* @returns Schema operations required to synchronize the database.
|
|
1802
|
+
*/
|
|
1803
|
+
diff(
|
|
1804
|
+
desired: any,
|
|
1805
|
+
current: any
|
|
1806
|
+
): any[];
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1809
|
+
/**
|
|
1810
|
+
* Inspects the current database schema.
|
|
1811
|
+
*
|
|
1812
|
+
* The inspector reads tables, columns, constraints and other
|
|
1813
|
+
* database metadata using the selected SQL dialect.
|
|
1814
|
+
*
|
|
1815
|
+
* @example
|
|
1816
|
+
* ```ts
|
|
1817
|
+
* const inspector = new SchemaInspector(
|
|
1818
|
+
* connection,
|
|
1819
|
+
* dialect
|
|
1820
|
+
* );
|
|
1821
|
+
*
|
|
1822
|
+
* const snapshot = await inspector.inspect();
|
|
1823
|
+
* ```
|
|
1824
|
+
*/
|
|
1825
|
+
export class SchemaInspector {
|
|
1826
|
+
/**
|
|
1827
|
+
* Creates a schema inspector.
|
|
1828
|
+
*
|
|
1829
|
+
* @param connection Active database connection.
|
|
1830
|
+
* @param dialect SQL dialect implementation.
|
|
1831
|
+
*/
|
|
1832
|
+
constructor(
|
|
1833
|
+
connection: any,
|
|
1834
|
+
dialect: any
|
|
1835
|
+
);
|
|
1836
|
+
|
|
1837
|
+
/**
|
|
1838
|
+
* Reads the current database schema.
|
|
1839
|
+
*/
|
|
1840
|
+
inspect(): Promise<any>;
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
/**
|
|
1844
|
+
* MySQL SQL dialect implementation.
|
|
1845
|
+
*
|
|
1846
|
+
* Converts SQL Connector schema and migration operations
|
|
1847
|
+
* into MySQL-compatible SQL.
|
|
1848
|
+
*
|
|
1849
|
+
* @example
|
|
1850
|
+
* ```ts
|
|
1851
|
+
* const dialect = new MySQLDialect();
|
|
1852
|
+
* ```
|
|
1853
|
+
*/
|
|
1854
|
+
export class MySQLDialect {
|
|
1855
|
+
/**
|
|
1856
|
+
* Creates the MySQL dialect.
|
|
1857
|
+
*/
|
|
1858
|
+
constructor();
|
|
1859
|
+
}
|
|
1860
|
+
|
|
1861
|
+
/**
|
|
1862
|
+
* PostgreSQL SQL dialect implementation.
|
|
1863
|
+
*
|
|
1864
|
+
* Converts SQL Connector schema and migration operations
|
|
1865
|
+
* into PostgreSQL-compatible SQL.
|
|
1866
|
+
*
|
|
1867
|
+
* @example
|
|
1868
|
+
* ```ts
|
|
1869
|
+
* const dialect = new PostgreSQLDialect();
|
|
1870
|
+
* ```
|
|
1871
|
+
*/
|
|
1872
|
+
export class PostgreSQLDialect {
|
|
1873
|
+
/**
|
|
1874
|
+
* Creates the PostgreSQL dialect.
|
|
1875
|
+
*/
|
|
1876
|
+
constructor();
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
/**
|
|
1880
|
+
* Base error thrown by the migration system.
|
|
1881
|
+
*
|
|
1882
|
+
* Use `code` to distinguish migration failures programmatically.
|
|
1883
|
+
*
|
|
1884
|
+
* @example
|
|
1885
|
+
* ```ts
|
|
1886
|
+
* try {
|
|
1887
|
+
* await Migration.migrate(options);
|
|
1888
|
+
* } catch (error) {
|
|
1889
|
+
* if (error instanceof MigrationError) {
|
|
1890
|
+
* console.error(error.code);
|
|
1891
|
+
* }
|
|
1892
|
+
* }
|
|
1893
|
+
* ```
|
|
1894
|
+
*/
|
|
1895
|
+
export class MigrationError extends Error {
|
|
1896
|
+
/**
|
|
1897
|
+
* Machine-readable migration error code.
|
|
1898
|
+
*/
|
|
1899
|
+
code: string;
|
|
1900
|
+
|
|
1901
|
+
/**
|
|
1902
|
+
* Additional error metadata.
|
|
1903
|
+
*/
|
|
1904
|
+
details?: any;
|
|
1905
|
+
}
|
|
1906
|
+
|
|
1907
|
+
/**
|
|
1908
|
+
* Error raised when a migration contains destructive changes
|
|
1909
|
+
* that are not explicitly allowed.
|
|
1910
|
+
*
|
|
1911
|
+
* @example
|
|
1912
|
+
* ```ts
|
|
1913
|
+
* try {
|
|
1914
|
+
* await plan.execute();
|
|
1915
|
+
* } catch (error) {
|
|
1916
|
+
* if (error instanceof DestructiveMigrationError) {
|
|
1917
|
+
* console.warn("Destructive migration blocked");
|
|
1918
|
+
* }
|
|
1919
|
+
* }
|
|
1920
|
+
* ```
|
|
1921
|
+
*/
|
|
1922
|
+
export class DestructiveMigrationError extends MigrationError {}
|
|
1923
|
+
|
|
1924
|
+
/**
|
|
1925
|
+
* Error raised when a persisted migration checksum does not match
|
|
1926
|
+
* the checksum calculated from its current contents.
|
|
1927
|
+
*
|
|
1928
|
+
* This protects the migration history from unexpected modifications.
|
|
1929
|
+
*/
|
|
1930
|
+
export class MigrationChecksumError extends MigrationError {}
|
|
1931
|
+
|
|
1932
|
+
/**
|
|
1933
|
+
* Main migration manager.
|
|
1934
|
+
*
|
|
1935
|
+
* Migration coordinates schema inspection, schema comparison,
|
|
1936
|
+
* migration generation, persistence, backups and execution.
|
|
1937
|
+
*
|
|
1938
|
+
* @example
|
|
1939
|
+
* ```ts
|
|
1940
|
+
* const migration = new Migration({
|
|
1941
|
+
* models: [UserModel],
|
|
1942
|
+
* dialect: "mysql",
|
|
1943
|
+
* directory: "./migrations"
|
|
1944
|
+
* });
|
|
1945
|
+
*
|
|
1946
|
+
* const plan = await migration.plan();
|
|
1947
|
+
*
|
|
1948
|
+
* if (plan.hasChanges()) {
|
|
1949
|
+
* await plan.execute();
|
|
1950
|
+
* }
|
|
1951
|
+
* ```
|
|
1952
|
+
*
|
|
1953
|
+
* @example Generate and execute a migration
|
|
1954
|
+
* ```ts
|
|
1955
|
+
* await Migration.migrate({
|
|
1956
|
+
* models: [UserModel],
|
|
1957
|
+
* dialect: "mysql"
|
|
1958
|
+
* });
|
|
1959
|
+
* ```
|
|
1960
|
+
*/
|
|
1961
|
+
export class Migration {
|
|
1962
|
+
/**
|
|
1963
|
+
* Active database connection.
|
|
1964
|
+
*/
|
|
1965
|
+
connection: any;
|
|
1966
|
+
|
|
1967
|
+
/**
|
|
1968
|
+
* SQL dialect used by the migration.
|
|
1969
|
+
*/
|
|
1970
|
+
dialect: any;
|
|
1971
|
+
|
|
1972
|
+
/**
|
|
1973
|
+
* Models included in schema comparison.
|
|
1974
|
+
*/
|
|
1975
|
+
models: Array<Model<any>>;
|
|
1976
|
+
|
|
1977
|
+
/**
|
|
1978
|
+
* Persistent migration store.
|
|
1979
|
+
*/
|
|
1980
|
+
store: MigrationStore;
|
|
1981
|
+
|
|
1982
|
+
/**
|
|
1983
|
+
* Database schema inspector.
|
|
1984
|
+
*/
|
|
1985
|
+
inspector: SchemaInspector;
|
|
1986
|
+
|
|
1987
|
+
/**
|
|
1988
|
+
* Schema difference calculator.
|
|
1989
|
+
*/
|
|
1990
|
+
differ: SchemaDiffer;
|
|
1991
|
+
|
|
1992
|
+
/**
|
|
1993
|
+
* Migration executor.
|
|
1994
|
+
*/
|
|
1995
|
+
runner: MigrationRunner;
|
|
1996
|
+
|
|
1997
|
+
/**
|
|
1998
|
+
* Creates a migration manager.
|
|
1999
|
+
*
|
|
2000
|
+
* @param options Migration configuration.
|
|
2001
|
+
*/
|
|
2002
|
+
constructor(options?: MigrationOptions);
|
|
2003
|
+
|
|
2004
|
+
/**
|
|
2005
|
+
* Generates a migration plan without executing it.
|
|
2006
|
+
*
|
|
2007
|
+
* @param options Optional migration configuration.
|
|
2008
|
+
* @returns Generated migration plan.
|
|
2009
|
+
*
|
|
2010
|
+
* @example
|
|
2011
|
+
* ```ts
|
|
2012
|
+
* const plan = await migration.plan({
|
|
2013
|
+
* name: "add-user-status"
|
|
2014
|
+
* });
|
|
2015
|
+
*
|
|
2016
|
+
* console.log(plan.sql);
|
|
2017
|
+
* ```
|
|
2018
|
+
*/
|
|
2019
|
+
plan(
|
|
2020
|
+
options?: MigrationOptions & {
|
|
2021
|
+
id?: string;
|
|
2022
|
+
name?: string;
|
|
2023
|
+
}
|
|
2024
|
+
): Promise<MigrationPlan>;
|
|
2025
|
+
|
|
2026
|
+
/**
|
|
2027
|
+
* Generates and executes a migration.
|
|
2028
|
+
*
|
|
2029
|
+
* @param options Migration and execution configuration.
|
|
2030
|
+
*
|
|
2031
|
+
* @example
|
|
2032
|
+
* ```ts
|
|
2033
|
+
* await migration.migrate({
|
|
2034
|
+
* name: "add-user-status",
|
|
2035
|
+
* approve: true
|
|
2036
|
+
* });
|
|
2037
|
+
* ```
|
|
2038
|
+
*/
|
|
2039
|
+
migrate(
|
|
2040
|
+
options?: MigrationOptions & {
|
|
2041
|
+
id?: string;
|
|
2042
|
+
name?: string;
|
|
2043
|
+
approve?: boolean;
|
|
2044
|
+
requireApproval?: boolean;
|
|
2045
|
+
}
|
|
2046
|
+
): Promise<any>;
|
|
2047
|
+
|
|
2048
|
+
/**
|
|
2049
|
+
* Returns the current migration status/history.
|
|
2050
|
+
*
|
|
2051
|
+
* @returns Applied migrations and their metadata.
|
|
2052
|
+
*
|
|
2053
|
+
* @example
|
|
2054
|
+
* ```ts
|
|
2055
|
+
* const status = await migration.status();
|
|
2056
|
+
*
|
|
2057
|
+
* console.table(status);
|
|
2058
|
+
* ```
|
|
2059
|
+
*/
|
|
2060
|
+
status(): Promise<any[]>;
|
|
2061
|
+
|
|
2062
|
+
/** Rolls back the latest applied migration and restores its backup. */
|
|
2063
|
+
rollback(id: string, options?: { allowOutOfOrder?: boolean }): Promise<any>;
|
|
2064
|
+
|
|
2065
|
+
/**
|
|
2066
|
+
* Removes expired migration files and backups.
|
|
2067
|
+
*
|
|
2068
|
+
* @returns Number of removed files.
|
|
2069
|
+
*/
|
|
2070
|
+
cleanup(): Promise<number>;
|
|
2071
|
+
|
|
2072
|
+
/**
|
|
2073
|
+
* Generates a migration plan using a temporary migration manager.
|
|
2074
|
+
*
|
|
2075
|
+
* @example
|
|
2076
|
+
* ```ts
|
|
2077
|
+
* const plan = await Migration.plan({
|
|
2078
|
+
* models: [UserModel],
|
|
2079
|
+
* dialect: "mysql"
|
|
2080
|
+
* });
|
|
2081
|
+
* ```
|
|
2082
|
+
*/
|
|
2083
|
+
static plan(
|
|
2084
|
+
options?: MigrationOptions & {
|
|
2085
|
+
id?: string;
|
|
2086
|
+
name?: string;
|
|
2087
|
+
}
|
|
2088
|
+
): Promise<MigrationPlan>;
|
|
2089
|
+
|
|
2090
|
+
/**
|
|
2091
|
+
* Generates and executes a migration using a temporary migration manager.
|
|
2092
|
+
*
|
|
2093
|
+
* @example
|
|
2094
|
+
* ```ts
|
|
2095
|
+
* await Migration.migrate({
|
|
2096
|
+
* models: [UserModel],
|
|
2097
|
+
* dialect: "mysql"
|
|
2098
|
+
* });
|
|
2099
|
+
* ```
|
|
2100
|
+
*/
|
|
2101
|
+
static migrate(
|
|
2102
|
+
options?: MigrationOptions & {
|
|
2103
|
+
id?: string;
|
|
2104
|
+
name?: string;
|
|
2105
|
+
approve?: boolean;
|
|
2106
|
+
requireApproval?: boolean;
|
|
2107
|
+
}
|
|
2108
|
+
): Promise<any>;
|
|
2109
|
+
|
|
2110
|
+
/**
|
|
2111
|
+
* Reads migration status using a temporary migration manager.
|
|
2112
|
+
*
|
|
2113
|
+
* @example
|
|
2114
|
+
* ```ts
|
|
2115
|
+
* const migrations = await Migration.status({
|
|
2116
|
+
* dialect: "mysql"
|
|
2117
|
+
* });
|
|
2118
|
+
* ```
|
|
2119
|
+
*/
|
|
2120
|
+
static status(
|
|
2121
|
+
options?: MigrationOptions
|
|
2122
|
+
): Promise<any[]>;
|
|
328
2123
|
}
|
|
329
2124
|
|
|
330
2125
|
/**
|
|
331
|
-
* Represents
|
|
332
|
-
*
|
|
2126
|
+
* Represents a row returned from a Model query.
|
|
2127
|
+
*
|
|
2128
|
+
* ModelInstance provides operations that act on the current row.
|
|
2129
|
+
*
|
|
2130
|
+
* @example
|
|
2131
|
+
* ```ts
|
|
2132
|
+
* const user = await userModel.find({
|
|
2133
|
+
* limit: 1
|
|
2134
|
+
* });
|
|
2135
|
+
*
|
|
2136
|
+
* await user[0].updateOne({
|
|
2137
|
+
* active: false
|
|
2138
|
+
* });
|
|
2139
|
+
* ```
|
|
333
2140
|
*/
|
|
334
|
-
export class ModelInstance<
|
|
2141
|
+
export class ModelInstance<
|
|
2142
|
+
TData extends Record<string, any> = Record<string, any>
|
|
2143
|
+
> {
|
|
2144
|
+
/**
|
|
2145
|
+
* Database model name.
|
|
2146
|
+
*/
|
|
335
2147
|
name: string;
|
|
2148
|
+
|
|
2149
|
+
/**
|
|
2150
|
+
* Row data.
|
|
2151
|
+
*/
|
|
336
2152
|
data: TData;
|
|
2153
|
+
|
|
2154
|
+
/**
|
|
2155
|
+
* Schema associated with the row.
|
|
2156
|
+
*/
|
|
337
2157
|
schema?: SchemaLike<any>;
|
|
338
|
-
|
|
2158
|
+
|
|
339
2159
|
/**
|
|
340
|
-
*
|
|
341
|
-
*
|
|
342
|
-
* @param
|
|
343
|
-
* @
|
|
344
|
-
* @
|
|
2160
|
+
* Creates a model instance.
|
|
2161
|
+
*
|
|
2162
|
+
* @param name Model/table name.
|
|
2163
|
+
* @param data Row data.
|
|
2164
|
+
* @param schema Optional schema definition.
|
|
345
2165
|
*/
|
|
346
|
-
|
|
2166
|
+
constructor(
|
|
2167
|
+
name: string,
|
|
2168
|
+
data: TData,
|
|
2169
|
+
schema?: SchemaLike<any>
|
|
2170
|
+
);
|
|
2171
|
+
|
|
347
2172
|
/**
|
|
348
|
-
*
|
|
349
|
-
*
|
|
350
|
-
* @
|
|
351
|
-
* @
|
|
2173
|
+
* Updates the current database row.
|
|
2174
|
+
*
|
|
2175
|
+
* @param model Values to update.
|
|
2176
|
+
* @returns Number of affected rows.
|
|
2177
|
+
*
|
|
2178
|
+
* @example
|
|
2179
|
+
* ```ts
|
|
2180
|
+
* await user.updateOne({
|
|
2181
|
+
* active: false
|
|
2182
|
+
* });
|
|
2183
|
+
* ```
|
|
352
2184
|
*/
|
|
353
|
-
|
|
2185
|
+
updateOne(
|
|
2186
|
+
model: Partial<TData>
|
|
2187
|
+
): Promise<number>;
|
|
354
2188
|
|
|
355
2189
|
/**
|
|
356
|
-
*
|
|
357
|
-
*
|
|
358
|
-
* @
|
|
359
|
-
* @
|
|
2190
|
+
* Deletes a database row matching the supplied filter.
|
|
2191
|
+
*
|
|
2192
|
+
* @param filter Conditions identifying the row.
|
|
2193
|
+
* @returns Number of affected rows.
|
|
2194
|
+
*
|
|
2195
|
+
* @example
|
|
2196
|
+
* ```ts
|
|
2197
|
+
* await user.delete({
|
|
2198
|
+
* id: user.data.id
|
|
2199
|
+
* });
|
|
2200
|
+
* ```
|
|
360
2201
|
*/
|
|
361
|
-
|
|
2202
|
+
delete(
|
|
2203
|
+
filter: Record<string, any>
|
|
2204
|
+
): Promise<number>;
|
|
2205
|
+
|
|
2206
|
+
/**
|
|
2207
|
+
* Executes a custom SQL query associated with this model instance.
|
|
2208
|
+
*
|
|
2209
|
+
* @param custom SQL query.
|
|
2210
|
+
* @returns Query result.
|
|
2211
|
+
*
|
|
2212
|
+
* @example
|
|
2213
|
+
* ```ts
|
|
2214
|
+
* const result = await user.customRequest(
|
|
2215
|
+
* "SELECT NOW() AS current_time"
|
|
2216
|
+
* );
|
|
2217
|
+
* ```
|
|
2218
|
+
*/
|
|
2219
|
+
customRequest<TResult = any>(
|
|
2220
|
+
custom: string
|
|
2221
|
+
): Promise<TResult>;
|
|
362
2222
|
}
|
|
363
2223
|
|
|
364
|
-
|
|
2224
|
+
/**
|
|
2225
|
+
* Active SQL Connector client object.
|
|
2226
|
+
*
|
|
2227
|
+
* This object is reserved for the connector runtime and shared client state.
|
|
2228
|
+
*/
|
|
2229
|
+
export const client: Record<string, any>;
|