@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/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; // Ajout de la propriété demandée
22
- [key: string]: any; // Permet d'accueillir d'autres types SQL généraux
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
- export type SchemaTypeInput = SqlType | { name: SqlType } | SqlTypeConstructor;
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> = K extends keyof T ? true : false;
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]: InferFieldNullable<TSchema[K]> extends true
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
- export type ModelRecord<TData extends Record<string, any> = Record<string, any>> = ModelInstance<TData> & TData;
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
- * const transferSchema = new Schema({
163
- * token: {
164
- * type: String,
165
- * length: 50
166
- * },
167
- * mdp: {
168
- * type: String,
169
- * length: 15
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 connection to the database using a given configuration.
181
- * @param {Object} config Database connection configuration.
182
- * @param {string} config.host The database host.
183
- * @param {number} config.port The database port.
184
- * @param {string} config.user The username for the connection.
185
- * @param {string} config.password The password for the connection.
186
- * @param {string} config.database The name of the database.
187
- * @returns {Promise<void>} A promise that resolves when the connection is established.
188
- *
189
- * @example
190
- * const config = {
191
- * host: 'localhost',
192
- * port: 6666,
193
- * user: 'root',
194
- * password: 'password',
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 to the database using a given configuration.
203
- * @param {Object} config Database connection configuration.
204
- * @param {string} config.host The database host.
205
- * @param {number} config.port The database port.
206
- * @param {string} config.user The username for the connection.
207
- * @param {string} config.password The password for the connection.
208
- * @param {string} config.database The name of the database.
209
- * @param {string} dialect The SQL dialect to use (e.g., 'mysql', 'postgres'). defaults to 'mysql'.
210
- * @returns {Promise<void>} A promise that resolves when the connection is established.
211
- *
212
- * @example
213
- * const config = {
214
- * host: 'localhost',
215
- * port: 6666,
216
- * user: 'root',
217
- * password: 'password',
218
- * database: 'mydatabase'
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(config: PoolOptions, dialect?: string): Promise<void>;
855
+ export function connect(
856
+ config: PoolOptions,
857
+ dialect?: string
858
+ ): Promise<void>;
223
859
 
224
860
  /**
225
- * Closes the database connection.
226
- * This function terminates the active database connection and records a logging message
227
- * indicating whether the shutdown succeeded or failed.
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
- * @class
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
- constructor(name: string, schema: SchemaLike<TSchema>);
914
+
246
915
  /**
247
- * Creates all tables in the correct order based on foreign keys.
248
- * @returns {Promise<void>}
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
- * Saves data to the database table.
253
- * @param {Object} data The data to insert into the table.
254
- * @returns {Promise<Object>} A promise that resolves with the result of the insertion.
255
- * @throws {Error} Throws an error if the insert fails.
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(data: Partial<InferSchema<TSchema>>): Promise<any>;
952
+ save(
953
+ data: Partial<InferSchema<TSchema>>
954
+ ): Promise<any>;
955
+
258
956
  /**
259
- * Retrieves multiple rows from the table.
260
- * @param {Object} [options] - Query options (attributes, where, order, limit).
261
- * @param {string[]} [options.select] - Fields to return.
262
- * @param {Object} [options.where] - Filters (key/value).
263
- * @param {Array} [options.order] - Example: [['points', 'DESC']]
264
- * @param {number} [options.limit] - Result limit.
265
- * @returns {Promise<Array<Object>>}
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
- where?: WhereClause
270
- order?: [string, string][];
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
- * @param {Object} filter The filter criteria for the query. Should be an object where keys are column names and values are the values to filter by.
276
- * @returns {Promise<ModelInstance|number>} - A promise that resolves to a `ModelInstance` if a record is found, or `0` if no records match the filter.
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(filter?: Record<string, any> | Partial<InferSchema<TSchema>>): Promise<number>;
1194
+ count(
1195
+ filter?: Record<string, any> | Partial<InferSchema<TSchema>>
1196
+ ): Promise<number>;
1197
+
279
1198
  /**
280
- * Runs a custom SQL_request query.
281
- * @param {string} custom The custom SQL_request query to execute.
282
- * @returns {Promise<void>} A promise that resolves when the query is executed.
283
- * @throws {Error} Throws an error if query execution fails.
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>>(custom: string): Promise<ModelRecord<TResult> | 0>;
1214
+ customRequest<TResult extends Record<string, any> = InferSchema<TSchema>>(
1215
+ custom: string
1216
+ ): Promise<ModelRecord<TResult> | 0>;
1217
+
286
1218
  /**
287
- * Deletes a record from the SQL table corresponding to the provided filter.
1219
+ * Deletes records matching the supplied filter.
288
1220
  *
289
- * @async
290
- * @function delete
291
- * @param {Object} filter - An object representing the filter conditions for the deletion.
292
- * @returns {Promise<number>} A promise that resolves to 0 if no rows were deleted,
293
- * or an instance of ModelInstance representing the deleted row.
294
- * @throws {Error} Throws an error if the SQL query fails.
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(filter: Record<string, any> | Partial<InferSchema<TSchema>>): Promise<number>;
1231
+ delete(
1232
+ filter: Record<string, any> | Partial<InferSchema<TSchema>>
1233
+ ): Promise<number>;
1234
+
297
1235
  /**
298
- * Asynchronously drops a table if it exists in the database.
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
- * @returns {Promise<void>} A promise that resolves when the query execution is complete.
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
- * Generates a unique UUID for the current model.
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 function generates a UUID using the SQL_request `UUID()` function and checks if the generated UUID
312
- * already exists in the database for the current model. If the UUID is unique, it is returned.
313
- * Otherwise, the function resolves to `null`.
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
- * @returns {Promise<string|null>} A promise that resolves to a unique UUID string if successful, or `null` if an error occurs or the UUID is not unique.
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
- * const uuid = await model.generate_uuid();
319
- * if (uuid) {
320
- * console.log(`Generated UUID: ${uuid}`);
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
- * @throws {Error} If there is an error executing the SQL_request query.
1505
+ * @example
1506
+ * ```ts
1507
+ * console.table(plan.destructiveChanges());
1508
+ * ```
326
1509
  */
327
- generate_uuid(var_uuid?: string): Promise<string | null>;
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 an instance of a database model.
332
- * @class
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<TData extends Record<string, any> = Record<string, any>> {
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
- constructor(name: string, data: TData, schema?: SchemaLike<any>);
2158
+
339
2159
  /**
340
- * Updates a single entry in the database table.
341
- *
342
- * @param {Object} model An object containing the key-value pairs to use for updating.
343
- * @returns {int} A promise that resolves with updated data.
344
- * @throws {Error} Throws an error if the update fails.
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
- updateOne(model: Partial<TData>): Promise<number>;
2166
+ constructor(
2167
+ name: string,
2168
+ data: TData,
2169
+ schema?: SchemaLike<any>
2170
+ );
2171
+
347
2172
  /**
348
- * Deletes a single entry in the database table.
349
- * @param {Object} model An object containing the key-value pairs to use for deletion.
350
- * @returns {Promise<Object>} A promise that resolves with the data deleted.
351
- * @throws {Error} Throws an error if the deletion fails.
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
- delete(filter: Record<string, any>): Promise<number>;
2185
+ updateOne(
2186
+ model: Partial<TData>
2187
+ ): Promise<number>;
354
2188
 
355
2189
  /**
356
- * Runs a custom SQL_request query.
357
- * @param {string} custom The custom SQL_request query to execute.
358
- * @returns {Promise<void>} A promise that resolves when the query is executed.
359
- * @throws {Error} Throws an error if query execution fails.
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
- customRequest<TResult = any>(custom: string): Promise<TResult>;
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
- export const client: Record<string, any>;
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>;