@uql/core 3.7.13 → 3.8.1

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 (210) hide show
  1. package/CHANGELOG.md +11 -2
  2. package/README.md +16 -8
  3. package/dist/browser/uql-browser.min.js +16 -15
  4. package/dist/browser/uql-browser.min.js.map +1 -1
  5. package/dist/dialect/abstractDialect.d.ts +7 -2
  6. package/dist/dialect/abstractDialect.d.ts.map +1 -1
  7. package/dist/dialect/abstractDialect.js +9 -1
  8. package/dist/dialect/abstractDialect.js.map +1 -1
  9. package/dist/dialect/abstractSqlDialect.d.ts +5 -6
  10. package/dist/dialect/abstractSqlDialect.d.ts.map +1 -1
  11. package/dist/dialect/abstractSqlDialect.js +14 -13
  12. package/dist/dialect/abstractSqlDialect.js.map +1 -1
  13. package/dist/dialect/dialectConfig.d.ts +17 -0
  14. package/dist/dialect/dialectConfig.d.ts.map +1 -0
  15. package/dist/dialect/dialectConfig.js +71 -0
  16. package/dist/dialect/dialectConfig.js.map +1 -0
  17. package/dist/dialect/index.d.ts +1 -0
  18. package/dist/dialect/index.d.ts.map +1 -1
  19. package/dist/dialect/index.js +1 -0
  20. package/dist/dialect/index.js.map +1 -1
  21. package/dist/entity/decorator/definition.d.ts.map +1 -1
  22. package/dist/entity/decorator/definition.js +2 -1
  23. package/dist/entity/decorator/definition.js.map +1 -1
  24. package/dist/entity/decorator/index-decorator.d.ts +36 -0
  25. package/dist/entity/decorator/index-decorator.d.ts.map +1 -0
  26. package/dist/entity/decorator/index-decorator.js +51 -0
  27. package/dist/entity/decorator/index-decorator.js.map +1 -0
  28. package/dist/entity/decorator/index.d.ts +1 -0
  29. package/dist/entity/decorator/index.d.ts.map +1 -1
  30. package/dist/entity/decorator/index.js +1 -0
  31. package/dist/entity/decorator/index.js.map +1 -1
  32. package/dist/maria/mariaDialect.d.ts +2 -1
  33. package/dist/maria/mariaDialect.d.ts.map +1 -1
  34. package/dist/maria/mariaDialect.js +3 -0
  35. package/dist/maria/mariaDialect.js.map +1 -1
  36. package/dist/migrate/builder/columnBuilder.d.ts +75 -0
  37. package/dist/migrate/builder/columnBuilder.d.ts.map +1 -0
  38. package/dist/migrate/builder/columnBuilder.js +149 -0
  39. package/dist/migrate/builder/columnBuilder.js.map +1 -0
  40. package/dist/migrate/builder/expressions.d.ts +87 -0
  41. package/dist/migrate/builder/expressions.d.ts.map +1 -0
  42. package/dist/migrate/builder/expressions.js +150 -0
  43. package/dist/migrate/builder/expressions.js.map +1 -0
  44. package/dist/migrate/builder/index.d.ts +6 -0
  45. package/dist/migrate/builder/index.d.ts.map +1 -0
  46. package/dist/migrate/builder/index.js +6 -0
  47. package/dist/migrate/builder/index.js.map +1 -0
  48. package/dist/migrate/builder/migrationBuilder.d.ts +73 -0
  49. package/dist/migrate/builder/migrationBuilder.d.ts.map +1 -0
  50. package/dist/migrate/builder/migrationBuilder.js +326 -0
  51. package/dist/migrate/builder/migrationBuilder.js.map +1 -0
  52. package/dist/migrate/builder/tableBuilder.d.ts +51 -0
  53. package/dist/migrate/builder/tableBuilder.d.ts.map +1 -0
  54. package/dist/migrate/builder/tableBuilder.js +278 -0
  55. package/dist/migrate/builder/tableBuilder.js.map +1 -0
  56. package/dist/migrate/builder/types.d.ts +462 -0
  57. package/dist/migrate/builder/types.d.ts.map +1 -0
  58. package/dist/migrate/builder/types.js +8 -0
  59. package/dist/migrate/builder/types.js.map +1 -0
  60. package/dist/migrate/cli.d.ts +4 -6
  61. package/dist/migrate/cli.d.ts.map +1 -1
  62. package/dist/migrate/cli.js +166 -23
  63. package/dist/migrate/cli.js.map +1 -1
  64. package/dist/migrate/codegen/entityCodeGenerator.d.ts +137 -0
  65. package/dist/migrate/codegen/entityCodeGenerator.d.ts.map +1 -0
  66. package/dist/migrate/codegen/entityCodeGenerator.js +401 -0
  67. package/dist/migrate/codegen/entityCodeGenerator.js.map +1 -0
  68. package/dist/migrate/codegen/entityMerger.d.ts +111 -0
  69. package/dist/migrate/codegen/entityMerger.d.ts.map +1 -0
  70. package/dist/migrate/codegen/entityMerger.js +291 -0
  71. package/dist/migrate/codegen/entityMerger.js.map +1 -0
  72. package/dist/migrate/codegen/index.d.ts +10 -0
  73. package/dist/migrate/codegen/index.d.ts.map +1 -0
  74. package/dist/migrate/codegen/index.js +14 -0
  75. package/dist/migrate/codegen/index.js.map +1 -0
  76. package/dist/migrate/codegen/migrationCodeGenerator.d.ts +62 -0
  77. package/dist/migrate/codegen/migrationCodeGenerator.d.ts.map +1 -0
  78. package/dist/migrate/codegen/migrationCodeGenerator.js +356 -0
  79. package/dist/migrate/codegen/migrationCodeGenerator.js.map +1 -0
  80. package/dist/migrate/codegen/smartRelationDetector.d.ts +48 -0
  81. package/dist/migrate/codegen/smartRelationDetector.d.ts.map +1 -0
  82. package/dist/migrate/codegen/smartRelationDetector.js +135 -0
  83. package/dist/migrate/codegen/smartRelationDetector.js.map +1 -0
  84. package/dist/migrate/drift/driftDetector.d.ts +81 -0
  85. package/dist/migrate/drift/driftDetector.d.ts.map +1 -0
  86. package/dist/migrate/drift/driftDetector.js +248 -0
  87. package/dist/migrate/drift/driftDetector.js.map +1 -0
  88. package/dist/migrate/drift/index.d.ts +7 -0
  89. package/dist/migrate/drift/index.d.ts.map +1 -0
  90. package/dist/migrate/drift/index.js +7 -0
  91. package/dist/migrate/drift/index.js.map +1 -0
  92. package/dist/migrate/generator/index.d.ts +1 -3
  93. package/dist/migrate/generator/index.d.ts.map +1 -1
  94. package/dist/migrate/generator/index.js +1 -3
  95. package/dist/migrate/generator/index.js.map +1 -1
  96. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +29 -3
  97. package/dist/migrate/generator/mongoSchemaGenerator.d.ts.map +1 -1
  98. package/dist/migrate/generator/mongoSchemaGenerator.js +86 -4
  99. package/dist/migrate/generator/mongoSchemaGenerator.js.map +1 -1
  100. package/dist/migrate/index.d.ts +7 -8
  101. package/dist/migrate/index.d.ts.map +1 -1
  102. package/dist/migrate/index.js +11 -9
  103. package/dist/migrate/index.js.map +1 -1
  104. package/dist/migrate/introspection/baseSqlIntrospector.d.ts +28 -0
  105. package/dist/migrate/introspection/baseSqlIntrospector.d.ts.map +1 -0
  106. package/dist/migrate/introspection/baseSqlIntrospector.js +135 -0
  107. package/dist/migrate/introspection/baseSqlIntrospector.js.map +1 -0
  108. package/dist/migrate/introspection/mongoIntrospector.d.ts +6 -0
  109. package/dist/migrate/introspection/mongoIntrospector.d.ts.map +1 -1
  110. package/dist/migrate/introspection/mongoIntrospector.js +54 -0
  111. package/dist/migrate/introspection/mongoIntrospector.js.map +1 -1
  112. package/dist/migrate/introspection/mysqlIntrospector.d.ts +2 -1
  113. package/dist/migrate/introspection/mysqlIntrospector.d.ts.map +1 -1
  114. package/dist/migrate/introspection/mysqlIntrospector.js +8 -6
  115. package/dist/migrate/introspection/mysqlIntrospector.js.map +1 -1
  116. package/dist/migrate/introspection/postgresIntrospector.d.ts +2 -1
  117. package/dist/migrate/introspection/postgresIntrospector.d.ts.map +1 -1
  118. package/dist/migrate/introspection/postgresIntrospector.js +3 -1
  119. package/dist/migrate/introspection/postgresIntrospector.js.map +1 -1
  120. package/dist/migrate/introspection/sqliteIntrospector.d.ts +2 -2
  121. package/dist/migrate/introspection/sqliteIntrospector.d.ts.map +1 -1
  122. package/dist/migrate/introspection/sqliteIntrospector.js +3 -4
  123. package/dist/migrate/introspection/sqliteIntrospector.js.map +1 -1
  124. package/dist/migrate/migrator.d.ts +29 -0
  125. package/dist/migrate/migrator.d.ts.map +1 -1
  126. package/dist/migrate/migrator.js +31 -23
  127. package/dist/migrate/migrator.js.map +1 -1
  128. package/dist/migrate/schemaGenerator.d.ts +72 -22
  129. package/dist/migrate/schemaGenerator.d.ts.map +1 -1
  130. package/dist/migrate/schemaGenerator.js +385 -153
  131. package/dist/migrate/schemaGenerator.js.map +1 -1
  132. package/dist/migrate/sync/index.d.ts +7 -0
  133. package/dist/migrate/sync/index.d.ts.map +1 -0
  134. package/dist/migrate/sync/index.js +7 -0
  135. package/dist/migrate/sync/index.js.map +1 -0
  136. package/dist/migrate/sync/schemaSync.d.ts +132 -0
  137. package/dist/migrate/sync/schemaSync.d.ts.map +1 -0
  138. package/dist/migrate/sync/schemaSync.js +260 -0
  139. package/dist/migrate/sync/schemaSync.js.map +1 -0
  140. package/dist/mongo/mongoDialect.d.ts +2 -1
  141. package/dist/mongo/mongoDialect.d.ts.map +1 -1
  142. package/dist/mongo/mongoDialect.js +3 -0
  143. package/dist/mongo/mongoDialect.js.map +1 -1
  144. package/dist/mysql/mysqlDialect.d.ts +2 -0
  145. package/dist/mysql/mysqlDialect.d.ts.map +1 -1
  146. package/dist/mysql/mysqlDialect.js +3 -0
  147. package/dist/mysql/mysqlDialect.js.map +1 -1
  148. package/dist/postgres/postgresDialect.js +1 -1
  149. package/dist/postgres/postgresDialect.js.map +1 -1
  150. package/dist/schema/canonicalType.d.ts +42 -0
  151. package/dist/schema/canonicalType.d.ts.map +1 -0
  152. package/dist/schema/canonicalType.js +524 -0
  153. package/dist/schema/canonicalType.js.map +1 -0
  154. package/dist/schema/index.d.ts +28 -0
  155. package/dist/schema/index.d.ts.map +1 -0
  156. package/dist/schema/index.js +29 -0
  157. package/dist/schema/index.js.map +1 -0
  158. package/dist/schema/schemaAST.d.ts +155 -0
  159. package/dist/schema/schemaAST.d.ts.map +1 -0
  160. package/dist/schema/schemaAST.js +496 -0
  161. package/dist/schema/schemaAST.js.map +1 -0
  162. package/dist/schema/schemaASTBuilder.d.ts +58 -0
  163. package/dist/schema/schemaASTBuilder.d.ts.map +1 -0
  164. package/dist/schema/schemaASTBuilder.js +193 -0
  165. package/dist/schema/schemaASTBuilder.js.map +1 -0
  166. package/dist/schema/schemaASTDiffer.d.ts +84 -0
  167. package/dist/schema/schemaASTDiffer.d.ts.map +1 -0
  168. package/dist/schema/schemaASTDiffer.js +431 -0
  169. package/dist/schema/schemaASTDiffer.js.map +1 -0
  170. package/dist/schema/types.d.ts +347 -0
  171. package/dist/schema/types.d.ts.map +1 -0
  172. package/dist/schema/types.js +11 -0
  173. package/dist/schema/types.js.map +1 -0
  174. package/dist/sqlite/sqliteDialect.js +1 -1
  175. package/dist/sqlite/sqliteDialect.js.map +1 -1
  176. package/dist/sqlite/sqliteQuerierPool.js.map +1 -1
  177. package/dist/type/config.d.ts +6 -0
  178. package/dist/type/config.d.ts.map +1 -1
  179. package/dist/type/entity.d.ts +24 -0
  180. package/dist/type/entity.d.ts.map +1 -1
  181. package/dist/type/migration.d.ts +50 -4
  182. package/dist/type/migration.d.ts.map +1 -1
  183. package/dist/util/field.util.d.ts +0 -1
  184. package/dist/util/field.util.d.ts.map +1 -1
  185. package/dist/util/field.util.js +8 -2
  186. package/dist/util/field.util.js.map +1 -1
  187. package/dist/util/logger.d.ts.map +1 -1
  188. package/dist/util/logger.js +2 -1
  189. package/dist/util/logger.js.map +1 -1
  190. package/dist/util/string.util.d.ts +24 -0
  191. package/dist/util/string.util.d.ts.map +1 -1
  192. package/dist/util/string.util.js +57 -0
  193. package/dist/util/string.util.js.map +1 -1
  194. package/package.json +2 -2
  195. package/dist/migrate/generator/mysqlSchemaGenerator.d.ts +0 -15
  196. package/dist/migrate/generator/mysqlSchemaGenerator.d.ts.map +0 -1
  197. package/dist/migrate/generator/mysqlSchemaGenerator.js +0 -88
  198. package/dist/migrate/generator/mysqlSchemaGenerator.js.map +0 -1
  199. package/dist/migrate/generator/postgresSchemaGenerator.d.ts +0 -19
  200. package/dist/migrate/generator/postgresSchemaGenerator.d.ts.map +0 -1
  201. package/dist/migrate/generator/postgresSchemaGenerator.js +0 -115
  202. package/dist/migrate/generator/postgresSchemaGenerator.js.map +0 -1
  203. package/dist/migrate/generator/sqliteSchemaGenerator.d.ts +0 -16
  204. package/dist/migrate/generator/sqliteSchemaGenerator.d.ts.map +0 -1
  205. package/dist/migrate/generator/sqliteSchemaGenerator.js +0 -74
  206. package/dist/migrate/generator/sqliteSchemaGenerator.js.map +0 -1
  207. package/dist/migrate/type.d.ts +0 -2
  208. package/dist/migrate/type.d.ts.map +0 -1
  209. package/dist/migrate/type.js +0 -2
  210. package/dist/migrate/type.js.map +0 -1
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Schema AST Module
3
+ *
4
+ * Provides a unified graph representation of database schema for:
5
+ * - Schema diffing and migration generation
6
+ * - Entity code generation from database
7
+ * - Drift detection
8
+ * - Smart relation inference
9
+ */
10
+ // Dialect configuration
11
+ export { DIALECT_CONFIG, getDialectConfig } from '../dialect/index.js';
12
+ // Canonical type utilities
13
+ export { areTypesEqual, canonicalToColumnType, canonicalToSql, canonicalToTypeScript, fieldOptionsToCanonical, isBreakingTypeChange, sqlToCanonical, } from './canonicalType.js';
14
+ /**
15
+ * Introspect the database and build a SchemaAST from it.
16
+ *
17
+ * @param introspector - The schema introspector to use
18
+ * @returns The SchemaAST representing the database schema
19
+ */
20
+ export async function introspectSchema(introspector) {
21
+ return introspector.introspect();
22
+ }
23
+ // SchemaAST class
24
+ export { SchemaAST } from './schemaAST.js';
25
+ // Builder
26
+ export { SchemaASTBuilder } from './schemaASTBuilder.js';
27
+ // Differ
28
+ export { diffSchemas, SchemaASTDiffer } from './schemaASTDiffer.js';
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,wBAAwB;AACxB,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvE,2BAA2B;AAC3B,OAAO,EACL,aAAa,EACb,qBAAqB,EACrB,cAAc,EACd,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACpB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAE5B;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,YAAgC;IACrE,OAAO,YAAY,CAAC,UAAU,EAAE,CAAC;AACnC,CAAC;AACD,kBAAkB;AAClB,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,UAAU;AACV,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAGzD,SAAS;AACT,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,155 @@
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
+ import type { ColumnNode, IndexNode, SchemaAST as ISchemaAST, RelationshipNode, RelationshipType, TableNode, ValidationError } from './types.js';
8
+ /**
9
+ * Schema AST - A graph representation of a database schema.
10
+ *
11
+ * Enables:
12
+ * - Graph navigation (dependencies, dependents)
13
+ * - Circular dependency detection
14
+ * - Topological sorting for correct DDL order
15
+ * - Smart relation inference
16
+ * - Schema validation
17
+ */
18
+ export declare class SchemaAST implements ISchemaAST {
19
+ readonly tables: Map<string, TableNode>;
20
+ readonly relationships: RelationshipNode[];
21
+ readonly indexes: IndexNode[];
22
+ /**
23
+ * Get a table by name.
24
+ */
25
+ getTable(name: string): TableNode | undefined;
26
+ /**
27
+ * Add a table to the schema.
28
+ */
29
+ addTable(table: TableNode): void;
30
+ /**
31
+ * Remove a table from the schema.
32
+ */
33
+ removeTable(name: string): boolean;
34
+ /**
35
+ * Get all table nodes.
36
+ */
37
+ getTables(): TableNode[];
38
+ /**
39
+ * Get all table names.
40
+ */
41
+ getTableNames(): string[];
42
+ /**
43
+ * Get all tables that depend on this table (have FKs pointing to it).
44
+ * These are tables that reference this table's primary key.
45
+ */
46
+ getDependentTables(table: TableNode): TableNode[];
47
+ /**
48
+ * Get all tables this table depends on (has FKs to).
49
+ * These are tables that this table references.
50
+ */
51
+ getDependencies(table: TableNode): TableNode[];
52
+ /**
53
+ * Get the relationship between two tables (if any).
54
+ */
55
+ getRelationship(from: TableNode, to: TableNode): RelationshipNode | undefined;
56
+ /**
57
+ * Get all relationships for a table.
58
+ */
59
+ getTableRelationships(table: TableNode): RelationshipNode[];
60
+ /**
61
+ * Get the column that a foreign key column references.
62
+ */
63
+ getReferencedColumn(fkColumn: ColumnNode): ColumnNode | undefined;
64
+ /**
65
+ * Detect circular foreign key dependencies.
66
+ * Returns arrays of tables that form cycles.
67
+ */
68
+ detectCircularDependencies(): TableNode[][];
69
+ /**
70
+ * Check if there are any circular dependencies.
71
+ */
72
+ hasCircularDependencies(): boolean;
73
+ /**
74
+ * Get tables in correct order for CREATE (dependencies first).
75
+ * Tables with no dependencies come first, then tables that depend on them, etc.
76
+ */
77
+ getCreateOrder(): TableNode[];
78
+ /**
79
+ * Get tables in correct order for DROP (dependents first).
80
+ * Tables that depend on others come first, then the tables they depend on.
81
+ */
82
+ getDropOrder(): TableNode[];
83
+ /**
84
+ * Topological sort respecting FK dependencies.
85
+ * Uses Kahn's algorithm for stable ordering.
86
+ */
87
+ private topologicalSort;
88
+ /**
89
+ * Validate schema integrity.
90
+ * Checks for:
91
+ * - Missing FK targets
92
+ * - Circular dependencies
93
+ * - Orphan columns
94
+ * - Duplicate indexes
95
+ */
96
+ validate(): ValidationError[];
97
+ /**
98
+ * Check if the schema is valid (no validation errors).
99
+ */
100
+ isValid(): boolean;
101
+ /**
102
+ * Check if a table looks like a junction table (ManyToMany through).
103
+ * Junction tables typically have:
104
+ * - Exactly 2 foreign keys
105
+ * - Few other columns (id, maybe timestamps)
106
+ * - Primary key might be composite of the FKs
107
+ */
108
+ isJunctionTable(table: TableNode): boolean;
109
+ /**
110
+ * Infer relation type from schema structure.
111
+ */
112
+ inferRelationType(rel: RelationshipNode): RelationshipType;
113
+ /**
114
+ * Get the inverse relation type.
115
+ */
116
+ getInverseRelationType(type: RelationshipType): RelationshipType;
117
+ /**
118
+ * Add an index to the schema.
119
+ */
120
+ addIndex(index: IndexNode): void;
121
+ /**
122
+ * Get all indexes for a table.
123
+ */
124
+ getTableIndexes(tableName: string): IndexNode[];
125
+ /**
126
+ * Find an index by name.
127
+ */
128
+ getIndex(name: string): IndexNode | undefined;
129
+ /**
130
+ * Add a relationship to the schema.
131
+ */
132
+ addRelationship(rel: RelationshipNode): void;
133
+ /**
134
+ * Remove a relationship from the schema.
135
+ */
136
+ removeRelationship(name: string): boolean;
137
+ /**
138
+ * Create a deep clone of this schema.
139
+ */
140
+ clone(): SchemaAST;
141
+ /**
142
+ * Get statistics about the schema.
143
+ */
144
+ getStats(): {
145
+ tableCount: number;
146
+ columnCount: number;
147
+ relationshipCount: number;
148
+ indexCount: number;
149
+ };
150
+ /**
151
+ * Convert schema to a plain object for serialization/debugging.
152
+ */
153
+ toJSON(): object;
154
+ }
155
+ //# sourceMappingURL=schemaAST.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schemaAST.d.ts","sourceRoot":"","sources":["../../src/schema/schemaAST.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EACV,UAAU,EACV,SAAS,EACT,SAAS,IAAI,UAAU,EACvB,gBAAgB,EAChB,gBAAgB,EAChB,SAAS,EACT,eAAe,EAChB,MAAM,YAAY,CAAC;AAEpB;;;;;;;;;GASG;AACH,qBAAa,SAAU,YAAW,UAAU;IAC1C,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAa;IACpD,QAAQ,CAAC,aAAa,EAAE,gBAAgB,EAAE,CAAM;IAChD,QAAQ,CAAC,OAAO,EAAE,SAAS,EAAE,CAAM;IAMnC;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAI7C;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAKhC;;OAEG;IACH,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAsBlC;;OAEG;IACH,SAAS,IAAI,SAAS,EAAE;IAIxB;;OAEG;IACH,aAAa,IAAI,MAAM,EAAE;IAQzB;;;OAGG;IACH,kBAAkB,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE;IAIjD;;;OAGG;IACH,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,EAAE;IAI9C;;OAEG;IACH,eAAe,CAAC,IAAI,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,GAAG,gBAAgB,GAAG,SAAS;IAI7E;;OAEG;IACH,qBAAqB,CAAC,KAAK,EAAE,SAAS,GAAG,gBAAgB,EAAE;IAI3D;;OAEG;IACH,mBAAmB,CAAC,QAAQ,EAAE,UAAU,GAAG,UAAU,GAAG,SAAS;IAQjE;;;OAGG;IACH,0BAA0B,IAAI,SAAS,EAAE,EAAE;IAgC3C;;OAEG;IACH,uBAAuB,IAAI,OAAO;IAIlC;;;OAGG;IACH,cAAc,IAAI,SAAS,EAAE;IAI7B;;;OAGG;IACH,YAAY,IAAI,SAAS,EAAE;IAI3B;;;OAGG;IACH,OAAO,CAAC,eAAe;IA4BvB;;;;;;;OAOG;IACH,QAAQ,IAAI,eAAe,EAAE;IA0C7B;;OAEG;IACH,OAAO,IAAI,OAAO;IAQlB;;;;;;OAMG;IACH,eAAe,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO;IA0B1C;;OAEG;IACH,iBAAiB,CAAC,GAAG,EAAE,gBAAgB,GAAG,gBAAgB;IAiB1D;;OAEG;IACH,sBAAsB,CAAC,IAAI,EAAE,gBAAgB,GAAG,gBAAgB;IAiBhE;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI;IAOhC;;OAEG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,EAAE;IAK/C;;OAEG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS;IAQ7C;;OAEG;IACH,eAAe,CAAC,GAAG,EAAE,gBAAgB,GAAG,IAAI;IAgB5C;;OAEG;IACH,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAgCzC;;OAEG;IACH,KAAK,IAAI,SAAS;IAyFlB;;OAEG;IACH,QAAQ,IAAI;QACV,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,EAAE,MAAM,CAAC;QACpB,iBAAiB,EAAE,MAAM,CAAC;QAC1B,UAAU,EAAE,MAAM,CAAC;KACpB;IAcD;;OAEG;IACH,MAAM,IAAI,MAAM;CA4BjB"}
@@ -0,0 +1,496 @@
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
+ /**
8
+ * Schema AST - A graph representation of a database schema.
9
+ *
10
+ * Enables:
11
+ * - Graph navigation (dependencies, dependents)
12
+ * - Circular dependency detection
13
+ * - Topological sorting for correct DDL order
14
+ * - Smart relation inference
15
+ * - Schema validation
16
+ */
17
+ export class SchemaAST {
18
+ tables = new Map();
19
+ relationships = [];
20
+ indexes = [];
21
+ // ============================================================================
22
+ // Table Operations
23
+ // ============================================================================
24
+ /**
25
+ * Get a table by name.
26
+ */
27
+ getTable(name) {
28
+ return this.tables.get(name);
29
+ }
30
+ /**
31
+ * Add a table to the schema.
32
+ */
33
+ addTable(table) {
34
+ table.schema = this;
35
+ this.tables.set(table.name, table);
36
+ }
37
+ /**
38
+ * Remove a table from the schema.
39
+ */
40
+ removeTable(name) {
41
+ const table = this.tables.get(name);
42
+ if (!table)
43
+ return false;
44
+ // Remove all relationships involving this table
45
+ for (let i = this.relationships.length - 1; i >= 0; i--) {
46
+ const rel = this.relationships[i];
47
+ if (rel.from.table === table || rel.to.table === table) {
48
+ this.relationships.splice(i, 1);
49
+ }
50
+ }
51
+ // Remove all indexes for this table
52
+ for (let i = this.indexes.length - 1; i >= 0; i--) {
53
+ if (this.indexes[i].table === table) {
54
+ this.indexes.splice(i, 1);
55
+ }
56
+ }
57
+ return this.tables.delete(name);
58
+ }
59
+ /**
60
+ * Get all table nodes.
61
+ */
62
+ getTables() {
63
+ return Array.from(this.tables.values());
64
+ }
65
+ /**
66
+ * Get all table names.
67
+ */
68
+ getTableNames() {
69
+ return Array.from(this.tables.keys());
70
+ }
71
+ // ============================================================================
72
+ // Graph Navigation
73
+ // ============================================================================
74
+ /**
75
+ * Get all tables that depend on this table (have FKs pointing to it).
76
+ * These are tables that reference this table's primary key.
77
+ */
78
+ getDependentTables(table) {
79
+ return table.incomingRelations.map((r) => r.from.table);
80
+ }
81
+ /**
82
+ * Get all tables this table depends on (has FKs to).
83
+ * These are tables that this table references.
84
+ */
85
+ getDependencies(table) {
86
+ return table.outgoingRelations.map((r) => r.to.table);
87
+ }
88
+ /**
89
+ * Get the relationship between two tables (if any).
90
+ */
91
+ getRelationship(from, to) {
92
+ return this.relationships.find((r) => r.from.table === from && r.to.table === to);
93
+ }
94
+ /**
95
+ * Get all relationships for a table.
96
+ */
97
+ getTableRelationships(table) {
98
+ return this.relationships.filter((r) => r.from.table === table || r.to.table === table);
99
+ }
100
+ /**
101
+ * Get the column that a foreign key column references.
102
+ */
103
+ getReferencedColumn(fkColumn) {
104
+ return fkColumn.references?.to.columns[0];
105
+ }
106
+ // ============================================================================
107
+ // Graph Analysis
108
+ // ============================================================================
109
+ /**
110
+ * Detect circular foreign key dependencies.
111
+ * Returns arrays of tables that form cycles.
112
+ */
113
+ detectCircularDependencies() {
114
+ const cycles = [];
115
+ const visited = new Set();
116
+ const stack = new Set();
117
+ const dfs = (table, path) => {
118
+ if (stack.has(table)) {
119
+ const cycleStart = path.indexOf(table);
120
+ if (cycleStart !== -1) {
121
+ cycles.push(path.slice(cycleStart));
122
+ }
123
+ return;
124
+ }
125
+ if (visited.has(table))
126
+ return;
127
+ visited.add(table);
128
+ stack.add(table);
129
+ for (const dep of this.getDependencies(table)) {
130
+ dfs(dep, [...path, table]);
131
+ }
132
+ stack.delete(table);
133
+ };
134
+ for (const table of this.tables.values()) {
135
+ dfs(table, []);
136
+ }
137
+ return cycles;
138
+ }
139
+ /**
140
+ * Check if there are any circular dependencies.
141
+ */
142
+ hasCircularDependencies() {
143
+ return this.detectCircularDependencies().length > 0;
144
+ }
145
+ /**
146
+ * Get tables in correct order for CREATE (dependencies first).
147
+ * Tables with no dependencies come first, then tables that depend on them, etc.
148
+ */
149
+ getCreateOrder() {
150
+ return this.topologicalSort();
151
+ }
152
+ /**
153
+ * Get tables in correct order for DROP (dependents first).
154
+ * Tables that depend on others come first, then the tables they depend on.
155
+ */
156
+ getDropOrder() {
157
+ return this.topologicalSort().reverse();
158
+ }
159
+ /**
160
+ * Topological sort respecting FK dependencies.
161
+ * Uses Kahn's algorithm for stable ordering.
162
+ */
163
+ topologicalSort() {
164
+ const result = [];
165
+ const visited = new Set();
166
+ const visit = (table) => {
167
+ if (visited.has(table))
168
+ return;
169
+ visited.add(table);
170
+ // Visit dependencies first (tables this table references)
171
+ for (const dep of this.getDependencies(table)) {
172
+ visit(dep);
173
+ }
174
+ result.push(table);
175
+ };
176
+ // Visit all tables
177
+ for (const table of this.tables.values()) {
178
+ visit(table);
179
+ }
180
+ return result;
181
+ }
182
+ // ============================================================================
183
+ // Validation
184
+ // ============================================================================
185
+ /**
186
+ * Validate schema integrity.
187
+ * Checks for:
188
+ * - Missing FK targets
189
+ * - Circular dependencies
190
+ * - Orphan columns
191
+ * - Duplicate indexes
192
+ */
193
+ validate() {
194
+ const errors = [];
195
+ // Check all FK targets exist
196
+ for (const rel of this.relationships) {
197
+ if (!this.tables.has(rel.to.table.name)) {
198
+ errors.push({
199
+ type: 'missing_fk_target',
200
+ message: `FK target table "${rel.to.table.name}" does not exist`,
201
+ relationship: rel,
202
+ });
203
+ }
204
+ }
205
+ // Check for circular dependencies
206
+ const cycles = this.detectCircularDependencies();
207
+ for (const cycle of cycles) {
208
+ errors.push({
209
+ type: 'circular_dependency',
210
+ message: `Circular FK: ${cycle.map((t) => t.name).join(' -> ')}`,
211
+ tables: cycle,
212
+ });
213
+ }
214
+ // Check for duplicate index names within same table
215
+ for (const table of this.tables.values()) {
216
+ const indexNames = new Set();
217
+ for (const index of table.indexes) {
218
+ if (indexNames.has(index.name)) {
219
+ errors.push({
220
+ type: 'duplicate_index',
221
+ message: `Duplicate index name "${index.name}" in table "${table.name}"`,
222
+ table,
223
+ });
224
+ }
225
+ indexNames.add(index.name);
226
+ }
227
+ }
228
+ return errors;
229
+ }
230
+ /**
231
+ * Check if the schema is valid (no validation errors).
232
+ */
233
+ isValid() {
234
+ return this.validate().length === 0;
235
+ }
236
+ // ============================================================================
237
+ // Smart Relation Detection
238
+ // ============================================================================
239
+ /**
240
+ * Check if a table looks like a junction table (ManyToMany through).
241
+ * Junction tables typically have:
242
+ * - Exactly 2 foreign keys
243
+ * - Few other columns (id, maybe timestamps)
244
+ * - Primary key might be composite of the FKs
245
+ */
246
+ isJunctionTable(table) {
247
+ const fkCount = table.outgoingRelations.length;
248
+ const columnCount = table.columns.size;
249
+ // Must have exactly 2 FKs
250
+ if (fkCount !== 2) {
251
+ return false;
252
+ }
253
+ // Should have few columns (typically: id + 2 FKs + maybe timestamps)
254
+ if (columnCount > 6) {
255
+ return false;
256
+ }
257
+ // Check if name suggests a junction (contains both related table names)
258
+ const relatedTables = table.outgoingRelations.map((r) => r.to.table.name.toLowerCase());
259
+ const tableName = table.name.toLowerCase();
260
+ // Common patterns: user_roles, post_tags, etc.
261
+ const containsBothNames = relatedTables.every((name) => tableName.includes(name.replace(/s$/, '')) || tableName.includes(name));
262
+ return containsBothNames || columnCount <= 5;
263
+ }
264
+ /**
265
+ * Infer relation type from schema structure.
266
+ */
267
+ inferRelationType(rel) {
268
+ const fromCol = rel.from.columns[0];
269
+ // Check if source is junction table -> ManyToMany
270
+ if (this.isJunctionTable(rel.from.table)) {
271
+ return 'ManyToMany';
272
+ }
273
+ // Unique FK -> OneToOne
274
+ if (fromCol?.isUnique) {
275
+ return 'OneToOne';
276
+ }
277
+ // Default: ManyToOne (many rows can reference same target)
278
+ return 'ManyToOne';
279
+ }
280
+ /**
281
+ * Get the inverse relation type.
282
+ */
283
+ getInverseRelationType(type) {
284
+ switch (type) {
285
+ case 'OneToOne':
286
+ return 'OneToOne';
287
+ case 'OneToMany':
288
+ return 'ManyToOne';
289
+ case 'ManyToOne':
290
+ return 'OneToMany';
291
+ case 'ManyToMany':
292
+ return 'ManyToMany';
293
+ }
294
+ }
295
+ // ============================================================================
296
+ // Index Operations
297
+ // ============================================================================
298
+ /**
299
+ * Add an index to the schema.
300
+ */
301
+ addIndex(index) {
302
+ this.indexes.push(index);
303
+ if (!index.table.indexes.includes(index)) {
304
+ index.table.indexes.push(index);
305
+ }
306
+ }
307
+ /**
308
+ * Get all indexes for a table.
309
+ */
310
+ getTableIndexes(tableName) {
311
+ const table = this.tables.get(tableName);
312
+ return table?.indexes ?? [];
313
+ }
314
+ /**
315
+ * Find an index by name.
316
+ */
317
+ getIndex(name) {
318
+ return this.indexes.find((i) => i.name === name);
319
+ }
320
+ // ============================================================================
321
+ // Relationship Operations
322
+ // ============================================================================
323
+ /**
324
+ * Add a relationship to the schema.
325
+ */
326
+ addRelationship(rel) {
327
+ this.relationships.push(rel);
328
+ // Update table links
329
+ rel.from.table.outgoingRelations.push(rel);
330
+ rel.to.table.incomingRelations.push(rel);
331
+ // Update column links
332
+ for (const col of rel.from.columns) {
333
+ col.references = rel;
334
+ }
335
+ for (const col of rel.to.columns) {
336
+ col.referencedBy.push(rel);
337
+ }
338
+ }
339
+ /**
340
+ * Remove a relationship from the schema.
341
+ */
342
+ removeRelationship(name) {
343
+ const index = this.relationships.findIndex((r) => r.name === name);
344
+ if (index === -1)
345
+ return false;
346
+ const rel = this.relationships[index];
347
+ // Remove from table links
348
+ const fromIdx = rel.from.table.outgoingRelations.indexOf(rel);
349
+ if (fromIdx !== -1)
350
+ rel.from.table.outgoingRelations.splice(fromIdx, 1);
351
+ const toIdx = rel.to.table.incomingRelations.indexOf(rel);
352
+ if (toIdx !== -1)
353
+ rel.to.table.incomingRelations.splice(toIdx, 1);
354
+ // Remove from column links
355
+ for (const col of rel.from.columns) {
356
+ if (col.references === rel) {
357
+ col.references = undefined;
358
+ }
359
+ }
360
+ for (const col of rel.to.columns) {
361
+ const refIdx = col.referencedBy.indexOf(rel);
362
+ if (refIdx !== -1)
363
+ col.referencedBy.splice(refIdx, 1);
364
+ }
365
+ this.relationships.splice(index, 1);
366
+ return true;
367
+ }
368
+ // ============================================================================
369
+ // Utility Methods
370
+ // ============================================================================
371
+ /**
372
+ * Create a deep clone of this schema.
373
+ */
374
+ clone() {
375
+ const clone = new SchemaAST();
376
+ // First pass: clone tables and columns (without links)
377
+ for (const [name, table] of this.tables) {
378
+ const clonedColumns = new Map();
379
+ for (const [colName, col] of table.columns) {
380
+ const clonedCol = {
381
+ ...col,
382
+ table: undefined, // Will be set below
383
+ referencedBy: [],
384
+ references: undefined,
385
+ };
386
+ clonedColumns.set(colName, clonedCol);
387
+ }
388
+ const clonedTable = {
389
+ name,
390
+ columns: clonedColumns,
391
+ primaryKey: [],
392
+ indexes: [],
393
+ comment: table.comment,
394
+ schema: clone,
395
+ incomingRelations: [],
396
+ outgoingRelations: [],
397
+ };
398
+ // Link columns to table
399
+ for (const col of clonedColumns.values()) {
400
+ col.table = clonedTable;
401
+ }
402
+ // Set primary key
403
+ clonedTable.primaryKey = table.primaryKey
404
+ .map((pk) => clonedColumns.get(pk.name))
405
+ .filter(Boolean);
406
+ clone.tables.set(name, clonedTable);
407
+ }
408
+ // Second pass: clone relationships
409
+ for (const rel of this.relationships) {
410
+ const fromTable = clone.tables.get(rel.from.table.name);
411
+ const toTable = clone.tables.get(rel.to.table.name);
412
+ if (!fromTable || !toTable)
413
+ continue;
414
+ const fromColumns = rel.from.columns
415
+ .map((c) => fromTable.columns.get(c.name))
416
+ .filter((c) => c !== undefined);
417
+ const toColumns = rel.to.columns
418
+ .map((c) => toTable.columns.get(c.name))
419
+ .filter((c) => c !== undefined);
420
+ const clonedRel = {
421
+ ...rel,
422
+ from: {
423
+ table: fromTable,
424
+ columns: fromColumns,
425
+ },
426
+ to: {
427
+ table: toTable,
428
+ columns: toColumns,
429
+ },
430
+ through: rel.through ? clone.tables.get(rel.through.name) : undefined,
431
+ };
432
+ clone.addRelationship(clonedRel);
433
+ }
434
+ // Third pass: clone indexes
435
+ for (const idx of this.indexes) {
436
+ const table = clone.tables.get(idx.table.name);
437
+ if (!table)
438
+ continue;
439
+ const columns = idx.columns.map((c) => table.columns.get(c.name)).filter((c) => c !== undefined);
440
+ const clonedIdx = {
441
+ ...idx,
442
+ table,
443
+ columns,
444
+ };
445
+ clone.addIndex(clonedIdx);
446
+ }
447
+ return clone;
448
+ }
449
+ /**
450
+ * Get statistics about the schema.
451
+ */
452
+ getStats() {
453
+ let columnCount = 0;
454
+ for (const table of this.tables.values()) {
455
+ columnCount += table.columns.size;
456
+ }
457
+ return {
458
+ tableCount: this.tables.size,
459
+ columnCount,
460
+ relationshipCount: this.relationships.length,
461
+ indexCount: this.indexes.length,
462
+ };
463
+ }
464
+ /**
465
+ * Convert schema to a plain object for serialization/debugging.
466
+ */
467
+ toJSON() {
468
+ return {
469
+ tables: Array.from(this.tables.values()).map((t) => ({
470
+ name: t.name,
471
+ columns: Array.from(t.columns.values()).map((c) => ({
472
+ name: c.name,
473
+ type: c.type,
474
+ nullable: c.nullable,
475
+ isPrimaryKey: c.isPrimaryKey,
476
+ isAutoIncrement: c.isAutoIncrement,
477
+ isUnique: c.isUnique,
478
+ })),
479
+ indexes: t.indexes.map((i) => ({
480
+ name: i.name,
481
+ columns: i.columns.map((c) => c.name),
482
+ unique: i.unique,
483
+ })),
484
+ })),
485
+ relationships: this.relationships.map((r) => ({
486
+ name: r.name,
487
+ type: r.type,
488
+ from: `${r.from.table.name}.${r.from.columns.map((c) => c.name).join(',')}`,
489
+ to: `${r.to.table.name}.${r.to.columns.map((c) => c.name).join(',')}`,
490
+ onDelete: r.onDelete,
491
+ onUpdate: r.onUpdate,
492
+ })),
493
+ };
494
+ }
495
+ }
496
+ //# sourceMappingURL=schemaAST.js.map