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
package/dist/index.js CHANGED
@@ -1,10 +1,23 @@
1
1
  // src/schema/table.ts
2
- var defineTable = (name, columns, relations = {}, hooks) => {
2
+ var defineTable = (name, columns, relations = {}, hooks, options = {}) => {
3
3
  const colsWithNames = Object.entries(columns).reduce((acc, [key, def]) => {
4
4
  acc[key] = { ...def, name: key, table: name };
5
5
  return acc;
6
6
  }, {});
7
- return { name, columns: colsWithNames, relations, hooks };
7
+ return {
8
+ name,
9
+ schema: options.schema,
10
+ columns: colsWithNames,
11
+ relations,
12
+ hooks,
13
+ primaryKey: options.primaryKey,
14
+ indexes: options.indexes,
15
+ checks: options.checks,
16
+ comment: options.comment,
17
+ engine: options.engine,
18
+ charset: options.charset,
19
+ collation: options.collation
20
+ };
8
21
  };
9
22
 
10
23
  // src/schema/column.ts
@@ -14,12 +27,52 @@ var col = {
14
27
  * @returns ColumnDef with INT type
15
28
  */
16
29
  int: () => ({ name: "", type: "INT" }),
30
+ /**
31
+ * Creates a big integer column definition
32
+ */
33
+ bigint: () => ({ name: "", type: "BIGINT" }),
17
34
  /**
18
35
  * Creates a variable character column definition
19
36
  * @param length - Maximum length of the string
20
37
  * @returns ColumnDef with VARCHAR type
21
38
  */
22
39
  varchar: (length) => ({ name: "", type: "VARCHAR", args: [length] }),
40
+ /**
41
+ * Creates a fixed precision decimal column definition
42
+ */
43
+ decimal: (precision, scale = 0) => ({
44
+ name: "",
45
+ type: "DECIMAL",
46
+ args: [precision, scale]
47
+ }),
48
+ /**
49
+ * Creates a floating point column definition
50
+ */
51
+ float: (precision) => ({
52
+ name: "",
53
+ type: "FLOAT",
54
+ args: precision !== void 0 ? [precision] : void 0
55
+ }),
56
+ /**
57
+ * Creates a UUID column definition
58
+ */
59
+ uuid: () => ({ name: "", type: "UUID" }),
60
+ /**
61
+ * Creates a timestamp column definition
62
+ */
63
+ timestamp: () => ({ name: "", type: "TIMESTAMP" }),
64
+ /**
65
+ * Creates a timestamptz column definition
66
+ */
67
+ timestamptz: () => ({ name: "", type: "TIMESTAMPTZ" }),
68
+ /**
69
+ * Creates a date column definition
70
+ */
71
+ date: () => ({ name: "", type: "DATE" }),
72
+ /**
73
+ * Creates a datetime column definition
74
+ */
75
+ datetime: () => ({ name: "", type: "DATETIME" }),
23
76
  /**
24
77
  * Creates a JSON column definition
25
78
  * @returns ColumnDef with JSON type
@@ -30,12 +83,64 @@ var col = {
30
83
  * @returns ColumnDef with BOOLEAN type
31
84
  */
32
85
  boolean: () => ({ name: "", type: "BOOLEAN" }),
86
+ /**
87
+ * Creates an enum column definition
88
+ * @param values - Enum values
89
+ */
90
+ enum: (values) => ({ name: "", type: "ENUM", args: values }),
33
91
  /**
34
92
  * Marks a column definition as a primary key
35
93
  * @param def - Column definition to modify
36
94
  * @returns Modified ColumnDef with primary: true
37
95
  */
38
- primaryKey: (def) => ({ ...def, primary: true })
96
+ primaryKey: (def) => ({ ...def, primary: true }),
97
+ /**
98
+ * Marks a column as NOT NULL
99
+ */
100
+ notNull: (def) => ({ ...def, notNull: true }),
101
+ /**
102
+ * Marks a column as UNIQUE
103
+ */
104
+ unique: (def, name) => ({
105
+ ...def,
106
+ unique: name ?? true
107
+ }),
108
+ /**
109
+ * Sets a default value for the column
110
+ */
111
+ default: (def, value) => ({
112
+ ...def,
113
+ default: value
114
+ }),
115
+ /**
116
+ * Sets a raw SQL default value for the column
117
+ */
118
+ defaultRaw: (def, expression) => ({
119
+ ...def,
120
+ default: { raw: expression }
121
+ }),
122
+ /**
123
+ * Marks a column as auto-increment / identity
124
+ */
125
+ autoIncrement: (def, strategy = "byDefault") => ({
126
+ ...def,
127
+ autoIncrement: true,
128
+ generated: strategy
129
+ }),
130
+ /**
131
+ * Adds a foreign key reference
132
+ */
133
+ references: (def, ref) => ({
134
+ ...def,
135
+ references: ref
136
+ }),
137
+ /**
138
+ * Adds a check constraint to the column
139
+ */
140
+ check: (def, expression) => ({
141
+ ...def,
142
+ check: expression
143
+ })
39
144
  };
40
145
 
41
146
  // src/schema/relation.ts
@@ -2899,8 +3004,132 @@ var Dialect = class {
2899
3004
  }
2900
3005
  };
2901
3006
 
3007
+ // src/core/dialect/base/sql-dialect.ts
3008
+ var SqlDialectBase = class extends Dialect {
3009
+ /**
3010
+ * Compiles SELECT query AST to SQL using common rules.
3011
+ */
3012
+ compileSelectAst(ast, ctx) {
3013
+ const ctes = this.compileCtes(ast, ctx);
3014
+ const columns = this.compileSelectColumns(ast, ctx);
3015
+ const from = this.compileFrom(ast.from);
3016
+ const joins = this.compileJoins(ast, ctx);
3017
+ const whereClause = this.compileWhere(ast.where, ctx);
3018
+ const groupBy = this.compileGroupBy(ast);
3019
+ const having = this.compileHaving(ast, ctx);
3020
+ const orderBy = this.compileOrderBy(ast);
3021
+ const pagination = this.compilePagination(ast, orderBy);
3022
+ return `${ctes}SELECT ${this.compileDistinct(ast)}${columns} FROM ${from}${joins}${whereClause}${groupBy}${having}${orderBy}${pagination}`;
3023
+ }
3024
+ compileInsertAst(ast, ctx) {
3025
+ const table = this.compileTableName(ast.into);
3026
+ const columnList = ast.columns.map((column) => `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`).join(", ");
3027
+ const values = ast.values.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
3028
+ const returning = this.compileReturning(ast.returning, ctx);
3029
+ return `INSERT INTO ${table} (${columnList}) VALUES ${values}${returning}`;
3030
+ }
3031
+ compileUpdateAst(ast, ctx) {
3032
+ const table = this.compileTableName(ast.table);
3033
+ const assignments = ast.set.map((assignment) => {
3034
+ const col2 = assignment.column;
3035
+ const target = `${this.quoteIdentifier(col2.table)}.${this.quoteIdentifier(col2.name)}`;
3036
+ const value = this.compileOperand(assignment.value, ctx);
3037
+ return `${target} = ${value}`;
3038
+ }).join(", ");
3039
+ const whereClause = this.compileWhere(ast.where, ctx);
3040
+ const returning = this.compileReturning(ast.returning, ctx);
3041
+ return `UPDATE ${table} SET ${assignments}${whereClause}${returning}`;
3042
+ }
3043
+ compileDeleteAst(ast, ctx) {
3044
+ const table = this.compileTableName(ast.from);
3045
+ const whereClause = this.compileWhere(ast.where, ctx);
3046
+ const returning = this.compileReturning(ast.returning, ctx);
3047
+ return `DELETE FROM ${table}${whereClause}${returning}`;
3048
+ }
3049
+ /**
3050
+ * Default RETURNING compilation: no support.
3051
+ */
3052
+ compileReturning(returning, _ctx) {
3053
+ if (!returning || returning.length === 0) return "";
3054
+ throw new Error("RETURNING is not supported by this dialect.");
3055
+ }
3056
+ /**
3057
+ * DISTINCT clause. Override for DISTINCT ON support.
3058
+ */
3059
+ compileDistinct(ast) {
3060
+ return ast.distinct ? "DISTINCT " : "";
3061
+ }
3062
+ compileSelectColumns(ast, ctx) {
3063
+ return ast.columns.map((c) => {
3064
+ const expr = this.compileOperand(c, ctx);
3065
+ if (c.alias) {
3066
+ if (c.alias.includes("(")) return c.alias;
3067
+ return `${expr} AS ${this.quoteIdentifier(c.alias)}`;
3068
+ }
3069
+ return expr;
3070
+ }).join(", ");
3071
+ }
3072
+ compileFrom(ast) {
3073
+ const base = this.compileTableName(ast);
3074
+ return ast.alias ? `${base} AS ${this.quoteIdentifier(ast.alias)}` : base;
3075
+ }
3076
+ compileTableName(table) {
3077
+ if (table.schema) {
3078
+ return `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(table.name)}`;
3079
+ }
3080
+ return this.quoteIdentifier(table.name);
3081
+ }
3082
+ compileJoins(ast, ctx) {
3083
+ if (!ast.joins || ast.joins.length === 0) return "";
3084
+ const parts = ast.joins.map((j) => {
3085
+ const table = this.compileFrom(j.table);
3086
+ const cond = this.compileExpression(j.condition, ctx);
3087
+ return `${j.kind} JOIN ${table} ON ${cond}`;
3088
+ });
3089
+ return ` ${parts.join(" ")}`;
3090
+ }
3091
+ compileGroupBy(ast) {
3092
+ if (!ast.groupBy || ast.groupBy.length === 0) return "";
3093
+ const cols = ast.groupBy.map((c) => `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`).join(", ");
3094
+ return ` GROUP BY ${cols}`;
3095
+ }
3096
+ compileHaving(ast, ctx) {
3097
+ if (!ast.having) return "";
3098
+ return ` HAVING ${this.compileExpression(ast.having, ctx)}`;
3099
+ }
3100
+ compileOrderBy(ast) {
3101
+ if (!ast.orderBy || ast.orderBy.length === 0) return "";
3102
+ const parts = ast.orderBy.map((o) => `${this.quoteIdentifier(o.column.table)}.${this.quoteIdentifier(o.column.name)} ${o.direction}`).join(", ");
3103
+ return ` ORDER BY ${parts}`;
3104
+ }
3105
+ /**
3106
+ * Default LIMIT/OFFSET pagination clause.
3107
+ */
3108
+ compilePagination(ast, _orderByClause) {
3109
+ const parts = [];
3110
+ if (ast.limit !== void 0) parts.push(`LIMIT ${ast.limit}`);
3111
+ if (ast.offset !== void 0) parts.push(`OFFSET ${ast.offset}`);
3112
+ return parts.length ? ` ${parts.join(" ")}` : "";
3113
+ }
3114
+ compileCtes(ast, ctx) {
3115
+ if (!ast.ctes || ast.ctes.length === 0) return "";
3116
+ const hasRecursive = ast.ctes.some((cte) => cte.recursive);
3117
+ const prefix = hasRecursive ? "WITH RECURSIVE " : "WITH ";
3118
+ const cteDefs = ast.ctes.map((cte) => {
3119
+ const name = this.quoteIdentifier(cte.name);
3120
+ const cols = cte.columns && cte.columns.length ? `(${cte.columns.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
3121
+ const query = this.stripTrailingSemicolon(this.compileSelectAst(cte.query, ctx));
3122
+ return `${name}${cols} AS (${query})`;
3123
+ }).join(", ");
3124
+ return `${prefix}${cteDefs} `;
3125
+ }
3126
+ stripTrailingSemicolon(sql) {
3127
+ return sql.trim().replace(/;$/, "");
3128
+ }
3129
+ };
3130
+
2902
3131
  // src/core/dialect/mysql/index.ts
2903
- var MySqlDialect = class extends Dialect {
3132
+ var MySqlDialect = class extends SqlDialectBase {
2904
3133
  /**
2905
3134
  * Creates a new MySqlDialect instance
2906
3135
  */
@@ -2924,78 +3153,6 @@ var MySqlDialect = class extends Dialect {
2924
3153
  const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
2925
3154
  return `${col2}->'${node.path}'`;
2926
3155
  }
2927
- /**
2928
- * Compiles SELECT query AST to MySQL SQL
2929
- * @param ast - Query AST
2930
- * @param ctx - Compiler context
2931
- * @returns MySQL SQL string
2932
- */
2933
- compileSelectAst(ast, ctx) {
2934
- const columns = ast.columns.map((c) => {
2935
- let expr = "";
2936
- if (c.type === "Function") {
2937
- expr = this.compileOperand(c, ctx);
2938
- } else if (c.type === "Column") {
2939
- expr = `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`;
2940
- } else if (c.type === "ScalarSubquery") {
2941
- expr = this.compileOperand(c, ctx);
2942
- } else if (c.type === "WindowFunction") {
2943
- expr = this.compileOperand(c, ctx);
2944
- }
2945
- if (c.alias) {
2946
- if (c.alias.includes("(")) return c.alias;
2947
- return `${expr} AS ${this.quoteIdentifier(c.alias)}`;
2948
- }
2949
- return expr;
2950
- }).join(", ");
2951
- const distinct = ast.distinct ? "DISTINCT " : "";
2952
- const from = `${this.quoteIdentifier(ast.from.name)}`;
2953
- const joins = ast.joins.map((j) => {
2954
- const table = this.quoteIdentifier(j.table.name);
2955
- const cond = this.compileExpression(j.condition, ctx);
2956
- return `${j.kind} JOIN ${table} ON ${cond}`;
2957
- }).join(" ");
2958
- const whereClause = this.compileWhere(ast.where, ctx);
2959
- const groupBy = ast.groupBy && ast.groupBy.length > 0 ? " GROUP BY " + ast.groupBy.map((c) => `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`).join(", ") : "";
2960
- const having = ast.having ? ` HAVING ${this.compileExpression(ast.having, ctx)}` : "";
2961
- const orderBy = ast.orderBy && ast.orderBy.length > 0 ? " ORDER BY " + ast.orderBy.map((o) => `${this.quoteIdentifier(o.column.table)}.${this.quoteIdentifier(o.column.name)} ${o.direction}`).join(", ") : "";
2962
- const limit = ast.limit ? ` LIMIT ${ast.limit}` : "";
2963
- const offset = ast.offset ? ` OFFSET ${ast.offset}` : "";
2964
- const ctes = ast.ctes && ast.ctes.length > 0 ? (() => {
2965
- const hasRecursive = ast.ctes.some((cte) => cte.recursive);
2966
- const prefix = hasRecursive ? "WITH RECURSIVE " : "WITH ";
2967
- const cteDefs = ast.ctes.map((cte) => {
2968
- const name = this.quoteIdentifier(cte.name);
2969
- const cols = cte.columns ? `(${cte.columns.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
2970
- const query = this.compileSelectAst(cte.query, ctx).trim().replace(/;$/, "");
2971
- return `${name}${cols} AS (${query})`;
2972
- }).join(", ");
2973
- return prefix + cteDefs + " ";
2974
- })() : "";
2975
- return `${ctes}SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${orderBy}${limit}${offset};`;
2976
- }
2977
- compileInsertAst(ast, ctx) {
2978
- const table = this.quoteIdentifier(ast.into.name);
2979
- const columnList = ast.columns.map((column) => `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`).join(", ");
2980
- const values = ast.values.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
2981
- return `INSERT INTO ${table} (${columnList}) VALUES ${values};`;
2982
- }
2983
- compileUpdateAst(ast, ctx) {
2984
- const table = this.quoteIdentifier(ast.table.name);
2985
- const assignments = ast.set.map((assignment) => {
2986
- const col2 = assignment.column;
2987
- const target = `${this.quoteIdentifier(col2.table)}.${this.quoteIdentifier(col2.name)}`;
2988
- const value = this.compileOperand(assignment.value, ctx);
2989
- return `${target} = ${value}`;
2990
- }).join(", ");
2991
- const whereClause = this.compileWhere(ast.where, ctx);
2992
- return `UPDATE ${table} SET ${assignments}${whereClause};`;
2993
- }
2994
- compileDeleteAst(ast, ctx) {
2995
- const table = this.quoteIdentifier(ast.from.name);
2996
- const whereClause = this.compileWhere(ast.where, ctx);
2997
- return `DELETE FROM ${table}${whereClause};`;
2998
- }
2999
3156
  };
3000
3157
 
3001
3158
  // src/core/dialect/mssql/index.ts
@@ -3109,7 +3266,7 @@ var SqlServerDialect = class extends Dialect {
3109
3266
  };
3110
3267
 
3111
3268
  // src/core/dialect/sqlite/index.ts
3112
- var SqliteDialect = class extends Dialect {
3269
+ var SqliteDialect = class extends SqlDialectBase {
3113
3270
  /**
3114
3271
  * Creates a new SqliteDialect instance
3115
3272
  */
@@ -3133,82 +3290,40 @@ var SqliteDialect = class extends Dialect {
3133
3290
  const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3134
3291
  return `json_extract(${col2}, '${node.path}')`;
3135
3292
  }
3136
- /**
3137
- * Compiles SELECT query AST to SQLite SQL
3138
- * @param ast - Query AST
3139
- * @param ctx - Compiler context
3140
- * @returns SQLite SQL string
3141
- */
3142
- compileSelectAst(ast, ctx) {
3143
- const columns = ast.columns.map((c) => {
3144
- let expr = "";
3145
- if (c.type === "Function") {
3146
- expr = this.compileOperand(c, ctx);
3147
- } else if (c.type === "Column") {
3148
- expr = `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`;
3149
- } else if (c.type === "ScalarSubquery") {
3150
- expr = this.compileOperand(c, ctx);
3151
- } else if (c.type === "CaseExpression") {
3152
- expr = this.compileOperand(c, ctx);
3153
- } else if (c.type === "WindowFunction") {
3154
- expr = this.compileOperand(c, ctx);
3155
- }
3156
- if (c.alias) {
3157
- if (c.alias.includes("(")) return c.alias;
3158
- return `${expr} AS ${this.quoteIdentifier(c.alias)}`;
3159
- }
3160
- return expr;
3293
+ compileReturning(returning, ctx) {
3294
+ if (!returning || returning.length === 0) return "";
3295
+ const columns = returning.map((column) => {
3296
+ const tablePart = column.table ? `${this.quoteIdentifier(column.table)}.` : "";
3297
+ return `${tablePart}${this.quoteIdentifier(column.name)}`;
3161
3298
  }).join(", ");
3162
- const distinct = ast.distinct ? "DISTINCT " : "";
3163
- const from = `${this.quoteIdentifier(ast.from.name)}`;
3164
- const joins = ast.joins.map((j) => {
3165
- const table = this.quoteIdentifier(j.table.name);
3166
- const cond = this.compileExpression(j.condition, ctx);
3167
- return `${j.kind} JOIN ${table} ON ${cond}`;
3168
- }).join(" ");
3169
- const whereClause = this.compileWhere(ast.where, ctx);
3170
- const groupBy = ast.groupBy && ast.groupBy.length > 0 ? " GROUP BY " + ast.groupBy.map((c) => `${this.quoteIdentifier(c.table)}.${this.quoteIdentifier(c.name)}`).join(", ") : "";
3171
- const having = ast.having ? ` HAVING ${this.compileExpression(ast.having, ctx)}` : "";
3172
- const orderBy = ast.orderBy && ast.orderBy.length > 0 ? " ORDER BY " + ast.orderBy.map((o) => `${this.quoteIdentifier(o.column.table)}.${this.quoteIdentifier(o.column.name)} ${o.direction}`).join(", ") : "";
3173
- const limit = ast.limit ? ` LIMIT ${ast.limit}` : "";
3174
- const offset = ast.offset ? ` OFFSET ${ast.offset}` : "";
3175
- const ctes = ast.ctes && ast.ctes.length > 0 ? (() => {
3176
- const hasRecursive = ast.ctes.some((cte) => cte.recursive);
3177
- const prefix = hasRecursive ? "WITH RECURSIVE " : "WITH ";
3178
- const cteDefs = ast.ctes.map((cte) => {
3179
- const name = this.quoteIdentifier(cte.name);
3180
- const cols = cte.columns ? `(${cte.columns.map((c) => this.quoteIdentifier(c)).join(", ")})` : "";
3181
- const query = this.compileSelectAst(cte.query, ctx).trim().replace(/;$/, "");
3182
- return `${name}${cols} AS (${query})`;
3183
- }).join(", ");
3184
- return prefix + cteDefs + " ";
3185
- })() : "";
3186
- return `${ctes}SELECT ${distinct}${columns} FROM ${from}${joins ? " " + joins : ""}${whereClause}${groupBy}${having}${orderBy}${limit}${offset};`;
3299
+ return ` RETURNING ${columns}`;
3187
3300
  }
3188
- compileInsertAst(ast, ctx) {
3189
- const table = this.quoteIdentifier(ast.into.name);
3190
- const columnList = ast.columns.map((column) => `${this.quoteIdentifier(column.table)}.${this.quoteIdentifier(column.name)}`).join(", ");
3191
- const values = ast.values.map((row) => `(${row.map((value) => this.compileOperand(value, ctx)).join(", ")})`).join(", ");
3192
- const returning = this.compileReturning(ast.returning, ctx);
3193
- return `INSERT INTO ${table} (${columnList}) VALUES ${values}${returning};`;
3301
+ };
3302
+
3303
+ // src/core/dialect/postgres/index.ts
3304
+ var PostgresDialect = class extends SqlDialectBase {
3305
+ /**
3306
+ * Creates a new PostgresDialect instance
3307
+ */
3308
+ constructor() {
3309
+ super();
3194
3310
  }
3195
- compileUpdateAst(ast, ctx) {
3196
- const table = this.quoteIdentifier(ast.table.name);
3197
- const assignments = ast.set.map((assignment) => {
3198
- const col2 = assignment.column;
3199
- const target = `${this.quoteIdentifier(col2.table)}.${this.quoteIdentifier(col2.name)}`;
3200
- const value = this.compileOperand(assignment.value, ctx);
3201
- return `${target} = ${value}`;
3202
- }).join(", ");
3203
- const whereClause = this.compileWhere(ast.where, ctx);
3204
- const returning = this.compileReturning(ast.returning, ctx);
3205
- return `UPDATE ${table} SET ${assignments}${whereClause}${returning};`;
3311
+ /**
3312
+ * Quotes an identifier using PostgreSQL double-quote syntax
3313
+ * @param id - Identifier to quote
3314
+ * @returns Quoted identifier
3315
+ */
3316
+ quoteIdentifier(id) {
3317
+ return `"${id}"`;
3206
3318
  }
3207
- compileDeleteAst(ast, ctx) {
3208
- const table = this.quoteIdentifier(ast.from.name);
3209
- const whereClause = this.compileWhere(ast.where, ctx);
3210
- const returning = this.compileReturning(ast.returning, ctx);
3211
- return `DELETE FROM ${table}${whereClause}${returning};`;
3319
+ /**
3320
+ * Compiles JSON path expression using PostgreSQL syntax
3321
+ * @param node - JSON path node
3322
+ * @returns PostgreSQL JSON path expression
3323
+ */
3324
+ compileJsonPath(node) {
3325
+ const col2 = `${this.quoteIdentifier(node.column.table)}.${this.quoteIdentifier(node.column.name)}`;
3326
+ return `${col2}->>'${node.path}'`;
3212
3327
  }
3213
3328
  compileReturning(returning, ctx) {
3214
3329
  if (!returning || returning.length === 0) return "";
@@ -3220,6 +3335,1100 @@ var SqliteDialect = class extends Dialect {
3220
3335
  }
3221
3336
  };
3222
3337
 
3338
+ // src/core/ddl/dialects/base-schema-dialect.ts
3339
+ var BaseSchemaDialect = class {
3340
+ supportsPartialIndexes() {
3341
+ return false;
3342
+ }
3343
+ formatTableName(table) {
3344
+ if (table.schema) {
3345
+ return `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(table.name)}`;
3346
+ }
3347
+ return this.quoteIdentifier(table.name);
3348
+ }
3349
+ renderDefault(value, _column) {
3350
+ return formatLiteral(value, this.name);
3351
+ }
3352
+ renderReference(ref, _table) {
3353
+ const parts = ["REFERENCES", quoteQualified(this, ref.table), `(${this.quoteIdentifier(ref.column)})`];
3354
+ if (ref.onDelete) parts.push("ON DELETE", ref.onDelete);
3355
+ if (ref.onUpdate) parts.push("ON UPDATE", ref.onUpdate);
3356
+ if (ref.deferrable && this.name === "postgres") parts.push("DEFERRABLE INITIALLY DEFERRED");
3357
+ return parts.join(" ");
3358
+ }
3359
+ renderTableOptions(_table) {
3360
+ return void 0;
3361
+ }
3362
+ dropTableSql(table) {
3363
+ return [`DROP TABLE IF EXISTS ${this.formatTableName(table)};`];
3364
+ }
3365
+ warnDropColumn(_table, _column) {
3366
+ return void 0;
3367
+ }
3368
+ };
3369
+
3370
+ // src/core/ddl/dialects/postgres-schema-dialect.ts
3371
+ var PostgresSchemaDialect = class extends BaseSchemaDialect {
3372
+ constructor() {
3373
+ super(...arguments);
3374
+ this.name = "postgres";
3375
+ }
3376
+ quoteIdentifier(id) {
3377
+ return `"${id}"`;
3378
+ }
3379
+ renderColumnType(column) {
3380
+ switch (column.type) {
3381
+ case "INT":
3382
+ case "INTEGER":
3383
+ case "int":
3384
+ case "integer":
3385
+ return "integer";
3386
+ case "BIGINT":
3387
+ case "bigint":
3388
+ return "bigint";
3389
+ case "UUID":
3390
+ case "uuid":
3391
+ return "uuid";
3392
+ case "BOOLEAN":
3393
+ case "boolean":
3394
+ return "boolean";
3395
+ case "JSON":
3396
+ case "json":
3397
+ return "jsonb";
3398
+ case "DECIMAL":
3399
+ case "decimal":
3400
+ return column.args?.length ? `numeric(${column.args[0]}, ${column.args[1] ?? 0})` : "numeric";
3401
+ case "FLOAT":
3402
+ case "float":
3403
+ case "DOUBLE":
3404
+ case "double":
3405
+ return "double precision";
3406
+ case "TIMESTAMPTZ":
3407
+ case "timestamptz":
3408
+ return "timestamptz";
3409
+ case "TIMESTAMP":
3410
+ case "timestamp":
3411
+ return "timestamp";
3412
+ case "DATE":
3413
+ case "date":
3414
+ return "date";
3415
+ case "DATETIME":
3416
+ case "datetime":
3417
+ return "timestamp";
3418
+ case "VARCHAR":
3419
+ case "varchar":
3420
+ return column.args?.length ? `varchar(${column.args[0]})` : "varchar";
3421
+ case "TEXT":
3422
+ case "text":
3423
+ return "text";
3424
+ case "ENUM":
3425
+ case "enum":
3426
+ return "text";
3427
+ default:
3428
+ return String(column.type).toLowerCase();
3429
+ }
3430
+ }
3431
+ renderAutoIncrement(column) {
3432
+ if (!column.autoIncrement) return void 0;
3433
+ const strategy = column.generated === "always" ? "GENERATED ALWAYS" : "GENERATED BY DEFAULT";
3434
+ return `${strategy} AS IDENTITY`;
3435
+ }
3436
+ renderIndex(table, index) {
3437
+ const name = index.name || deriveIndexName(table, index);
3438
+ const cols = renderIndexColumns(this, index.columns);
3439
+ const unique = index.unique ? "UNIQUE " : "";
3440
+ const where = index.where ? ` WHERE ${index.where}` : "";
3441
+ return `CREATE ${unique}INDEX IF NOT EXISTS ${this.quoteIdentifier(name)} ON ${this.formatTableName(table)} (${cols})${where};`;
3442
+ }
3443
+ supportsPartialIndexes() {
3444
+ return true;
3445
+ }
3446
+ dropColumnSql(table, column) {
3447
+ return [`ALTER TABLE ${this.formatTableName(table)} DROP COLUMN ${this.quoteIdentifier(column)};`];
3448
+ }
3449
+ dropIndexSql(table, index) {
3450
+ const qualified = table.schema ? `${this.quoteIdentifier(table.schema)}.${this.quoteIdentifier(index)}` : this.quoteIdentifier(index);
3451
+ return [`DROP INDEX IF EXISTS ${qualified};`];
3452
+ }
3453
+ };
3454
+
3455
+ // src/core/ddl/dialects/mysql-schema-dialect.ts
3456
+ var MySqlSchemaDialect = class extends BaseSchemaDialect {
3457
+ constructor() {
3458
+ super(...arguments);
3459
+ this.name = "mysql";
3460
+ }
3461
+ quoteIdentifier(id) {
3462
+ return `\`${id}\``;
3463
+ }
3464
+ renderColumnType(column) {
3465
+ switch (column.type) {
3466
+ case "INT":
3467
+ case "INTEGER":
3468
+ case "int":
3469
+ case "integer":
3470
+ return "INT";
3471
+ case "BIGINT":
3472
+ case "bigint":
3473
+ return "BIGINT";
3474
+ case "UUID":
3475
+ case "uuid":
3476
+ return "CHAR(36)";
3477
+ case "BOOLEAN":
3478
+ case "boolean":
3479
+ return "TINYINT(1)";
3480
+ case "JSON":
3481
+ case "json":
3482
+ return "JSON";
3483
+ case "DECIMAL":
3484
+ case "decimal":
3485
+ return column.args?.length ? `DECIMAL(${column.args[0]},${column.args[1] ?? 0})` : "DECIMAL";
3486
+ case "FLOAT":
3487
+ case "float":
3488
+ return column.args?.length ? `FLOAT(${column.args[0]})` : "FLOAT";
3489
+ case "DOUBLE":
3490
+ case "double":
3491
+ return "DOUBLE";
3492
+ case "TIMESTAMPTZ":
3493
+ case "timestamptz":
3494
+ return "TIMESTAMP";
3495
+ case "TIMESTAMP":
3496
+ case "timestamp":
3497
+ return "TIMESTAMP";
3498
+ case "DATETIME":
3499
+ case "datetime":
3500
+ return "DATETIME";
3501
+ case "DATE":
3502
+ case "date":
3503
+ return "DATE";
3504
+ case "VARCHAR":
3505
+ case "varchar":
3506
+ return column.args?.length ? `VARCHAR(${column.args[0]})` : "VARCHAR(255)";
3507
+ case "TEXT":
3508
+ case "text":
3509
+ return "TEXT";
3510
+ case "ENUM":
3511
+ case "enum":
3512
+ return column.args && Array.isArray(column.args) && column.args.length ? `ENUM(${column.args.map((v) => `'${escapeLiteral(v)}'`).join(",")})` : "ENUM";
3513
+ default:
3514
+ return String(column.type).toUpperCase();
3515
+ }
3516
+ }
3517
+ renderDefault(value) {
3518
+ return formatLiteral(value, this.name);
3519
+ }
3520
+ renderAutoIncrement(column) {
3521
+ return column.autoIncrement ? "AUTO_INCREMENT" : void 0;
3522
+ }
3523
+ renderIndex(table, index) {
3524
+ if (index.where) {
3525
+ throw new Error("MySQL does not support partial/filtered indexes");
3526
+ }
3527
+ const name = index.name || deriveIndexName(table, index);
3528
+ const cols = renderIndexColumns(this, index.columns);
3529
+ const unique = index.unique ? "UNIQUE " : "";
3530
+ return `CREATE ${unique}INDEX ${this.quoteIdentifier(name)} ON ${this.formatTableName(table)} (${cols});`;
3531
+ }
3532
+ renderTableOptions(table) {
3533
+ const parts = [];
3534
+ if (table.engine) parts.push(`ENGINE=${table.engine}`);
3535
+ if (table.charset) parts.push(`DEFAULT CHARSET=${table.charset}`);
3536
+ if (table.collation) parts.push(`COLLATE=${table.collation}`);
3537
+ return parts.length ? parts.join(" ") : void 0;
3538
+ }
3539
+ dropColumnSql(table, column) {
3540
+ return [`ALTER TABLE ${this.formatTableName(table)} DROP COLUMN ${this.quoteIdentifier(column)};`];
3541
+ }
3542
+ dropIndexSql(table, index) {
3543
+ return [`DROP INDEX ${this.quoteIdentifier(index)} ON ${this.formatTableName(table)};`];
3544
+ }
3545
+ };
3546
+
3547
+ // src/core/ddl/dialects/sqlite-schema-dialect.ts
3548
+ var SQLiteSchemaDialect = class extends BaseSchemaDialect {
3549
+ constructor() {
3550
+ super(...arguments);
3551
+ this.name = "sqlite";
3552
+ }
3553
+ quoteIdentifier(id) {
3554
+ return `"${id}"`;
3555
+ }
3556
+ renderColumnType(column) {
3557
+ switch (column.type) {
3558
+ case "INT":
3559
+ case "INTEGER":
3560
+ case "int":
3561
+ case "integer":
3562
+ case "BIGINT":
3563
+ case "bigint":
3564
+ return "INTEGER";
3565
+ case "BOOLEAN":
3566
+ case "boolean":
3567
+ return "INTEGER";
3568
+ case "DECIMAL":
3569
+ case "decimal":
3570
+ case "FLOAT":
3571
+ case "float":
3572
+ case "DOUBLE":
3573
+ case "double":
3574
+ return "REAL";
3575
+ case "DATE":
3576
+ case "date":
3577
+ case "DATETIME":
3578
+ case "datetime":
3579
+ case "TIMESTAMP":
3580
+ case "timestamp":
3581
+ case "TIMESTAMPTZ":
3582
+ case "timestamptz":
3583
+ return "TEXT";
3584
+ case "VARCHAR":
3585
+ case "varchar":
3586
+ case "TEXT":
3587
+ case "text":
3588
+ case "JSON":
3589
+ case "json":
3590
+ case "UUID":
3591
+ case "uuid":
3592
+ return "TEXT";
3593
+ case "ENUM":
3594
+ case "enum":
3595
+ return "TEXT";
3596
+ default:
3597
+ return "TEXT";
3598
+ }
3599
+ }
3600
+ renderAutoIncrement(column, table) {
3601
+ const pk = resolvePrimaryKey(table);
3602
+ if (column.autoIncrement && pk.length === 1 && pk[0] === column.name) {
3603
+ return "PRIMARY KEY AUTOINCREMENT";
3604
+ }
3605
+ return void 0;
3606
+ }
3607
+ preferInlinePkAutoincrement(column, table, pk) {
3608
+ return !!(column.autoIncrement && pk.length === 1 && pk[0] === column.name);
3609
+ }
3610
+ renderDefault(value) {
3611
+ return formatLiteral(value, this.name);
3612
+ }
3613
+ renderIndex(table, index) {
3614
+ if (index.where) {
3615
+ throw new Error("SQLite does not support partial/filtered indexes");
3616
+ }
3617
+ const name = index.name || deriveIndexName(table, index);
3618
+ const cols = renderIndexColumns(this, index.columns);
3619
+ const unique = index.unique ? "UNIQUE " : "";
3620
+ return `CREATE ${unique}INDEX IF NOT EXISTS ${this.quoteIdentifier(name)} ON ${this.formatTableName(table)} (${cols});`;
3621
+ }
3622
+ dropColumnSql(_table, _column) {
3623
+ return [];
3624
+ }
3625
+ dropIndexSql(_table, index) {
3626
+ return [`DROP INDEX IF EXISTS ${this.quoteIdentifier(index)};`];
3627
+ }
3628
+ warnDropColumn(table, column) {
3629
+ const key = table.schema ? `${table.schema}.${table.name}` : table.name;
3630
+ return `Dropping columns on SQLite requires table rebuild (column ${column} on ${key}).`;
3631
+ }
3632
+ };
3633
+
3634
+ // src/core/ddl/dialects/mssql-schema-dialect.ts
3635
+ var MSSqlSchemaDialect = class extends BaseSchemaDialect {
3636
+ constructor() {
3637
+ super(...arguments);
3638
+ this.name = "mssql";
3639
+ }
3640
+ quoteIdentifier(id) {
3641
+ return `[${id.replace(/]/g, "]]")}]`;
3642
+ }
3643
+ renderColumnType(column) {
3644
+ switch (column.type) {
3645
+ case "INT":
3646
+ case "INTEGER":
3647
+ case "int":
3648
+ case "integer":
3649
+ return "INT";
3650
+ case "BIGINT":
3651
+ case "bigint":
3652
+ return "BIGINT";
3653
+ case "UUID":
3654
+ case "uuid":
3655
+ return "UNIQUEIDENTIFIER";
3656
+ case "BOOLEAN":
3657
+ case "boolean":
3658
+ return "BIT";
3659
+ case "JSON":
3660
+ case "json":
3661
+ return "NVARCHAR(MAX)";
3662
+ case "DECIMAL":
3663
+ case "decimal":
3664
+ return column.args?.length ? `DECIMAL(${column.args[0]},${column.args[1] ?? 0})` : "DECIMAL(18,0)";
3665
+ case "FLOAT":
3666
+ case "float":
3667
+ case "DOUBLE":
3668
+ case "double":
3669
+ return "FLOAT";
3670
+ case "TIMESTAMPTZ":
3671
+ case "timestamptz":
3672
+ case "TIMESTAMP":
3673
+ case "timestamp":
3674
+ case "DATETIME":
3675
+ case "datetime":
3676
+ return "DATETIME2";
3677
+ case "DATE":
3678
+ case "date":
3679
+ return "DATE";
3680
+ case "VARCHAR":
3681
+ case "varchar":
3682
+ return column.args?.length ? `NVARCHAR(${column.args[0]})` : "NVARCHAR(255)";
3683
+ case "TEXT":
3684
+ case "text":
3685
+ return "NVARCHAR(MAX)";
3686
+ case "ENUM":
3687
+ case "enum":
3688
+ return "NVARCHAR(255)";
3689
+ default:
3690
+ return String(column.type).toUpperCase();
3691
+ }
3692
+ }
3693
+ renderDefault(value) {
3694
+ return formatLiteral(value, this.name);
3695
+ }
3696
+ renderAutoIncrement(column) {
3697
+ return column.autoIncrement ? "IDENTITY(1,1)" : void 0;
3698
+ }
3699
+ renderIndex(table, index) {
3700
+ const name = index.name || deriveIndexName(table, index);
3701
+ const cols = renderIndexColumns(this, index.columns);
3702
+ const unique = index.unique ? "UNIQUE " : "";
3703
+ const where = index.where ? ` WHERE ${index.where}` : "";
3704
+ return `CREATE ${unique}INDEX ${this.quoteIdentifier(name)} ON ${this.formatTableName(table)} (${cols})${where};`;
3705
+ }
3706
+ supportsPartialIndexes() {
3707
+ return true;
3708
+ }
3709
+ dropColumnSql(table, column) {
3710
+ return [`ALTER TABLE ${this.formatTableName(table)} DROP COLUMN ${this.quoteIdentifier(column)};`];
3711
+ }
3712
+ dropIndexSql(table, index) {
3713
+ return [`DROP INDEX ${this.quoteIdentifier(index)} ON ${this.formatTableName(table)};`];
3714
+ }
3715
+ };
3716
+
3717
+ // src/core/ddl/schema-generator.ts
3718
+ var escapeLiteral = (value) => value.replace(/'/g, "''");
3719
+ var isRawDefault = (value) => {
3720
+ return !!value && typeof value === "object" && "raw" in value && typeof value.raw === "string";
3721
+ };
3722
+ var formatLiteral = (value, dialect) => {
3723
+ if (isRawDefault(value)) return value.raw;
3724
+ if (value === null) return "NULL";
3725
+ if (typeof value === "number") return Number.isFinite(value) ? String(value) : "NULL";
3726
+ if (typeof value === "boolean") {
3727
+ if (dialect === "mysql" || dialect === "sqlite" || dialect === "mssql") {
3728
+ return value ? "1" : "0";
3729
+ }
3730
+ return value ? "TRUE" : "FALSE";
3731
+ }
3732
+ if (value instanceof Date) return `'${escapeLiteral(value.toISOString())}'`;
3733
+ if (typeof value === "string") return `'${escapeLiteral(value)}'`;
3734
+ return `'${escapeLiteral(JSON.stringify(value))}'`;
3735
+ };
3736
+ var resolvePrimaryKey = (table) => {
3737
+ if (table.primaryKey && table.primaryKey.length > 0) {
3738
+ return table.primaryKey;
3739
+ }
3740
+ const cols = Object.values(table.columns);
3741
+ return cols.filter((c) => c.primary).map((c) => c.name);
3742
+ };
3743
+ var quoteQualified = (dialect, identifier) => {
3744
+ if (identifier.includes(".")) {
3745
+ return identifier.split(".").map((part) => dialect.quoteIdentifier(part)).join(".");
3746
+ }
3747
+ return dialect.quoteIdentifier(identifier);
3748
+ };
3749
+ var renderIndexColumns = (dialect, columns) => {
3750
+ return columns.map((col2) => {
3751
+ if (typeof col2 === "string") return dialect.quoteIdentifier(col2);
3752
+ const parts = [dialect.quoteIdentifier(col2.column)];
3753
+ if (col2.order) parts.push(col2.order);
3754
+ if (col2.nulls) parts.push(`NULLS ${col2.nulls}`);
3755
+ return parts.join(" ");
3756
+ }).join(", ");
3757
+ };
3758
+ var deriveIndexName = (table, index) => {
3759
+ const base = (index.columns || []).map((col2) => typeof col2 === "string" ? col2 : col2.column).join("_");
3760
+ const suffix = index.unique ? "uniq" : "idx";
3761
+ return `${table.name}_${base}_${suffix}`;
3762
+ };
3763
+ var renderColumnDefinition = (table, col2, dialect, options = {}) => {
3764
+ const parts = [];
3765
+ parts.push(dialect.quoteIdentifier(col2.name));
3766
+ parts.push(dialect.renderColumnType(col2));
3767
+ const autoInc = dialect.renderAutoIncrement(col2, table);
3768
+ if (autoInc) parts.push(autoInc);
3769
+ if (col2.notNull) parts.push("NOT NULL");
3770
+ if (col2.unique) parts.push("UNIQUE");
3771
+ if (col2.default !== void 0) {
3772
+ parts.push(`DEFAULT ${dialect.renderDefault(col2.default, col2)}`);
3773
+ }
3774
+ if (options.includePrimary && col2.primary) {
3775
+ parts.push("PRIMARY KEY");
3776
+ }
3777
+ if (col2.check) {
3778
+ parts.push(`CHECK (${col2.check})`);
3779
+ }
3780
+ if (col2.references) {
3781
+ parts.push(dialect.renderReference(col2.references, table));
3782
+ }
3783
+ return { sql: parts.join(" "), inlinePrimary: !!(options.includePrimary && col2.primary) };
3784
+ };
3785
+ var generateCreateTableSql = (table, dialect) => {
3786
+ const pk = resolvePrimaryKey(table);
3787
+ const inlinePkColumns = /* @__PURE__ */ new Set();
3788
+ const columnLines = Object.values(table.columns).map((col2) => {
3789
+ const includePk = dialect.preferInlinePkAutoincrement?.(col2, table, pk) && pk.includes(col2.name);
3790
+ if (includePk) {
3791
+ inlinePkColumns.add(col2.name);
3792
+ }
3793
+ return renderColumnDefinition(table, col2, dialect, { includePrimary: includePk }).sql;
3794
+ });
3795
+ const constraintLines = [];
3796
+ if (pk.length > 0 && !(pk.length === 1 && inlinePkColumns.has(pk[0]))) {
3797
+ const cols = pk.map((c) => dialect.quoteIdentifier(c)).join(", ");
3798
+ constraintLines.push(`PRIMARY KEY (${cols})`);
3799
+ }
3800
+ if (table.checks) {
3801
+ table.checks.forEach((check) => {
3802
+ const name = check.name ? `${dialect.quoteIdentifier(check.name)} ` : "";
3803
+ constraintLines.push(`CONSTRAINT ${name}CHECK (${check.expression})`);
3804
+ });
3805
+ }
3806
+ const allLines = [...columnLines, ...constraintLines];
3807
+ const body = allLines.map((line) => ` ${line}`).join(",\n");
3808
+ const tableOptions = dialect.renderTableOptions(table);
3809
+ const tableSql = `CREATE TABLE ${dialect.formatTableName(table)} (
3810
+ ${body}
3811
+ )${tableOptions ? " " + tableOptions : ""};`;
3812
+ const indexSql = [];
3813
+ if (table.indexes && table.indexes.length > 0) {
3814
+ for (const idx of table.indexes) {
3815
+ if (idx.where && !dialect.supportsPartialIndexes()) {
3816
+ throw new Error(`Dialect ${dialect.name} does not support partial/filtered indexes (${idx.name || idx.columns.join("_")}).`);
3817
+ }
3818
+ indexSql.push(dialect.renderIndex(table, idx));
3819
+ }
3820
+ }
3821
+ return { tableSql, indexSql };
3822
+ };
3823
+ var generateSchemaSql = (tables, dialect) => {
3824
+ const ordered = orderTablesByDependencies(tables);
3825
+ const statements = [];
3826
+ ordered.forEach((table) => {
3827
+ const { tableSql, indexSql } = generateCreateTableSql(table, dialect);
3828
+ statements.push(tableSql, ...indexSql);
3829
+ });
3830
+ return statements;
3831
+ };
3832
+ var orderTablesByDependencies = (tables) => {
3833
+ const map = /* @__PURE__ */ new Map();
3834
+ tables.forEach((t) => map.set(t.name, t));
3835
+ const deps = /* @__PURE__ */ new Map();
3836
+ for (const table of tables) {
3837
+ const refTables = /* @__PURE__ */ new Set();
3838
+ Object.values(table.columns).forEach((col2) => {
3839
+ if (col2.references?.table) {
3840
+ refTables.add(col2.references.table);
3841
+ }
3842
+ });
3843
+ deps.set(table.name, refTables);
3844
+ }
3845
+ const visited = /* @__PURE__ */ new Set();
3846
+ const ordered = [];
3847
+ const visit = (name, stack) => {
3848
+ if (visited.has(name)) return;
3849
+ const table = map.get(name);
3850
+ if (!table) return;
3851
+ if (stack.has(name)) {
3852
+ ordered.push(table);
3853
+ visited.add(name);
3854
+ return;
3855
+ }
3856
+ stack.add(name);
3857
+ for (const dep of deps.get(name) || []) {
3858
+ visit(dep, stack);
3859
+ }
3860
+ stack.delete(name);
3861
+ visited.add(name);
3862
+ ordered.push(table);
3863
+ };
3864
+ tables.forEach((t) => visit(t.name, /* @__PURE__ */ new Set()));
3865
+ return ordered;
3866
+ };
3867
+
3868
+ // src/core/ddl/schema-diff.ts
3869
+ var tableKey = (name, schema) => schema ? `${schema}.${name}` : name;
3870
+ var mapTables = (schema) => {
3871
+ const map = /* @__PURE__ */ new Map();
3872
+ for (const table of schema.tables) {
3873
+ map.set(tableKey(table.name, table.schema), table);
3874
+ }
3875
+ return map;
3876
+ };
3877
+ var buildAddColumnSql = (table, colName, dialect) => {
3878
+ const column = table.columns[colName];
3879
+ const rendered = renderColumnDefinition(table, column, dialect);
3880
+ return `ALTER TABLE ${dialect.formatTableName(table)} ADD ${rendered.sql};`;
3881
+ };
3882
+ var diffSchema = (expectedTables, actualSchema, dialect, options = {}) => {
3883
+ const allowDestructive = options.allowDestructive ?? false;
3884
+ const plan = { changes: [], warnings: [] };
3885
+ const actualMap = mapTables(actualSchema);
3886
+ for (const table of expectedTables) {
3887
+ const key = tableKey(table.name, table.schema);
3888
+ const actual = actualMap.get(key);
3889
+ if (!actual) {
3890
+ const { tableSql, indexSql } = generateCreateTableSql(table, dialect);
3891
+ plan.changes.push({
3892
+ kind: "createTable",
3893
+ table: key,
3894
+ description: `Create table ${key}`,
3895
+ statements: [tableSql, ...indexSql],
3896
+ safe: true
3897
+ });
3898
+ continue;
3899
+ }
3900
+ const actualCols = new Map(actual.columns.map((c) => [c.name, c]));
3901
+ for (const colName of Object.keys(table.columns)) {
3902
+ if (!actualCols.has(colName)) {
3903
+ plan.changes.push({
3904
+ kind: "addColumn",
3905
+ table: key,
3906
+ description: `Add column ${colName} to ${key}`,
3907
+ statements: [buildAddColumnSql(table, colName, dialect)],
3908
+ safe: true
3909
+ });
3910
+ }
3911
+ }
3912
+ for (const colName of actualCols.keys()) {
3913
+ if (!table.columns[colName]) {
3914
+ plan.changes.push({
3915
+ kind: "dropColumn",
3916
+ table: key,
3917
+ description: `Drop column ${colName} from ${key}`,
3918
+ statements: allowDestructive ? dialect.dropColumnSql(actual, colName) : [],
3919
+ safe: false
3920
+ });
3921
+ const warning = dialect.warnDropColumn?.(actual, colName);
3922
+ if (warning) plan.warnings.push(warning);
3923
+ }
3924
+ }
3925
+ const expectedIndexes = table.indexes ?? [];
3926
+ const actualIndexes = actual.indexes ?? [];
3927
+ const actualIndexMap = new Map(actualIndexes.map((idx) => [idx.name, idx]));
3928
+ for (const idx of expectedIndexes) {
3929
+ const name = idx.name || deriveIndexName(table, idx);
3930
+ if (!actualIndexMap.has(name)) {
3931
+ plan.changes.push({
3932
+ kind: "addIndex",
3933
+ table: key,
3934
+ description: `Create index ${name} on ${key}`,
3935
+ statements: [dialect.renderIndex(table, { ...idx, name })],
3936
+ safe: true
3937
+ });
3938
+ }
3939
+ }
3940
+ for (const idx of actualIndexes) {
3941
+ if (idx.name && !expectedIndexes.find((expected) => (expected.name || deriveIndexName(table, expected)) === idx.name)) {
3942
+ plan.changes.push({
3943
+ kind: "dropIndex",
3944
+ table: key,
3945
+ description: `Drop index ${idx.name} on ${key}`,
3946
+ statements: allowDestructive ? dialect.dropIndexSql(actual, idx.name) : [],
3947
+ safe: false
3948
+ });
3949
+ }
3950
+ }
3951
+ }
3952
+ for (const actual of actualSchema.tables) {
3953
+ const key = tableKey(actual.name, actual.schema);
3954
+ if (!expectedTables.find((t) => tableKey(t.name, t.schema) === key)) {
3955
+ plan.changes.push({
3956
+ kind: "dropTable",
3957
+ table: key,
3958
+ description: `Drop table ${key}`,
3959
+ statements: allowDestructive ? dialect.dropTableSql(actual) : [],
3960
+ safe: false
3961
+ });
3962
+ }
3963
+ }
3964
+ return plan;
3965
+ };
3966
+ var synchronizeSchema = async (expectedTables, actualSchema, dialect, executor, options = {}) => {
3967
+ const plan = diffSchema(expectedTables, actualSchema, dialect, options);
3968
+ if (options.dryRun) return plan;
3969
+ for (const change of plan.changes) {
3970
+ if (!change.statements.length) continue;
3971
+ if (!change.safe && !options.allowDestructive) continue;
3972
+ for (const stmt of change.statements) {
3973
+ if (!stmt.trim()) continue;
3974
+ await executor.executeSql(stmt);
3975
+ }
3976
+ }
3977
+ return plan;
3978
+ };
3979
+
3980
+ // src/core/ddl/introspect/utils.ts
3981
+ var toRows = (result) => {
3982
+ if (!result) return [];
3983
+ return result.values.map(
3984
+ (row) => result.columns.reduce((acc, col2, idx) => {
3985
+ acc[col2] = row[idx];
3986
+ return acc;
3987
+ }, {})
3988
+ );
3989
+ };
3990
+ var queryRows = async (executor, sql, params = []) => {
3991
+ const [first] = await executor.executeSql(sql, params);
3992
+ return toRows(first);
3993
+ };
3994
+ var shouldIncludeTable = (name, options) => {
3995
+ if (options.includeTables && !options.includeTables.includes(name)) return false;
3996
+ if (options.excludeTables && options.excludeTables.includes(name)) return false;
3997
+ return true;
3998
+ };
3999
+
4000
+ // src/core/ddl/introspect/postgres.ts
4001
+ var postgresIntrospector = {
4002
+ async introspect(executor, options) {
4003
+ const schema = options.schema || "public";
4004
+ const tables = [];
4005
+ const columnRows = await queryRows(
4006
+ executor,
4007
+ `
4008
+ SELECT table_schema, table_name, column_name, data_type, is_nullable, column_default
4009
+ FROM information_schema.columns
4010
+ WHERE table_schema = $1
4011
+ ORDER BY table_name, ordinal_position
4012
+ `,
4013
+ [schema]
4014
+ );
4015
+ const pkRows = await queryRows(
4016
+ executor,
4017
+ `
4018
+ SELECT
4019
+ ns.nspname AS table_schema,
4020
+ tbl.relname AS table_name,
4021
+ array_agg(att.attname ORDER BY arr.idx) AS pk_columns
4022
+ FROM pg_index i
4023
+ JOIN pg_class tbl ON tbl.oid = i.indrelid
4024
+ JOIN pg_namespace ns ON ns.oid = tbl.relnamespace
4025
+ JOIN LATERAL unnest(i.indkey) WITH ORDINALITY AS arr(attnum, idx) ON TRUE
4026
+ LEFT JOIN pg_attribute att ON att.attrelid = tbl.oid AND att.attnum = arr.attnum
4027
+ WHERE i.indisprimary AND ns.nspname = $1
4028
+ GROUP BY ns.nspname, tbl.relname
4029
+ `,
4030
+ [schema]
4031
+ );
4032
+ const pkMap = /* @__PURE__ */ new Map();
4033
+ pkRows.forEach((r) => {
4034
+ pkMap.set(`${r.table_schema}.${r.table_name}`, r.pk_columns || []);
4035
+ });
4036
+ const fkRows = await queryRows(
4037
+ executor,
4038
+ `
4039
+ SELECT
4040
+ tc.table_schema,
4041
+ tc.table_name,
4042
+ kcu.column_name,
4043
+ ccu.table_schema AS foreign_table_schema,
4044
+ ccu.table_name AS foreign_table_name,
4045
+ ccu.column_name AS foreign_column_name,
4046
+ rc.update_rule AS on_update,
4047
+ rc.delete_rule AS on_delete
4048
+ FROM information_schema.table_constraints AS tc
4049
+ JOIN information_schema.key_column_usage AS kcu
4050
+ ON tc.constraint_name = kcu.constraint_name AND tc.table_schema = kcu.table_schema
4051
+ JOIN information_schema.constraint_column_usage AS ccu
4052
+ ON ccu.constraint_name = tc.constraint_name AND ccu.table_schema = tc.table_schema
4053
+ JOIN information_schema.referential_constraints rc
4054
+ ON rc.constraint_name = tc.constraint_name AND rc.constraint_schema = tc.table_schema
4055
+ WHERE tc.constraint_type = 'FOREIGN KEY' AND tc.table_schema = $1
4056
+ `,
4057
+ [schema]
4058
+ );
4059
+ const fkMap = /* @__PURE__ */ new Map();
4060
+ fkRows.forEach((r) => {
4061
+ const key = `${r.table_schema}.${r.table_name}.${r.column_name}`;
4062
+ fkMap.set(key, [{
4063
+ table: `${r.foreign_table_schema}.${r.foreign_table_name}`,
4064
+ column: r.foreign_column_name,
4065
+ onDelete: r.on_delete?.toUpperCase(),
4066
+ onUpdate: r.on_update?.toUpperCase()
4067
+ }]);
4068
+ });
4069
+ const indexRows = await queryRows(
4070
+ executor,
4071
+ `
4072
+ SELECT
4073
+ ns.nspname AS table_schema,
4074
+ tbl.relname AS table_name,
4075
+ idx.relname AS index_name,
4076
+ i.indisunique AS is_unique,
4077
+ pg_get_expr(i.indpred, i.indrelid) AS predicate,
4078
+ array_agg(att.attname ORDER BY arr.idx) AS column_names
4079
+ FROM pg_index i
4080
+ JOIN pg_class tbl ON tbl.oid = i.indrelid
4081
+ JOIN pg_namespace ns ON ns.oid = tbl.relnamespace
4082
+ JOIN pg_class idx ON idx.oid = i.indexrelid
4083
+ JOIN LATERAL unnest(i.indkey) WITH ORDINALITY AS arr(attnum, idx) ON TRUE
4084
+ LEFT JOIN pg_attribute att ON att.attrelid = tbl.oid AND att.attnum = arr.attnum
4085
+ WHERE ns.nspname = $1 AND NOT i.indisprimary
4086
+ GROUP BY ns.nspname, tbl.relname, idx.relname, i.indisunique, i.indpred
4087
+ `,
4088
+ [schema]
4089
+ );
4090
+ const tablesByKey = /* @__PURE__ */ new Map();
4091
+ columnRows.forEach((r) => {
4092
+ const key = `${r.table_schema}.${r.table_name}`;
4093
+ if (!shouldIncludeTable(r.table_name, options)) {
4094
+ return;
4095
+ }
4096
+ if (!tablesByKey.has(key)) {
4097
+ tablesByKey.set(key, {
4098
+ name: r.table_name,
4099
+ schema: r.table_schema,
4100
+ columns: [],
4101
+ primaryKey: pkMap.get(key) || [],
4102
+ indexes: []
4103
+ });
4104
+ }
4105
+ const cols = tablesByKey.get(key);
4106
+ const fk = fkMap.get(`${r.table_schema}.${r.table_name}.${r.column_name}`)?.[0];
4107
+ const column = {
4108
+ name: r.column_name,
4109
+ type: r.data_type,
4110
+ notNull: r.is_nullable === "NO",
4111
+ default: r.column_default ?? void 0,
4112
+ references: fk ? {
4113
+ table: fk.table,
4114
+ column: fk.column,
4115
+ onDelete: fk.onDelete,
4116
+ onUpdate: fk.onUpdate
4117
+ } : void 0
4118
+ };
4119
+ cols.columns.push(column);
4120
+ });
4121
+ indexRows.forEach((r) => {
4122
+ const key = `${r.table_schema}.${r.table_name}`;
4123
+ const table = tablesByKey.get(key);
4124
+ if (!table) return;
4125
+ const idx = {
4126
+ name: r.index_name,
4127
+ columns: (r.column_names || []).map((c) => ({ column: c })),
4128
+ unique: !!r.is_unique,
4129
+ where: r.predicate || void 0
4130
+ };
4131
+ table.indexes = table.indexes || [];
4132
+ table.indexes.push(idx);
4133
+ });
4134
+ tables.push(...tablesByKey.values());
4135
+ return { tables };
4136
+ }
4137
+ };
4138
+
4139
+ // src/core/ddl/introspect/mysql.ts
4140
+ var mysqlIntrospector = {
4141
+ async introspect(executor, options) {
4142
+ const schema = options.schema;
4143
+ const filterClause = schema ? "table_schema = ?" : "table_schema = database()";
4144
+ const params = schema ? [schema] : [];
4145
+ const columnRows = await queryRows(
4146
+ executor,
4147
+ `
4148
+ SELECT table_schema, table_name, column_name, data_type, is_nullable, column_default, extra
4149
+ FROM information_schema.columns
4150
+ WHERE ${filterClause}
4151
+ ORDER BY table_name, ordinal_position
4152
+ `,
4153
+ params
4154
+ );
4155
+ const pkRows = await queryRows(
4156
+ executor,
4157
+ `
4158
+ SELECT table_schema, table_name, column_name
4159
+ FROM information_schema.key_column_usage
4160
+ WHERE constraint_name = 'PRIMARY' AND ${filterClause}
4161
+ ORDER BY ordinal_position
4162
+ `,
4163
+ params
4164
+ );
4165
+ const pkMap = /* @__PURE__ */ new Map();
4166
+ pkRows.forEach((r) => {
4167
+ const key = `${r.table_schema}.${r.table_name}`;
4168
+ const list = pkMap.get(key) || [];
4169
+ list.push(r.column_name);
4170
+ pkMap.set(key, list);
4171
+ });
4172
+ const indexRows = await queryRows(
4173
+ executor,
4174
+ `
4175
+ SELECT
4176
+ table_schema,
4177
+ table_name,
4178
+ index_name,
4179
+ non_unique,
4180
+ GROUP_CONCAT(column_name ORDER BY seq_in_index) AS cols
4181
+ FROM information_schema.statistics
4182
+ WHERE ${filterClause} AND index_name <> 'PRIMARY'
4183
+ GROUP BY table_schema, table_name, index_name, non_unique
4184
+ `,
4185
+ params
4186
+ );
4187
+ const tablesByKey = /* @__PURE__ */ new Map();
4188
+ columnRows.forEach((r) => {
4189
+ const key = `${r.table_schema}.${r.table_name}`;
4190
+ if (!shouldIncludeTable(r.table_name, options)) return;
4191
+ if (!tablesByKey.has(key)) {
4192
+ tablesByKey.set(key, {
4193
+ name: r.table_name,
4194
+ schema: r.table_schema,
4195
+ columns: [],
4196
+ primaryKey: pkMap.get(key) || [],
4197
+ indexes: []
4198
+ });
4199
+ }
4200
+ const cols = tablesByKey.get(key);
4201
+ const column = {
4202
+ name: r.column_name,
4203
+ type: r.data_type,
4204
+ notNull: r.is_nullable === "NO",
4205
+ default: r.column_default ?? void 0,
4206
+ autoIncrement: typeof r.extra === "string" && r.extra.includes("auto_increment")
4207
+ };
4208
+ cols.columns.push(column);
4209
+ });
4210
+ indexRows.forEach((r) => {
4211
+ const key = `${r.table_schema}.${r.table_name}`;
4212
+ const table = tablesByKey.get(key);
4213
+ if (!table) return;
4214
+ const cols = (typeof r.cols === "string" ? r.cols.split(",") : []).map((c) => ({ column: c.trim() }));
4215
+ const idx = {
4216
+ name: r.index_name,
4217
+ columns: cols,
4218
+ unique: r.non_unique === 0
4219
+ };
4220
+ table.indexes = table.indexes || [];
4221
+ table.indexes.push(idx);
4222
+ });
4223
+ return { tables: Array.from(tablesByKey.values()) };
4224
+ }
4225
+ };
4226
+
4227
+ // src/core/ddl/introspect/sqlite.ts
4228
+ var escapeSingleQuotes = (name) => name.replace(/'/g, "''");
4229
+ var sqliteIntrospector = {
4230
+ async introspect(executor, options) {
4231
+ const tables = [];
4232
+ const tableRows = await queryRows(
4233
+ executor,
4234
+ `SELECT name FROM sqlite_master WHERE type = 'table' AND name NOT LIKE 'sqlite_%';`
4235
+ );
4236
+ for (const row of tableRows) {
4237
+ const name = row.name;
4238
+ if (!shouldIncludeTable(name, options)) continue;
4239
+ const table = { name, columns: [], primaryKey: [], indexes: [] };
4240
+ const cols = await queryRows(executor, `PRAGMA table_info('${escapeSingleQuotes(name)}');`);
4241
+ cols.forEach((c) => {
4242
+ table.columns.push({
4243
+ name: c.name,
4244
+ type: c.type,
4245
+ notNull: c.notnull === 1,
4246
+ default: c.dflt_value ?? void 0,
4247
+ autoIncrement: false
4248
+ });
4249
+ if (c.pk && c.pk > 0) {
4250
+ table.primaryKey = table.primaryKey || [];
4251
+ table.primaryKey.push(c.name);
4252
+ }
4253
+ });
4254
+ const fkRows = await queryRows(executor, `PRAGMA foreign_key_list('${escapeSingleQuotes(name)}');`);
4255
+ fkRows.forEach((fk) => {
4256
+ const col2 = table.columns.find((c) => c.name === fk.from);
4257
+ if (col2) {
4258
+ col2.references = {
4259
+ table: fk.table,
4260
+ column: fk.to,
4261
+ onDelete: fk.on_delete?.toUpperCase(),
4262
+ onUpdate: fk.on_update?.toUpperCase()
4263
+ };
4264
+ }
4265
+ });
4266
+ const idxList = await queryRows(executor, `PRAGMA index_list('${escapeSingleQuotes(name)}');`);
4267
+ for (const idx of idxList) {
4268
+ const idxName = idx.name;
4269
+ const columnsInfo = await queryRows(executor, `PRAGMA index_info('${escapeSingleQuotes(idxName)}');`);
4270
+ const idxEntry = {
4271
+ name: idxName,
4272
+ columns: columnsInfo.map((ci) => ({ column: ci.name })),
4273
+ unique: idx.unique === 1
4274
+ };
4275
+ table.indexes.push(idxEntry);
4276
+ }
4277
+ tables.push(table);
4278
+ }
4279
+ return { tables };
4280
+ }
4281
+ };
4282
+
4283
+ // src/core/ddl/introspect/mssql.ts
4284
+ var mssqlIntrospector = {
4285
+ async introspect(executor, options) {
4286
+ const schema = options.schema;
4287
+ const filterSchema = schema ? "sch.name = @p1" : "1=1";
4288
+ const params = schema ? [schema] : [];
4289
+ const columnRows = await queryRows(
4290
+ executor,
4291
+ `
4292
+ SELECT
4293
+ sch.name AS table_schema,
4294
+ t.name AS table_name,
4295
+ c.name AS column_name,
4296
+ ty.name AS data_type,
4297
+ c.is_nullable,
4298
+ c.is_identity,
4299
+ object_definition(c.default_object_id) AS column_default
4300
+ FROM sys.columns c
4301
+ JOIN sys.tables t ON t.object_id = c.object_id
4302
+ JOIN sys.schemas sch ON sch.schema_id = t.schema_id
4303
+ JOIN sys.types ty ON ty.user_type_id = c.user_type_id
4304
+ WHERE t.is_ms_shipped = 0 AND ${filterSchema}
4305
+ `,
4306
+ params
4307
+ );
4308
+ const pkRows = await queryRows(
4309
+ executor,
4310
+ `
4311
+ SELECT
4312
+ sch.name AS table_schema,
4313
+ t.name AS table_name,
4314
+ c.name AS column_name,
4315
+ ic.key_ordinal
4316
+ FROM sys.indexes i
4317
+ JOIN sys.index_columns ic ON ic.object_id = i.object_id AND ic.index_id = i.index_id
4318
+ JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
4319
+ JOIN sys.tables t ON t.object_id = i.object_id
4320
+ JOIN sys.schemas sch ON sch.schema_id = t.schema_id
4321
+ WHERE i.is_primary_key = 1 AND ${filterSchema}
4322
+ ORDER BY ic.key_ordinal
4323
+ `,
4324
+ params
4325
+ );
4326
+ const pkMap = /* @__PURE__ */ new Map();
4327
+ pkRows.forEach((r) => {
4328
+ const key = `${r.table_schema}.${r.table_name}`;
4329
+ const list = pkMap.get(key) || [];
4330
+ list.push(r.column_name);
4331
+ pkMap.set(key, list);
4332
+ });
4333
+ const indexRows = await queryRows(
4334
+ executor,
4335
+ `
4336
+ SELECT
4337
+ sch.name AS table_schema,
4338
+ t.name AS table_name,
4339
+ i.name AS index_name,
4340
+ i.is_unique,
4341
+ i.has_filter,
4342
+ i.filter_definition
4343
+ FROM sys.indexes i
4344
+ JOIN sys.tables t ON t.object_id = i.object_id
4345
+ JOIN sys.schemas sch ON sch.schema_id = t.schema_id
4346
+ WHERE i.is_primary_key = 0 AND i.is_hypothetical = 0 AND ${filterSchema}
4347
+ `,
4348
+ params
4349
+ );
4350
+ const indexColsRows = await queryRows(
4351
+ executor,
4352
+ `
4353
+ SELECT
4354
+ sch.name AS table_schema,
4355
+ t.name AS table_name,
4356
+ i.name AS index_name,
4357
+ c.name AS column_name,
4358
+ ic.key_ordinal
4359
+ FROM sys.index_columns ic
4360
+ JOIN sys.indexes i ON i.object_id = ic.object_id AND i.index_id = ic.index_id
4361
+ JOIN sys.columns c ON c.object_id = ic.object_id AND c.column_id = ic.column_id
4362
+ JOIN sys.tables t ON t.object_id = i.object_id
4363
+ JOIN sys.schemas sch ON sch.schema_id = t.schema_id
4364
+ WHERE i.is_primary_key = 0 AND ${filterSchema}
4365
+ ORDER BY ic.key_ordinal
4366
+ `,
4367
+ params
4368
+ );
4369
+ const indexColumnsMap = /* @__PURE__ */ new Map();
4370
+ indexColsRows.forEach((r) => {
4371
+ const key = `${r.table_schema}.${r.table_name}.${r.index_name}`;
4372
+ const list = indexColumnsMap.get(key) || [];
4373
+ list.push({ column: r.column_name, order: r.key_ordinal });
4374
+ indexColumnsMap.set(key, list);
4375
+ });
4376
+ const tablesByKey = /* @__PURE__ */ new Map();
4377
+ columnRows.forEach((r) => {
4378
+ if (!shouldIncludeTable(r.table_name, options)) return;
4379
+ const key = `${r.table_schema}.${r.table_name}`;
4380
+ if (!tablesByKey.has(key)) {
4381
+ tablesByKey.set(key, {
4382
+ name: r.table_name,
4383
+ schema: r.table_schema,
4384
+ columns: [],
4385
+ primaryKey: pkMap.get(key) || [],
4386
+ indexes: []
4387
+ });
4388
+ }
4389
+ const t = tablesByKey.get(key);
4390
+ const column = {
4391
+ name: r.column_name,
4392
+ type: r.data_type,
4393
+ notNull: r.is_nullable === false || r.is_nullable === 0,
4394
+ default: r.column_default ?? void 0,
4395
+ autoIncrement: !!r.is_identity
4396
+ };
4397
+ t.columns.push(column);
4398
+ });
4399
+ indexRows.forEach((r) => {
4400
+ const key = `${r.table_schema}.${r.table_name}`;
4401
+ const table = tablesByKey.get(key);
4402
+ if (!table) return;
4403
+ const cols = (indexColumnsMap.get(`${r.table_schema}.${r.table_name}.${r.index_name}`) || []).sort((a, b) => a.order - b.order).map((c) => ({ column: c.column }));
4404
+ const idx = {
4405
+ name: r.index_name,
4406
+ columns: cols,
4407
+ unique: !!r.is_unique,
4408
+ where: r.has_filter ? r.filter_definition : void 0
4409
+ };
4410
+ table.indexes = table.indexes || [];
4411
+ table.indexes.push(idx);
4412
+ });
4413
+ return { tables: Array.from(tablesByKey.values()) };
4414
+ }
4415
+ };
4416
+
4417
+ // src/core/ddl/schema-introspect.ts
4418
+ var INTROSPECTORS = {
4419
+ postgres: postgresIntrospector,
4420
+ mysql: mysqlIntrospector,
4421
+ sqlite: sqliteIntrospector,
4422
+ mssql: mssqlIntrospector
4423
+ };
4424
+ var introspectSchema = async (executor, dialect, options = {}) => {
4425
+ const handler = INTROSPECTORS[dialect];
4426
+ if (!handler) {
4427
+ throw new Error(`Unsupported dialect for introspection: ${dialect}`);
4428
+ }
4429
+ return handler.introspect(executor, options);
4430
+ };
4431
+
3223
4432
  // src/orm/als.ts
3224
4433
  var AsyncLocalStorage = class {
3225
4434
  /**
@@ -4057,15 +5266,21 @@ var OrmContext = class {
4057
5266
  };
4058
5267
  export {
4059
5268
  AsyncLocalStorage,
5269
+ BaseSchemaDialect,
4060
5270
  DefaultBelongsToReference,
4061
5271
  DefaultHasManyCollection,
4062
5272
  DefaultManyToManyCollection,
4063
5273
  DeleteQueryBuilder,
4064
5274
  EntityStatus,
4065
5275
  InsertQueryBuilder,
5276
+ MSSqlSchemaDialect,
4066
5277
  MySqlDialect,
5278
+ MySqlSchemaDialect,
4067
5279
  OrmContext,
5280
+ PostgresDialect,
5281
+ PostgresSchemaDialect,
4068
5282
  RelationKinds,
5283
+ SQLiteSchemaDialect,
4069
5284
  SelectQueryBuilder,
4070
5285
  SqlServerDialect,
4071
5286
  SqliteDialect,
@@ -4087,15 +5302,22 @@ export {
4087
5302
  createLiteral,
4088
5303
  defineTable,
4089
5304
  denseRank,
5305
+ deriveIndexName,
5306
+ diffSchema,
4090
5307
  eq,
5308
+ escapeLiteral,
4091
5309
  executeHydrated,
4092
5310
  exists,
4093
5311
  firstValue,
5312
+ formatLiteral,
5313
+ generateCreateTableSql,
5314
+ generateSchemaSql,
4094
5315
  gt,
4095
5316
  gte,
4096
5317
  hasMany,
4097
5318
  hydrateRows,
4098
5319
  inList,
5320
+ introspectSchema,
4099
5321
  isCaseExpressionNode,
4100
5322
  isExpressionSelectionNode,
4101
5323
  isFunctionNode,
@@ -4120,9 +5342,14 @@ export {
4120
5342
  notLike,
4121
5343
  ntile,
4122
5344
  or,
5345
+ quoteQualified,
4123
5346
  rank,
5347
+ renderColumnDefinition,
5348
+ renderIndexColumns,
5349
+ resolvePrimaryKey,
4124
5350
  rowNumber,
4125
5351
  sum,
5352
+ synchronizeSchema,
4126
5353
  valueToOperand,
4127
5354
  visitExpression,
4128
5355
  visitOperand,