@voltro/database 0.86.0 → 0.87.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,44 +7,45 @@ import { _voltroMigrationPlansTable as c, _voltroPluginMigrationsTable as l, _vo
7
7
  import { REPLACE_IN_PROGRESS_TABLE as d, _voltroReplaceInProgressTable as f } from "../replaceInProgress.js";
8
8
  import { pgIndexClauses as p } from "../indexStorage.js";
9
9
  import { formatDdlError as m } from "./ddlError.js";
10
- import { acquireMigrationLock as ee } from "./lock.js";
11
- import { MIGRATION_OPS_TABLE as h, SHADOW_COLUMN_SUFFIX as te, SHADOW_OLD_SUFFIX as g, SQLITE_REBUILD_SUFFIX as ne, _voltroMigrationOpsTable as re, dialectOf as _, migrationAtomicityFor as ie, opStillOutstanding as v, opTargetLabel as ae, resumeIdempotencyFor as y } from "./resumeLedger.js";
12
- import { mssqlJsonValueCheck as b } from "../mssqlJsonValueCheck.js";
13
- import { defaultArrayClause as x, defaultClause as S, defaultJsonClause as C, enumRenameBlocks as oe, enumTypeBlocks as se, extensionBlocks as ce, numericIdSql as w, sqlType as T } from "../migrate.js";
14
- import { runSqliteMigrationBatch as le } from "./sqliteMigrationBatch.js";
15
- import { declaredSnapshot as ue, snapshotColumn as E } from "./declaredSchema.js";
16
- import { DEPLOY_LEDGER_TABLE as de, _voltroDeploysTable as fe } from "./deployLedger.js";
17
- import { parseEnumCheck as D } from "./introspect.js";
18
- import { migrationTableExists as O } from "./migrationTableExists.js";
19
- import { bindSoftDropSnapshot as pe, readSoftDropSnapshot as me } from "./softDropSnapshot.js";
20
- import { limitClause as k } from "./sqlLimit.js";
21
- import { resolveMysqlEngine as A } from "./mysqlEngine.js";
22
- import { MYSQL_COLUMN_OR_INDEX_ABSENT as he, MYSQL_CONSTRAINT_ABSENT as ge, MYSQL_FOREIGN_KEY_EXISTS as _e, MYSQL_INDEX_EXISTS as ve, SQLITE_COLUMN_ABSENT as ye, isAlreadySatisfied as be } from "./idempotentDdl.js";
23
- import { withMigrationTransaction as xe } from "./transactionCause.js";
24
- import { renameMssqlCheck as Se } from "./renameMssqlCheck.js";
25
- import { alterColumnWithDependenciesMssql as Ce } from "./mssqlColumnDependencies.js";
26
- import { appliedAtValue as j } from "./appliedAtValue.js";
27
- import { Effect as M } from "effect";
28
- import { isDeepStrictEqual as we } from "node:util";
29
- import { randomUUID as Te } from "node:crypto";
30
- import { SqlClient as Ee } from "effect/sql";
10
+ import { acquireMigrationLock as h } from "./lock.js";
11
+ import { MIGRATION_OPS_TABLE as g, SHADOW_COLUMN_SUFFIX as ee, SHADOW_OLD_SUFFIX as _, SQLITE_REBUILD_SUFFIX as te, _voltroMigrationOpsTable as v, dialectOf as y, migrationAtomicityFor as ne, opStillOutstanding as b, opTargetLabel as x, resumeIdempotencyFor as re } from "./resumeLedger.js";
12
+ import { mssqlJsonValueCheck as S } from "../mssqlJsonValueCheck.js";
13
+ import { defaultArrayClause as ie, defaultClause as C, defaultJsonClause as w, enumRenameBlocks as ae, enumTypeBlocks as oe, extensionBlocks as se, numericIdSql as T, sqlType as E } from "../migrate.js";
14
+ import { runSqliteMigrationBatch as ce } from "./sqliteMigrationBatch.js";
15
+ import { declaredSnapshot as le, snapshotColumn as D } from "./declaredSchema.js";
16
+ import { DEPLOY_LEDGER_TABLE as ue, _voltroDeploysTable as de } from "./deployLedger.js";
17
+ import { parseEnumCheck as fe } from "./introspect.js";
18
+ import { migrationTableExists as pe } from "./migrationTableExists.js";
19
+ import { bindSoftDropSnapshot as me, readSoftDropSnapshot as he } from "./softDropSnapshot.js";
20
+ import { limitClause as O } from "./sqlLimit.js";
21
+ import { resolveMysqlEngine as k } from "./mysqlEngine.js";
22
+ import { ddlStatementsFor as ge } from "./ddlStatements.js";
23
+ import { MYSQL_COLUMN_OR_INDEX_ABSENT as _e, MYSQL_CONSTRAINT_ABSENT as ve, MYSQL_FOREIGN_KEY_EXISTS as ye, MYSQL_INDEX_EXISTS as be, SQLITE_COLUMN_ABSENT as xe, isAlreadySatisfied as Se } from "./idempotentDdl.js";
24
+ import { withMigrationTransaction as Ce } from "./transactionCause.js";
25
+ import { renameMssqlCheck as we } from "./renameMssqlCheck.js";
26
+ import { alterColumnWithDependenciesMssql as Te } from "./mssqlColumnDependencies.js";
27
+ import { appliedAtValue as A } from "./appliedAtValue.js";
28
+ import { Effect as j } from "effect";
29
+ import { isDeepStrictEqual as Ee } from "node:util";
30
+ import { createHash as De, randomUUID as Oe } from "node:crypto";
31
+ import { SqlClient as ke } from "effect/sql";
31
32
  //#region src/migrations/applier.ts
32
- var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.type === "text" && (e.hasDefault && e.defaultValue !== void 0 || e.oneOf !== void 0 && e.oneOf.length > 0), N = (e, t) => {
33
+ var Ae = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, je = (e) => e.type === "text" && (e.hasDefault && e.defaultValue !== void 0 || e.oneOf !== void 0 && e.oneOf.length > 0), M = (e, t) => {
33
34
  let n = e.type === "text" && e.maxLength !== void 0;
34
- if (e.sqliteDecimalEncoding === void 0 && !n && !Oe(e) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
35
+ if (e.sqliteDecimalEncoding === void 0 && !n && !je(e) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
35
36
  let r = e.type === "vector" && e.vectorDim === void 0 ? "vector dimension" : e.type === "array" && e.arrayElement === void 0 ? "array element type" : e.type === "enum" && e.enumName === void 0 && e.enumValues === void 0 ? "enum name/values" : void 0;
36
37
  if (r !== void 0) throw Error(`migration applier: cannot render '${e.name}' (${e.type}) — the schema snapshot carries no ${r}. Rendering it as 'text' would emit DDL that applies successfully and changes nothing, so this fails instead. This is a framework bug: declaredSchema.ts must carry the parameter into the ColumnSnapshot.`);
37
- return T(e, t);
38
- }, P = (e) => {
39
- let t = N(e, "postgres");
40
- return t === void 0 ? ke(e) : t;
41
- }, ke = (e) => {
38
+ return E(e, t);
39
+ }, Me = (e) => {
40
+ let t = M(e, "postgres");
41
+ return t === void 0 ? Ne(e) : t;
42
+ }, Ne = (e) => {
42
43
  switch (e.type) {
43
44
  case "id": return "text";
44
45
  case "text": return "text";
45
46
  case "integer": return "integer";
46
47
  case "real": return "double precision";
47
- case "decimal": return De(e, "NUMERIC");
48
+ case "decimal": return Ae(e, "NUMERIC");
48
49
  case "bigint": return "bigint";
49
50
  case "boolean": return "boolean";
50
51
  case "timestamp": return "timestamptz";
@@ -58,15 +59,15 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
58
59
  case "interval": return "interval";
59
60
  case "raw": return e.rawDdl ?? "text";
60
61
  }
61
- }, Ae = (e) => {
62
- let t = N(e, "mariadb");
62
+ }, Pe = (e) => {
63
+ let t = M(e, "mariadb");
63
64
  if (t !== void 0) return t;
64
65
  switch (e.type) {
65
66
  case "id": return "VARCHAR(64)";
66
67
  case "text": return "LONGTEXT";
67
68
  case "integer": return "INT";
68
69
  case "real": return "DOUBLE";
69
- case "decimal": return De(e, "DECIMAL");
70
+ case "decimal": return Ae(e, "DECIMAL");
70
71
  case "bigint": return "BIGINT";
71
72
  case "boolean": return "TINYINT(1)";
72
73
  case "timestamp": return "DATETIME(6)";
@@ -80,72 +81,72 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
80
81
  case "interval": return "BIGINT";
81
82
  case "raw": return e.rawDdl ?? "LONGTEXT";
82
83
  }
83
- }, F = (e) => `"${e}"`, I = (e) => `\`${e.replace(/`/g, "``")}\``, je = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", L = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, Me = (e, t = "mariadb") => `ALTER TABLE ${I(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${I(e.column)}, ALGORITHM=COPY;`, R = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Ne = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(t)};`, Pe = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${Ie(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, Fe = (e, t) => {
84
+ }, N = (e) => `"${e}"`, P = (e) => `\`${e.replace(/`/g, "``")}\``, Fe = (e) => e === "mariadb" ? "IF NOT EXISTS " : "", F = (e, t, n = !0) => `ALTER TABLE ${t(e.table)} DROP COLUMN ${n ? "IF EXISTS " : ""}${t(e.column)};`, Ie = (e, t = "mariadb") => `ALTER TABLE ${P(e.table)} DROP COLUMN ${t === "mariadb" ? "IF EXISTS " : ""}${P(e.column)}, ALGORITHM=COPY;`, I = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, Le = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(t)};`, Re = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${Be(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, ze = (e, t) => {
84
85
  let { defaultFactory: n, ...r } = e;
85
- return T(e, t) !== T({
86
+ return E(e, t) !== E({
86
87
  ...r,
87
88
  hasDefault: !1
88
89
  }, t);
89
- }, Ie = (e, t) => {
90
+ }, Be = (e, t) => {
90
91
  let n = t(e.defaultValue);
91
92
  if (n === null) throw Error(`migration applier: cannot render the declared default for '${e.table}.${e.column}' (${JSON.stringify(e.defaultValue)}). Emitting 'DEFAULT NULL' would apply cleanly and drop the default silently, so this fails instead. This is a framework bug — report the column type + default.`);
92
93
  return n;
93
- }, z = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], B = (e, t, n) => {
94
- let r = z(e, t, n);
95
- return r ? E(n, r) : void 0;
96
- }, Le = (e, t, n, r) => {
97
- let i = n ?? e.nullable, a = S(e, "mariadb");
94
+ }, L = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], R = (e, t, n) => {
95
+ let r = L(e, t, n);
96
+ return r ? D(n, r) : void 0;
97
+ }, Ve = (e, t, n, r) => {
98
+ let i = n ?? e.nullable, a = C(e, "mariadb");
98
99
  return [
99
- I(t),
100
- T(e, "mariadb"),
100
+ P(t),
101
+ E(e, "mariadb"),
101
102
  i ? null : "NOT NULL",
102
103
  a,
103
104
  r === void 0 ? null : `CHECK (${r})`
104
105
  ].filter(Boolean).join(" ");
105
- }, Re = /^json_valid\(`[^`]+`\)$/i, ze = (e, t) => A(e).pipe(M.flatMap((n) => n === "mariadb" ? e`
106
+ }, He = /^json_valid\(`[^`]+`\)$/i, Ue = (e, t) => k(e).pipe(j.flatMap((n) => n === "mariadb" ? e`
106
107
  SELECT constraint_name AS n, check_clause AS c
107
108
  FROM information_schema.check_constraints
108
- WHERE constraint_schema = DATABASE() AND table_name = ${t} AND level = 'Column'`.pipe(M.map((e) => new Map(e.map((e) => [String(e.n ?? ""), String(e.c ?? "")]).filter(([e, t]) => e !== "" && t !== "" && !Re.test(t.trim()))))) : M.succeed(/* @__PURE__ */ new Map()))), V = (e, t, n, r, i) => M.map(ze(e, t), (e) => `ALTER TABLE ${I(t)} MODIFY COLUMN ${Le(n, r, i, e.get(r))};`), Be = (e, t) => e == null ? null : Array.isArray(e) ? Ve(e, t, "mariadb") : e === "now" ? "DEFAULT CURRENT_TIMESTAMP(6)" : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? C(e, "mariadb") : null, Ve = (e, t, n) => x(e, t ?? { type: "json" }, n), He = (e, t) => e == null ? null : Array.isArray(e) ? Ve(e, t, "postgres") : e === "now" ? "DEFAULT now()" : typeof e == "boolean" || typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|::|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? C(e, "postgres") : null, H = (e, t) => {
109
+ WHERE constraint_schema = DATABASE() AND table_name = ${t} AND level = 'Column'`.pipe(j.map((e) => new Map(e.map((e) => [String(e.n ?? ""), String(e.c ?? "")]).filter(([e, t]) => e !== "" && t !== "" && !He.test(t.trim()))))) : j.succeed(/* @__PURE__ */ new Map()))), z = (e, t, n, r, i) => j.map(Ue(e, t), (e) => `ALTER TABLE ${P(t)} MODIFY COLUMN ${Ve(n, r, i, e.get(r))};`), We = (e, t) => e == null ? null : Array.isArray(e) ? Ge(e, t, "mariadb") : e === "now" ? "DEFAULT CURRENT_TIMESTAMP(6)" : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? w(e, "mariadb") : null, Ge = (e, t, n) => ie(e, t ?? { type: "json" }, n), Ke = (e, t) => e == null ? null : Array.isArray(e) ? Ge(e, t, "postgres") : e === "now" ? "DEFAULT now()" : typeof e == "boolean" || typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|::|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? w(e, "postgres") : null, B = (e, t) => {
109
110
  if (!e.generatedAs) return null;
110
111
  let { expr: n, stored: r } = e.generatedAs;
111
112
  return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
112
- }, Ue = (e, t = !1) => {
113
- if (e.type === "id" && e.idScheme?.kind === "numeric") return w(e.name, "postgres");
114
- let n = H(e, "postgres");
115
- if (n) return `${F(e.name)} ${P(e)} ${n}`;
116
- let r = [F(e.name), P(e)];
113
+ }, qe = (e, t = !1) => {
114
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return T(e.name, "postgres");
115
+ let n = B(e, "postgres");
116
+ if (n) return `${N(e.name)} ${Me(e)} ${n}`;
117
+ let r = [N(e.name), Me(e)];
117
118
  if (e.type === "id" && !t && r.push("PRIMARY KEY"), e.nullable || r.push("NOT NULL"), e.unique && e.type !== "id" && r.push("UNIQUE"), e.hasDefault) {
118
- let t = He(e.defaultValue, e);
119
+ let t = Ke(e.defaultValue, e);
119
120
  t && r.push(t);
120
121
  }
121
- return e.references && (r.push(`REFERENCES ${F(e.references.table)} (${F(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${{
122
+ return e.references && (r.push(`REFERENCES ${N(e.references.table)} (${N(e.references.column)})`), e.references.onDelete && r.push(`ON DELETE ${{
122
123
  cascade: "CASCADE",
123
124
  restrict: "RESTRICT",
124
125
  setNull: "SET NULL",
125
126
  noAction: "NO ACTION"
126
127
  }[e.references.onDelete]}`)), r.join(" ");
127
- }, U = (e) => (e.primaryKey?.length ?? 0) > 0, W = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", We = (e) => {
128
- let t = e.columns.map((t) => ` ${Ue(t, U(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${F(e.table)} (\n${t}${W(e, F)}\n)`];
129
- for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(gt({
128
+ }, V = (e) => (e.primaryKey?.length ?? 0) > 0, H = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", Je = (e) => {
129
+ let t = e.columns.map((t) => ` ${qe(t, V(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${N(e.table)} (\n${t}${H(e, N)}\n)`];
130
+ for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(yt({
130
131
  kind: "add-index",
131
132
  table: e.table,
132
133
  index: t
133
134
  }, !1));
134
135
  return n;
135
- }, Ge = 191, Ke = (e) => {
136
- let t = Ae(e).toUpperCase();
136
+ }, Ye = 191, Xe = (e) => {
137
+ let t = Pe(e).toUpperCase();
137
138
  return t.endsWith("TEXT") || t.endsWith("BLOB");
138
- }, qe = (e) => e.charset === void 0 ? Ae(e) : `${Ae(e)} CHARACTER SET ${e.charset}`, Je = (e, t = !1) => {
139
- if (e.type === "id" && e.idScheme?.kind === "numeric") return w(e.name, "mariadb");
140
- let n = qe(e), r = H(e, "mariadb");
141
- if (r) return `${I(e.name)} ${n} ${r}`;
142
- let i = [I(e.name), n];
143
- if (e.type === "id" && !t && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && !Ke(e) && i.push("UNIQUE"), e.hasDefault) {
144
- let t = Be(e.defaultValue, e);
139
+ }, Ze = (e) => e.charset === void 0 ? Pe(e) : `${Pe(e)} CHARACTER SET ${e.charset}`, Qe = (e, t = !1) => {
140
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return T(e.name, "mariadb");
141
+ let n = Ze(e), r = B(e, "mariadb");
142
+ if (r) return `${P(e.name)} ${n} ${r}`;
143
+ let i = [P(e.name), n];
144
+ if (e.type === "id" && !t && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && !Xe(e) && i.push("UNIQUE"), e.hasDefault) {
145
+ let t = We(e.defaultValue, e);
145
146
  t && i.push(t);
146
147
  }
147
148
  return i.join(" ");
148
- }, Ye = (e) => e.columns.flatMap((t) => {
149
+ }, $e = (e) => e.columns.flatMap((t) => {
149
150
  if (!t.references) return [];
150
151
  let n = t.references.onDelete ? ` ON DELETE ${{
151
152
  cascade: "CASCADE",
@@ -153,21 +154,21 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
153
154
  setNull: "SET NULL",
154
155
  noAction: "NO ACTION"
155
156
  }[t.references.onDelete]}` : "";
156
- return [` CONSTRAINT ${I(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${I(t.name)}) REFERENCES ${I(t.references.table)} (${I(t.references.column)})${n}`];
157
- }), Xe = (e) => {
157
+ return [` CONSTRAINT ${P(`${e.table}_${t.name}_fkey`)} FOREIGN KEY (${P(t.name)}) REFERENCES ${P(t.references.table)} (${P(t.references.column)})${n}`];
158
+ }), et = (e) => {
158
159
  let t = e.find((e) => e.charset !== void 0)?.charset;
159
160
  return t === void 0 ? "" : ` DEFAULT CHARACTER SET ${t}`;
160
- }, Ze = (e, t, n = /* @__PURE__ */ new Map()) => {
161
- let r = e.foreignKeys.map((e) => `ALTER TABLE ${I(e.table)} DROP FOREIGN KEY ${I(e.name)}`), i = e.columns.map((r) => {
162
- let i = z(t, e.table, r), a = B(t, e.table, r);
161
+ }, tt = (e, t, n = /* @__PURE__ */ new Map()) => {
162
+ let r = e.foreignKeys.map((e) => `ALTER TABLE ${P(e.table)} DROP FOREIGN KEY ${P(e.name)}`), i = e.columns.map((r) => {
163
+ let i = L(t, e.table, r), a = R(t, e.table, r);
163
164
  if (i === void 0 || a === void 0) throw Error(`convert-charset: no declared column '${e.table}.${r}' to render MODIFY COLUMN from; it was not in ctx.declared.`);
164
- let o = H(a, "mariadb"), s = `${I(r)} ${T(i, "mariadb")} CHARACTER SET ${e.charset}`, c = n.get(r), l = c === void 0 ? null : `CHECK (${c})`;
165
+ let o = B(a, "mariadb"), s = `${P(r)} ${E(i, "mariadb")} CHARACTER SET ${e.charset}`, c = n.get(r), l = c === void 0 ? null : `CHECK (${c})`;
165
166
  if (o) return `MODIFY COLUMN ${[
166
167
  s,
167
168
  o,
168
169
  l
169
170
  ].filter(Boolean).join(" ")}`;
170
- let u = S(i, "mariadb");
171
+ let u = C(i, "mariadb");
171
172
  return `MODIFY COLUMN ${[
172
173
  s,
173
174
  i.nullable ? null : "NOT NULL",
@@ -177,30 +178,30 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
177
178
  });
178
179
  return {
179
180
  drops: r,
180
- rewrite: `ALTER TABLE ${I(e.table)} ${[...i, `DEFAULT CHARACTER SET ${e.charset}`].join(", ")}`,
181
- restores: e.foreignKeys.filter((e) => e.restore === "here").map((e) => `ALTER TABLE ${I(e.table)} ADD CONSTRAINT ${I(e.name)} FOREIGN KEY (${I(e.column)}) REFERENCES ${I(e.targetTable)} (${I(e.targetColumn)})` + (e.onDelete ? ` ON DELETE ${$e[e.onDelete]}` : "") + (e.onUpdate && e.onUpdate !== "noAction" ? ` ON UPDATE ${$e[e.onUpdate]}` : ""))
181
+ rewrite: `ALTER TABLE ${P(e.table)} ${[...i, `DEFAULT CHARACTER SET ${e.charset}`].join(", ")}`,
182
+ restores: e.foreignKeys.filter((e) => e.restore === "here").map((e) => `ALTER TABLE ${P(e.table)} ADD CONSTRAINT ${P(e.name)} FOREIGN KEY (${P(e.column)}) REFERENCES ${P(e.targetTable)} (${P(e.targetColumn)})` + (e.onDelete ? ` ON DELETE ${U[e.onDelete]}` : "") + (e.onUpdate && e.onUpdate !== "noAction" ? ` ON UPDATE ${U[e.onUpdate]}` : ""))
182
183
  };
183
- }, Qe = (e, t = "mariadb") => {
184
- for (let n of e.indexes) vt(n, t);
184
+ }, nt = (e, t = "mariadb") => {
185
+ for (let n of e.indexes) xt(n, t);
185
186
  let n = new Map(e.columns.map((e) => [e.name, e])), r = (e) => {
186
- let t = pt(n.get(e));
187
- return t === void 0 ? I(e) : `${I(e)}(${t})`;
188
- }, i = e.columns.map((t) => ` ${Je(t, U(e))}`).join(",\n"), a = Ye(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${I(e.table)} (\n${o}${W(e, r)}\n)${Xe(e.columns)}`];
189
- for (let n of e.columns) n.unique && n.type !== "id" && Ke(n) && s.push(`CREATE UNIQUE INDEX ${je(t)}${I(`${e.table}_${n.name}_key`)} ON ${I(e.table)} (${r(n.name)})`);
190
- for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${je(t)}${I(n.name)} ON ${I(e.table)} (${n.columns.map(r).join(", ")})`);
187
+ let t = ht(n.get(e));
188
+ return t === void 0 ? P(e) : `${P(e)}(${t})`;
189
+ }, i = e.columns.map((t) => ` ${Qe(t, V(e))}`).join(",\n"), a = $e(e), o = a.length > 0 ? `${i},\n${a.join(",\n")}` : i, s = [`CREATE TABLE IF NOT EXISTS ${P(e.table)} (\n${o}${H(e, r)}\n)${et(e.columns)}`];
190
+ for (let n of e.columns) n.unique && n.type !== "id" && Xe(n) && s.push(`CREATE UNIQUE INDEX ${Fe(t)}${P(gt(e.table, n.name))} ON ${P(e.table)} (${r(n.name)})`);
191
+ for (let n of e.indexes) n.name !== `${e.table}_pkey` && s.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Fe(t)}${P(n.name)} ON ${P(e.table)} (${n.columns.map(r).join(", ")})`);
191
192
  return s;
192
- }, $e = {
193
+ }, U = {
193
194
  cascade: "CASCADE",
194
195
  restrict: "RESTRICT",
195
196
  setNull: "SET NULL",
196
197
  noAction: "NO ACTION"
197
- }, et = {
198
+ }, rt = {
198
199
  cascade: "CASCADE",
199
200
  restrict: "NO ACTION",
200
201
  setNull: "SET NULL",
201
202
  noAction: "NO ACTION"
202
- }, tt = (e) => {
203
- let t = N(e, "sqlite");
203
+ }, it = (e) => {
204
+ let t = M(e, "sqlite");
204
205
  if (t !== void 0) return t;
205
206
  switch (e.type) {
206
207
  case "integer":
@@ -212,61 +213,61 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
212
213
  case "bytes": return "BLOB";
213
214
  default: return "TEXT";
214
215
  }
215
- }, G = (e, t) => e == null ? null : e === "now" ? `DEFAULT ${t}` : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? C(e, "sqlite") : null, nt = (e, t = !1) => {
216
- if (e.type === "id" && e.idScheme?.kind === "numeric") return w(e.name, "sqlite");
217
- let n = H(e, "sqlite"), a = i(e), o = a === void 0 ? void 0 : `CHECK (${r(F(e.name), a)})`;
218
- if (n) return `${F(e.name)} ${tt(e)} ${n}${o ? ` ${o}` : ""}`;
219
- let s = [F(e.name), tt(e)];
216
+ }, W = (e, t) => e == null ? null : e === "now" ? `DEFAULT ${t}` : typeof e == "boolean" ? `DEFAULT ${+!!e}` : typeof e == "number" ? `DEFAULT ${e}` : typeof e == "string" ? /[()]|^'/.test(e) ? `DEFAULT ${e}` : `DEFAULT '${e.replace(/'/g, "''")}'` : typeof e == "object" ? w(e, "sqlite") : null, at = (e, t = !1) => {
217
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return T(e.name, "sqlite");
218
+ let n = B(e, "sqlite"), a = i(e), o = a === void 0 ? void 0 : `CHECK (${r(N(e.name), a)})`;
219
+ if (n) return `${N(e.name)} ${it(e)} ${n}${o ? ` ${o}` : ""}`;
220
+ let s = [N(e.name), it(e)];
220
221
  if (o && s.push(o), e.type === "id" && !t && s.push("PRIMARY KEY"), e.nullable || s.push("NOT NULL"), e.unique && e.type !== "id" && s.push("UNIQUE"), e.hasDefault) {
221
- let t = G(e.defaultValue, "CURRENT_TIMESTAMP");
222
+ let t = W(e.defaultValue, "CURRENT_TIMESTAMP");
222
223
  t && s.push(t);
223
224
  }
224
- if (e.references && (s.push(`REFERENCES ${F(e.references.table)} (${F(e.references.column)})`), e.references.onDelete && s.push(`ON DELETE ${$e[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
225
+ if (e.references && (s.push(`REFERENCES ${N(e.references.table)} (${N(e.references.column)})`), e.references.onDelete && s.push(`ON DELETE ${U[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
225
226
  let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
226
- s.push(`CHECK (${F(e.name)} IN (${t}))`);
227
+ s.push(`CHECK (${N(e.name)} IN (${t}))`);
227
228
  }
228
229
  return s.join(" ");
229
- }, rt = (e) => {
230
- let t = e.columns.map((t) => ` ${nt(t, U(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${F(e.table)} (\n${t}${W(e, F)}\n)`];
231
- for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${F(t.name)} ON ${F(e.table)} (${t.columns.map(F).join(", ")})${q(t)}`);
230
+ }, G = (e) => {
231
+ let t = e.columns.map((t) => ` ${at(t, V(e))}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${N(e.table)} (\n${t}${H(e, N)}\n)`];
232
+ for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${N(t.name)} ON ${N(e.table)} (${t.columns.map(N).join(", ")})${q(t)}`);
232
233
  return n;
233
- }, it = (e, t) => {
234
+ }, ot = (e, t) => {
234
235
  let n = t.find((t) => t.tableName === e);
235
- return n ? at(ue([n], "sqlite").tables[0]) : [];
236
- }, at = (e) => {
237
- let t = e.name, n = `${t}__voltro_rebuild_${Te().replaceAll("-", "")}`, r = e.columns.map((e) => F(e.name)).join(", "), i = [
238
- ...rt({
236
+ return n ? st(le([n], "sqlite").tables[0]) : [];
237
+ }, st = (e) => {
238
+ let t = e.name, n = `${t}__voltro_rebuild_${Oe().replaceAll("-", "")}`, r = e.columns.map((e) => N(e.name)).join(", "), i = [
239
+ ...G({
239
240
  kind: "create-table",
240
241
  table: n,
241
242
  columns: e.columns,
242
243
  indexes: [],
243
244
  ...e.primaryKey ? { primaryKey: e.primaryKey } : {}
244
245
  }).map((e) => e.replace(/^CREATE TABLE IF NOT EXISTS /, "CREATE TABLE ")),
245
- `INSERT INTO ${F(n)} (${r}) SELECT ${r} FROM ${F(t)}`,
246
- `DROP TABLE ${F(t)}`,
247
- `ALTER TABLE ${F(n)} RENAME TO ${F(t)}`
246
+ `INSERT INTO ${N(n)} (${r}) SELECT ${r} FROM ${N(t)}`,
247
+ `DROP TABLE ${N(t)}`,
248
+ `ALTER TABLE ${N(n)} RENAME TO ${N(t)}`
248
249
  ];
249
- for (let n of e.indexes) n.name !== `${t}_pkey` && i.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${F(n.name)} ON ${F(t)} (${n.columns.map(F).join(", ")})${q(n)}`);
250
+ for (let n of e.indexes) n.name !== `${t}_pkey` && i.push(`CREATE ${n.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${N(n.name)} ON ${N(t)} (${n.columns.map(N).join(", ")})${q(n)}`);
250
251
  return i;
251
- }, ot = (e, t, n, r) => {
252
+ }, ct = (e, t, n, r) => {
252
253
  let i = r ?? e.nullable;
253
- return `ALTER TABLE ${K(n)} ALTER COLUMN ${K(t)} ${T(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
254
- }, st = (e, t) => {
254
+ return `ALTER TABLE ${K(n)} ALTER COLUMN ${K(t)} ${E(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
255
+ }, lt = (e, t) => {
255
256
  let n = `DECLARE @dc sysname; SELECT @dc = dc.name FROM sys.default_constraints dc JOIN sys.columns col ON col.object_id = dc.parent_object_id AND col.column_id = dc.parent_column_id WHERE dc.parent_object_id = OBJECT_ID(N'${e.table.replace(/'/g, "''")}') AND col.name = N'${e.column.replace(/'/g, "''")}'; IF @dc IS NOT NULL EXEC(N'ALTER TABLE ${K(e.table)} DROP CONSTRAINT [' + @dc + ']');` + (t ? ` ${t}` : "");
256
257
  if (!e.hasDefault) return n;
257
- let r = G(e.defaultValue, "SYSUTCDATETIME()");
258
+ let r = W(e.defaultValue, "SYSUTCDATETIME()");
258
259
  if (!r) return n;
259
260
  let i = r.replace(/^DEFAULT\s+/i, "");
260
261
  return `${n} ALTER TABLE ${K(e.table)} ADD DEFAULT ${i} FOR ${K(e.column)};`;
261
- }, K = (e) => `[${e.replace(/]/g, "]]")}]`, ct = (e) => {
262
- let t = N(e, "mssql");
262
+ }, K = (e) => `[${e.replace(/]/g, "]]")}]`, ut = (e) => {
263
+ let t = M(e, "mssql");
263
264
  if (t !== void 0) return t;
264
265
  switch (e.type) {
265
266
  case "id": return "NVARCHAR(64)";
266
267
  case "reference": return e.referenceStorage === "numeric" ? "BIGINT" : "NVARCHAR(64)";
267
268
  case "integer": return "INT";
268
269
  case "real": return "FLOAT";
269
- case "decimal": return De(e, "DECIMAL");
270
+ case "decimal": return Ae(e, "DECIMAL");
270
271
  case "bigint": return "BIGINT";
271
272
  case "boolean": return "BIT";
272
273
  case "timestamp": return "DATETIME2(6)";
@@ -274,50 +275,55 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
274
275
  case "bytes": return "VARBINARY(MAX)";
275
276
  default: return "NVARCHAR(MAX)";
276
277
  }
277
- }, lt = (e, t, n = !1) => {
278
- if (e.type === "id" && e.idScheme?.kind === "numeric") return w(e.name, "mssql");
279
- let r = e.type === "text" && t?.has(e.name) ? `NVARCHAR(${Math.min(e.maxLength ?? 450, 450)})` : ct(e), i = H(e, "mssql");
278
+ }, dt = (e, t, n = !1) => {
279
+ if (e.type === "id" && e.idScheme?.kind === "numeric") return T(e.name, "mssql");
280
+ let r = e.type === "text" && t?.has(e.name) ? `NVARCHAR(${Math.min(e.maxLength ?? 450, 450)})` : ut(e), i = B(e, "mssql");
280
281
  if (i) return `${K(e.name)} ${i}`;
281
282
  let a = [K(e.name), r];
282
- if (e.type === "json" && a.push(`CHECK ${b(K(e.name))}`), e.type === "array" && a.push(`CHECK (${K(e.name)} IS NULL OR ISJSON(${K(e.name)}) = 1)`), e.type === "id" && !n && a.push("PRIMARY KEY"), e.nullable || a.push("NOT NULL"), e.unique && e.type !== "id" && a.push("UNIQUE"), e.hasDefault) {
283
- let t = G(e.defaultValue, "SYSUTCDATETIME()");
283
+ if (e.type === "json" && a.push(`CHECK ${S(K(e.name))}`), e.type === "array" && a.push(`CHECK (${K(e.name)} IS NULL OR ISJSON(${K(e.name)}) = 1)`), e.type === "id" && !n && a.push("PRIMARY KEY"), e.nullable || a.push("NOT NULL"), e.unique && e.type !== "id" && a.push("UNIQUE"), e.hasDefault) {
284
+ let t = W(e.defaultValue, "SYSUTCDATETIME()");
284
285
  t && a.push(t);
285
286
  }
286
- return e.references && (a.push(`REFERENCES ${K(e.references.table)} (${K(e.references.column)})`), e.references.onDelete && a.push(`ON DELETE ${et[e.references.onDelete]}`)), a.join(" ");
287
- }, ut = (e) => {
288
- let t = (e) => e.replace(/'/g, "''"), n = /* @__PURE__ */ new Set([...e.indexes.flatMap((e) => e.columns), ...e.columns.filter((e) => e.unique).map((e) => e.name)]), r = e.columns.map((t) => ` ${lt(t, n, U(e))}`).join(",\n"), i = `CREATE TABLE ${K(e.table)} (\n${r}${W(e, K)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
287
+ return e.references && (a.push(`REFERENCES ${K(e.references.table)} (${K(e.references.column)})`), e.references.onDelete && a.push(`ON DELETE ${rt[e.references.onDelete]}`)), a.join(" ");
288
+ }, ft = (e) => {
289
+ let t = (e) => e.replace(/'/g, "''"), n = /* @__PURE__ */ new Set([...e.indexes.flatMap((e) => e.columns), ...e.columns.filter((e) => e.unique).map((e) => e.name)]), r = e.columns.map((t) => ` ${dt(t, n, V(e))}`).join(",\n"), i = `CREATE TABLE ${K(e.table)} (\n${r}${H(e, K)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
289
290
  for (let n of e.indexes) {
290
291
  if (n.name === `${e.table}_pkey`) continue;
291
292
  let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${K(n.name)} ON ${K(e.table)} (${n.columns.map(K).join(", ")})${q(n)}`;
292
293
  a.push(`IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'${t(n.name)}' AND object_id = OBJECT_ID(N'${t(e.table)}')) EXEC(N'${t(r)}')`);
293
294
  }
294
295
  return a;
295
- }, dt = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, ft = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME TO ${n(t)};`, pt = (e) => {
296
- if (e === void 0 || !Ke(e)) return;
296
+ }, pt = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, mt = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME TO ${n(t)};`, ht = (e) => {
297
+ if (e === void 0 || !Xe(e)) return;
297
298
  let t = typeof e.maxLength == "number" && e.maxLength > 0 ? e.maxLength : void 0;
298
- return t === void 0 ? Ge : Math.min(Ge, t);
299
- }, mt = (e, t, n) => {
300
- let r = pt(B(e, t, n));
301
- return r === void 0 ? I(n) : `${I(n)}(${r})`;
302
- }, ht = (e) => e.startsWith("(") ? e : F(e), q = (e) => e.where === void 0 ? "" : ` WHERE ${e.where}`, gt = (e, t) => {
303
- let n = p(e.index.kind, e.index.kindOptions), r = e.index.columns.map(ht);
299
+ return t === void 0 ? Ye : Math.min(Ye, t);
300
+ }, gt = (e, t) => {
301
+ let n = `${e}_${t}_key`;
302
+ if (n.length <= 64) return n;
303
+ let r = De("sha256").update(`${e}.${t}`).digest("hex").slice(0, 8);
304
+ return `${`${e}_${t}`.slice(0, 64 - r.length - 5)}_${r}_key`;
305
+ }, _t = (e, t, n, r) => {
306
+ let i = ht(r ?? R(e, t, n));
307
+ return i === void 0 ? P(n) : `${P(n)}(${i})`;
308
+ }, vt = (e) => e.startsWith("(") ? e : N(e), q = (e) => e.where === void 0 ? "" : ` WHERE ${e.where}`, yt = (e, t) => {
309
+ let n = p(e.index.kind, e.index.kindOptions), r = e.index.columns.map(vt);
304
310
  if (n.opclass !== void 0) {
305
311
  if (r.length !== 1) throw Error("HNSW index requires exactly one column");
306
312
  r[0] = `${r[0]} ${n.opclass}`;
307
313
  }
308
- return `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${F(e.index.name)} ON ${F(e.table)}${n.using} (${r.join(", ")})${n.withSuffix}${q(e.index)};`;
309
- }, _t = (e, t, n = "mariadb") => (vt(e.index, n), `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${je(n)}${I(e.index.name)} ON ${I(e.table)} (${e.index.columns.map((n) => mt(t, e.table, n)).join(", ")});`), vt = (e, t) => {
314
+ return `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${N(e.index.name)} ON ${N(e.table)}${n.using} (${r.join(", ")})${n.withSuffix}${q(e.index)};`;
315
+ }, bt = (e, t, n = "mariadb") => (xt(e.index, n), `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Fe(n)}${P(e.index.name)} ON ${P(e.table)} (${e.index.columns.map((n) => _t(t, e.table, n)).join(", ")});`), xt = (e, t) => {
310
316
  if (e.where !== void 0) throw Error(`Partial index '${e.name}' is not supported by ${t}; uniqueActive must be lowered before applying the plan.`);
311
- }, yt = (e) => `DROP INDEX IF EXISTS ${F(e.index)};`, bt = (e) => `DROP INDEX ${I(e.index)} ON ${I(e.table)};`, xt = (e) => `DROP INDEX IF EXISTS ${K(e.index)} ON ${K(e.table)};`, St = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, Ct = (e) => {
317
+ }, St = (e) => `DROP INDEX IF EXISTS ${N(e.index)};`, Ct = (e) => `DROP INDEX ${P(e.index)} ON ${P(e.table)};`, wt = (e) => `DROP INDEX IF EXISTS ${K(e.index)} ON ${K(e.table)};`, Tt = (e, t) => `ALTER TABLE ${t(e.from)} RENAME TO ${t(e.to)};`, Et = (e) => {
312
318
  let t = (e) => e.replace(/'/g, "''");
313
319
  return `EXEC sp_rename N'${t(e.from)}', N'${t(e.to)}';`;
314
- }, wt = (e) => `ALTER INDEX ${F(e.from)} RENAME TO ${F(e.to)};`, Tt = (e) => `ALTER TABLE ${I(e.table)} RENAME INDEX ${I(e.from)} TO ${I(e.to)};`, Et = (e) => {
320
+ }, Dt = (e) => `ALTER INDEX ${N(e.from)} RENAME TO ${N(e.to)};`, Ot = (e) => `ALTER TABLE ${P(e.table)} RENAME INDEX ${P(e.from)} TO ${P(e.to)};`, kt = (e) => {
315
321
  let t = (e) => e.replace(/'/g, "''");
316
322
  return `EXEC sp_rename N'${t(e.table)}.${t(e.from)}', N'${t(e.to)}', N'INDEX';`;
317
- }, Dt = (e) => {
323
+ }, At = (e) => {
318
324
  let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map(K).join(", ")})${q(e.index)}`;
319
325
  return `IF NOT EXISTS (SELECT 1 FROM sys.indexes WHERE name = N'${t(e.index.name)}' AND object_id = OBJECT_ID(N'${t(e.table)}')) EXEC(N'${t(n)}');`;
320
- }, Ot = (e, t, n) => {
326
+ }, jt = (e, t, n) => {
321
327
  let r = n.find((t) => t.tableName === e);
322
328
  if (!r) return [];
323
329
  let i = [];
@@ -329,13 +335,22 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
329
335
  }
330
336
  }
331
337
  return i;
332
- }, kt = (e) => `ALTER TABLE ${F(e.table)} ADD CONSTRAINT ${F(`${e.table}_${e.column}_key`)} UNIQUE (${F(e.column)});`, At = (e, t) => `ALTER TABLE ${I(e.table)} ADD CONSTRAINT ${I(`${e.table}_${e.column}_key`)} UNIQUE (${mt(t, e.table, e.column)});`, jt = (e) => {
333
- let t = e.fields.map((e) => F(e)).join(", ");
334
- return `ALTER TABLE ${F(e.table)} ADD CONSTRAINT ${F(e.name)} UNIQUE (${t});`;
335
- }, Mt = (e, t) => {
336
- let n = e.fields.map((n) => mt(t, e.table, n)).join(", ");
337
- return `ALTER TABLE ${I(e.table)} ADD CONSTRAINT ${I(e.name)} UNIQUE (${n});`;
338
- }, Nt = (e) => `ALTER TABLE ${F(e.table)} DROP CONSTRAINT IF EXISTS ${F(e.name)};`, Pt = (e) => [Nt(e), `DROP INDEX IF EXISTS ${F(e.name)};`], Ft = (e) => e.name === `${e.table}_pkey` ? `ALTER TABLE ${I(e.table)} DROP PRIMARY KEY;` : `ALTER TABLE ${I(e.table)} DROP INDEX ${I(e.name)};`, It = (e) => `ALTER TABLE ${F(e.table)} DROP CONSTRAINT IF EXISTS ${F(`${e.table}_${e.column}_key`)};`, Lt = (e) => `ALTER TABLE ${I(e.table)} DROP INDEX ${I(`${e.table}_${e.column}_key`)};`, Rt = (e, t, n = $e) => {
338
+ }, Mt = (e) => `ALTER TABLE ${N(e.table)} ADD CONSTRAINT ${N(`${e.table}_${e.column}_key`)} UNIQUE (${N(e.column)});`, Nt = (e, t, n) => `ALTER TABLE ${P(e.table)} ADD CONSTRAINT ${P(gt(e.table, e.column))} UNIQUE (${_t(t, e.table, e.column, n)});`, Pt = (e) => {
339
+ let t = e.fields.map((e) => N(e)).join(", ");
340
+ return `ALTER TABLE ${N(e.table)} ADD CONSTRAINT ${N(e.name)} UNIQUE (${t});`;
341
+ }, Ft = (e, t) => {
342
+ let n = e.fields.map((n) => _t(t, e.table, n)).join(", ");
343
+ return `ALTER TABLE ${P(e.table)} ADD CONSTRAINT ${P(e.name)} UNIQUE (${n});`;
344
+ }, It = (e) => `ALTER TABLE ${N(e.table)} DROP CONSTRAINT IF EXISTS ${N(e.name)};`, Lt = (e) => [It(e), `DROP INDEX IF EXISTS ${N(e.name)};`], Rt = (e) => e.name === `${e.table}_pkey` ? `ALTER TABLE ${P(e.table)} DROP PRIMARY KEY;` : `ALTER TABLE ${P(e.table)} DROP INDEX ${P(e.name)};`, zt = (e) => `ALTER TABLE ${N(e.table)} DROP CONSTRAINT IF EXISTS ${N(`${e.table}_${e.column}_key`)};`, Bt = (e) => `DECLARE @drop NVARCHAR(MAX) = N'';
345
+ SELECT @drop = @drop + CASE WHEN i.is_unique_constraint = 1
346
+ THEN N'ALTER TABLE ' + QUOTENAME(OBJECT_SCHEMA_NAME(i.object_id)) + N'.' + QUOTENAME(OBJECT_NAME(i.object_id)) + N' DROP CONSTRAINT ' + QUOTENAME(i.name) + N';'
347
+ ELSE N'DROP INDEX ' + QUOTENAME(i.name) + N' ON ' + QUOTENAME(OBJECT_SCHEMA_NAME(i.object_id)) + N'.' + QUOTENAME(OBJECT_NAME(i.object_id)) + N';' END
348
+ FROM sys.indexes i
349
+ WHERE i.object_id = OBJECT_ID(N'${e.table.replace(/'/g, "''")}') AND i.is_unique = 1 AND i.is_primary_key = 0 AND i.has_filter = 0
350
+ AND (SELECT COUNT(*) FROM sys.index_columns k WHERE k.object_id = i.object_id AND k.index_id = i.index_id AND k.is_included_column = 0) = 1
351
+ AND EXISTS (SELECT 1 FROM sys.index_columns k JOIN sys.columns c ON c.object_id = k.object_id AND c.column_id = k.column_id
352
+ WHERE k.object_id = i.object_id AND k.index_id = i.index_id AND k.is_included_column = 0 AND c.name = N'${e.column.replace(/'/g, "''")}');
353
+ EXEC sp_executesql @drop;`, Vt = (e) => `ALTER TABLE ${P(e.table)} DROP INDEX ${P(gt(e.table, e.column))};`, Ht = (e, t, n = U) => {
339
354
  let r = [], i = t(e.table), a = t(e.column), o = t(e.targetTable), s = t(e.targetColumn);
340
355
  if (e.orphanPolicy) {
341
356
  let t = `${a} IS NOT NULL AND ${a} NOT IN (SELECT ${s} FROM ${o})`;
@@ -348,43 +363,44 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
348
363
  `REFERENCES ${o} (${s})`
349
364
  ];
350
365
  return e.onDelete && c.push(`ON DELETE ${n[e.onDelete]}`), r.push(c.join(" ") + ";"), r;
351
- }, zt = (e) => e.name ?? `${e.table}_${e.column}_fkey`, Bt = (e) => `ALTER TABLE ${F(e.table)} DROP CONSTRAINT IF EXISTS ${F(zt(e))};`, Vt = (e) => `ALTER TABLE ${I(e.table)} DROP FOREIGN KEY ${I(zt(e))};`, Ht = (e, t) => {
366
+ }, Ut = (e) => e.name ?? `${e.table}_${e.column}_fkey`, Wt = (e) => `ALTER TABLE ${N(e.table)} DROP CONSTRAINT IF EXISTS ${N(Ut(e))};`, Gt = (e) => `ALTER TABLE ${P(e.table)} DROP FOREIGN KEY ${P(Ut(e))};`, Kt = (e, t) => {
352
367
  let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
353
368
  return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
354
- }, Ut = (e) => `ALTER TABLE ${F(e.table)} DROP CONSTRAINT IF EXISTS ${F(`${e.table}_${e.column}_check`)};`, Wt = (e, t) => M.gen(function* () {
369
+ }, qt = (e) => `ALTER TABLE ${N(e.table)} DROP CONSTRAINT IF EXISTS ${N(`${e.table}_${e.column}_check`)};`, Jt = (e, t) => j.gen(function* () {
355
370
  let n = yield* e`
356
371
  SELECT cc.constraint_name AS n, cc.check_clause AS c
357
372
  FROM information_schema.check_constraints cc
358
- WHERE cc.constraint_schema = DATABASE() AND cc.table_name = ${t.table}`.pipe(M.catch(() => e`
373
+ WHERE cc.constraint_schema = DATABASE() AND cc.table_name = ${t.table}`.pipe(j.catch(() => e`
359
374
  SELECT cc.constraint_name AS n, cc.check_clause AS c
360
375
  FROM information_schema.check_constraints cc
361
376
  JOIN information_schema.table_constraints tc
362
377
  ON tc.constraint_schema = cc.constraint_schema
363
378
  AND tc.constraint_name = cc.constraint_name
364
- WHERE tc.table_schema = DATABASE() AND tc.table_name = ${t.table}`), M.orElseSucceed(() => []));
379
+ WHERE tc.table_schema = DATABASE() AND tc.table_name = ${t.table}`), j.orElseSucceed(() => []));
365
380
  for (let e of n) {
366
381
  let n = String(e.n ?? "");
367
- if (n !== "" && D(String(e.c ?? ""))?.column === t.column) return n;
382
+ if (n !== "" && fe(String(e.c ?? ""))?.column === t.column) return n;
368
383
  }
369
- }), Gt = (e, t, n) => M.gen(function* () {
370
- let r = yield* Wt(e, t);
371
- r !== void 0 && (yield* J(e, `ALTER TABLE ${I(t.table)} DROP CONSTRAINT ${I(r)};`, t.kind, [ge]));
372
- let i = yield* Wt(e, t);
384
+ }), Yt = (e, t, n) => j.gen(function* () {
385
+ let r = yield* Jt(e, t);
386
+ r !== void 0 && (yield* J(e, `ALTER TABLE ${P(t.table)} DROP CONSTRAINT ${P(r)};`, t.kind, [ve]));
387
+ let i = yield* Jt(e, t);
373
388
  if (i === void 0) return;
374
- let a = z(n, t.table, t.column);
375
- if (!a) return yield* M.die(/* @__PURE__ */ Error(`applier: cannot drop the CHECK on '${t.table}.${t.column}' — it is column-level (catalog name '${i}'), which this family removes only by redefining the column, and the declared column is not available to redefine it from.`));
376
- yield* J(e, `ALTER TABLE ${I(t.table)} MODIFY COLUMN ${Le(a, t.column)};`, t.kind);
377
- }), Kt = (e, t, n, r) => {
378
- let i = e.column, a = r === "mariadb", o = a ? I : r === "mssql" ? K : F, s = a ? qe(i) : r === "mssql" ? ct(i) : r === "sqlite" ? tt(i) : P(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = r === "mssql" ? i.type === "json" ? ` CHECK ${b(o(i.name))}` : i.type === "array" ? ` CHECK (${o(i.name)} IS NULL OR ISJSON(${o(i.name)}) = 1)` : "" : "", u = (e) => a ? Be(e, i) : r === "mssql" ? G(e, "SYSUTCDATETIME()") : r === "sqlite" ? G(e, "CURRENT_TIMESTAMP") : He(e, i), d = H(i, r);
389
+ let a = L(n, t.table, t.column);
390
+ if (!a) return yield* j.die(/* @__PURE__ */ Error(`applier: cannot drop the CHECK on '${t.table}.${t.column}' — it is column-level (catalog name '${i}'), which this family removes only by redefining the column, and the declared column is not available to redefine it from.`));
391
+ yield* J(e, `ALTER TABLE ${P(t.table)} MODIFY COLUMN ${Ve(a, t.column)};`, t.kind);
392
+ }), Xt = (e, t, n, r) => {
393
+ let i = e.column, a = r === "mariadb", o = a ? P : r === "mssql" ? K : N, s = a ? Ze(i) : r === "mssql" ? ut(i) : r === "sqlite" ? it(i) : Me(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = r === "mssql" ? i.type === "json" ? ` CHECK ${S(o(i.name))}` : i.type === "array" ? ` CHECK (${o(i.name)} IS NULL OR ISJSON(${o(i.name)}) = 1)` : "" : "", u = (e) => a ? We(e, i) : r === "mssql" ? W(e, "SYSUTCDATETIME()") : r === "sqlite" ? W(e, "CURRENT_TIMESTAMP") : Ke(e, i), d = B(i, r);
379
394
  if (d) {
380
395
  let t = r === "mssql" ? `${o(i.name)} ${d}` : `${o(i.name)} ${s} ${d}`;
381
396
  return {
382
397
  pre: [`ALTER TABLE ${o(e.table)} ${c} ${t};`],
383
- post: []
398
+ post: [],
399
+ ...i.unique && i.type !== "id" ? { uniquePending: !0 } : {}
384
400
  };
385
401
  }
386
402
  if (i.type === "id" && i.idScheme?.kind === "numeric" && (r === "postgres" || a)) return {
387
- pre: [`ALTER TABLE ${o(e.table)} ${c} ${w(i.name, r)};`],
403
+ pre: [`ALTER TABLE ${o(e.table)} ${c} ${T(i.name, r)};`],
388
404
  post: []
389
405
  };
390
406
  if (t.classification === "safe") {
@@ -408,7 +424,7 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
408
424
  post: p ? [p] : []
409
425
  };
410
426
  return i.unique && i.type !== "id" && (m.uniquePending = !0), f?.sql && (m.backfillKind = "sql", m.backfillSql = f.sql), f?.js && (m.backfillKind = "js", m.backfillJs = f.js), f?.batchSize !== void 0 && (m.batchSize = f.batchSize), f?.sleepMs !== void 0 && (m.sleepMs = f.sleepMs), m;
411
- }, qt = /* @__PURE__ */ new Set([
427
+ }, Zt = /* @__PURE__ */ new Set([
412
428
  "drop-index",
413
429
  "drop-check",
414
430
  "drop-unique",
@@ -416,7 +432,7 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
416
432
  "drop-foreign-key",
417
433
  "drop-column",
418
434
  "drop-table"
419
- ]), Jt = (e) => {
435
+ ]), Qt = (e) => {
420
436
  let t = new Map(e.map((e) => [e.tableName, e]));
421
437
  return (e, n) => {
422
438
  let r = t.get(e);
@@ -436,12 +452,15 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
436
452
  ...o
437
453
  };
438
454
  };
439
- }, J = (e, t, n, r = []) => e.unsafe(t).pipe(M.catchIf((e) => be(e, r), () => M.void), M.tapError((e) => M.sync(() => {
455
+ }, J = (e, t, n, r = []) => j.forEach(ge($t(e), t), (t) => en(e, t, n, r), { discard: !0 }), $t = (e) => e.onDialectOrElse({
456
+ pg: () => "postgres",
457
+ orElse: () => "other"
458
+ }), en = (e, t, n, r) => e.unsafe(t).pipe(j.catchIf((e) => Se(e, r), () => j.void), j.tapError((e) => j.sync(() => {
440
459
  process.stderr.write(m(`applier: statement failed (op=${n})`, t, e, 400));
441
- })), M.mapError((e) => {
460
+ })), j.mapError((e) => {
442
461
  let r = m(`applier: statement failed (op=${n})`, t, e, 400).trim();
443
462
  return s(r, e);
444
- }), M.map(() => void 0)), Y = (e, t, n, r) => Yt(e, t, it(t, n), r), Yt = (e, t, n, r) => le(e, n).pipe(M.mapError((e) => s(`applier: atomic SQLite rebuild failed (op=${r}, table=${t}): ${e.message}`, e))), Xt = (e, t) => M.gen(function* () {
463
+ }), j.map(() => void 0)), Y = (e, t, n, r) => tn(e, t, ot(t, n), r), tn = (e, t, n, r) => ce(e, n).pipe(j.mapError((e) => s(`applier: atomic SQLite rebuild failed (op=${r}, table=${t}): ${e.message}`, e))), nn = (e, t) => j.gen(function* () {
445
464
  let r = (yield* e`
446
465
  SELECT ck.name, ck.definition, ck.is_disabled AS disabled,
447
466
  ck.is_not_trusted AS untrusted, ck.is_not_for_replication AS notForReplication
@@ -453,53 +472,53 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
453
472
  ) ORDER BY ck.name
454
473
  `).map((e) => ({
455
474
  ...e,
456
- definition: Se(e.definition, t.from, t.to)
475
+ definition: we(e.definition, t.from, t.to)
457
476
  })), i = (e) => n(e, "mssql"), a = (e) => e.replace(/'/g, "''");
458
477
  return yield* X(e, [
459
478
  ...r.map((e) => `ALTER TABLE ${i(t.table)} DROP CONSTRAINT ${i(e.name)}`),
460
479
  `EXEC sp_rename N'${a(`${i(t.table)}.${i(t.from)}`)}', N'${a(t.to)}', 'COLUMN';`,
461
480
  ...r.flatMap((e) => [`ALTER TABLE ${i(t.table)} WITH ${e.untrusted ? "NOCHECK" : "CHECK"} ADD CONSTRAINT ${i(e.name)} CHECK ${e.notForReplication ? "NOT FOR REPLICATION " : ""}${e.definition}`, ...e.disabled ? [`ALTER TABLE ${i(t.table)} NOCHECK CONSTRAINT ${i(e.name)}`] : []])
462
481
  ], t.kind);
463
- }), Zt = (e, t, n) => e == null ? e : t.type === "json" ? JSON.stringify(e) : (t.type === "array" || t.type === "vector") && n !== "postgres" ? typeof e == "string" ? e : JSON.stringify(e) : e, X = (e, t, n) => M.forEach(t, (t) => J(e, t, n), { discard: !0 }), Z = (e, t, r, i) => e.unsafe(`SELECT ${i === void 0 ? "*" : n(i, t)} FROM ${n(r, t)} WHERE 1=0`).pipe(M.as(!0), M.catch(() => M.succeed(!1))), Qt = (e, t, n) => Q(e, t, re, h, n), $t = (e, t, n) => Q(e, t, c, "_voltro_migration_plans", n), en = (e, t, n) => Q(e, t, u, "_voltro_schema_owner", n), tn = (e, t, n) => Q(e, t, l, "_voltro_plugin_migrations", n), nn = (e, t, n) => Q(e, t, fe, de, n), rn = (e, t, n) => Q(e, t, f, d, n), Q = (t, n, r, i, a) => M.gen(function* () {
464
- let o = ue([r], n, a !== void 0 && e(n) ? { charset: a } : {}).tables[0];
465
- if (!o) return yield* M.die(/* @__PURE__ */ Error(`migration applier: the ${i} table descriptor produced no snapshot. This is a framework bug.`));
482
+ }), rn = (e, t, n) => e == null ? e : t.type === "json" ? JSON.stringify(e) : (t.type === "array" || t.type === "vector") && n !== "postgres" ? typeof e == "string" ? e : JSON.stringify(e) : e, X = (e, t, n) => j.forEach(t, (t) => J(e, t, n), { discard: !0 }), Z = (e, t, r, i) => e.unsafe(`SELECT ${i === void 0 ? "*" : n(i, t)} FROM ${n(r, t)} WHERE 1=0`).pipe(j.as(!0), j.catch(() => j.succeed(!1))), an = (e, t, n) => Q(e, t, v, g, n), on = (e, t, n) => Q(e, t, c, "_voltro_migration_plans", n), sn = (e, t, n) => Q(e, t, u, "_voltro_schema_owner", n), cn = (e, t, n) => Q(e, t, l, "_voltro_plugin_migrations", n), ln = (e, t, n) => Q(e, t, de, ue, n), un = (e, t, n) => Q(e, t, f, d, n), Q = (t, n, r, i, a) => j.gen(function* () {
483
+ let o = le([r], n, a !== void 0 && e(n) ? { charset: a } : {}).tables[0];
484
+ if (!o) return yield* j.die(/* @__PURE__ */ Error(`migration applier: the ${i} table descriptor produced no snapshot. This is a framework bug.`));
466
485
  let s = {
467
486
  kind: "create-table",
468
487
  table: i,
469
488
  columns: o.columns,
470
489
  indexes: []
471
490
  }, c = yield* t.onDialectOrElse({
472
- mysql: () => A(t).pipe(M.map((e) => Qe(s, e))),
473
- mssql: () => M.succeed(ut(s)),
474
- sqlite: () => M.succeed(rt(s)),
475
- orElse: () => M.succeed(We(s))
491
+ mysql: () => k(t).pipe(j.map((e) => nt(s, e))),
492
+ mssql: () => j.succeed(ft(s)),
493
+ sqlite: () => j.succeed(G(s)),
494
+ orElse: () => j.succeed(Je(s))
476
495
  });
477
- yield* M.forEach(c, (e) => J(t, e, "resume-ledger-bootstrap"), { discard: !0 });
478
- }), an = (e) => e`
496
+ yield* j.forEach(c, (e) => J(t, e, "resume-ledger-bootstrap"), { discard: !0 });
497
+ }), dn = (e) => e`
479
498
  SELECT ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
480
499
  ${e("status")}, ${e("payload")}
481
- FROM ${e(h)}
482
- `, on = (e) => O(e, h).pipe(M.flatMap((t) => t ? an(e).pipe(M.map((e) => e.length > 0)) : M.succeed(!1))), sn = (e, t, n, r) => M.gen(function* () {
483
- let i = yield* j(e, (/* @__PURE__ */ new Date()).toISOString());
484
- yield* M.forEach(r, ({ index: r, planned: a }) => e`
485
- INSERT INTO ${e(h)}
500
+ FROM ${e(g)}
501
+ `, fn = (e) => pe(e, g).pipe(j.flatMap((t) => t ? dn(e).pipe(j.map((e) => e.length > 0)) : j.succeed(!1))), pn = (e, t, n, r) => j.gen(function* () {
502
+ let i = yield* A(e, (/* @__PURE__ */ new Date()).toISOString());
503
+ yield* j.forEach(r, ({ index: r, planned: a }) => e`
504
+ INSERT INTO ${e(g)}
486
505
  (${e("id")}, ${e("runId")}, ${e("planFingerprint")}, ${e("opIndex")},
487
506
  ${e("opKind")}, ${e("opTarget")}, ${e("status")}, ${e("payload")},
488
507
  ${e("createdAt")})
489
508
  VALUES
490
509
  (${`mop_${t}_${r}`}, ${t}, ${n}, ${r},
491
- ${a.op.kind}, ${ae(a.op)}, ${"pending"},
510
+ ${a.op.kind}, ${x(a.op)}, ${"pending"},
492
511
  ${JSON.stringify(a)}, ${i})
493
512
  `, { discard: !0 });
494
- }), $ = (e, t, n, r, i, a) => M.gen(function* () {
495
- let o = yield* j(e, (/* @__PURE__ */ new Date()).toISOString());
513
+ }), $ = (e, t, n, r, i, a) => j.gen(function* () {
514
+ let o = yield* A(e, (/* @__PURE__ */ new Date()).toISOString());
496
515
  r === "applied" ? yield* e`
497
- UPDATE ${e(h)}
516
+ UPDATE ${e(g)}
498
517
  SET ${e("status")} = ${r}, ${e("appliedAt")} = ${o},
499
518
  ${e("durationMs")} = ${i ?? null}
500
519
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
501
- ` : r === "started" && a !== void 0 && ["sqlite", "turso"].includes(_(e)) ? yield* e`
502
- UPDATE ${e(h)}
520
+ ` : r === "started" && a !== void 0 && ["sqlite", "turso"].includes(y(e)) ? yield* e`
521
+ UPDATE ${e(g)}
503
522
  SET ${e("status")} = ${r}, ${e("startedAt")} = ${o},
504
523
  ${e("payload")} = ${JSON.stringify({
505
524
  ...a,
@@ -507,23 +526,23 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
507
526
  })}
508
527
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
509
528
  ` : yield* e`
510
- UPDATE ${e(h)}
529
+ UPDATE ${e(g)}
511
530
  SET ${e("status")} = ${r}, ${e("startedAt")} = ${o}
512
531
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} = ${n}
513
532
  `;
514
- }), cn = (e, t, n, r) => M.gen(function* () {
515
- let i = yield* j(e, (/* @__PURE__ */ new Date()).toISOString());
533
+ }), mn = (e, t, n, r) => j.gen(function* () {
534
+ let i = yield* A(e, (/* @__PURE__ */ new Date()).toISOString());
516
535
  r.length > 0 && (yield* e`
517
- UPDATE ${e(h)}
536
+ UPDATE ${e(g)}
518
537
  SET ${e("status")} = ${"applied"}, ${e("appliedAt")} = ${i}
519
538
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(r)}
520
539
  `), n.length > 0 && (yield* e`
521
- UPDATE ${e(h)}
540
+ UPDATE ${e(g)}
522
541
  SET ${e("status")} = ${"pending"}
523
542
  WHERE ${e("runId")} = ${t} AND ${e("opIndex")} IN ${e.in(n)}
524
543
  `);
525
- }), ln = (e, t) => t === void 0 ? e`DELETE FROM ${e(h)}`.pipe(M.asVoid) : e`DELETE FROM ${e(h)} WHERE ${e("runId")} = ${t}`.pipe(M.asVoid), un = (e) => an(e).pipe(M.map((e) => e.filter((e) => e.status === "started" || e.status === "added" || e.status === "applied").map((e) => JSON.parse(e.payload))), M.catch(() => M.succeed([]))), dn = (e) => ln(e).pipe(M.catch(() => M.void)), fn = (e, t, r) => M.gen(function* () {
526
- if (y(r.op, r.classification, t) !== "artefact-repair") return "clean";
544
+ }), hn = (e, t) => t === void 0 ? e`DELETE FROM ${e(g)}`.pipe(j.asVoid) : e`DELETE FROM ${e(g)} WHERE ${e("runId")} = ${t}`.pipe(j.asVoid), gn = (e) => dn(e).pipe(j.map((e) => e.filter((e) => e.status === "started" || e.status === "added" || e.status === "applied").map((e) => JSON.parse(e.payload))), j.catch(() => j.succeed([]))), _n = (e) => hn(e).pipe(j.catch(() => j.void)), vn = (e, t, r) => j.gen(function* () {
545
+ if (re(r.op, r.classification, t) !== "artefact-repair") return "clean";
527
546
  let i = r.op, a = (e) => n(e, t);
528
547
  if (t === "postgres" && i.kind === "add-index") {
529
548
  let t = yield* e`
@@ -539,185 +558,186 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
539
558
  }
540
559
  if (t === "sqlite" || t === "turso") {
541
560
  if (!("table" in i)) return "clean";
542
- let n = `${i.table}${ne}`;
543
- return (yield* Z(e, t, n)) ? ((yield* Z(e, t, i.table)) ? yield* J(e, `DROP TABLE ${a(n)}`, "resume-repair") : yield* J(e, `ALTER TABLE ${a(n)} RENAME TO ${a(i.table)}`, "resume-repair"), yield* M.logWarning(`migration resume: reconciled an interrupted sqlite table rebuild on '${i.table}' — replaying the operation`).pipe(M.annotateLogs({ scope: "voltro:migrate" })), "outstanding") : "clean";
561
+ let n = `${i.table}${te}`;
562
+ return (yield* Z(e, t, n)) ? ((yield* Z(e, t, i.table)) ? yield* J(e, `DROP TABLE ${a(n)}`, "resume-repair") : yield* J(e, `ALTER TABLE ${a(n)} RENAME TO ${a(i.table)}`, "resume-repair"), yield* j.logWarning(`migration resume: reconciled an interrupted sqlite table rebuild on '${i.table}' — replaying the operation`).pipe(j.annotateLogs({ scope: "voltro:migrate" })), "outstanding") : "clean";
544
563
  }
545
564
  if (i.kind !== "alter-column-type") return "clean";
546
- let o = `${i.column}${te}`, s = `${i.column}${g}`, c = yield* Z(e, t, i.table, i.column), l = yield* Z(e, t, i.table, o), u = yield* Z(e, t, i.table, s), d = (e) => M.logWarning(`migration resume: ${e}`).pipe(M.annotateLogs({ scope: "voltro:migrate" }));
547
- return !l && !u ? "clean" : c && l && !u ? (yield* J(e, `ALTER TABLE ${a(i.table)} DROP COLUMN ${a(o)}`, "resume-repair"), yield* d(`dropped a half-populated shadow column '${i.table}.${o}' — replaying the type change`), "outstanding") : !c && l && u ? (yield* J(e, `ALTER TABLE ${a(i.table)} RENAME COLUMN ${a(o)} TO ${a(i.column)}`, "resume-repair"), yield* J(e, `ALTER TABLE ${a(i.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`completed an interrupted shadow swap on '${i.table}.${i.column}'`), "applied") : c && !l && u ? (yield* J(e, `ALTER TABLE ${a(i.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`dropped the leftover pre-swap column '${i.table}.${s}'`), "applied") : yield* M.die(/* @__PURE__ */ Error(`applyPlan: an interrupted online type change on '${i.table}.${i.column}' left a shadow-swap state this resume cannot classify (column=${c}, ${o}=${l}, ${s}=${u}).\nNothing was changed. Inspect those three columns and reconcile them by hand — the data is in whichever of them is populated — then re-run the migration.`));
548
- }), pn = (e, r, i, o = "fresh", c) => M.gen(function* () {
549
- let l = process.hrtime.bigint(), u = Jt(i.declared), d = r.op, f = _(e);
565
+ let o = `${i.column}${ee}`, s = `${i.column}${_}`, c = yield* Z(e, t, i.table, i.column), l = yield* Z(e, t, i.table, o), u = yield* Z(e, t, i.table, s), d = (e) => j.logWarning(`migration resume: ${e}`).pipe(j.annotateLogs({ scope: "voltro:migrate" }));
566
+ return !l && !u ? "clean" : c && l && !u ? (yield* J(e, `ALTER TABLE ${a(i.table)} DROP COLUMN ${a(o)}`, "resume-repair"), yield* d(`dropped a half-populated shadow column '${i.table}.${o}' — replaying the type change`), "outstanding") : !c && l && u ? (yield* J(e, `ALTER TABLE ${a(i.table)} RENAME COLUMN ${a(o)} TO ${a(i.column)}`, "resume-repair"), yield* J(e, `ALTER TABLE ${a(i.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`completed an interrupted shadow swap on '${i.table}.${i.column}'`), "applied") : c && !l && u ? (yield* J(e, `ALTER TABLE ${a(i.table)} DROP COLUMN ${a(s)}`, "resume-repair"), yield* d(`dropped the leftover pre-swap column '${i.table}.${s}'`), "applied") : yield* j.die(/* @__PURE__ */ Error(`applyPlan: an interrupted online type change on '${i.table}.${i.column}' left a shadow-swap state this resume cannot classify (column=${c}, ${o}=${l}, ${s}=${u}).\nNothing was changed. Inspect those three columns and reconcile them by hand — the data is in whichever of them is populated — then re-run the migration.`));
567
+ }), yn = (e, r, i, o = "fresh", c) => j.gen(function* () {
568
+ let l = process.hrtime.bigint(), u = Qt(i.declared), d = r.op, f = y(e);
550
569
  switch (d.kind) {
551
570
  case "create-table": {
552
571
  let t = yield* e.onDialectOrElse({
553
- mysql: () => A(e).pipe(M.map((e) => Qe(d, e))),
554
- mssql: () => M.succeed(ut(d)),
555
- sqlite: () => M.succeed(rt(d)),
556
- orElse: () => M.succeed(We(d))
572
+ mysql: () => k(e).pipe(j.map((e) => nt(d, e))),
573
+ mssql: () => j.succeed(ft(d)),
574
+ sqlite: () => j.succeed(G(d)),
575
+ orElse: () => j.succeed(Je(d))
557
576
  }), n = yield* e.onDialectOrElse({
558
- mysql: () => M.succeed([ve]),
559
- orElse: () => M.succeed([])
577
+ mysql: () => j.succeed([be]),
578
+ orElse: () => j.succeed([])
560
579
  });
561
580
  for (let r of t) yield* J(e, r, d.kind, n);
562
581
  break;
563
582
  }
564
583
  case "drop-table": {
565
- let t = me(r), n = t !== void 0 || process.env.VOLTRO_SOFT_DROP === "1", i = t ?? pe(r, (/* @__PURE__ */ new Date()).toISOString()).softDropSnapshot, a = (e) => n ? ft(d, i, e) : dt(d, e);
584
+ let t = he(r), n = t !== void 0 || process.env.VOLTRO_SOFT_DROP === "1", i = t ?? me(r, (/* @__PURE__ */ new Date()).toISOString()).softDropSnapshot, a = (e) => n ? mt(d, i, e) : pt(d, e);
566
585
  yield* e.onDialectOrElse({
567
- mysql: () => J(e, a(I), d.kind),
568
- mssql: () => J(e, n ? Ct({
586
+ mysql: () => J(e, a(P), d.kind),
587
+ mssql: () => J(e, n ? Et({
569
588
  kind: "rename-table",
570
589
  from: d.table,
571
590
  to: i
572
- }) : dt(d, F), d.kind),
573
- orElse: () => J(e, a(F), d.kind)
591
+ }) : pt(d, N), d.kind),
592
+ orElse: () => J(e, a(N), d.kind)
574
593
  });
575
594
  break;
576
595
  }
577
596
  case "drop-column": {
578
- let t = me(r), n = t !== void 0 || process.env.VOLTRO_SOFT_DROP === "1", i = t ?? pe(r, (/* @__PURE__ */ new Date()).toISOString()).softDropSnapshot;
597
+ let t = he(r), n = t !== void 0 || process.env.VOLTRO_SOFT_DROP === "1", i = t ?? me(r, (/* @__PURE__ */ new Date()).toISOString()).softDropSnapshot;
579
598
  yield* e.onDialectOrElse({
580
- mysql: () => A(e).pipe(M.flatMap((t) => J(e, n ? Ne(d, i, I) : Me(d, t), d.kind, n ? [] : [he]))),
581
- mssql: () => n ? Xt(e, {
599
+ mysql: () => k(e).pipe(j.flatMap((t) => J(e, n ? Le(d, i, P) : Ie(d, t), d.kind, n ? [] : [_e]))),
600
+ mssql: () => n ? nn(e, {
582
601
  kind: "rename-column",
583
602
  table: d.table,
584
603
  from: d.column,
585
604
  to: i
586
- }) : J(e, L(d, F), d.kind),
587
- sqlite: () => J(e, n ? Ne(d, i, F) : L(d, F, !1), d.kind, n ? [] : [ye]),
588
- orElse: () => J(e, n ? Ne(d, i, F) : L(d, F), d.kind)
605
+ }) : J(e, F(d, N), d.kind),
606
+ sqlite: () => J(e, n ? Le(d, i, N) : F(d, N, !1), d.kind, n ? [] : [xe]),
607
+ orElse: () => J(e, n ? Le(d, i, N) : F(d, N), d.kind)
589
608
  });
590
609
  break;
591
610
  }
592
611
  case "rename-column":
593
612
  yield* e.onDialectOrElse({
594
- mysql: () => J(e, R(d, I), d.kind),
595
- mssql: () => Xt(e, d),
596
- orElse: () => J(e, R(d, F), d.kind)
613
+ mysql: () => J(e, I(d, P), d.kind),
614
+ mssql: () => nn(e, d),
615
+ orElse: () => J(e, I(d, N), d.kind)
597
616
  });
598
617
  break;
599
618
  case "add-index":
600
619
  yield* e.onDialectOrElse({
601
- sqlite: () => J(e, gt(d, !1), d.kind),
602
- mysql: () => A(e).pipe(M.flatMap((t) => J(e, _t(d, i.declared, t), d.kind, [ve]))),
603
- mssql: () => X(e, [...Ot(d.table, d.index.columns, i.declared), Dt(d)], d.kind),
604
- orElse: () => J(e, gt(d, r.classification === "online-required"), d.kind)
620
+ sqlite: () => J(e, yt(d, !1), d.kind),
621
+ mysql: () => k(e).pipe(j.flatMap((t) => J(e, bt(d, i.declared, t), d.kind, [be]))),
622
+ mssql: () => X(e, [...jt(d.table, d.index.columns, i.declared), At(d)], d.kind),
623
+ orElse: () => J(e, yt(d, r.classification === "online-required"), d.kind)
605
624
  });
606
625
  break;
607
626
  case "drop-index":
608
627
  yield* e.onDialectOrElse({
609
- mysql: () => J(e, bt(d), d.kind),
610
- mssql: () => J(e, xt(d), d.kind),
611
- orElse: () => J(e, yt(d), d.kind)
628
+ mysql: () => J(e, Ct(d), d.kind),
629
+ mssql: () => J(e, wt(d), d.kind),
630
+ orElse: () => J(e, St(d), d.kind)
612
631
  });
613
632
  break;
614
633
  case "rename-table":
615
634
  yield* e.onDialectOrElse({
616
- mysql: () => J(e, St(d, I), d.kind),
617
- mssql: () => J(e, Ct(d), d.kind),
618
- orElse: () => J(e, St(d, F), d.kind)
635
+ mysql: () => J(e, Tt(d, P), d.kind),
636
+ mssql: () => J(e, Et(d), d.kind),
637
+ orElse: () => J(e, Tt(d, N), d.kind)
619
638
  });
620
639
  break;
621
640
  case "rename-index":
622
641
  yield* e.onDialectOrElse({
623
- mysql: () => J(e, Tt(d), d.kind),
624
- mssql: () => J(e, Et(d), d.kind),
625
- orElse: () => J(e, wt(d), d.kind)
642
+ mysql: () => J(e, Ot(d), d.kind),
643
+ mssql: () => J(e, kt(d), d.kind),
644
+ orElse: () => J(e, Dt(d), d.kind)
626
645
  });
627
646
  break;
628
647
  case "add-unique":
629
648
  yield* e.onDialectOrElse({
630
- mysql: () => J(e, At(d, i.declared), d.kind),
649
+ mysql: () => J(e, Nt(d, i.declared), d.kind),
631
650
  sqlite: () => Y(e, d.table, i.declared, d.kind),
632
- mssql: () => X(e, [...Ot(d.table, [d.column], i.declared), kt(d)], d.kind),
633
- orElse: () => J(e, kt(d), d.kind)
651
+ mssql: () => X(e, [...jt(d.table, [d.column], i.declared), Mt(d)], d.kind),
652
+ orElse: () => J(e, Mt(d), d.kind)
634
653
  });
635
654
  break;
636
655
  case "drop-unique":
637
656
  yield* e.onDialectOrElse({
638
- mysql: () => J(e, Lt(d), d.kind),
657
+ mysql: () => J(e, Vt(d), d.kind),
658
+ mssql: () => J(e, Bt(d), d.kind),
639
659
  sqlite: () => Y(e, d.table, i.declared, d.kind),
640
- orElse: () => J(e, It(d), d.kind)
660
+ orElse: () => J(e, zt(d), d.kind)
641
661
  });
642
662
  break;
643
663
  case "add-enum-value":
644
664
  yield* e.onDialectOrElse({
645
- pg: () => d.enumName === void 0 ? M.die(/* @__PURE__ */ Error(`add-enum-value on postgres needs the type name for ${d.table}.${d.column}; the plan carries none.`)) : J(e, `ALTER TYPE ${n(d.enumName, "postgres")} ADD VALUE IF NOT EXISTS '${d.value.replace(/'/g, "''")}'`, d.kind),
665
+ pg: () => d.enumName === void 0 ? j.die(/* @__PURE__ */ Error(`add-enum-value on postgres needs the type name for ${d.table}.${d.column}; the plan carries none.`)) : J(e, `ALTER TYPE ${n(d.enumName, "postgres")} ADD VALUE IF NOT EXISTS '${d.value.replace(/'/g, "''")}'`, d.kind),
646
666
  mysql: () => {
647
- let t = z(i.declared, d.table, d.column);
648
- return t === void 0 || t.enumValues === void 0 || t.enumValues.length === 0 ? M.die(/* @__PURE__ */ Error(`add-enum-value on the mysql family needs the declared column ${d.table}.${d.column} and its labels; the declaration carries none.`)) : M.flatMap(V(e, d.table, t, d.column), (t) => J(e, t, d.kind));
667
+ let t = L(i.declared, d.table, d.column);
668
+ return t === void 0 || t.enumValues === void 0 || t.enumValues.length === 0 ? j.die(/* @__PURE__ */ Error(`add-enum-value on the mysql family needs the declared column ${d.table}.${d.column} and its labels; the declaration carries none.`)) : j.flatMap(z(e, d.table, t, d.column), (t) => J(e, t, d.kind));
649
669
  },
650
- orElse: () => M.void
670
+ orElse: () => j.void
651
671
  });
652
672
  break;
653
673
  case "add-unique-composite":
654
674
  yield* e.onDialectOrElse({
655
- mysql: () => J(e, Mt(d, i.declared), d.kind),
675
+ mysql: () => J(e, Ft(d, i.declared), d.kind),
656
676
  sqlite: () => Y(e, d.table, i.declared, d.kind),
657
- mssql: () => X(e, [...Ot(d.table, d.fields, i.declared), jt(d)], d.kind),
658
- orElse: () => J(e, jt(d), d.kind)
677
+ mssql: () => X(e, [...jt(d.table, d.fields, i.declared), Pt(d)], d.kind),
678
+ orElse: () => J(e, Pt(d), d.kind)
659
679
  });
660
680
  break;
661
681
  case "drop-unique-composite":
662
682
  yield* e.onDialectOrElse({
663
- mysql: () => J(e, Ft(d), d.kind),
683
+ mysql: () => J(e, Rt(d), d.kind),
664
684
  sqlite: () => Y(e, d.table, i.declared, d.kind),
665
- mssql: () => J(e, Nt(d), d.kind),
666
- orElse: () => X(e, Pt(d), d.kind)
685
+ mssql: () => J(e, It(d), d.kind),
686
+ orElse: () => X(e, Lt(d), d.kind)
667
687
  });
668
688
  break;
669
689
  case "add-foreign-key":
670
690
  yield* e.onDialectOrElse({
671
- mysql: () => X(e, Rt(d, I), d.kind),
691
+ mysql: () => X(e, Ht(d, P), d.kind),
672
692
  sqlite: () => Y(e, d.table, i.declared, d.kind),
673
- mssql: () => X(e, Rt(d, K, et), d.kind),
674
- orElse: () => X(e, Rt(d, F), d.kind)
693
+ mssql: () => X(e, Ht(d, K, rt), d.kind),
694
+ orElse: () => X(e, Ht(d, N), d.kind)
675
695
  });
676
696
  break;
677
697
  case "add-column": {
678
- let n = Kt(d, r, u, yield* e.onDialectOrElse({
679
- mysql: () => M.succeed("mariadb"),
680
- mssql: () => M.succeed("mssql"),
681
- sqlite: () => M.succeed("sqlite"),
682
- orElse: () => M.succeed("postgres")
698
+ let n = Xt(d, r, u, yield* e.onDialectOrElse({
699
+ mysql: () => j.succeed("mariadb"),
700
+ mssql: () => j.succeed("mssql"),
701
+ sqlite: () => j.succeed("sqlite"),
702
+ orElse: () => j.succeed("postgres")
683
703
  }));
684
- if (!(o === "resume" && (yield* Z(e, _(e), d.table, d.column.name)))) for (let t of n.pre) yield* J(e, t, d.kind);
685
- let s = r.classification === "online-required" || n.batchSize !== void 0 || n.sleepMs !== void 0, p = M.gen(function* () {
704
+ if (!(o === "resume" && (yield* Z(e, y(e), d.table, d.column.name)))) for (let t of n.pre) yield* J(e, t, d.kind);
705
+ let s = r.classification === "online-required" || n.batchSize !== void 0 || n.sleepMs !== void 0, p = j.gen(function* () {
686
706
  if (n.backfillKind === "sql" && n.backfillSql) {
687
707
  if (r.classification !== "online-required" && n.batchSize === void 0) yield* e`UPDATE ${e(d.table)} SET ${e(d.column.name)} = ${n.backfillSql}`;
688
708
  else {
689
709
  let t = n.batchSize ?? 5e3, r = n.sleepMs ?? 0, i, a = 0;
690
710
  for (;;) {
691
- let o = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(d.table)} WHERE ${e(d.column.name)} IS NULL ORDER BY ${e("id")} ${k(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(d.table)} WHERE ${e(d.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${k(e, t)}`;
711
+ let o = i === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(d.table)} WHERE ${e(d.column.name)} IS NULL ORDER BY ${e("id")} ${O(e, t)}` : yield* e`SELECT ${e("id")} FROM ${e(d.table)} WHERE ${e(d.column.name)} IS NULL AND ${e("id")} > ${i} ORDER BY ${e("id")} ${O(e, t)}`;
692
712
  if (o.length === 0) break;
693
713
  let s = o.map((e) => e.id);
694
- yield* e`UPDATE ${e(d.table)} SET ${e(d.column.name)} = ${n.backfillSql} WHERE ${e("id")} IN ${e.in(s)}`, a += o.length, yield* M.logInfo(`backfill ${d.table}.${d.column.name}: ${a} rows`).pipe(M.annotateLogs({
714
+ yield* e`UPDATE ${e(d.table)} SET ${e(d.column.name)} = ${n.backfillSql} WHERE ${e("id")} IN ${e.in(s)}`, a += o.length, yield* j.logInfo(`backfill ${d.table}.${d.column.name}: ${a} rows`).pipe(j.annotateLogs({
695
715
  scope: "voltro:migrate",
696
716
  mode: "sql-batched"
697
- })), i = o[o.length - 1].id, r > 0 && (yield* M.sleep(`${r} millis`));
717
+ })), i = o[o.length - 1].id, r > 0 && (yield* j.sleep(`${r} millis`));
698
718
  }
699
719
  }
700
720
  } else if (n.backfillKind === "js" && n.backfillJs) {
701
721
  let t = n.batchSize ?? 1e3, r = n.sleepMs ?? 0, o = i.declared.find((e) => e.tableName === d.table), s, c = 0;
702
722
  for (;;) {
703
- let i = s === void 0 ? yield* e`SELECT * FROM ${e(d.table)} WHERE ${e(d.column.name)} IS NULL ORDER BY ${e("id")} ${k(e, t)}` : yield* e`SELECT * FROM ${e(d.table)} WHERE ${e(d.column.name)} IS NULL AND ${e("id")} > ${s} ORDER BY ${e("id")} ${k(e, t)}`;
723
+ let i = s === void 0 ? yield* e`SELECT * FROM ${e(d.table)} WHERE ${e(d.column.name)} IS NULL ORDER BY ${e("id")} ${O(e, t)}` : yield* e`SELECT * FROM ${e(d.table)} WHERE ${e(d.column.name)} IS NULL AND ${e("id")} > ${s} ORDER BY ${e("id")} ${O(e, t)}`;
704
724
  if (i.length === 0) break;
705
725
  let l = o === void 0 ? i : a(i, o, f);
706
726
  for (let t of l) {
707
- let r = yield* M.tryPromise({
727
+ let r = yield* j.tryPromise({
708
728
  try: () => Promise.resolve(n.backfillJs(t)),
709
729
  catch: (e) => e
710
- }).pipe(M.orDie);
711
- yield* e`UPDATE ${e(d.table)} SET ${e(d.column.name)} = ${Zt(r, d.column, f)} WHERE ${e("id")} = ${t.id}`;
730
+ }).pipe(j.orDie);
731
+ yield* e`UPDATE ${e(d.table)} SET ${e(d.column.name)} = ${rn(r, d.column, f)} WHERE ${e("id")} = ${t.id}`;
712
732
  }
713
- c += l.length, yield* M.logInfo(`backfill ${d.table}.${d.column.name}: ${c} rows processed`).pipe(M.annotateLogs({
733
+ c += l.length, yield* j.logInfo(`backfill ${d.table}.${d.column.name}: ${c} rows processed`).pipe(j.annotateLogs({
714
734
  scope: "voltro:migrate",
715
735
  table: d.table,
716
736
  column: d.column.name
717
- })), s = l[l.length - 1].id, r > 0 && (yield* M.sleep(`${r} millis`));
737
+ })), s = l[l.length - 1].id, r > 0 && (yield* j.sleep(`${r} millis`));
718
738
  }
719
739
  }
720
- }), m = M.gen(function* () {
740
+ }), m = j.gen(function* () {
721
741
  for (let t of n.post) yield* J(e, t, d.kind);
722
742
  if (t(f) && (n.uniquePending === !0 || n.backfillKind !== void 0 && !d.column.nullable)) yield* Y(e, d.table, i.declared, d.kind);
723
743
  else if (n.uniquePending === !0) {
@@ -727,9 +747,9 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
727
747
  column: d.column.name
728
748
  };
729
749
  yield* e.onDialectOrElse({
730
- mysql: () => J(e, At(t, i.declared), d.kind),
731
- mssql: () => X(e, [...Ot(d.table, [d.column.name], i.declared), kt(t)], d.kind),
732
- orElse: () => J(e, kt(t), d.kind)
750
+ mysql: () => J(e, Nt(t, i.declared, d.column), d.kind),
751
+ mssql: () => X(e, [...jt(d.table, [d.column.name], i.declared), Mt(t)], d.kind),
752
+ orElse: () => J(e, Mt(t), d.kind)
733
753
  });
734
754
  }
735
755
  });
@@ -750,105 +770,105 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
750
770
  case "alter-column-nullability":
751
771
  yield* e.onDialectOrElse({
752
772
  mysql: () => {
753
- let t = z(i.declared, d.table, d.column);
754
- return t ? M.flatMap(V(e, d.table, t, d.column, d.toNullable), (t) => J(e, t, d.kind)) : M.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${d.table}.${d.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
773
+ let t = L(i.declared, d.table, d.column);
774
+ return t ? j.flatMap(z(e, d.table, t, d.column, d.toNullable), (t) => J(e, t, d.kind)) : j.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${d.table}.${d.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
755
775
  },
756
776
  mssql: () => {
757
- let t = z(i.declared, d.table, d.column);
758
- return t ? J(e, ot(t, d.column, d.table, d.toNullable), d.kind) : M.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${d.table}.${d.column}'.`));
777
+ let t = L(i.declared, d.table, d.column);
778
+ return t ? J(e, ct(t, d.column, d.table, d.toNullable), d.kind) : j.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${d.table}.${d.column}'.`));
759
779
  },
760
780
  sqlite: () => Y(e, d.table, i.declared, d.kind),
761
- orElse: () => J(e, `ALTER TABLE ${F(d.table)} ALTER COLUMN ${F(d.column)} ${d.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, d.kind)
781
+ orElse: () => J(e, `ALTER TABLE ${N(d.table)} ALTER COLUMN ${N(d.column)} ${d.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, d.kind)
762
782
  });
763
783
  break;
764
784
  case "alter-column-default": {
765
- let t = B(i.declared, d.table, d.column), n = z(i.declared, d.table, d.column), r = (e) => d.hasDefault && n !== void 0 && Fe(n, e) ? n : void 0;
785
+ let t = R(i.declared, d.table, d.column), n = L(i.declared, d.table, d.column), r = (e) => d.hasDefault && n !== void 0 && ze(n, e) ? n : void 0;
766
786
  yield* e.onDialectOrElse({
767
787
  mysql: () => {
768
788
  let n = r("mariadb");
769
- return M.flatMap(n ? V(e, d.table, n, d.column) : M.succeed(Pe(d, I, (e) => Be(e, t))), (t) => J(e, t, d.kind));
789
+ return j.flatMap(n ? z(e, d.table, n, d.column) : j.succeed(Re(d, P, (e) => We(e, t))), (t) => J(e, t, d.kind));
770
790
  },
771
791
  mssql: () => {
772
792
  let t = r("mssql");
773
- return J(e, st(d, t ? ot(t, d.column, d.table) : void 0), d.kind);
793
+ return J(e, lt(d, t ? ct(t, d.column, d.table) : void 0), d.kind);
774
794
  },
775
795
  sqlite: () => Y(e, d.table, i.declared, d.kind),
776
- orElse: () => J(e, Pe(d, F, (e) => He(e, t)), d.kind)
796
+ orElse: () => J(e, Re(d, N, (e) => Ke(e, t)), d.kind)
777
797
  });
778
798
  break;
779
799
  }
780
800
  case "alter-column-type": {
781
- let t = P(B(i.declared, d.table, d.column) ?? { type: d.to }), n = d.using ? ` USING ${d.using}` : "";
801
+ let t = Me(R(i.declared, d.table, d.column) ?? { type: d.to }), n = d.using ? ` USING ${d.using}` : "";
782
802
  if (r.classification !== "online-required") {
783
803
  yield* e.onDialectOrElse({
784
804
  mysql: () => {
785
- let t = z(i.declared, d.table, d.column);
786
- return t ? M.flatMap(V(e, d.table, t, d.column), (t) => J(e, t, d.kind)) : M.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${d.table}.${d.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
805
+ let t = L(i.declared, d.table, d.column);
806
+ return t ? j.flatMap(z(e, d.table, t, d.column), (t) => J(e, t, d.kind)) : j.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${d.table}.${d.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
787
807
  },
788
808
  mssql: () => {
789
- let t = z(i.declared, d.table, d.column);
790
- if (!t) return M.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${d.table}.${d.column}'.`));
791
- if (d.using !== void 0) return M.fail(s(`SQL Server cannot apply a USING expression for ${d.table}.${d.column}; use a reviewed file migration for the explicit transform.`));
792
- let n = ot(t, d.column, d.table);
793
- return d.from === "integer" && d.to === "bigint" || d.from === "bigint" && d.to === "integer" ? Ce(e, d.table, d.column, n) : J(e, n, d.kind);
809
+ let t = L(i.declared, d.table, d.column);
810
+ if (!t) return j.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${d.table}.${d.column}'.`));
811
+ if (d.using !== void 0) return j.fail(s(`SQL Server cannot apply a USING expression for ${d.table}.${d.column}; use a reviewed file migration for the explicit transform.`));
812
+ let n = ct(t, d.column, d.table);
813
+ return d.from === "integer" && d.to === "bigint" || d.from === "bigint" && d.to === "integer" ? Te(e, d.table, d.column, n) : J(e, n, d.kind);
794
814
  },
795
815
  sqlite: () => Y(e, d.table, i.declared, d.kind),
796
- orElse: () => J(e, `ALTER TABLE ${F(d.table)} ALTER COLUMN ${F(d.column)} TYPE ${t}${n};`, d.kind)
816
+ orElse: () => J(e, `ALTER TABLE ${N(d.table)} ALTER COLUMN ${N(d.column)} TYPE ${t}${n};`, d.kind)
797
817
  });
798
818
  break;
799
819
  }
800
820
  yield* e.onDialectOrElse({
801
- mysql: () => M.die(/* @__PURE__ */ Error(`online-required alter-column-type on ${d.table}.${d.column} is not supported on mariadb (the shadow-swap path is postgres-only). Use a smaller-table window or an external online-DDL tool.`)),
802
- orElse: () => M.void
821
+ mysql: () => j.die(/* @__PURE__ */ Error(`online-required alter-column-type on ${d.table}.${d.column} is not supported on mariadb (the shadow-swap path is postgres-only). Use a smaller-table window or an external online-DDL tool.`)),
822
+ orElse: () => j.void
803
823
  });
804
824
  let a = `${d.column}__shadow`, o = `${d.column}__old`;
805
- yield* e.unsafe(`ALTER TABLE ${F(d.table)} ADD COLUMN ${F(a)} ${t}`);
806
- let c = d.using ?? F(d.column), l;
825
+ yield* e.unsafe(`ALTER TABLE ${N(d.table)} ADD COLUMN ${N(a)} ${t}`);
826
+ let c = d.using ?? N(d.column), l;
807
827
  for (;;) {
808
- let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(d.table)} WHERE ${e(a)} IS NULL ORDER BY ${e("id")} ${k(e, 5e3)}` : yield* e`SELECT ${e("id")} FROM ${e(d.table)} WHERE ${e(a)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} ${k(e, 5e3)}`;
828
+ let t = l === void 0 ? yield* e`SELECT ${e("id")} FROM ${e(d.table)} WHERE ${e(a)} IS NULL ORDER BY ${e("id")} ${O(e, 5e3)}` : yield* e`SELECT ${e("id")} FROM ${e(d.table)} WHERE ${e(a)} IS NULL AND ${e("id")} > ${l} ORDER BY ${e("id")} ${O(e, 5e3)}`;
809
829
  if (t.length === 0) break;
810
- yield* e.unsafe(`UPDATE ${F(d.table)} SET ${F(a)} = ${c} WHERE ${F(d.column)} IS NOT NULL AND ${F(a)} IS NULL AND ${F("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
830
+ yield* e.unsafe(`UPDATE ${N(d.table)} SET ${N(a)} = ${c} WHERE ${N(d.column)} IS NOT NULL AND ${N(a)} IS NULL AND ${N("id")} IN (${t.map((e) => `'${e.id.replace(/'/g, "''")}'`).join(",")})`), l = t[t.length - 1].id;
811
831
  }
812
- yield* M.logInfo(`alter-column-type shadow ${d.table}.${d.column}: shadow populated`).pipe(M.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${F(d.table)} RENAME COLUMN ${F(d.column)} TO ${F(o)}`), yield* e.unsafe(`ALTER TABLE ${F(d.table)} RENAME COLUMN ${F(a)} TO ${F(d.column)}`), yield* e.unsafe(`ALTER TABLE ${F(d.table)} DROP COLUMN ${F(o)}`);
832
+ yield* j.logInfo(`alter-column-type shadow ${d.table}.${d.column}: shadow populated`).pipe(j.annotateLogs({ scope: "voltro:migrate" })), yield* e.unsafe(`ALTER TABLE ${N(d.table)} RENAME COLUMN ${N(d.column)} TO ${N(o)}`), yield* e.unsafe(`ALTER TABLE ${N(d.table)} RENAME COLUMN ${N(a)} TO ${N(d.column)}`), yield* e.unsafe(`ALTER TABLE ${N(d.table)} DROP COLUMN ${N(o)}`);
813
833
  break;
814
834
  }
815
835
  case "drop-foreign-key":
816
836
  yield* e.onDialectOrElse({
817
- mysql: () => J(e, Vt(d), d.kind),
837
+ mysql: () => J(e, Gt(d), d.kind),
818
838
  sqlite: () => Y(e, d.table, i.declared, d.kind),
819
- orElse: () => J(e, Bt(d), d.kind)
839
+ orElse: () => J(e, Wt(d), d.kind)
820
840
  });
821
841
  break;
822
842
  case "add-check":
823
843
  yield* e.onDialectOrElse({
824
- mysql: () => J(e, Ht(d, I), d.kind),
844
+ mysql: () => J(e, Kt(d, P), d.kind),
825
845
  sqlite: () => Y(e, d.table, i.declared, d.kind),
826
- orElse: () => J(e, Ht(d, F), d.kind)
846
+ orElse: () => J(e, Kt(d, N), d.kind)
827
847
  });
828
848
  break;
829
849
  case "convert-charset":
830
850
  yield* e.onDialectOrElse({
831
- mysql: () => M.gen(function* () {
832
- let { drops: t, rewrite: n, restores: r } = Ze(d, i.declared, yield* ze(e, d.table));
833
- for (let n of t) yield* J(e, n, d.kind, [ge]);
851
+ mysql: () => j.gen(function* () {
852
+ let { drops: t, rewrite: n, restores: r } = tt(d, i.declared, yield* Ue(e, d.table));
853
+ for (let n of t) yield* J(e, n, d.kind, [ve]);
834
854
  yield* J(e, n, d.kind);
835
- for (let t of r) yield* J(e, t, d.kind, [_e]);
855
+ for (let t of r) yield* J(e, t, d.kind, [ye]);
836
856
  }),
837
- orElse: () => M.die(/* @__PURE__ */ Error("convert-charset requires MySQL or MariaDB"))
857
+ orElse: () => j.die(/* @__PURE__ */ Error("convert-charset requires MySQL or MariaDB"))
838
858
  });
839
859
  break;
840
860
  case "reconcile-json-check": {
841
- let t = K(d.column), n = d.validation === "value" ? b(t) : `(${t} IS NULL OR ISJSON(${t}) = 1)`;
861
+ let t = K(d.column), n = d.validation === "value" ? S(t) : `(${t} IS NULL OR ISJSON(${t}) = 1)`;
842
862
  yield* e.onDialectOrElse({
843
863
  mssql: () => X(e, [...d.dropConstraints.map((e) => `ALTER TABLE ${K(d.table)} DROP CONSTRAINT ${K(e)}`), `ALTER TABLE ${K(d.table)} WITH CHECK ADD CHECK ${n}`], d.kind),
844
- orElse: () => M.die(/* @__PURE__ */ Error("reconcile-json-check requires SQL Server"))
864
+ orElse: () => j.die(/* @__PURE__ */ Error("reconcile-json-check requires SQL Server"))
845
865
  });
846
866
  break;
847
867
  }
848
868
  case "drop-check": yield* e.onDialectOrElse({
849
- mysql: () => Gt(e, d, i.declared),
869
+ mysql: () => Yt(e, d, i.declared),
850
870
  sqlite: () => Y(e, d.table, i.declared, d.kind),
851
- orElse: () => J(e, Ut(d), d.kind)
871
+ orElse: () => J(e, qt(d), d.kind)
852
872
  });
853
873
  }
854
874
  return {
@@ -856,22 +876,22 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
856
876
  status: "applied",
857
877
  durationMs: Number((process.hrtime.bigint() - l) / 1000000n)
858
878
  };
859
- }), mn = (e, t, n, r, i) => M.gen(function* () {
879
+ }), bn = (e, t, n, r, i) => j.gen(function* () {
860
880
  let a = [...new Set(r.map((e) => e.runId))];
861
- if (a.length > 1) return yield* M.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger holds ${a.length} unfinished runs (${a.join(", ")}). Only one migration may be in flight at a time — the advisory lock enforces it — so this means a run was interrupted and a LATER one wrote over it without clearing.\nNothing was changed. Inspect \`${h}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
881
+ if (a.length > 1) return yield* j.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger holds ${a.length} unfinished runs (${a.join(", ")}). Only one migration may be in flight at a time — the advisory lock enforces it — so this means a run was interrupted and a LATER one wrote over it without clearing.\nNothing was changed. Inspect \`${g}\`, reconcile the schema by hand, and delete the rows of the run you have finished.`));
862
882
  let o = a[0], s = [...r].map((e) => ({
863
883
  index: Number(e.opIndex),
864
884
  status: e.status,
865
885
  planned: JSON.parse(e.payload)
866
886
  })).sort((e, t) => e.index - t.index), c = s.find((e) => e.status === "started"), l = s.filter((e) => e.status === "started").length;
867
- if (l > 1) return yield* M.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger records ${l} operations as in-flight for run ${o}. It is written strictly sequentially, so at most one can be — this ledger is corrupt and the schema state it describes cannot be trusted.\nNothing was changed. Reconcile \`${h}\` by hand before re-running.`));
887
+ if (l > 1) return yield* j.die(/* @__PURE__ */ Error(`applyPlan: the resume ledger records ${l} operations as in-flight for run ${o}. It is written strictly sequentially, so at most one can be — this ledger is corrupt and the schema state it describes cannot be trusted.\nNothing was changed. Reconcile \`${g}\` by hand before re-running.`));
868
888
  let u = s.filter((e) => e.status === "added");
869
- if (yield* M.logWarning(`migration resume: found an interrupted run (${o}) — ${s.filter((e) => e.status === "applied").length} of ${s.length} operation(s) completed${c ? `, in flight: ${c.planned.op.kind} ${ae(c.planned.op)}` : ""}${u.length > 0 ? `, ${u.length} column(s) added with the backfill still owed` : ""}`).pipe(M.annotateLogs({ scope: "voltro:migrate" })), s.every((e) => e.status === "pending")) return {
889
+ if (yield* j.logWarning(`migration resume: found an interrupted run (${o}) — ${s.filter((e) => e.status === "applied").length} of ${s.length} operation(s) completed${c ? `, in flight: ${c.planned.op.kind} ${x(c.planned.op)}` : ""}${u.length > 0 ? `, ${u.length} column(s) added with the backfill still owed` : ""}`).pipe(j.annotateLogs({ scope: "voltro:migrate" })), s.every((e) => e.status === "pending")) return {
870
890
  kind: "discard",
871
891
  runId: o,
872
892
  why: "no operation had started — no DDL ran"
873
893
  };
874
- let d = c && !(["sqlite", "turso"].includes(t) && c.planned.sqliteAtomicRebuild === !0) ? yield* fn(e, t, c.planned) : "clean";
894
+ let d = c && !(["sqlite", "turso"].includes(t) && c.planned.sqliteAtomicRebuild === !0) ? yield* vn(e, t, c.planned) : "clean";
875
895
  d !== "clean" && (n = yield* i());
876
896
  let f = r[0].planFingerprint;
877
897
  if (f !== n.toFingerprint) return {
@@ -879,8 +899,8 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
879
899
  runId: o,
880
900
  why: `the declared schema changed since the interruption (recorded target ${f.slice(0, 12)}…, current ${n.toFingerprint.slice(0, 12)}…) — applying the freshly-diffed plan instead`
881
901
  };
882
- let p = (e) => e.status === "applied" ? !1 : c && e.index === c.index && d !== "clean" ? d === "outstanding" : v(n, e.planned.op), m = s.filter(p), ee = s.filter((e) => e.status !== "applied" && !p(e));
883
- return yield* cn(e, o, m.map((e) => e.index), ee.map((e) => e.index)), yield* M.logWarning(`migration resume: continuing run ${o} — replaying ${m.length} operation(s), ${s.length - m.length} already applied`).pipe(M.annotateLogs({ scope: "voltro:migrate" })), {
902
+ let p = (e) => e.status === "applied" ? !1 : c && e.index === c.index && d !== "clean" ? d === "outstanding" : b(n, e.planned.op), m = s.filter(p), h = s.filter((e) => e.status !== "applied" && !p(e));
903
+ return yield* mn(e, o, m.map((e) => e.index), h.map((e) => e.index)), yield* j.logWarning(`migration resume: continuing run ${o} — replaying ${m.length} operation(s), ${s.length - m.length} already applied`).pipe(j.annotateLogs({ scope: "voltro:migrate" })), {
884
904
  kind: "resume",
885
905
  runId: o,
886
906
  ops: m.map((e) => ({
@@ -889,7 +909,7 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
889
909
  })),
890
910
  history: s.filter((e) => e.status !== "pending" || p(e)).map((e) => e.planned)
891
911
  };
892
- }), hn = (e, t, r) => M.gen(function* () {
912
+ }), xn = (e, t, r) => j.gen(function* () {
893
913
  let i, a = 0;
894
914
  for (let o of t.operations) {
895
915
  let s = o.op;
@@ -905,9 +925,9 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
905
925
  "rename-column"
906
926
  ].includes(e.op.kind)) : i.has(s.table)) continue;
907
927
  let c = s.index.columns.map((e) => e.startsWith("(") ? e : n(e, r)), l = r === "mssql" ? "" : c.map((e) => ` AND ${e} IS NOT NULL`).join(""), u = r === "mssql" ? "SELECT TOP (1) 1" : "SELECT 1", d = r === "mssql" ? "" : " LIMIT 1";
908
- if ((yield* e.unsafe(`${u} FROM ${n(s.table, r)} WHERE (${s.index.where})${l} GROUP BY ${c.join(", ")} HAVING COUNT(*) > 1${d}`)).length > 0) return yield* M.die(/* @__PURE__ */ Error(`applyPlan: partial unique index '${s.index.name}' on '${s.table}' conflicts with existing qualifying rows. No schema or row changes were applied. Resolve the conflicting data explicitly before retrying.`));
928
+ if ((yield* e.unsafe(`${u} FROM ${n(s.table, r)} WHERE (${s.index.where})${l} GROUP BY ${c.join(", ")} HAVING COUNT(*) > 1${d}`)).length > 0) return yield* j.die(/* @__PURE__ */ Error(`applyPlan: partial unique index '${s.index.name}' on '${s.table}' conflicts with existing qualifying rows. No schema or row changes were applied. Resolve the conflicting data explicitly before retrying.`));
909
929
  }
910
- }), gn = (e) => {
930
+ }), Sn = (e) => {
911
931
  let t = e.op, n = (e) => typeof t[e] == "string" ? t[e] : "";
912
932
  return [
913
933
  t.kind,
@@ -916,115 +936,110 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
916
936
  n("name"),
917
937
  n("to")
918
938
  ].join("\0");
919
- }, _n = (e, t, n) => M.acquireUseRelease(ee(e, { schema: n.lockSchema }), () => vn(e, t, n), (e) => e.release.pipe(M.orDie)), vn = (e, t, n) => M.gen(function* () {
939
+ }, Cn = (e, t, n) => j.acquireUseRelease(h(e, { schema: n.lockSchema }), () => wn(e, t, n), (e) => e.release.pipe(j.orDie)), wn = (e, t, n) => j.gen(function* () {
920
940
  let r = t.operations.filter((e) => e.blocked);
921
- if (r.length > 0) return yield* M.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
922
- let i = Date.now(), a = [], c = _(e), l = yield* n.replan(e, "execution"), u = new Set(t.operations.filter((e) => !e.blocked).map((e) => gn(e))), d = {
941
+ if (r.length > 0) return yield* j.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
942
+ let i = Date.now(), a = [], c = y(e), l = yield* n.replan(e, "execution"), u = new Set(t.operations.filter((e) => !e.blocked).map((e) => Sn(e))), d = {
923
943
  ...l,
924
944
  operations: l.operations.map((e) => {
925
- if (!e.blocked || !u.has(gn(e))) return e;
945
+ if (!e.blocked || !u.has(Sn(e))) return e;
926
946
  let { blocked: t, ...n } = e;
927
947
  return n;
928
948
  })
929
949
  };
930
- (d.operations.length !== t.operations.length || d.toFingerprint !== t.toFingerprint) && (yield* M.logInfo(`migration: re-planned under the lock — ${t.operations.length} operation(s) became ${d.operations.length}. Another writer changed the schema while this plan waited.`).pipe(M.annotateLogs({ scope: "voltro:migrate" })));
950
+ (d.operations.length !== t.operations.length || d.toFingerprint !== t.toFingerprint) && (yield* j.logInfo(`migration: re-planned under the lock — ${t.operations.length} operation(s) became ${d.operations.length}. Another writer changed the schema while this plan waited.`).pipe(j.annotateLogs({ scope: "voltro:migrate" })));
931
951
  let f = d.operations.filter((e) => e.blocked);
932
- if (f.length > 0) return yield* M.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — re-planning under the migration lock found ${f.length} blocked operation(s). Run \`voltro db plan\` to see the fixes.`));
933
- let p = ce(n.declared, c);
934
- p && (yield* J(e, p, "extensions"));
935
- let m = oe(n.declared, c);
936
- m && (yield* J(e, m, "enum-types"));
937
- let ee = se(n.declared, c);
938
- ee && (yield* J(e, ee, "enum-types"));
939
- let h = ie(c) === "plan-transactional";
940
- yield* hn(e, d, c), yield* Qt(e, c, n.charset);
941
- let te = yield* an(e), g = te.length > 0 ? yield* mn(e, c, d, te, () => n.replan(e, "execution").pipe(M.map((e) => (d = {
952
+ if (f.length > 0) return yield* j.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — re-planning under the migration lock found ${f.length} blocked operation(s). Run \`voltro db plan\` to see the fixes.`));
953
+ yield* j.forEach(se(n.declared, c), (t) => J(e, t, "extensions"), { discard: !0 }), yield* j.forEach(ae(n.declared, c), (t) => J(e, t, "enum-types"), { discard: !0 }), yield* j.forEach(oe(n.declared, c), (t) => J(e, t, "enum-types"), { discard: !0 });
954
+ let p = ne(c) === "plan-transactional";
955
+ yield* xn(e, d, c), yield* an(e, c, n.charset);
956
+ let m = yield* dn(e), h = m.length > 0 ? yield* bn(e, c, d, m, () => n.replan(e, "execution").pipe(j.map((e) => (d = {
942
957
  ...e,
943
958
  operations: e.operations.map((e) => {
944
- if (!e.blocked || !u.has(gn(e))) return e;
959
+ if (!e.blocked || !u.has(Sn(e))) return e;
945
960
  let { blocked: t, ...n } = e;
946
961
  return n;
947
962
  })
948
963
  }, d)))) : void 0;
949
- if (d.operations.some((e) => e.blocked)) return yield* M.die(/* @__PURE__ */ Error("applyPlan: refusing blocked operations after interrupted-run repair. Run `voltro db plan` to inspect the remaining work."));
950
- g?.kind === "discard" && (yield* M.logWarning(`migration resume: discarding ledger of run ${g.runId} — ${g.why}`).pipe(M.annotateLogs({ scope: "voltro:migrate" })), yield* ln(e, g.runId));
951
- let ne = (/* @__PURE__ */ new Date()).toISOString(), re = process.env.VOLTRO_SOFT_DROP === "1" ? d.operations.map((e) => pe(e, ne)) : d.operations, v = h ? re.filter((e) => e.classification !== "online-required") : [], ae = h ? re.filter((e) => e.classification === "online-required") : re, y = `plan_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`, b = ae.map((e, t) => ({
952
- index: v.length + t,
964
+ if (d.operations.some((e) => e.blocked)) return yield* j.die(/* @__PURE__ */ Error("applyPlan: refusing blocked operations after interrupted-run repair. Run `voltro db plan` to inspect the remaining work."));
965
+ h?.kind === "discard" && (yield* j.logWarning(`migration resume: discarding ledger of run ${h.runId} — ${h.why}`).pipe(j.annotateLogs({ scope: "voltro:migrate" })), yield* hn(e, h.runId));
966
+ let g = (/* @__PURE__ */ new Date()).toISOString(), ee = process.env.VOLTRO_SOFT_DROP === "1" ? d.operations.map((e) => me(e, g)) : d.operations, _ = p ? ee.filter((e) => e.classification !== "online-required") : [], te = p ? ee.filter((e) => e.classification === "online-required") : ee, v = `plan_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`, b = te.map((e, t) => ({
967
+ index: _.length + t,
953
968
  planned: e
954
- })), x = "fresh", S;
955
- g?.kind === "resume" && (y = g.runId, b = g.ops, S = g.history, x = "resume"), (v.length > 0 || b.length > 0) && n.beforeExecute !== void 0 && (yield* n.beforeExecute), x === "fresh" && b.length > 0 && (yield* sn(e, y, d.toFingerprint, b)), v.length > 0 && (yield* xe(e, M.gen(function* () {
956
- let e = yield* Ee.SqlClient;
957
- if (x === "resume") return yield* M.die(/* @__PURE__ */ Error("applyPlan: transactional work appeared while resuming an interrupted run with the same target. Inspect the live schema and operation ledger before retrying."));
958
- let t = v.map((e, t) => ({
969
+ })), x = "fresh", re;
970
+ h?.kind === "resume" && (v = h.runId, b = h.ops, re = h.history, x = "resume"), (_.length > 0 || b.length > 0) && n.beforeExecute !== void 0 && (yield* n.beforeExecute), x === "fresh" && b.length > 0 && (yield* pn(e, v, d.toFingerprint, b)), _.length > 0 && (yield* Ce(e, j.gen(function* () {
971
+ let e = yield* ke.SqlClient;
972
+ if (x === "resume") return yield* j.die(/* @__PURE__ */ Error("applyPlan: transactional work appeared while resuming an interrupted run with the same target. Inspect the live schema and operation ledger before retrying."));
973
+ let t = _.map((e, t) => ({
959
974
  index: t,
960
975
  planned: e
961
976
  }));
962
- yield* sn(e, y, d.toFingerprint, t);
963
- let r = [], i = () => M.gen(function* () {
977
+ yield* pn(e, v, d.toFingerprint, t);
978
+ let r = [], i = () => j.gen(function* () {
964
979
  for (let e of r.splice(0)) yield* e.data, yield* e.after;
965
980
  });
966
- for (let t of v) qt.has(t.op.kind) && r.length > 0 && (yield* i()), a.push(yield* pn(e, t, n, "fresh", (e) => r.push(e)));
981
+ for (let t of _) Zt.has(t.op.kind) && r.length > 0 && (yield* i()), a.push(yield* yn(e, t, n, "fresh", (e) => r.push(e)));
967
982
  yield* i();
968
- for (let { index: n } of t) yield* $(e, y, n, "applied");
983
+ for (let { index: n } of t) yield* $(e, v, n, "applied");
969
984
  })));
970
- let C = [], w = () => M.gen(function* () {
971
- let t = C.splice(0);
985
+ let S = [], ie = () => j.gen(function* () {
986
+ let t = S.splice(0);
972
987
  if (t.length !== 0) {
973
- yield* xe(e, M.gen(function* () {
988
+ yield* Ce(e, j.gen(function* () {
974
989
  for (let e of t) yield* e.data;
975
990
  }));
976
991
  for (let n of t) yield* n.after, a.push({
977
992
  op: n.op,
978
993
  status: "applied",
979
994
  durationMs: Number(process.hrtime.bigint() - n.startedAt) / 1e6
980
- }), yield* $(e, y, n.index, "applied", Number(process.hrtime.bigint() - n.startedAt) / 1e6);
995
+ }), yield* $(e, v, n.index, "applied", Number(process.hrtime.bigint() - n.startedAt) / 1e6);
981
996
  }
982
997
  });
983
998
  for (let { index: t, planned: r } of b) {
984
- qt.has(r.op.kind) && C.length > 0 && (yield* w()), yield* $(e, y, t, "started", void 0, r);
985
- let i = a.length, o = process.hrtime.bigint(), c = yield* pn(e, r, n, x, (e) => C.push({
999
+ Zt.has(r.op.kind) && S.length > 0 && (yield* ie()), yield* $(e, v, t, "started", void 0, r);
1000
+ let i = a.length, o = process.hrtime.bigint(), c = yield* yn(e, r, n, x, (e) => S.push({
986
1001
  ...e,
987
1002
  index: t,
988
1003
  startedAt: o
989
- })).pipe(M.mapError((e) => s(`${String(e?.message ?? e)}\n\n progress: ${i} of ${b.length + v.length} operation(s) applied before this one${v.length > 0 ? ` (${v.length} of them in a transaction)` : ""}.\n` + (h ? (v.length > 0 ? "The transactional batch completed before this phase; this failure does not roll it back.\n" : "This phase runs outside a transactional batch; completed operations are not rolled back by this failure.\n") + "An enclosing deployment transaction may still undo its own changes. Inspect the live schema and operation ledger before retrying.\nThe failing operation may also have made partial progress.\n" : ` This dialect does NOT apply a plan atomically: those ${i} are COMMITTED and there is no rollback.\n The ledger records how far it got (operation ${t} was in flight).\n`), e)));
990
- c.deferred === !0 ? yield* $(e, y, t, "added") : (a.push(c), yield* $(e, y, t, "applied", c.durationMs));
1004
+ })).pipe(j.mapError((e) => s(`${String(e.message)}\n\n progress: ${i} of ${b.length + _.length} operation(s) applied before this one${_.length > 0 ? ` (${_.length} of them in a transaction)` : ""}.\n` + (p ? (_.length > 0 ? "The transactional batch completed before this phase; this failure does not roll it back.\n" : "This phase runs outside a transactional batch; completed operations are not rolled back by this failure.\n") + "An enclosing deployment transaction may still undo its own changes. Inspect the live schema and operation ledger before retrying.\nThe failing operation may also have made partial progress.\n" : ` This dialect does NOT apply a plan atomically: those ${i} are COMMITTED and there is no rollback.\n The ledger records how far it got (operation ${t} was in flight).\n`), e)));
1005
+ c.deferred === !0 ? yield* $(e, v, t, "added") : (a.push(c), yield* $(e, v, t, "applied", c.durationMs));
991
1006
  }
992
- yield* w();
993
- let T = yield* n.replan(e, "convergence");
994
- if (T.operations.length > 0) {
995
- let e = (e) => "column" in e ? typeof e.column == "string" ? `.${e.column}` : `.${String(e.column.name ?? "")}` : "", t = T.operations.slice(0, 10).map((t) => ` - ${t.op.kind} ${"table" in t.op ? t.op.table : ""}${e(t.op)}`).join("\n"), n = a.filter((e) => e.status === "applied"), r = n.slice(0, 10).map((t) => ` - ${t.op.kind} ${"table" in t.op ? t.op.table : ""}${e(t.op)}`).join("\n") + (n.length > 10 ? `\n … and ${n.length - 10} more` : "");
996
- return yield* M.die(/* @__PURE__ */ Error(`applyPlan: the migration did not converge. ${d.operations.length} operation(s) were executed without error, but re-planning against the live schema still finds ${T.operations.length}:\n${t}${T.operations.length > 10 ? `\n … and ${T.operations.length - 10} more` : ""}\nNo fingerprint was recorded — recording one would make the next boot report "schema up to date" for a schema that was never applied. This is a framework bug.\n` + (h ? (v.length > 0 ? "The transactional batch completed before this convergence check; this check does not roll it back.\n" : "This convergence check does not roll back completed operations; this plan had no transactional batch.\n") + `An enclosing deployment transaction may still undo its own changes. Inspect the live schema and operation ledger before retrying.\nOperations reported applied before this check:\n${r}\n` : ` This dialect does NOT apply a plan atomically. The ${n.length} operation(s) below are COMMITTED\n and there is no rollback — the schema is PART-APPLIED, not unchanged:\n${r}\n Re-running plans from where the database now is, which is a different plan from the one that failed.\n`) + "Two causes look identical from here, so read the list before assuming either:\n - the DDL for those operations is a no-op (it succeeded and changed nothing), or\n - the planner cannot see what the DDL did, so it proposes the same work again — which is what an\n operation naming an object a PREVIOUS operation created or renamed usually means.\nReport the operation kinds above with the column types involved."));
1007
+ yield* ie();
1008
+ let C = yield* n.replan(e, "convergence");
1009
+ if (C.operations.length > 0) {
1010
+ let e = (e) => "column" in e ? typeof e.column == "string" ? `.${e.column}` : `.${String(e.column.name ?? "")}` : "", t = C.operations.slice(0, 10).map((t) => ` - ${t.op.kind} ${"table" in t.op ? t.op.table : ""}${e(t.op)}`).join("\n"), n = a.filter((e) => e.status === "applied"), r = n.slice(0, 10).map((t) => ` - ${t.op.kind} ${"table" in t.op ? t.op.table : ""}${e(t.op)}`).join("\n") + (n.length > 10 ? `\n … and ${n.length - 10} more` : "");
1011
+ return yield* j.die(/* @__PURE__ */ Error(`applyPlan: the migration did not converge. ${d.operations.length} operation(s) were executed without error, but re-planning against the live schema still finds ${C.operations.length}:\n${t}${C.operations.length > 10 ? `\n … and ${C.operations.length - 10} more` : ""}\nNo fingerprint was recorded — recording one would make the next boot report "schema up to date" for a schema that was never applied. This is a framework bug.\n` + (p ? (_.length > 0 ? "The transactional batch completed before this convergence check; this check does not roll it back.\n" : "This convergence check does not roll back completed operations; this plan had no transactional batch.\n") + `An enclosing deployment transaction may still undo its own changes. Inspect the live schema and operation ledger before retrying.\nOperations reported applied before this check:\n${r}\n` : ` This dialect does NOT apply a plan atomically. The ${n.length} operation(s) below are COMMITTED\n and there is no rollback — the schema is PART-APPLIED, not unchanged:\n${r}\n Re-running plans from where the database now is, which is a different plan from the one that failed.\n`) + "Two causes look identical from here, so read the list before assuming either:\n - the DDL for those operations is a no-op (it succeeded and changed nothing), or\n - the planner cannot see what the DDL did, so it proposes the same work again — which is what an\n operation naming an object a PREVIOUS operation created or renamed usually means.\nReport the operation kinds above with the column types involved."));
997
1012
  }
998
- let le = a.filter((e) => e.status === "applied").length, ue = Date.now() - i, E = y, de = (/* @__PURE__ */ new Date()).toISOString(), fe = yield* j(e, de), D = [...v, ...S ?? b.map((e) => e.planned)], O = x === "resume" ? yield* e`SELECT ${e("fingerprint")}, ${e("operations")}
1013
+ let w = a.filter((e) => e.status === "applied").length, T = Date.now() - i, E = v, ce = (/* @__PURE__ */ new Date()).toISOString(), le = yield* A(e, ce), D = [..._, ...re ?? b.map((e) => e.planned)], ue = x === "resume" ? yield* e`SELECT ${e("fingerprint")}, ${e("operations")}
999
1014
  FROM ${e("_voltro_migration_plans")} WHERE ${e("id")} = ${E}` : [];
1000
- if (O.length > 0) {
1001
- let e = O[0], t = typeof e.operations == "string" ? JSON.parse(e.operations) : e.operations;
1002
- if (e.fingerprint !== d.toFingerprint || !Array.isArray(t) || !we(t, JSON.parse(JSON.stringify(D)))) return yield* M.die(/* @__PURE__ */ Error(`applyPlan: history for resumed run ${E} does not match its recorded operations; the resume ledger was retained.`));
1015
+ if (ue.length > 0) {
1016
+ let e = ue[0], t = typeof e.operations == "string" ? JSON.parse(e.operations) : e.operations;
1017
+ if (e.fingerprint !== d.toFingerprint || !Array.isArray(t) || !Ee(t, JSON.parse(JSON.stringify(D)))) return yield* j.die(/* @__PURE__ */ Error(`applyPlan: history for resumed run ${E} does not match its recorded operations; the resume ledger was retained.`));
1003
1018
  }
1004
- O.length === 0 && (yield* e`
1019
+ ue.length === 0 && (yield* e`
1005
1020
  INSERT INTO ${e("_voltro_migration_plans")}
1006
1021
  (${e("id")}, ${e("fingerprint")}, ${e("liveFingerprint")}, ${e("operations")},
1007
1022
  ${e("appliedBy")}, ${e("environment")}, ${e("source")},
1008
1023
  ${e("durationMs")}, ${e("appliedAt")}, ${e("notes")})
1009
1024
  VALUES
1010
- (${E}, ${d.toFingerprint}, ${T.fromFingerprint}, ${JSON.stringify(D)},
1025
+ (${E}, ${d.toFingerprint}, ${C.fromFingerprint}, ${JSON.stringify(D)},
1011
1026
  ${n.appliedBy}, ${n.environment}, ${n.source},
1012
- ${ue}, ${fe}, ${n.notes ?? null})
1013
- `.pipe(M.mapError((e) => s(`${String(e?.message ?? e)}\n\nMigration ${E}: schema work completed, but writing its history failed.\nThe operation ledger is retained for recovery. This error does not establish whole-plan rollback; inspect the live schema before retrying.`, e)))), yield* ln(e, y).pipe(M.mapError((e) => s(`${String(e?.message ?? e)}\n\nMigration ${E}: the history row was written, but operation-ledger cleanup failed.\nAn enclosing transaction may still roll back its own changes. Inspect the recorded history and any remaining operation ledger before retrying; do not assume the schema is unchanged.`, e)));
1014
- let me = [...new Set(D.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
1015
- return yield* M.promise(() => o({ changedTables: me }).catch(() => {})), {
1027
+ ${T}, ${le}, ${n.notes ?? null})
1028
+ `.pipe(j.mapError((e) => s(`${String(e.message)}\n\nMigration ${E}: schema work completed, but writing its history failed.\nThe operation ledger is retained for recovery. This error does not establish whole-plan rollback; inspect the live schema before retrying.`, e)))), yield* hn(e, v).pipe(j.mapError((e) => s(`${String(e.message)}\n\nMigration ${E}: the history row was written, but operation-ledger cleanup failed.\nAn enclosing transaction may still roll back its own changes. Inspect the recorded history and any remaining operation ledger before retrying; do not assume the schema is unchanged.`, e)));
1029
+ let de = [...new Set(D.flatMap((e) => e.op.kind === "rename-table" ? [e.op.to] : [e.op.table]))];
1030
+ return yield* j.promise(() => o({ changedTables: de }).catch(() => {})), {
1016
1031
  id: E,
1017
- appliedAt: de,
1032
+ appliedAt: ce,
1018
1033
  fingerprint: d.toFingerprint,
1019
1034
  operations: D,
1020
1035
  appliedBy: n.appliedBy,
1021
1036
  environment: n.environment,
1022
- durationMs: ue,
1023
- appliedOps: le,
1037
+ durationMs: T,
1038
+ appliedOps: w,
1024
1039
  source: n.source,
1025
1040
  ...n.notes ? { notes: n.notes } : {}
1026
1041
  };
1027
- }), yn = (e, t) => {
1042
+ }), Tn = (e, t) => {
1028
1043
  switch (t.kind) {
1029
1044
  case "drop-foreign-key": return {
1030
1045
  ...e,
@@ -1056,30 +1071,30 @@ var De = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, Oe = (e) => e.
1056
1071
  ...e.primaryKey === void 0 ? {} : { primaryKey: e.primaryKey.map((e) => e === t.from ? t.to : e) }
1057
1072
  };
1058
1073
  }
1059
- }, bn = (e, t, n) => {
1060
- let r = n.tables.find((e) => e.name === t.table), i = () => r === void 0 ? M.void : Yt(e, t.table, at(yn(r, t)), t.kind);
1074
+ }, En = (e, t, n) => {
1075
+ let r = n.tables.find((e) => e.name === t.table), i = () => r === void 0 ? j.void : tn(e, t.table, st(Tn(r, t)), t.kind);
1061
1076
  switch (t.kind) {
1062
1077
  case "drop-foreign-key": return e.onDialectOrElse({
1063
- mysql: () => J(e, Vt(t), t.kind),
1078
+ mysql: () => J(e, Gt(t), t.kind),
1064
1079
  sqlite: i,
1065
- orElse: () => J(e, Bt(t), t.kind)
1080
+ orElse: () => J(e, Wt(t), t.kind)
1066
1081
  });
1067
1082
  case "drop-index": return e.onDialectOrElse({
1068
- mysql: () => J(e, bt(t), t.kind),
1069
- mssql: () => J(e, xt(t), t.kind),
1070
- orElse: () => J(e, yt(t), t.kind)
1083
+ mysql: () => J(e, Ct(t), t.kind),
1084
+ mssql: () => J(e, wt(t), t.kind),
1085
+ orElse: () => J(e, St(t), t.kind)
1071
1086
  });
1072
1087
  case "drop-column": return e.onDialectOrElse({
1073
- mysql: () => A(e).pipe(M.flatMap((n) => J(e, Me(t, n), t.kind, [he]))),
1088
+ mysql: () => k(e).pipe(j.flatMap((n) => J(e, Ie(t, n), t.kind, [_e]))),
1074
1089
  sqlite: i,
1075
- orElse: () => J(e, L(t, F), t.kind)
1090
+ orElse: () => J(e, F(t, N), t.kind)
1076
1091
  });
1077
1092
  case "rename-column": return e.onDialectOrElse({
1078
- mysql: () => J(e, R(t, I), t.kind),
1079
- mssql: () => Xt(e, t),
1080
- orElse: () => J(e, R(t, F), t.kind)
1093
+ mysql: () => J(e, I(t, P), t.kind),
1094
+ mssql: () => nn(e, t),
1095
+ orElse: () => J(e, I(t, N), t.kind)
1081
1096
  });
1082
1097
  }
1083
- }, xn = (e, t, n) => pn(e, t, { declared: n });
1098
+ }, Dn = (e, t, n) => yn(e, t, { declared: n });
1084
1099
  //#endregion
1085
- export { Kt as addColumnDdl, un as appliedLedgerOperations, _n as applyPlan, dn as clearResumeLedger, ze as columnLevelChecksMysql, _t as emitAddIndexMysql, Ze as emitConvertCharsetMysql, ut as emitCreateTableMssql, Qe as emitCreateTableMysql, We as emitCreateTablePg, rt as emitCreateTableSqlite, L as emitDropColumnDdl, Me as emitDropColumnDdlMysql, nn as ensureDeployLedgerTable, Qt as ensureLedgerTable, $t as ensurePlanLedgerTable, tn as ensurePluginMigrationsLedgerTable, rn as ensureReplaceMarkerTable, en as ensureSchemaOwnerTable, on as hasInterruptedMigration, pt as mysqlIndexPrefixFor, Je as renderColumnMysql, Ue as renderColumnPg, xn as runMigrationOp, bn as runSchemaOp };
1100
+ export { Xt as addColumnDdl, gn as appliedLedgerOperations, Cn as applyPlan, _n as clearResumeLedger, Ue as columnLevelChecksMysql, bt as emitAddIndexMysql, tt as emitConvertCharsetMysql, ft as emitCreateTableMssql, nt as emitCreateTableMysql, Je as emitCreateTablePg, G as emitCreateTableSqlite, F as emitDropColumnDdl, Ie as emitDropColumnDdlMysql, ln as ensureDeployLedgerTable, an as ensureLedgerTable, on as ensurePlanLedgerTable, cn as ensurePluginMigrationsLedgerTable, un as ensureReplaceMarkerTable, sn as ensureSchemaOwnerTable, fn as hasInterruptedMigration, ht as mysqlIndexPrefixFor, Qe as renderColumnMysql, qe as renderColumnPg, Dn as runMigrationOp, En as runSchemaOp };