uql-orm 0.66.0 → 0.67.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.
Files changed (193) hide show
  1. package/dist/browser/querier/httpQuerier.js +1 -8
  2. package/dist/browser/uql-browser.min.js.map +5 -5
  3. package/dist/bunSql/bunSql.util.d.ts +2 -6
  4. package/dist/bunSql/bunSql.util.js +2 -6
  5. package/dist/bunSql/bunSqlQuerier.d.ts +2 -5
  6. package/dist/bunSql/bunSqlQuerier.js +2 -5
  7. package/dist/cockroachdb/cockroachDialect.d.ts +4 -13
  8. package/dist/cockroachdb/cockroachDialect.js +4 -13
  9. package/dist/context/context.browser.js +2 -10
  10. package/dist/context/context.d.ts +4 -17
  11. package/dist/context/context.js +4 -17
  12. package/dist/dialect/abstractDialect.d.ts +4 -19
  13. package/dist/dialect/abstractDialect.js +2 -20
  14. package/dist/dialect/abstractSqlDialect.d.ts +47 -212
  15. package/dist/dialect/abstractSqlDialect.js +68 -222
  16. package/dist/dialect/aliases.d.ts +2 -12
  17. package/dist/dialect/aliases.js +4 -12
  18. package/dist/dialect/hydrateColumn.d.ts +2 -6
  19. package/dist/dialect/hydrateColumn.js +3 -13
  20. package/dist/dialect/jsonArrayElemMatchUtils.d.ts +1 -7
  21. package/dist/dialect/jsonArrayElemMatchUtils.js +1 -7
  22. package/dist/dialect/jsonSql.d.ts +6 -27
  23. package/dist/dialect/jsonSql.js +6 -27
  24. package/dist/dialect/mergeSqlDialect.d.ts +4 -22
  25. package/dist/dialect/mergeSqlDialect.js +4 -22
  26. package/dist/dialect/mysqlLikeSqlDialect.d.ts +11 -37
  27. package/dist/dialect/mysqlLikeSqlDialect.js +35 -51
  28. package/dist/dialect/pgLikeSqlDialect.d.ts +8 -22
  29. package/dist/dialect/pgLikeSqlDialect.js +36 -39
  30. package/dist/dialect/queryContext.d.ts +4 -22
  31. package/dist/dialect/queryContext.js +4 -22
  32. package/dist/dialect/queryJoins.d.ts +3 -12
  33. package/dist/dialect/queryJoins.js +3 -12
  34. package/dist/dialect/vectorCast.d.ts +2 -12
  35. package/dist/dialect/vectorCast.js +3 -19
  36. package/dist/dialect/vectorSqlDialect.d.ts +8 -38
  37. package/dist/dialect/vectorSqlDialect.js +7 -38
  38. package/dist/entity/decorator/bag.d.ts +6 -19
  39. package/dist/entity/decorator/bag.js +6 -22
  40. package/dist/entity/decorator/entity.d.ts +2 -7
  41. package/dist/entity/decorator/entity.js +2 -7
  42. package/dist/entity/decorator/members.d.ts +7 -30
  43. package/dist/entity/decorator/members.js +3 -12
  44. package/dist/entity/metadata/definition.d.ts +2 -18
  45. package/dist/entity/metadata/definition.js +6 -28
  46. package/dist/http/handler.d.ts +2 -14
  47. package/dist/index.d.ts +3 -1
  48. package/dist/index.js +3 -1
  49. package/dist/libsql/libsqlDialect.d.ts +1 -8
  50. package/dist/libsql/libsqlDialect.js +1 -8
  51. package/dist/maria/mariaDialect.d.ts +3 -5
  52. package/dist/maria/mariaDialect.js +5 -5
  53. package/dist/maria/mariadbQuerier.js +2 -2
  54. package/dist/maria/mariadbQuerierPool.js +1 -6
  55. package/dist/migrate/builder/migrationBuilder.js +3 -19
  56. package/dist/migrate/builder/splitSqlStatements.d.ts +1 -14
  57. package/dist/migrate/builder/splitSqlStatements.js +2 -22
  58. package/dist/migrate/builder/types.d.ts +2 -15
  59. package/dist/migrate/cli-config.js +2 -11
  60. package/dist/migrate/cli.js +2 -7
  61. package/dist/migrate/codegen/entityCodeGenerator.d.ts +0 -15
  62. package/dist/migrate/codegen/entityCodeGenerator.js +15 -44
  63. package/dist/migrate/codegen/fieldOptionsSource.d.ts +1 -8
  64. package/dist/migrate/codegen/fieldOptionsSource.js +3 -22
  65. package/dist/migrate/ddl/indexDdl.d.ts +2 -5
  66. package/dist/migrate/ddl/indexDdl.js +2 -5
  67. package/dist/migrate/ddl/pgIndexDdl.d.ts +3 -13
  68. package/dist/migrate/ddl/pgIndexDdl.js +3 -13
  69. package/dist/migrate/generator/definitionToNode.d.ts +2 -9
  70. package/dist/migrate/generator/definitionToNode.js +3 -17
  71. package/dist/migrate/generator/indexNodeToSchema.d.ts +2 -3
  72. package/dist/migrate/generator/indexNodeToSchema.js +2 -3
  73. package/dist/migrate/generator/mongoCommand.d.ts +1 -8
  74. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +1 -8
  75. package/dist/migrate/generator/mongoSchemaGenerator.js +1 -8
  76. package/dist/migrate/introspection/abstractSqlSchemaIntrospector.d.ts +6 -26
  77. package/dist/migrate/introspection/abstractSqlSchemaIntrospector.js +9 -41
  78. package/dist/migrate/introspection/baseSqlIntrospector.js +0 -1
  79. package/dist/migrate/introspection/mongoIntrospector.d.ts +3 -1
  80. package/dist/migrate/introspection/mongoIntrospector.js +48 -46
  81. package/dist/migrate/introspection/mssqlIntrospector.d.ts +4 -4
  82. package/dist/migrate/introspection/mssqlIntrospector.js +18 -27
  83. package/dist/migrate/introspection/mysqlIntrospector.d.ts +7 -2
  84. package/dist/migrate/introspection/mysqlIntrospector.js +16 -14
  85. package/dist/migrate/introspection/postgresIntrospector.d.ts +24 -9
  86. package/dist/migrate/introspection/postgresIntrospector.js +68 -59
  87. package/dist/migrate/introspection/sqliteIntrospector.d.ts +1 -1
  88. package/dist/migrate/introspection/sqliteIntrospector.js +8 -10
  89. package/dist/migrate/migrator.d.ts +9 -53
  90. package/dist/migrate/migrator.js +32 -65
  91. package/dist/migrate/schemaGenerator.d.ts +16 -66
  92. package/dist/migrate/schemaGenerator.js +21 -74
  93. package/dist/mongo/mongoDialect.d.ts +21 -53
  94. package/dist/mongo/mongoDialect.js +25 -70
  95. package/dist/mongo/mongodbQuerier.d.ts +5 -8
  96. package/dist/mongo/mongodbQuerier.js +31 -65
  97. package/dist/mssql/mssqlDialect.d.ts +8 -34
  98. package/dist/mssql/mssqlDialect.js +37 -51
  99. package/dist/mssql/mssqlQuerier.d.ts +37 -4
  100. package/dist/mssql/mssqlQuerier.js +2 -2
  101. package/dist/mssql/mssqlWireTypes.d.ts +2 -14
  102. package/dist/mssql/mssqlWireTypes.js +2 -14
  103. package/dist/nestjs/uqlModule.js +2 -7
  104. package/dist/pglite/pgliteQuerier.d.ts +1 -9
  105. package/dist/pglite/pgliteQuerierPool.d.ts +4 -26
  106. package/dist/pglite/pgliteQuerierPool.js +3 -18
  107. package/dist/postgres/abstractPgQuerierPool.d.ts +1 -8
  108. package/dist/postgres/abstractPgQuerierPool.js +1 -8
  109. package/dist/postgres/pgNumericTypes.d.ts +3 -26
  110. package/dist/postgres/pgNumericTypes.js +3 -26
  111. package/dist/postgres/postgresDialect.d.ts +4 -10
  112. package/dist/postgres/postgresDialect.js +4 -10
  113. package/dist/querier/abstractQuerier.d.ts +35 -103
  114. package/dist/querier/abstractQuerier.js +105 -201
  115. package/dist/querier/abstractSharedHandleQuerierPool.d.ts +3 -17
  116. package/dist/querier/abstractSharedHandleQuerierPool.js +3 -17
  117. package/dist/querier/abstractSqlQuerier.d.ts +15 -36
  118. package/dist/querier/abstractSqlQuerier.js +49 -131
  119. package/dist/schema/canonicalType.d.ts +3 -21
  120. package/dist/schema/canonicalType.js +22 -67
  121. package/dist/schema/dependencyGraph.d.ts +2 -8
  122. package/dist/schema/dependencyGraph.js +2 -32
  123. package/dist/schema/index.d.ts +1 -25
  124. package/dist/schema/index.js +0 -26
  125. package/dist/schema/indexColumns.d.ts +1 -8
  126. package/dist/schema/indexColumns.js +1 -8
  127. package/dist/schema/indexDifferences.d.ts +7 -40
  128. package/dist/schema/indexDifferences.js +6 -31
  129. package/dist/schema/schemaAST.d.ts +8 -175
  130. package/dist/schema/schemaAST.js +13 -365
  131. package/dist/schema/schemaASTBuilder.d.ts +2 -24
  132. package/dist/schema/schemaASTBuilder.js +2 -30
  133. package/dist/schema/schemaASTDiffer.d.ts +6 -46
  134. package/dist/schema/schemaASTDiffer.js +8 -56
  135. package/dist/schema/types.d.ts +5 -61
  136. package/dist/schema/types.js +3 -6
  137. package/dist/sqlite/abstractSqliteQuerier.d.ts +1 -8
  138. package/dist/sqlite/localSqliteQuerierPool.d.ts +1 -7
  139. package/dist/sqlite/localSqliteQuerierPool.js +1 -7
  140. package/dist/sqlite/nodeSqliteQuerierPool.d.ts +2 -7
  141. package/dist/sqlite/nodeSqliteQuerierPool.js +2 -7
  142. package/dist/sqlite/sqliteDialect.d.ts +5 -20
  143. package/dist/sqlite/sqliteDialect.js +29 -35
  144. package/dist/turso/tursoDialect.d.ts +4 -6
  145. package/dist/turso/tursoDialect.js +4 -6
  146. package/dist/turso/tursoLocalQuerierPool.d.ts +1 -7
  147. package/dist/turso/tursoLocalQuerierPool.js +1 -7
  148. package/dist/turso/tursoQuerierPool.d.ts +2 -6
  149. package/dist/turso/tursoQuerierPool.js +2 -6
  150. package/dist/turso/tursoSessionQuerier.d.ts +1 -7
  151. package/dist/turso/tursoSessionQuerier.js +1 -7
  152. package/dist/type/dialect.d.ts +42 -94
  153. package/dist/type/dialect.js +3 -13
  154. package/dist/type/entity.d.ts +163 -534
  155. package/dist/type/entity.js +26 -9
  156. package/dist/type/logger.d.ts +2 -14
  157. package/dist/type/migration.d.ts +9 -38
  158. package/dist/type/querier.d.ts +9 -28
  159. package/dist/type/querierPool.d.ts +4 -26
  160. package/dist/type/query.d.ts +19 -73
  161. package/dist/type/query.js +2 -7
  162. package/dist/type/queryAggregate.d.ts +18 -98
  163. package/dist/type/queryRaw.d.ts +1 -8
  164. package/dist/type/queryRaw.js +1 -8
  165. package/dist/type/queryWhere.d.ts +13 -61
  166. package/dist/type/universalQuerier.d.ts +18 -105
  167. package/dist/type/utility.d.ts +12 -24
  168. package/dist/type/vector.d.ts +8 -38
  169. package/dist/type/vector.js +1 -1
  170. package/dist/type/wire.d.ts +2 -5
  171. package/dist/util/dialect.util.d.ts +9 -27
  172. package/dist/util/dialect.util.js +10 -27
  173. package/dist/util/field.util.d.ts +2 -31
  174. package/dist/util/field.util.js +3 -43
  175. package/dist/util/fieldOption.util.d.ts +7 -15
  176. package/dist/util/fieldOption.util.js +1 -1
  177. package/dist/util/filters.util.d.ts +2 -5
  178. package/dist/util/filters.util.js +2 -5
  179. package/dist/util/logger.d.ts +2 -6
  180. package/dist/util/logger.js +2 -6
  181. package/dist/util/object.util.d.ts +2 -6
  182. package/dist/util/object.util.js +1 -5
  183. package/dist/util/raw.d.ts +3 -23
  184. package/dist/util/relationQuery.util.d.ts +3 -14
  185. package/dist/util/relationQuery.util.js +3 -14
  186. package/dist/util/rowKey.util.d.ts +2 -10
  187. package/dist/util/rowKey.util.js +2 -10
  188. package/dist/util/sql.util.d.ts +6 -37
  189. package/dist/util/sql.util.js +13 -73
  190. package/dist/util/sqlLiteral.d.ts +2 -13
  191. package/dist/util/sqlLiteral.js +8 -13
  192. package/dist/util/string.util.js +0 -2
  193. package/package.json +4 -4
@@ -1,16 +1,6 @@
1
- /**
2
- * SchemaAST Class
3
- *
4
- * The main class for working with schema graphs.
5
- * Provides graph operations like navigation, validation, and topological sorting.
6
- */
7
1
  import { qualifyName } from '../util/sql.util.js';
8
- import { createOrder, dropOrder, findCycles } from './dependencyGraph.js';
9
- /**
10
- * A table node with its collections empty, ready to be filled. Six places build one, and the fields
11
- * that are pure boilerplate are exactly the ones a new field gets forgotten in: {@link TableNode.schema}
12
- * was added and `SchemaAST.clone` kept rebuilding nodes without it.
13
- */
2
+ import { createOrder, dropOrder } from './dependencyGraph.js';
3
+ /** A table node with its collections empty, ready to be filled. */
14
4
  export function createTableNode(name, schema, comment) {
15
5
  return {
16
6
  name,
@@ -24,264 +14,40 @@ export function createTableNode(name, schema, comment) {
24
14
  outgoingRelations: [],
25
15
  };
26
16
  }
27
- /**
28
- * Schema AST - A graph representation of a database schema.
29
- *
30
- * Enables:
31
- * - Graph navigation (dependencies, dependents)
32
- * - Circular dependency detection
33
- * - Topological sorting for correct DDL order
34
- * - Smart relation inference
35
- * - Schema validation
36
- */
17
+ /** A database schema as a graph: tables, the foreign keys between them, and their indexes. */
37
18
  export class SchemaAST {
38
19
  tables = new Map();
39
20
  relationships = [];
40
21
  indexes = [];
41
- /**
42
- * Get a table by the name it is keyed under: schema-qualified where it has one, so two tables of
43
- * the same name in different schemas stay distinct. Build the key with `qualifyName`.
44
- */
22
+ /** A table by the key it is stored under: schema-qualified where it has one (see `qualifyName`). */
45
23
  getTable(name) {
46
24
  return this.tables.get(name);
47
25
  }
48
- /**
49
- * Add a table to the schema.
50
- */
51
26
  addTable(table) {
52
27
  this.tables.set(qualifyName(table.name, table.schema), table);
53
28
  }
54
- /**
55
- * Remove a table from the schema.
56
- */
57
- removeTable(name) {
58
- const table = this.tables.get(name);
59
- if (!table)
60
- return false;
61
- // Remove all relationships involving this table
62
- for (let i = this.relationships.length - 1; i >= 0; i--) {
63
- const rel = this.relationships[i];
64
- if (rel.from.table === table || rel.to.table === table) {
65
- this.relationships.splice(i, 1);
66
- }
67
- }
68
- // Remove all indexes for this table
69
- for (let i = this.indexes.length - 1; i >= 0; i--) {
70
- if (this.indexes[i].table === table) {
71
- this.indexes.splice(i, 1);
72
- }
73
- }
74
- return this.tables.delete(name);
75
- }
76
- /**
77
- * Get all table nodes.
78
- */
79
29
  getTables() {
80
- return Array.from(this.tables.values());
81
- }
82
- /**
83
- * Get all table names.
84
- */
85
- getTableNames() {
86
- return Array.from(this.tables.keys());
87
- }
88
- /**
89
- * Get all tables that depend on this table (have FKs pointing to it).
90
- * These are tables that reference this table's primary key.
91
- */
92
- getDependentTables(table) {
93
- return table.incomingRelations.map((r) => r.from.table);
94
- }
95
- /**
96
- * Get all tables this table depends on (has FKs to).
97
- * These are tables that this table references.
98
- */
99
- getDependencies(table) {
100
- return table.outgoingRelations.map((r) => r.to.table);
101
- }
102
- /**
103
- * Get the relationship between two tables (if any).
104
- */
105
- getRelationship(from, to) {
106
- return this.relationships.find((r) => r.from.table === from && r.to.table === to);
107
- }
108
- /**
109
- * Get all relationships for a table.
110
- */
111
- getTableRelationships(table) {
112
- return this.relationships.filter((r) => r.from.table === table || r.to.table === table);
113
- }
114
- /**
115
- * Get the column that a foreign key column references.
116
- */
117
- getReferencedColumn(fkColumn) {
118
- return fkColumn.references?.to.columns[0];
119
- }
120
- /**
121
- * Detect circular foreign key dependencies.
122
- * Returns arrays of tables that form cycles.
123
- */
124
- detectCircularDependencies() {
125
- return findCycles(this.tables.values(), (table) => this.getDependencies(table));
30
+ return [...this.tables.values()];
126
31
  }
127
- /**
128
- * Check if there are any circular dependencies.
129
- */
130
- hasCircularDependencies() {
131
- return this.detectCircularDependencies().length > 0;
132
- }
133
- /**
134
- * Get tables in correct order for CREATE (dependencies first).
135
- * Tables with no dependencies come first, then tables that depend on them, etc.
136
- */
32
+ /** Tables in `CREATE` order, each after the tables it references. */
137
33
  getCreateOrder() {
138
- return createOrder(this.tables.values(), (table) => this.getDependencies(table));
34
+ return createOrder(this.tables.values(), referencedTables);
139
35
  }
140
- /**
141
- * Get tables in correct order for DROP (dependents first).
142
- * Tables that depend on others come first, then the tables they depend on.
143
- */
36
+ /** Tables in `DROP` order, each before the tables it references. */
144
37
  getDropOrder() {
145
- return dropOrder(this.tables.values(), (table) => this.getDependencies(table));
146
- }
147
- /**
148
- * Validate schema integrity.
149
- * Checks for:
150
- * - Missing FK targets
151
- * - Circular dependencies
152
- * - Orphan columns
153
- * - Duplicate indexes
154
- */
155
- validate() {
156
- const errors = [];
157
- // Check all FK targets exist
158
- for (const rel of this.relationships) {
159
- if (!this.tables.has(rel.to.table.name)) {
160
- errors.push({
161
- type: 'missing_fk_target',
162
- message: `FK target table "${rel.to.table.name}" does not exist`,
163
- relationship: rel,
164
- });
165
- }
166
- }
167
- // Check for circular dependencies
168
- const cycles = this.detectCircularDependencies();
169
- for (const cycle of cycles) {
170
- errors.push({
171
- type: 'circular_dependency',
172
- message: `Circular FK: ${cycle.map((t) => t.name).join(' -> ')}`,
173
- tables: cycle,
174
- });
175
- }
176
- // Check for duplicate index names within same table
177
- for (const table of this.tables.values()) {
178
- const indexNames = new Set();
179
- for (const index of table.indexes) {
180
- if (indexNames.has(index.name)) {
181
- errors.push({
182
- type: 'duplicate_index',
183
- message: `Duplicate index name "${index.name}" in table "${table.name}"`,
184
- table,
185
- });
186
- }
187
- indexNames.add(index.name);
188
- }
189
- }
190
- return errors;
38
+ return dropOrder(this.tables.values(), referencedTables);
191
39
  }
192
- /**
193
- * Check if the schema is valid (no validation errors).
194
- */
195
- isValid() {
196
- return this.validate().length === 0;
197
- }
198
- /**
199
- * Check if a table looks like a junction table (ManyToMany through).
200
- * Junction tables typically have:
201
- * - Exactly 2 foreign keys
202
- * - Few other columns (id, maybe timestamps)
203
- * - Primary key might be composite of the FKs
204
- */
205
- isJunctionTable(table) {
206
- const fkCount = table.outgoingRelations.length;
207
- const columnCount = table.columns.size;
208
- // Must have exactly 2 FKs
209
- if (fkCount !== 2) {
210
- return false;
211
- }
212
- // Should have few columns (typically: id + 2 FKs + maybe timestamps)
213
- if (columnCount > 6) {
214
- return false;
215
- }
216
- // Check if name suggests a junction (contains both related table names)
217
- const relatedTables = table.outgoingRelations.map((r) => r.to.table.name.toLowerCase());
218
- const tableName = table.name.toLowerCase();
219
- // Common patterns: user_roles, post_tags, etc.
220
- const containsBothNames = relatedTables.every((name) => tableName.includes(name.replace(/s$/, '')) || tableName.includes(name));
221
- return containsBothNames || columnCount <= 5;
222
- }
223
- /**
224
- * Infer relation type from schema structure.
225
- */
226
- inferRelationType(rel) {
227
- const fromCol = rel.from.columns[0];
228
- // Check if source is junction table -> ManyToMany
229
- if (this.isJunctionTable(rel.from.table)) {
230
- return 'ManyToMany';
231
- }
232
- // Unique FK -> OneToOne
233
- if (fromCol?.isUnique) {
234
- return 'OneToOne';
235
- }
236
- // Default: ManyToOne (many rows can reference same target)
237
- return 'ManyToOne';
238
- }
239
- /**
240
- * Get the inverse relation type.
241
- */
242
- getInverseRelationType(type) {
243
- switch (type) {
244
- case 'OneToOne':
245
- return 'OneToOne';
246
- case 'OneToMany':
247
- return 'ManyToOne';
248
- case 'ManyToOne':
249
- return 'OneToMany';
250
- case 'ManyToMany':
251
- return 'ManyToMany';
252
- }
253
- }
254
- /**
255
- * Add an index to the schema.
256
- */
257
40
  addIndex(index) {
258
41
  this.indexes.push(index);
259
42
  if (!index.table.indexes.includes(index)) {
260
43
  index.table.indexes.push(index);
261
44
  }
262
45
  }
263
- /**
264
- * Get all indexes for a table.
265
- */
266
- getTableIndexes(tableName) {
267
- const table = this.tables.get(tableName);
268
- return table?.indexes ?? [];
269
- }
270
- /**
271
- * Find an index by name.
272
- */
273
- getIndex(name) {
274
- return this.indexes.find((i) => i.name === name);
275
- }
276
- /**
277
- * Add a relationship to the schema.
278
- */
46
+ /** Adds a foreign key, linking it from both tables and both column sets. */
279
47
  addRelationship(rel) {
280
48
  this.relationships.push(rel);
281
- // Update table links
282
49
  rel.from.table.outgoingRelations.push(rel);
283
50
  rel.to.table.incomingRelations.push(rel);
284
- // Update column links
285
51
  for (const col of rel.from.columns) {
286
52
  col.references = rel;
287
53
  }
@@ -289,125 +55,7 @@ export class SchemaAST {
289
55
  col.referencedBy.push(rel);
290
56
  }
291
57
  }
292
- /**
293
- * Remove a relationship from the schema.
294
- */
295
- removeRelationship(name) {
296
- const index = this.relationships.findIndex((r) => r.name === name);
297
- if (index === -1)
298
- return false;
299
- const rel = this.relationships[index];
300
- // Remove from table links
301
- const fromIdx = rel.from.table.outgoingRelations.indexOf(rel);
302
- if (fromIdx !== -1)
303
- rel.from.table.outgoingRelations.splice(fromIdx, 1);
304
- const toIdx = rel.to.table.incomingRelations.indexOf(rel);
305
- if (toIdx !== -1)
306
- rel.to.table.incomingRelations.splice(toIdx, 1);
307
- // Remove from column links
308
- for (const col of rel.from.columns) {
309
- if (col.references === rel) {
310
- col.references = undefined;
311
- }
312
- }
313
- for (const col of rel.to.columns) {
314
- const refIdx = col.referencedBy.indexOf(rel);
315
- if (refIdx !== -1)
316
- col.referencedBy.splice(refIdx, 1);
317
- }
318
- this.relationships.splice(index, 1);
319
- return true;
320
- }
321
- /**
322
- * Create a deep clone of this schema.
323
- */
324
- clone() {
325
- const clone = new SchemaAST();
326
- // First pass: tables and columns. The table is built before its columns so each clone can link
327
- // back to it on creation - `columns` and `primaryKey` are readonly properties holding mutable
328
- // containers, so they are filled in afterwards without reassigning anything.
329
- for (const [name, table] of this.tables) {
330
- const clonedTable = createTableNode(table.name, table.schema, table.comment);
331
- for (const [colName, col] of table.columns) {
332
- clonedTable.columns.set(colName, { ...col, table: clonedTable, referencedBy: [], references: undefined });
333
- }
334
- clonedTable.primaryKey.push(...table.primaryKey.flatMap((pk) => clonedTable.columns.get(pk.name) ?? []));
335
- clone.tables.set(name, clonedTable);
336
- }
337
- // Second pass: clone relationships
338
- for (const rel of this.relationships) {
339
- const fromTable = clone.tables.get(rel.from.table.name);
340
- const toTable = clone.tables.get(rel.to.table.name);
341
- if (!fromTable || !toTable)
342
- continue;
343
- const fromColumns = rel.from.columns
344
- .map((c) => fromTable.columns.get(c.name))
345
- .filter((c) => c !== undefined);
346
- const toColumns = rel.to.columns
347
- .map((c) => toTable.columns.get(c.name))
348
- .filter((c) => c !== undefined);
349
- const clonedRel = {
350
- ...rel,
351
- from: {
352
- table: fromTable,
353
- columns: fromColumns,
354
- },
355
- to: {
356
- table: toTable,
357
- columns: toColumns,
358
- },
359
- through: rel.through ? clone.tables.get(rel.through.name) : undefined,
360
- };
361
- clone.addRelationship(clonedRel);
362
- }
363
- // Third pass: clone indexes
364
- for (const idx of this.indexes) {
365
- const table = clone.tables.get(idx.table.name);
366
- if (!table)
367
- continue;
368
- clone.addIndex({ ...idx, table });
369
- }
370
- return clone;
371
- }
372
- /**
373
- * Get statistics about the schema.
374
- */
375
- getStats() {
376
- let columnCount = 0;
377
- for (const table of this.tables.values()) {
378
- columnCount += table.columns.size;
379
- }
380
- return {
381
- tableCount: this.tables.size,
382
- columnCount,
383
- relationshipCount: this.relationships.length,
384
- indexCount: this.indexes.length,
385
- };
386
- }
387
- /**
388
- * The schema as a plain object, for serialization and debugging. The graph links are what is left
389
- * out - they are cycles, and nothing else is: listing the fields to keep instead dropped every
390
- * option a column had gained since, `defaultValue` and `enum` included.
391
- */
392
- toJSON() {
393
- return {
394
- tables: Array.from(this.tables.values()).map((t) => ({
395
- name: t.name,
396
- columns: Array.from(t.columns.values()).map(({ table: _table, referencedBy: _referencedBy, references: _references, ...column }) => column),
397
- indexes: t.indexes.map((i) => ({
398
- name: i.name,
399
- columns: i.entries.map((entry) => entry.column),
400
- unique: i.unique,
401
- })),
402
- })),
403
- relationships: this.relationships.map((r) => ({
404
- name: r.name,
405
- type: r.type,
406
- from: `${r.from.table.name}.${r.from.columns.map((c) => c.name).join(',')}`,
407
- to: `${r.to.table.name}.${r.to.columns.map((c) => c.name).join(',')}`,
408
- onDelete: r.onDelete,
409
- onUpdate: r.onUpdate,
410
- })),
411
- };
412
- }
58
+ }
59
+ function referencedTables(table) {
60
+ return table.outgoingRelations.map((rel) => rel.to.table);
413
61
  }
@@ -1,10 +1,3 @@
1
- /**
2
- * SchemaAST Builder
3
- *
4
- * Constructs a SchemaAST from:
5
- * - Entity metadata (decorator-based entities)
6
- * - Database introspection results (TableSchema[])
7
- */
8
1
  import type { EntityGetter } from '../type/entity.js';
9
2
  import type { EntityMeta, EntityWhereMeta, FieldMeta, FieldOptions, Type } from '../type/index.js';
10
3
  import type { NamingStrategy } from '../type/namingStrategy.js';
@@ -40,22 +33,7 @@ export interface BuildSchemaASTOptions {
40
33
  */
41
34
  export declare function buildSchemaAST(entities: readonly Type<object>[], options?: BuildSchemaASTOptions): SchemaAST;
42
35
  /**
43
- * Resolve the canonical type for a field, inheriting from the referenced
44
- * entity's primary key when the field is a foreign-key reference
45
- * (`@Field({ references: () => SomeEntity })`) with no explicit type of its
46
- * own.
47
- *
48
- * Without this, a field like `creatorId?: UUID` (a bare TypeScript alias for
49
- * `string`, erased at runtime) falls back to the generic string inference in
50
- * {@link fieldOptionsToCanonical} and gets typed as TEXT/VARCHAR - producing a
51
- * foreign key column whose type doesn't match the UUID primary key it
52
- * references, which Postgres (and most databases) reject outright.
53
- *
54
- * `field.typeFromReference` (set by `defineField`, see entity/metadata/definition.ts)
55
- * is what distinguishes "no type was given" from "the decorator explicitly set
56
- * a type" - including explicit constructor overrides like `type: BigInt`, which
57
- * a value-based check (e.g. `typeof field.type === 'string'`) would miss since
58
- * reflection also produces constructor values like `String`/`Number`.
59
- * `columnType` remains the unambiguous, always-respected explicit override.
36
+ * A field's canonical type, taken from the referenced key where the field gave `references` and no
37
+ * `type` (`typeFromReference`), so a foreign key matches the key it points at; `columnType` always wins.
60
38
  */
61
39
  export declare function resolveColumnCanonicalType(field: FieldMeta, seen?: Set<EntityGetter>): CanonicalType;
@@ -1,10 +1,3 @@
1
- /**
2
- * SchemaAST Builder
3
- *
4
- * Constructs a SchemaAST from:
5
- * - Entity metadata (decorator-based entities)
6
- * - Database introspection results (TableSchema[])
7
- */
8
1
  import { fieldOf, foreignKeysOf, getMeta, soleIdOf } from '../entity/metadata/definition.js';
9
2
  import { declaredIndexes, indexNameParts, renderIndexColumn } from '../util/ddlExpression.util.js';
10
3
  import { isInlinedExpression } from '../util/field.util.js';
@@ -46,23 +39,8 @@ function refuseDdl() {
46
39
  throw new TypeError('building the schema of an entity that declares SQL (a check, a stored computed column, an index expression or predicate) needs a dialect to render it: pass `compileDdl`, as `buildEntityAST` does');
47
40
  }
48
41
  /**
49
- * Resolve the canonical type for a field, inheriting from the referenced
50
- * entity's primary key when the field is a foreign-key reference
51
- * (`@Field({ references: () => SomeEntity })`) with no explicit type of its
52
- * own.
53
- *
54
- * Without this, a field like `creatorId?: UUID` (a bare TypeScript alias for
55
- * `string`, erased at runtime) falls back to the generic string inference in
56
- * {@link fieldOptionsToCanonical} and gets typed as TEXT/VARCHAR - producing a
57
- * foreign key column whose type doesn't match the UUID primary key it
58
- * references, which Postgres (and most databases) reject outright.
59
- *
60
- * `field.typeFromReference` (set by `defineField`, see entity/metadata/definition.ts)
61
- * is what distinguishes "no type was given" from "the decorator explicitly set
62
- * a type" - including explicit constructor overrides like `type: BigInt`, which
63
- * a value-based check (e.g. `typeof field.type === 'string'`) would miss since
64
- * reflection also produces constructor values like `String`/`Number`.
65
- * `columnType` remains the unambiguous, always-respected explicit override.
42
+ * A field's canonical type, taken from the referenced key where the field gave `references` and no
43
+ * `type` (`typeFromReference`), so a foreign key matches the key it points at; `columnType` always wins.
66
44
  */
67
45
  export function resolveColumnCanonicalType(field, seen = new Set()) {
68
46
  const hasExplicitType = !!field.columnType || !field.typeFromReference;
@@ -156,8 +134,6 @@ function addRelationshipsFromEntity(ctx, meta) {
156
134
  // references, onDelete })` work with no relation declared at all.
157
135
  onDelete: foreignKey.onDelete ?? meta.fields[foreignKey.references[0].local]?.onDelete ?? ctx.defaultForeignKeyAction,
158
136
  onUpdate: foreignKey.onUpdate ?? ctx.defaultForeignKeyAction,
159
- confidence: 1.0,
160
- inferredFrom: 'entity_decorator',
161
137
  });
162
138
  }
163
139
  }
@@ -190,8 +166,6 @@ function addForeignKeyIndexes(ctx, meta, table) {
190
166
  table,
191
167
  entries: columns.map((column) => ({ column })),
192
168
  unique: false,
193
- source: 'entity',
194
- syncStatus: 'entity_only',
195
169
  });
196
170
  }
197
171
  }
@@ -237,7 +211,5 @@ function addCompositeIndex(ctx, table, meta, idxMeta) {
237
211
  m: idxMeta.m,
238
212
  efConstruction: idxMeta.efConstruction,
239
213
  lists: idxMeta.lists,
240
- source: 'entity',
241
- syncStatus: 'entity_only',
242
214
  });
243
215
  }
@@ -1,12 +1,3 @@
1
- /**
2
- * SchemaAST Differ
3
- *
4
- * Compares two SchemaAST instances and produces a detailed diff.
5
- * Used for:
6
- * - Migration generation (entity vs database)
7
- * - Drift detection (expected vs actual)
8
- * - Schema synchronization
9
- */
10
1
  import { type IndexFacet } from './indexDifferences.js';
11
2
  import type { SchemaAST } from './schemaAST.js';
12
3
  import type { CanonicalType } from './types.js';
@@ -26,52 +17,21 @@ export interface DiffOptions {
26
17
  /** Tables to exclude from comparison */
27
18
  excludeTables?: string[];
28
19
  /**
29
- * A type as the engine would actually store it, for the caller that has a dialect.
30
- *
31
- * Several canonical types share one storage type per engine - a `boolean` is `TINYINT(1)` on MySQL
32
- * and `INTEGER` on SQLite - so comparing them canonically reports an alteration on every sync for
33
- * those columns. Passing both sides through the engine first is what settles that, and it is the
34
- * only thing here a dialect is needed for, so it arrives as a function rather than as a dependency.
20
+ * A type as the engine stores it, since several canonical types share one storage type (a boolean is
21
+ * `TINYINT(1)` on MySQL): the one thing a dialect is needed for, passed as a function.
35
22
  */
36
23
  normalizeType?: (type: CanonicalType) => CanonicalType;
37
- /**
38
- * Whether two defaults are the same value, for the caller that has a dialect.
39
- *
40
- * A database reprints a default from its parse tree, so `'active'` comes back as
41
- * `'active'::character varying` on Postgres and a symbolic `now()` matches no spelling of
42
- * `CURRENT_TIMESTAMP`. Undoing that needs the dialect that wrote it, so it arrives as a function.
43
- */
24
+ /** Whether two defaults are one value, as the dialect that reprinted them can tell: `'a'::character varying` is `'a'`. */
44
25
  defaultsEqual?: (expected: unknown, actual: unknown) => boolean;
45
26
  }
46
- /**
47
- * Compare two schemas and return the differences.
48
- *
49
- * @param source - The "expected" or "desired" schema (e.g., from entities)
50
- * @param target - The "actual" or "current" schema (e.g., from database)
51
- * @param options - Diff options
52
- * @returns Detailed diff result
53
- */
27
+ /** The differences between the expected schema (the entities) and the actual one (the database). */
54
28
  export declare function diffSchemas(source: SchemaAST, target: SchemaAST, options?: DiffOptions): SchemaDiffResult;
55
- /**
56
- * Compare two tables and return the differences.
57
- *
58
- * Exported because it is also how a migration is planned: the generator diffs one entity's table
59
- * against the one the database reported, then projects the result into a `SchemaDiff`. One
60
- * comparison serves both, so drift and migrations can no longer disagree about what has changed.
61
- */
29
+ /** The differences between two tables, shared by migrations and drift detection so they cannot disagree. */
62
30
  export declare function diffTable(source: TableNode, target: TableNode, options?: DiffOptions): (TableDiff & {
63
31
  readonly columnDiffs: ColumnDiff[];
64
32
  readonly indexDiffs: IndexDiff[];
65
33
  }) | undefined;
66
- /**
67
- * Compare two lists of relationships.
68
- *
69
- * Lists rather than whole schemas, because a migration diffs one table: its two sides are that
70
- * table's `outgoingRelations`, where `diffSchemas` passes the schema's every relationship.
71
- *
72
- * Matched by columns, never by name - the engine named every constraint that already exists, so
73
- * pairing on names would report every hand-named one as a drop and an add.
74
- */
34
+ /** The differences between two lists of foreign keys, matched by their columns and never by the name the engine gave them. */
75
35
  export declare function diffRelationshipNodes(source: readonly RelationshipNode[], target: readonly RelationshipNode[], opts?: DiffOptions): RelationshipDiff[];
76
36
  /** A relationship's `ON DELETE` and `ON UPDATE`, an unstated one read as the action the database applies. */
77
37
  export declare function referentialActions(rel: RelationshipNode): {