metal-orm 1.0.11 → 1.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +4 -3
  2. package/dist/decorators/index.cjs +15 -2
  3. package/dist/decorators/index.cjs.map +1 -1
  4. package/dist/decorators/index.d.cts +1 -1
  5. package/dist/decorators/index.d.ts +1 -1
  6. package/dist/decorators/index.js +15 -2
  7. package/dist/decorators/index.js.map +1 -1
  8. package/dist/index.cjs +1394 -149
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +257 -23
  11. package/dist/index.d.ts +257 -23
  12. package/dist/index.js +1376 -149
  13. package/dist/index.js.map +1 -1
  14. package/dist/{select-654m4qy8.d.cts → select-BKlr2ivY.d.cts} +141 -4
  15. package/dist/{select-654m4qy8.d.ts → select-BKlr2ivY.d.ts} +141 -4
  16. package/package.json +1 -1
  17. package/src/core/ddl/dialects/base-schema-dialect.ts +48 -0
  18. package/src/core/ddl/dialects/index.ts +5 -0
  19. package/src/core/ddl/dialects/mssql-schema-dialect.ts +97 -0
  20. package/src/core/ddl/dialects/mysql-schema-dialect.ts +109 -0
  21. package/src/core/ddl/dialects/postgres-schema-dialect.ts +99 -0
  22. package/src/core/ddl/dialects/sqlite-schema-dialect.ts +103 -0
  23. package/src/core/ddl/introspect/mssql.ts +149 -0
  24. package/src/core/ddl/introspect/mysql.ts +99 -0
  25. package/src/core/ddl/introspect/postgres.ts +154 -0
  26. package/src/core/ddl/introspect/sqlite.ts +66 -0
  27. package/src/core/ddl/introspect/types.ts +19 -0
  28. package/src/core/ddl/introspect/utils.ts +27 -0
  29. package/src/core/ddl/schema-diff.ts +179 -0
  30. package/src/core/ddl/schema-generator.ts +229 -0
  31. package/src/core/ddl/schema-introspect.ts +32 -0
  32. package/src/core/ddl/schema-types.ts +39 -0
  33. package/src/core/dialect/base/sql-dialect.ts +161 -0
  34. package/src/core/dialect/mysql/index.ts +18 -112
  35. package/src/core/dialect/postgres/index.ts +30 -126
  36. package/src/core/dialect/sqlite/index.ts +29 -129
  37. package/src/index.ts +4 -0
  38. package/src/schema/column.ts +206 -27
  39. package/src/schema/table.ts +89 -32
  40. package/src/schema/types.ts +8 -5
@@ -1,7 +1,26 @@
1
1
  /**
2
2
  * Supported column data types for database schema definitions
3
3
  */
4
- type ColumnType = 'INT' | 'INTEGER' | 'VARCHAR' | 'TEXT' | 'JSON' | 'ENUM' | 'BOOLEAN' | 'int' | 'integer' | 'varchar' | 'text' | 'json' | 'enum' | 'boolean';
4
+ type ColumnType = 'INT' | 'INTEGER' | 'BIGINT' | 'VARCHAR' | 'TEXT' | 'JSON' | 'ENUM' | 'DECIMAL' | 'FLOAT' | 'DOUBLE' | 'UUID' | 'DATE' | 'DATETIME' | 'TIMESTAMP' | 'TIMESTAMPTZ' | 'BOOLEAN' | 'int' | 'integer' | 'bigint' | 'varchar' | 'text' | 'json' | 'enum' | 'decimal' | 'float' | 'double' | 'uuid' | 'date' | 'datetime' | 'timestamp' | 'timestamptz' | 'boolean';
5
+ type ReferentialAction = 'NO ACTION' | 'RESTRICT' | 'CASCADE' | 'SET NULL' | 'SET DEFAULT';
6
+ interface RawDefaultValue {
7
+ raw: string;
8
+ }
9
+ type DefaultValue = unknown | RawDefaultValue;
10
+ interface ForeignKeyReference {
11
+ /** Target table name */
12
+ table: string;
13
+ /** Target column name */
14
+ column: string;
15
+ /** Optional constraint name */
16
+ name?: string;
17
+ /** ON DELETE action */
18
+ onDelete?: ReferentialAction;
19
+ /** ON UPDATE action */
20
+ onUpdate?: ReferentialAction;
21
+ /** Whether the constraint is deferrable (Postgres) */
22
+ deferrable?: boolean;
23
+ }
5
24
  /**
6
25
  * Definition of a database column
7
26
  */
@@ -14,6 +33,20 @@ interface ColumnDef<T extends ColumnType = ColumnType> {
14
33
  primary?: boolean;
15
34
  /** Whether this column cannot be null */
16
35
  notNull?: boolean;
36
+ /** Whether this column must be unique (or name of the unique constraint) */
37
+ unique?: boolean | string;
38
+ /** Default value for the column */
39
+ default?: DefaultValue;
40
+ /** Whether the column auto-increments / identity */
41
+ autoIncrement?: boolean;
42
+ /** Identity strategy where supported */
43
+ generated?: 'always' | 'byDefault';
44
+ /** Inline check constraint expression */
45
+ check?: string;
46
+ /** Foreign key reference */
47
+ references?: ForeignKeyReference;
48
+ /** Column comment/description */
49
+ comment?: string;
17
50
  /** Additional arguments for the column type (e.g., VARCHAR length) */
18
51
  args?: any[];
19
52
  /** Table name this column belongs to (filled at runtime by defineTable) */
@@ -28,12 +61,44 @@ declare const col: {
28
61
  * @returns ColumnDef with INT type
29
62
  */
30
63
  int: () => ColumnDef<"INT">;
64
+ /**
65
+ * Creates a big integer column definition
66
+ */
67
+ bigint: () => ColumnDef<"BIGINT">;
31
68
  /**
32
69
  * Creates a variable character column definition
33
70
  * @param length - Maximum length of the string
34
71
  * @returns ColumnDef with VARCHAR type
35
72
  */
36
73
  varchar: (length: number) => ColumnDef<"VARCHAR">;
74
+ /**
75
+ * Creates a fixed precision decimal column definition
76
+ */
77
+ decimal: (precision: number, scale?: number) => ColumnDef<"DECIMAL">;
78
+ /**
79
+ * Creates a floating point column definition
80
+ */
81
+ float: (precision?: number) => ColumnDef<"FLOAT">;
82
+ /**
83
+ * Creates a UUID column definition
84
+ */
85
+ uuid: () => ColumnDef<"UUID">;
86
+ /**
87
+ * Creates a timestamp column definition
88
+ */
89
+ timestamp: () => ColumnDef<"TIMESTAMP">;
90
+ /**
91
+ * Creates a timestamptz column definition
92
+ */
93
+ timestamptz: () => ColumnDef<"TIMESTAMPTZ">;
94
+ /**
95
+ * Creates a date column definition
96
+ */
97
+ date: () => ColumnDef<"DATE">;
98
+ /**
99
+ * Creates a datetime column definition
100
+ */
101
+ datetime: () => ColumnDef<"DATETIME">;
37
102
  /**
38
103
  * Creates a JSON column definition
39
104
  * @returns ColumnDef with JSON type
@@ -44,12 +109,45 @@ declare const col: {
44
109
  * @returns ColumnDef with BOOLEAN type
45
110
  */
46
111
  boolean: () => ColumnDef<"BOOLEAN">;
112
+ /**
113
+ * Creates an enum column definition
114
+ * @param values - Enum values
115
+ */
116
+ enum: (values: string[]) => ColumnDef<"ENUM">;
47
117
  /**
48
118
  * Marks a column definition as a primary key
49
119
  * @param def - Column definition to modify
50
120
  * @returns Modified ColumnDef with primary: true
51
121
  */
52
122
  primaryKey: <T extends ColumnType>(def: ColumnDef<T>) => ColumnDef<T>;
123
+ /**
124
+ * Marks a column as NOT NULL
125
+ */
126
+ notNull: <T extends ColumnType>(def: ColumnDef<T>) => ColumnDef<T>;
127
+ /**
128
+ * Marks a column as UNIQUE
129
+ */
130
+ unique: <T extends ColumnType>(def: ColumnDef<T>, name?: string) => ColumnDef<T>;
131
+ /**
132
+ * Sets a default value for the column
133
+ */
134
+ default: <T extends ColumnType>(def: ColumnDef<T>, value: unknown) => ColumnDef<T>;
135
+ /**
136
+ * Sets a raw SQL default value for the column
137
+ */
138
+ defaultRaw: <T extends ColumnType>(def: ColumnDef<T>, expression: string) => ColumnDef<T>;
139
+ /**
140
+ * Marks a column as auto-increment / identity
141
+ */
142
+ autoIncrement: <T extends ColumnType>(def: ColumnDef<T>, strategy?: ColumnDef["generated"]) => ColumnDef<T>;
143
+ /**
144
+ * Adds a foreign key reference
145
+ */
146
+ references: <T extends ColumnType>(def: ColumnDef<T>, ref: ForeignKeyReference) => ColumnDef<T>;
147
+ /**
148
+ * Adds a check constraint to the column
149
+ */
150
+ check: <T extends ColumnType>(def: ColumnDef<T>, expression: string) => ColumnDef<T>;
53
151
  };
54
152
 
55
153
  /**
@@ -150,6 +248,31 @@ declare const belongsToMany: <TTarget extends TableDef>(target: TTarget, pivotTa
150
248
  cascade?: CascadeMode;
151
249
  }) => BelongsToManyRelation<TTarget>;
152
250
 
251
+ interface IndexColumn {
252
+ column: string;
253
+ order?: 'ASC' | 'DESC';
254
+ nulls?: 'FIRST' | 'LAST';
255
+ }
256
+ interface IndexDef {
257
+ name?: string;
258
+ columns: (string | IndexColumn)[];
259
+ unique?: boolean;
260
+ where?: string;
261
+ }
262
+ interface CheckConstraint {
263
+ name?: string;
264
+ expression: string;
265
+ }
266
+ interface TableOptions {
267
+ schema?: string;
268
+ primaryKey?: string[];
269
+ indexes?: IndexDef[];
270
+ checks?: CheckConstraint[];
271
+ comment?: string;
272
+ engine?: string;
273
+ charset?: string;
274
+ collation?: string;
275
+ }
153
276
  interface TableHooks {
154
277
  beforeInsert?(ctx: unknown, entity: any): Promise<void> | void;
155
278
  afterInsert?(ctx: unknown, entity: any): Promise<void> | void;
@@ -165,12 +288,26 @@ interface TableHooks {
165
288
  interface TableDef<T extends Record<string, ColumnDef> = Record<string, ColumnDef>> {
166
289
  /** Name of the table */
167
290
  name: string;
291
+ /** Optional schema/catalog name */
292
+ schema?: string;
168
293
  /** Record of column definitions keyed by column name */
169
294
  columns: T;
170
295
  /** Record of relationship definitions keyed by relation name */
171
296
  relations: Record<string, RelationDef>;
172
297
  /** Optional lifecycle hooks */
173
298
  hooks?: TableHooks;
299
+ /** Composite primary key definition (falls back to column.primary flags) */
300
+ primaryKey?: string[];
301
+ /** Secondary indexes */
302
+ indexes?: IndexDef[];
303
+ /** Table-level check constraints */
304
+ checks?: CheckConstraint[];
305
+ /** Table comment/description */
306
+ comment?: string;
307
+ /** Dialect-specific options */
308
+ engine?: string;
309
+ charset?: string;
310
+ collation?: string;
174
311
  }
175
312
  /**
176
313
  * Creates a table definition with columns and relationships
@@ -189,12 +326,12 @@ interface TableDef<T extends Record<string, ColumnDef> = Record<string, ColumnDe
189
326
  * });
190
327
  * ```
191
328
  */
192
- declare const defineTable: <T extends Record<string, ColumnDef>>(name: string, columns: T, relations?: Record<string, RelationDef>, hooks?: TableHooks) => TableDef<T>;
329
+ declare const defineTable: <T extends Record<string, ColumnDef>>(name: string, columns: T, relations?: Record<string, RelationDef>, hooks?: TableHooks, options?: TableOptions) => TableDef<T>;
193
330
 
194
331
  /**
195
332
  * Maps a ColumnDef to its TypeScript type representation
196
333
  */
197
- type ColumnToTs<T extends ColumnDef> = T['type'] extends 'INT' | 'INTEGER' | 'int' | 'integer' ? number : T['type'] extends 'BOOLEAN' | 'boolean' ? boolean : T['type'] extends 'JSON' | 'json' ? unknown : string;
334
+ type ColumnToTs<T extends ColumnDef> = T['type'] extends 'INT' | 'INTEGER' | 'int' | 'integer' ? number : T['type'] extends 'BIGINT' | 'bigint' ? number | bigint : T['type'] extends 'DECIMAL' | 'decimal' | 'FLOAT' | 'float' | 'DOUBLE' | 'double' ? number : T['type'] extends 'BOOLEAN' | 'boolean' ? boolean : T['type'] extends 'JSON' | 'json' ? unknown : T['type'] extends 'DATE' | 'date' | 'DATETIME' | 'datetime' | 'TIMESTAMP' | 'timestamp' | 'TIMESTAMPTZ' | 'timestamptz' ? string : string;
198
335
  /**
199
336
  * Infers a row shape from a table definition
200
337
  */
@@ -1519,4 +1656,4 @@ declare const createColumn: (table: string, name: string) => ColumnNode;
1519
1656
  */
1520
1657
  declare const createLiteral: (val: string | number) => LiteralNode;
1521
1658
 
1522
- export { createLiteral as $, RelationKinds as A, type BinaryExpressionNode as B, type ColumnDef as C, type DeleteQueryNode as D, type ExpressionNode as E, type FunctionNode as F, type RelationType as G, type HydrationPlan as H, type InExpressionNode as I, type JsonPathNode as J, type CascadeMode as K, type LogicalExpressionNode as L, type ManyToManyCollection as M, type NullExpressionNode as N, type OperandNode as O, type RelationDef as P, hasMany as Q, type RelationMap as R, type SelectQueryNode as S, type TableDef as T, type UpdateQueryNode as U, belongsTo as V, type WindowFunctionNode as W, belongsToMany as X, type ColumnToTs as Y, type InferRow as Z, createColumn as _, type ColumnNode as a, isOperandNode as a0, isFunctionNode as a1, isCaseExpressionNode as a2, isWindowFunctionNode as a3, isExpressionSelectionNode as a4, addDomainEvent as a5, EntityStatus as a6, type QueryResult as a7, type DbExecutor as a8, type RelationKey as a9, type RelationChange as aa, type HasDomainEvents as ab, type OrmInterceptor as ac, type DomainEventHandler as ad, type OrmContextOptions as ae, type LiteralNode as b, type BetweenExpressionNode as c, type CaseExpressionNode as d, type ExistsExpressionNode as e, type OrderDirection as f, type ScalarSubqueryNode as g, type InsertQueryNode as h, type InsertCompiler as i, type CompiledQuery as j, type UpdateCompiler as k, type DeleteCompiler as l, Dialect as m, type CompilerContext as n, OrmContext as o, type Entity as p, type HasManyRelation as q, type BelongsToRelation as r, type BelongsToManyRelation as s, type HasManyCollection as t, type BelongsToReference as u, SelectQueryBuilder as v, type TableHooks as w, defineTable as x, type ColumnType as y, col as z };
1659
+ export { type RelationType as $, type CheckConstraint as A, type BinaryExpressionNode as B, type ColumnDef as C, type DeleteQueryNode as D, type ExpressionNode as E, type FunctionNode as F, type TableOptions as G, type HydrationPlan as H, type InExpressionNode as I, type JsonPathNode as J, type TableHooks as K, type LogicalExpressionNode as L, type ManyToManyCollection as M, type NullExpressionNode as N, type OperandNode as O, defineTable as P, type ColumnType as Q, type RelationMap as R, type SelectQueryNode as S, type TableDef as T, type UpdateQueryNode as U, type ReferentialAction as V, type WindowFunctionNode as W, type RawDefaultValue as X, type DefaultValue as Y, col as Z, RelationKinds as _, type ColumnNode as a, type CascadeMode as a0, type RelationDef as a1, hasMany as a2, belongsTo as a3, belongsToMany as a4, type ColumnToTs as a5, type InferRow as a6, createColumn as a7, createLiteral as a8, isOperandNode as a9, isFunctionNode as aa, isCaseExpressionNode as ab, isWindowFunctionNode as ac, isExpressionSelectionNode as ad, addDomainEvent as ae, EntityStatus as af, type QueryResult as ag, type RelationKey as ah, type RelationChange as ai, type HasDomainEvents as aj, type OrmInterceptor as ak, type DomainEventHandler as al, type OrmContextOptions as am, type LiteralNode as b, type BetweenExpressionNode as c, type CaseExpressionNode as d, type ExistsExpressionNode as e, type OrderDirection as f, type ScalarSubqueryNode as g, type InsertQueryNode as h, type InsertCompiler as i, type CompiledQuery as j, type UpdateCompiler as k, type DeleteCompiler as l, Dialect as m, type CompilerContext as n, type ForeignKeyReference as o, type IndexColumn as p, type IndexDef as q, type DbExecutor as r, OrmContext as s, type Entity as t, type HasManyRelation as u, type BelongsToRelation as v, type BelongsToManyRelation as w, type HasManyCollection as x, type BelongsToReference as y, SelectQueryBuilder as z };
@@ -1,7 +1,26 @@
1
1
  /**
2
2
  * Supported column data types for database schema definitions
3
3
  */
4
- type ColumnType = 'INT' | 'INTEGER' | 'VARCHAR' | 'TEXT' | 'JSON' | 'ENUM' | 'BOOLEAN' | 'int' | 'integer' | 'varchar' | 'text' | 'json' | 'enum' | 'boolean';
4
+ type ColumnType = 'INT' | 'INTEGER' | 'BIGINT' | 'VARCHAR' | 'TEXT' | 'JSON' | 'ENUM' | 'DECIMAL' | 'FLOAT' | 'DOUBLE' | 'UUID' | 'DATE' | 'DATETIME' | 'TIMESTAMP' | 'TIMESTAMPTZ' | 'BOOLEAN' | 'int' | 'integer' | 'bigint' | 'varchar' | 'text' | 'json' | 'enum' | 'decimal' | 'float' | 'double' | 'uuid' | 'date' | 'datetime' | 'timestamp' | 'timestamptz' | 'boolean';
5
+ type ReferentialAction = 'NO ACTION' | 'RESTRICT' | 'CASCADE' | 'SET NULL' | 'SET DEFAULT';
6
+ interface RawDefaultValue {
7
+ raw: string;
8
+ }
9
+ type DefaultValue = unknown | RawDefaultValue;
10
+ interface ForeignKeyReference {
11
+ /** Target table name */
12
+ table: string;
13
+ /** Target column name */
14
+ column: string;
15
+ /** Optional constraint name */
16
+ name?: string;
17
+ /** ON DELETE action */
18
+ onDelete?: ReferentialAction;
19
+ /** ON UPDATE action */
20
+ onUpdate?: ReferentialAction;
21
+ /** Whether the constraint is deferrable (Postgres) */
22
+ deferrable?: boolean;
23
+ }
5
24
  /**
6
25
  * Definition of a database column
7
26
  */
@@ -14,6 +33,20 @@ interface ColumnDef<T extends ColumnType = ColumnType> {
14
33
  primary?: boolean;
15
34
  /** Whether this column cannot be null */
16
35
  notNull?: boolean;
36
+ /** Whether this column must be unique (or name of the unique constraint) */
37
+ unique?: boolean | string;
38
+ /** Default value for the column */
39
+ default?: DefaultValue;
40
+ /** Whether the column auto-increments / identity */
41
+ autoIncrement?: boolean;
42
+ /** Identity strategy where supported */
43
+ generated?: 'always' | 'byDefault';
44
+ /** Inline check constraint expression */
45
+ check?: string;
46
+ /** Foreign key reference */
47
+ references?: ForeignKeyReference;
48
+ /** Column comment/description */
49
+ comment?: string;
17
50
  /** Additional arguments for the column type (e.g., VARCHAR length) */
18
51
  args?: any[];
19
52
  /** Table name this column belongs to (filled at runtime by defineTable) */
@@ -28,12 +61,44 @@ declare const col: {
28
61
  * @returns ColumnDef with INT type
29
62
  */
30
63
  int: () => ColumnDef<"INT">;
64
+ /**
65
+ * Creates a big integer column definition
66
+ */
67
+ bigint: () => ColumnDef<"BIGINT">;
31
68
  /**
32
69
  * Creates a variable character column definition
33
70
  * @param length - Maximum length of the string
34
71
  * @returns ColumnDef with VARCHAR type
35
72
  */
36
73
  varchar: (length: number) => ColumnDef<"VARCHAR">;
74
+ /**
75
+ * Creates a fixed precision decimal column definition
76
+ */
77
+ decimal: (precision: number, scale?: number) => ColumnDef<"DECIMAL">;
78
+ /**
79
+ * Creates a floating point column definition
80
+ */
81
+ float: (precision?: number) => ColumnDef<"FLOAT">;
82
+ /**
83
+ * Creates a UUID column definition
84
+ */
85
+ uuid: () => ColumnDef<"UUID">;
86
+ /**
87
+ * Creates a timestamp column definition
88
+ */
89
+ timestamp: () => ColumnDef<"TIMESTAMP">;
90
+ /**
91
+ * Creates a timestamptz column definition
92
+ */
93
+ timestamptz: () => ColumnDef<"TIMESTAMPTZ">;
94
+ /**
95
+ * Creates a date column definition
96
+ */
97
+ date: () => ColumnDef<"DATE">;
98
+ /**
99
+ * Creates a datetime column definition
100
+ */
101
+ datetime: () => ColumnDef<"DATETIME">;
37
102
  /**
38
103
  * Creates a JSON column definition
39
104
  * @returns ColumnDef with JSON type
@@ -44,12 +109,45 @@ declare const col: {
44
109
  * @returns ColumnDef with BOOLEAN type
45
110
  */
46
111
  boolean: () => ColumnDef<"BOOLEAN">;
112
+ /**
113
+ * Creates an enum column definition
114
+ * @param values - Enum values
115
+ */
116
+ enum: (values: string[]) => ColumnDef<"ENUM">;
47
117
  /**
48
118
  * Marks a column definition as a primary key
49
119
  * @param def - Column definition to modify
50
120
  * @returns Modified ColumnDef with primary: true
51
121
  */
52
122
  primaryKey: <T extends ColumnType>(def: ColumnDef<T>) => ColumnDef<T>;
123
+ /**
124
+ * Marks a column as NOT NULL
125
+ */
126
+ notNull: <T extends ColumnType>(def: ColumnDef<T>) => ColumnDef<T>;
127
+ /**
128
+ * Marks a column as UNIQUE
129
+ */
130
+ unique: <T extends ColumnType>(def: ColumnDef<T>, name?: string) => ColumnDef<T>;
131
+ /**
132
+ * Sets a default value for the column
133
+ */
134
+ default: <T extends ColumnType>(def: ColumnDef<T>, value: unknown) => ColumnDef<T>;
135
+ /**
136
+ * Sets a raw SQL default value for the column
137
+ */
138
+ defaultRaw: <T extends ColumnType>(def: ColumnDef<T>, expression: string) => ColumnDef<T>;
139
+ /**
140
+ * Marks a column as auto-increment / identity
141
+ */
142
+ autoIncrement: <T extends ColumnType>(def: ColumnDef<T>, strategy?: ColumnDef["generated"]) => ColumnDef<T>;
143
+ /**
144
+ * Adds a foreign key reference
145
+ */
146
+ references: <T extends ColumnType>(def: ColumnDef<T>, ref: ForeignKeyReference) => ColumnDef<T>;
147
+ /**
148
+ * Adds a check constraint to the column
149
+ */
150
+ check: <T extends ColumnType>(def: ColumnDef<T>, expression: string) => ColumnDef<T>;
53
151
  };
54
152
 
55
153
  /**
@@ -150,6 +248,31 @@ declare const belongsToMany: <TTarget extends TableDef>(target: TTarget, pivotTa
150
248
  cascade?: CascadeMode;
151
249
  }) => BelongsToManyRelation<TTarget>;
152
250
 
251
+ interface IndexColumn {
252
+ column: string;
253
+ order?: 'ASC' | 'DESC';
254
+ nulls?: 'FIRST' | 'LAST';
255
+ }
256
+ interface IndexDef {
257
+ name?: string;
258
+ columns: (string | IndexColumn)[];
259
+ unique?: boolean;
260
+ where?: string;
261
+ }
262
+ interface CheckConstraint {
263
+ name?: string;
264
+ expression: string;
265
+ }
266
+ interface TableOptions {
267
+ schema?: string;
268
+ primaryKey?: string[];
269
+ indexes?: IndexDef[];
270
+ checks?: CheckConstraint[];
271
+ comment?: string;
272
+ engine?: string;
273
+ charset?: string;
274
+ collation?: string;
275
+ }
153
276
  interface TableHooks {
154
277
  beforeInsert?(ctx: unknown, entity: any): Promise<void> | void;
155
278
  afterInsert?(ctx: unknown, entity: any): Promise<void> | void;
@@ -165,12 +288,26 @@ interface TableHooks {
165
288
  interface TableDef<T extends Record<string, ColumnDef> = Record<string, ColumnDef>> {
166
289
  /** Name of the table */
167
290
  name: string;
291
+ /** Optional schema/catalog name */
292
+ schema?: string;
168
293
  /** Record of column definitions keyed by column name */
169
294
  columns: T;
170
295
  /** Record of relationship definitions keyed by relation name */
171
296
  relations: Record<string, RelationDef>;
172
297
  /** Optional lifecycle hooks */
173
298
  hooks?: TableHooks;
299
+ /** Composite primary key definition (falls back to column.primary flags) */
300
+ primaryKey?: string[];
301
+ /** Secondary indexes */
302
+ indexes?: IndexDef[];
303
+ /** Table-level check constraints */
304
+ checks?: CheckConstraint[];
305
+ /** Table comment/description */
306
+ comment?: string;
307
+ /** Dialect-specific options */
308
+ engine?: string;
309
+ charset?: string;
310
+ collation?: string;
174
311
  }
175
312
  /**
176
313
  * Creates a table definition with columns and relationships
@@ -189,12 +326,12 @@ interface TableDef<T extends Record<string, ColumnDef> = Record<string, ColumnDe
189
326
  * });
190
327
  * ```
191
328
  */
192
- declare const defineTable: <T extends Record<string, ColumnDef>>(name: string, columns: T, relations?: Record<string, RelationDef>, hooks?: TableHooks) => TableDef<T>;
329
+ declare const defineTable: <T extends Record<string, ColumnDef>>(name: string, columns: T, relations?: Record<string, RelationDef>, hooks?: TableHooks, options?: TableOptions) => TableDef<T>;
193
330
 
194
331
  /**
195
332
  * Maps a ColumnDef to its TypeScript type representation
196
333
  */
197
- type ColumnToTs<T extends ColumnDef> = T['type'] extends 'INT' | 'INTEGER' | 'int' | 'integer' ? number : T['type'] extends 'BOOLEAN' | 'boolean' ? boolean : T['type'] extends 'JSON' | 'json' ? unknown : string;
334
+ type ColumnToTs<T extends ColumnDef> = T['type'] extends 'INT' | 'INTEGER' | 'int' | 'integer' ? number : T['type'] extends 'BIGINT' | 'bigint' ? number | bigint : T['type'] extends 'DECIMAL' | 'decimal' | 'FLOAT' | 'float' | 'DOUBLE' | 'double' ? number : T['type'] extends 'BOOLEAN' | 'boolean' ? boolean : T['type'] extends 'JSON' | 'json' ? unknown : T['type'] extends 'DATE' | 'date' | 'DATETIME' | 'datetime' | 'TIMESTAMP' | 'timestamp' | 'TIMESTAMPTZ' | 'timestamptz' ? string : string;
198
335
  /**
199
336
  * Infers a row shape from a table definition
200
337
  */
@@ -1519,4 +1656,4 @@ declare const createColumn: (table: string, name: string) => ColumnNode;
1519
1656
  */
1520
1657
  declare const createLiteral: (val: string | number) => LiteralNode;
1521
1658
 
1522
- export { createLiteral as $, RelationKinds as A, type BinaryExpressionNode as B, type ColumnDef as C, type DeleteQueryNode as D, type ExpressionNode as E, type FunctionNode as F, type RelationType as G, type HydrationPlan as H, type InExpressionNode as I, type JsonPathNode as J, type CascadeMode as K, type LogicalExpressionNode as L, type ManyToManyCollection as M, type NullExpressionNode as N, type OperandNode as O, type RelationDef as P, hasMany as Q, type RelationMap as R, type SelectQueryNode as S, type TableDef as T, type UpdateQueryNode as U, belongsTo as V, type WindowFunctionNode as W, belongsToMany as X, type ColumnToTs as Y, type InferRow as Z, createColumn as _, type ColumnNode as a, isOperandNode as a0, isFunctionNode as a1, isCaseExpressionNode as a2, isWindowFunctionNode as a3, isExpressionSelectionNode as a4, addDomainEvent as a5, EntityStatus as a6, type QueryResult as a7, type DbExecutor as a8, type RelationKey as a9, type RelationChange as aa, type HasDomainEvents as ab, type OrmInterceptor as ac, type DomainEventHandler as ad, type OrmContextOptions as ae, type LiteralNode as b, type BetweenExpressionNode as c, type CaseExpressionNode as d, type ExistsExpressionNode as e, type OrderDirection as f, type ScalarSubqueryNode as g, type InsertQueryNode as h, type InsertCompiler as i, type CompiledQuery as j, type UpdateCompiler as k, type DeleteCompiler as l, Dialect as m, type CompilerContext as n, OrmContext as o, type Entity as p, type HasManyRelation as q, type BelongsToRelation as r, type BelongsToManyRelation as s, type HasManyCollection as t, type BelongsToReference as u, SelectQueryBuilder as v, type TableHooks as w, defineTable as x, type ColumnType as y, col as z };
1659
+ export { type RelationType as $, type CheckConstraint as A, type BinaryExpressionNode as B, type ColumnDef as C, type DeleteQueryNode as D, type ExpressionNode as E, type FunctionNode as F, type TableOptions as G, type HydrationPlan as H, type InExpressionNode as I, type JsonPathNode as J, type TableHooks as K, type LogicalExpressionNode as L, type ManyToManyCollection as M, type NullExpressionNode as N, type OperandNode as O, defineTable as P, type ColumnType as Q, type RelationMap as R, type SelectQueryNode as S, type TableDef as T, type UpdateQueryNode as U, type ReferentialAction as V, type WindowFunctionNode as W, type RawDefaultValue as X, type DefaultValue as Y, col as Z, RelationKinds as _, type ColumnNode as a, type CascadeMode as a0, type RelationDef as a1, hasMany as a2, belongsTo as a3, belongsToMany as a4, type ColumnToTs as a5, type InferRow as a6, createColumn as a7, createLiteral as a8, isOperandNode as a9, isFunctionNode as aa, isCaseExpressionNode as ab, isWindowFunctionNode as ac, isExpressionSelectionNode as ad, addDomainEvent as ae, EntityStatus as af, type QueryResult as ag, type RelationKey as ah, type RelationChange as ai, type HasDomainEvents as aj, type OrmInterceptor as ak, type DomainEventHandler as al, type OrmContextOptions as am, type LiteralNode as b, type BetweenExpressionNode as c, type CaseExpressionNode as d, type ExistsExpressionNode as e, type OrderDirection as f, type ScalarSubqueryNode as g, type InsertQueryNode as h, type InsertCompiler as i, type CompiledQuery as j, type UpdateCompiler as k, type DeleteCompiler as l, Dialect as m, type CompilerContext as n, type ForeignKeyReference as o, type IndexColumn as p, type IndexDef as q, type DbExecutor as r, OrmContext as s, type Entity as t, type HasManyRelation as u, type BelongsToRelation as v, type BelongsToManyRelation as w, type HasManyCollection as x, type BelongsToReference as y, SelectQueryBuilder as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "metal-orm",
3
- "version": "1.0.11",
3
+ "version": "1.0.12",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -0,0 +1,48 @@
1
+ import { SchemaDialect, DialectName, formatLiteral, quoteQualified } from '../schema-generator.js';
2
+ import { ColumnDef, ForeignKeyReference } from '../../../schema/column.js';
3
+ import { IndexDef, TableDef } from '../../../schema/table.js';
4
+ import { DatabaseTable } from '../schema-types.js';
5
+
6
+ type TableLike = { name: string; schema?: string };
7
+
8
+ /**
9
+ * Common behavior for schema dialects (DDL).
10
+ * Concrete dialects only override the small surface area instead of reimplementing everything.
11
+ */
12
+ export abstract class BaseSchemaDialect implements SchemaDialect {
13
+ abstract name: DialectName;
14
+ abstract quoteIdentifier(id: string): string;
15
+ abstract renderColumnType(column: ColumnDef): string;
16
+ abstract renderAutoIncrement(column: ColumnDef, table: TableDef): string | undefined;
17
+ abstract renderIndex(table: TableDef, index: IndexDef): string;
18
+ supportsPartialIndexes(): boolean {
19
+ return false;
20
+ }
21
+ formatTableName(table: TableLike): string {
22
+ if (table.schema) {
23
+ return `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(table.name)}`;
24
+ }
25
+ return this.quoteIdentifier(table.name);
26
+ }
27
+ renderDefault(value: unknown, _column: ColumnDef): string {
28
+ return formatLiteral(value, this.name);
29
+ }
30
+ renderReference(ref: ForeignKeyReference, _table: TableDef): string {
31
+ const parts = ['REFERENCES', quoteQualified(this, ref.table), `(${this.quoteIdentifier(ref.column)})`];
32
+ if (ref.onDelete) parts.push('ON DELETE', ref.onDelete);
33
+ if (ref.onUpdate) parts.push('ON UPDATE', ref.onUpdate);
34
+ if (ref.deferrable && this.name === 'postgres') parts.push('DEFERRABLE INITIALLY DEFERRED');
35
+ return parts.join(' ');
36
+ }
37
+ renderTableOptions(_table: TableDef): string | undefined {
38
+ return undefined;
39
+ }
40
+ dropTableSql(table: DatabaseTable): string[] {
41
+ return [`DROP TABLE IF EXISTS ${this.formatTableName(table)};`];
42
+ }
43
+ abstract dropColumnSql(table: DatabaseTable, column: string): string[];
44
+ abstract dropIndexSql(table: DatabaseTable, index: string): string[];
45
+ warnDropColumn(_table: DatabaseTable, _column: string): string | undefined {
46
+ return undefined;
47
+ }
48
+ }
@@ -0,0 +1,5 @@
1
+ export { BaseSchemaDialect } from './base-schema-dialect.js';
2
+ export { PostgresSchemaDialect } from './postgres-schema-dialect.js';
3
+ export { MySqlSchemaDialect } from './mysql-schema-dialect.js';
4
+ export { SQLiteSchemaDialect } from './sqlite-schema-dialect.js';
5
+ export { MSSqlSchemaDialect } from './mssql-schema-dialect.js';
@@ -0,0 +1,97 @@
1
+ import { BaseSchemaDialect } from './base-schema-dialect.js';
2
+ import {
3
+ deriveIndexName,
4
+ renderIndexColumns,
5
+ DialectName,
6
+ formatLiteral
7
+ } from '../schema-generator.js';
8
+ import { ColumnDef } from '../../../schema/column.js';
9
+ import { IndexDef, TableDef } from '../../../schema/table.js';
10
+ import { DatabaseTable } from '../schema-types.js';
11
+
12
+ export class MSSqlSchemaDialect extends BaseSchemaDialect {
13
+ name: DialectName = 'mssql';
14
+
15
+ quoteIdentifier(id: string): string {
16
+ return `[${id.replace(/]/g, ']]')}]`;
17
+ }
18
+
19
+ renderColumnType(column: ColumnDef): string {
20
+ switch (column.type) {
21
+ case 'INT':
22
+ case 'INTEGER':
23
+ case 'int':
24
+ case 'integer':
25
+ return 'INT';
26
+ case 'BIGINT':
27
+ case 'bigint':
28
+ return 'BIGINT';
29
+ case 'UUID':
30
+ case 'uuid':
31
+ return 'UNIQUEIDENTIFIER';
32
+ case 'BOOLEAN':
33
+ case 'boolean':
34
+ return 'BIT';
35
+ case 'JSON':
36
+ case 'json':
37
+ return 'NVARCHAR(MAX)';
38
+ case 'DECIMAL':
39
+ case 'decimal':
40
+ return column.args?.length ? `DECIMAL(${column.args[0]},${column.args[1] ?? 0})` : 'DECIMAL(18,0)';
41
+ case 'FLOAT':
42
+ case 'float':
43
+ case 'DOUBLE':
44
+ case 'double':
45
+ return 'FLOAT';
46
+ case 'TIMESTAMPTZ':
47
+ case 'timestamptz':
48
+ case 'TIMESTAMP':
49
+ case 'timestamp':
50
+ case 'DATETIME':
51
+ case 'datetime':
52
+ return 'DATETIME2';
53
+ case 'DATE':
54
+ case 'date':
55
+ return 'DATE';
56
+ case 'VARCHAR':
57
+ case 'varchar':
58
+ return column.args?.length ? `NVARCHAR(${column.args[0]})` : 'NVARCHAR(255)';
59
+ case 'TEXT':
60
+ case 'text':
61
+ return 'NVARCHAR(MAX)';
62
+ case 'ENUM':
63
+ case 'enum':
64
+ return 'NVARCHAR(255)';
65
+ default:
66
+ return String(column.type).toUpperCase();
67
+ }
68
+ }
69
+
70
+ renderDefault(value: unknown): string {
71
+ return formatLiteral(value, this.name);
72
+ }
73
+
74
+ renderAutoIncrement(column: ColumnDef): string | undefined {
75
+ return column.autoIncrement ? 'IDENTITY(1,1)' : undefined;
76
+ }
77
+
78
+ renderIndex(table: TableDef, index: IndexDef): string {
79
+ const name = index.name || deriveIndexName(table, index);
80
+ const cols = renderIndexColumns(this, index.columns);
81
+ const unique = index.unique ? 'UNIQUE ' : '';
82
+ const where = index.where ? ` WHERE ${index.where}` : '';
83
+ return `CREATE ${unique}INDEX ${this.quoteIdentifier(name)} ON ${this.formatTableName(table)} (${cols})${where};`;
84
+ }
85
+
86
+ supportsPartialIndexes(): boolean {
87
+ return true;
88
+ }
89
+
90
+ dropColumnSql(table: DatabaseTable, column: string): string[] {
91
+ return [`ALTER TABLE ${this.formatTableName(table)} DROP COLUMN ${this.quoteIdentifier(column)};`];
92
+ }
93
+
94
+ dropIndexSql(table: DatabaseTable, index: string): string[] {
95
+ return [`DROP INDEX ${this.quoteIdentifier(index)} ON ${this.formatTableName(table)};`];
96
+ }
97
+ }