@voltro/database 0.20.2 → 0.21.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.
package/dist/sql.js CHANGED
@@ -74,7 +74,7 @@ var _ = (e, t, n, r = 400) => {
74
74
  appliedIndexes: r,
75
75
  appliedUniques: [...e.appliedUniques ?? [], ...i]
76
76
  };
77
- }, x = (e, t) => `${e}::${t}`, S = (e, t) => {
77
+ }, x = (e, t) => `${e}::${t}`, re = (e, t) => {
78
78
  let n = /* @__PURE__ */ new Set(), r = /* @__PURE__ */ new Set(), i = /* @__PURE__ */ new Set(), a = (e) => {
79
79
  n.add(e);
80
80
  let o = [...t(e)].filter((t) => t.target !== e).sort((e, t) => e.column.localeCompare(t.column));
@@ -83,43 +83,43 @@ var _ = (e, t, n, r = 400) => {
83
83
  };
84
84
  for (let t of [...e].sort()) r.has(t) || a(t);
85
85
  return i;
86
- }, C = 6322741009312437n, re = 250, ie = () => {
86
+ }, S = 6322741009312437n, ie = 250, ae = () => {
87
87
  let e = Number(process.env.VOLTRO_MIGRATION_LOCK_TIMEOUT_MS);
88
88
  return Number.isFinite(e) && e > 0 ? e : 3e4;
89
- }, ae = (e) => d.gen(function* () {
90
- let t = ie(), n = Date.now();
89
+ }, oe = (e) => d.gen(function* () {
90
+ let t = ae(), n = Date.now();
91
91
  for (;;) {
92
92
  if ((yield* e`
93
93
  SELECT pg_try_advisory_lock(${"6322741009312437"}::bigint) AS got`)[0]?.got) return;
94
- Date.now() - n >= t && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(t / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* d.sleep(`${re} millis`);
94
+ Date.now() - n >= t && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the postgres migration advisory lock within ${Math.round(t / 1e3)}s. Another migration is in progress, or a prior boot crashed while holding it. (A crashed process's session-level advisory lock is released once its DB connection closes; if this persists, find + terminate the holder via pg_stat_activity, or raise VOLTRO_MIGRATION_LOCK_TIMEOUT_MS.)`))), yield* d.sleep(`${ie} millis`);
95
95
  }
96
- }), oe = (e) => d.gen(function* () {
97
- yield* e`SELECT pg_advisory_unlock(${C.toString()}::bigint)`;
98
- }), se = `voltro_migration_${C.toString(36)}`, ce = 30, le = (e) => d.gen(function* () {
96
+ }), se = (e) => d.gen(function* () {
97
+ yield* e`SELECT pg_advisory_unlock(${S.toString()}::bigint)`;
98
+ }), ce = `voltro_migration_${S.toString(36)}`, le = 30, ue = (e) => d.gen(function* () {
99
99
  (yield* e`
100
- SELECT GET_LOCK(${se}, ${ce}) AS got`)[0]?.got !== 1 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${se}' within ${ce}s (another migration is in progress, or a prior one left it held).`)));
101
- }), ue = (e) => d.gen(function* () {
102
- yield* e`SELECT RELEASE_LOCK(${se})`;
103
- }), de = `voltro_migration_${C.toString(36)}`, fe = 3e4, pe = (e) => d.gen(function* () {
100
+ SELECT GET_LOCK(${ce}, ${le}) AS got`)[0]?.got !== 1 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${ce}' within ${le}s (another migration is in progress, or a prior one left it held).`)));
101
+ }), de = (e) => d.gen(function* () {
102
+ yield* e`SELECT RELEASE_LOCK(${ce})`;
103
+ }), fe = `voltro_migration_${S.toString(36)}`, pe = 3e4, me = (e) => d.gen(function* () {
104
104
  let t = yield* e`
105
105
  DECLARE @res int;
106
- EXEC @res = sp_getapplock @Resource = ${de}, @LockMode = 'Exclusive',
107
- @LockOwner = 'Session', @LockTimeout = ${fe};
106
+ EXEC @res = sp_getapplock @Resource = ${fe}, @LockMode = 'Exclusive',
107
+ @LockOwner = 'Session', @LockTimeout = ${pe};
108
108
  SELECT @res AS res`;
109
- (t[0]?.res ?? -999) < 0 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${de}' (sp_getapplock returned ${t[0]?.res ?? "no row"}; another migration is in progress).`)));
110
- }), me = (e) => d.gen(function* () {
111
- yield* e`EXEC sp_releaseapplock @Resource = ${de}, @LockOwner = 'Session'`;
112
- }), he = d.void, w = (e) => e.onDialectOrElse({
113
- mysql: () => le(e),
114
- mssql: () => pe(e),
115
- sqlite: () => he,
116
- orElse: () => ae(e)
117
- }), T = (e) => e.onDialectOrElse({
109
+ (t[0]?.res ?? -999) < 0 && (yield* d.die(/* @__PURE__ */ Error(`could not acquire the migration lock '${fe}' (sp_getapplock returned ${t[0]?.res ?? "no row"}; another migration is in progress).`)));
110
+ }), he = (e) => d.gen(function* () {
111
+ yield* e`EXEC sp_releaseapplock @Resource = ${fe}, @LockOwner = 'Session'`;
112
+ }), ge = d.void, C = (e) => e.onDialectOrElse({
118
113
  mysql: () => ue(e),
119
114
  mssql: () => me(e),
120
- sqlite: () => he,
115
+ sqlite: () => ge,
121
116
  orElse: () => oe(e)
122
- }), ge = (e, t) => d.acquireUseRelease(w(e), () => t, () => T(e).pipe(d.orDie)), _e = f({ scope: "voltro:migrate" }), E = (e) => {
117
+ }), w = (e) => e.onDialectOrElse({
118
+ mysql: () => de(e),
119
+ mssql: () => he(e),
120
+ sqlite: () => ge,
121
+ orElse: () => se(e)
122
+ }), T = (e, t) => d.acquireUseRelease(C(e), () => t, () => w(e).pipe(d.orDie)), _e = f({ scope: "voltro:migrate" }), E = (e) => {
123
123
  _e.warn(e.replace(/^\[voltro:migrate\]\s*/, ""));
124
124
  }, D = (e, t) => {
125
125
  let n = e.type;
@@ -431,7 +431,7 @@ CREATE TRIGGER framework_changes_${e.tableName}
431
431
  AFTER INSERT OR UPDATE OR DELETE ON "${e.tableName}"
432
432
  FOR EACH ROW EXECUTE FUNCTION framework_notify_change();
433
433
  `.trim(), je = (e) => e.some((e) => Object.values(e.fields).some((e) => e.type === "vector")), Me = (e) => e.some((e) => Object.values(e.fields).some((e) => e.spatial !== void 0)), Ne = (e) => {
434
- let t = new Map(e.map((e) => [e.tableName, e])), n = S(e.map((e) => e.tableName), (e) => {
434
+ let t = new Map(e.map((e) => [e.tableName, e])), n = re(e.map((e) => e.tableName), (e) => {
435
435
  let n = t.get(e);
436
436
  return n ? Object.entries(n.fields).flatMap(([e, n]) => {
437
437
  if (n.type !== "reference" || !n.references) return [];
@@ -598,7 +598,7 @@ BEGIN
598
598
  return o.join("\n\n") + "\n";
599
599
  }, He = (e, t = "postgres") => d.gen(function* () {
600
600
  let n = yield* p.SqlClient;
601
- yield* ge(n, Ge(n, A(e, t), t)).pipe(d.orDie);
601
+ yield* T(n, Ge(n, A(e, t), t)).pipe(d.orDie);
602
602
  }), Ue = (e, t) => {
603
603
  let n = t.cause ?? {};
604
604
  return (n.errno === 1061 || n.code === "ER_DUP_KEYNAME") && /^\s*CREATE\s+(UNIQUE\s+|FULLTEXT\s+)?INDEX\b/i.test(e);
@@ -626,13 +626,13 @@ BEGIN
626
626
  await d.runPromise(He(e, n).pipe(d.provide(t)));
627
627
  }, Je = (e, t, n = "postgres") => d.gen(function* () {
628
628
  let r = Be(e, n, t), i = yield* p.SqlClient;
629
- yield* ge(i, Ge(i, r, n)).pipe(d.orDie);
629
+ yield* T(i, Ge(i, r, n)).pipe(d.orDie);
630
630
  }), Ye = async (e, t, n, r = "postgres") => {
631
631
  await d.runPromise(Je(e, t, r).pipe(d.provide(n)));
632
632
  }, Xe = async (e, t, n = "postgres") => {
633
633
  await d.runPromise(d.gen(function* () {
634
634
  let t = Ve(e, n), r = yield* p.SqlClient;
635
- yield* ge(r, Ge(r, t, n)).pipe(d.orDie);
635
+ yield* T(r, Ge(r, t, n)).pipe(d.orDie);
636
636
  }).pipe(d.provide(t)));
637
637
  }, Ze = (e) => {
638
638
  if (e == null) return e;
@@ -674,6 +674,7 @@ BEGIN
674
674
  ...t.oneOf && t.oneOf.length > 0 ? { oneOf: t.oneOf } : {},
675
675
  ...t.idScheme ? { idScheme: { kind: t.idScheme.kind } } : {},
676
676
  ...t.rawDdl === void 0 ? {} : { rawDdl: t.rawDdl },
677
+ ...t.maxLength === void 0 ? {} : { maxLength: t.maxLength },
677
678
  ...t.precision === void 0 ? {} : { precision: t.precision },
678
679
  ...t.scale === void 0 ? {} : { scale: t.scale },
679
680
  ...t.generatedAs ? { generatedAs: {
@@ -875,35 +876,42 @@ BEGIN
875
876
  if (!n || !r || n.length !== r.length) return !1;
876
877
  let i = [...n].sort(), a = [...r].sort();
877
878
  return i.every((e, t) => e === a[t]);
878
- }, yt = (e, t) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && _t(e, t) && JSON.stringify(I(e.references)) === JSON.stringify(I(t.references)) && vt(e.oneOf, t.oneOf), bt = (e, t) => t.oneOf && t.oneOf.length > 0 ? L({
879
+ }, yt = (e, t) => {
880
+ try {
881
+ let n = /\((\d+)\)/.exec(D(e, t));
882
+ return n ? Number(n[1]) : void 0;
883
+ } catch {
884
+ return;
885
+ }
886
+ }, bt = (e, t, n) => n === void 0 || u(n) ? !0 : e.type !== "text" || t.type !== "text" || yt(e, n) === t.maxLength, xt = (e, t, n) => e.type === t.type && e.nullable === t.nullable && e.unique === t.unique && _t(e, t) && bt(e, t, n) && JSON.stringify(I(e.references)) === JSON.stringify(I(t.references)) && vt(e.oneOf, t.oneOf), St = (e, t) => t.oneOf && t.oneOf.length > 0 ? L({
879
887
  kind: "add-check",
880
888
  table: e,
881
889
  column: t.name,
882
890
  values: t.oneOf
883
- }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, xt = (e, t) => e.unique === t.unique && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), St = (e, t) => {
884
- let n = new Map(t.columns.map((e) => [e.name, e])), r = new Map(e.columns.map((e) => [e.name, e])), i = [], a = [], o = [];
891
+ }, "safe", `enum-membership CHECK on ${e}.${t.name}`) : void 0, Ct = (e, t) => e.unique === t.unique && (e.expression || t.expression ? !0 : e.columns.length === t.columns.length && e.columns.every((e, n) => e === t.columns[n])), wt = (e, t, n) => {
892
+ let r = new Map(t.columns.map((e) => [e.name, e])), i = new Map(e.columns.map((e) => [e.name, e])), a = [], o = [], s = [];
885
893
  for (let t of e.columns) {
886
- let e = n.get(t.name);
894
+ let e = r.get(t.name);
887
895
  if (!e) {
888
- i.push(t);
896
+ a.push(t);
889
897
  continue;
890
898
  }
891
- yt(t, e) || o.push({
899
+ xt(t, e, n) || s.push({
892
900
  declared: t,
893
901
  live: e
894
902
  });
895
903
  }
896
- for (let e of t.columns) r.has(e.name) || a.push(e);
904
+ for (let e of t.columns) i.has(e.name) || o.push(e);
897
905
  return {
898
- added: i,
899
- removed: a,
900
- changed: o
906
+ added: a,
907
+ removed: o,
908
+ changed: s
901
909
  };
902
- }, Ct = (e, t) => {
910
+ }, Tt = (e, t) => {
903
911
  let n = new Map(t.indexes.map((e) => [e.name, e])), r = new Map(e.indexes.map((e) => [e.name, e])), i = [], a = [];
904
912
  for (let t of e.indexes) {
905
913
  let e = n.get(t.name);
906
- (!e || !xt(t, e)) && i.push(t);
914
+ (!e || !Ct(t, e)) && i.push(t);
907
915
  }
908
916
  for (let e of t.indexes) r.has(e.name) || a.push(e);
909
917
  return {
@@ -916,30 +924,30 @@ BEGIN
916
924
  atomicByDialect: mt(e.kind),
917
925
  ...n ? { reason: n } : {},
918
926
  ...r ? { blocked: r } : {}
919
- }), wt = (e, t, n) => {
927
+ }), Et = (e, t, n) => {
920
928
  let r = {
921
929
  kind: "add-column",
922
930
  table: e,
923
931
  column: t
924
932
  };
925
933
  return t.nullable ? L(r, "safe", "nullable column add — no backfill needed") : t.hasDefault && t.defaultValue !== void 0 ? L(r, "needs-default", "NOT NULL with literal default — DDL DEFAULT will populate existing rows") : n?.backfill ? L(r, "needs-backfill", `backfill declared (kind=${n.backfill.kind}) — applier will run 3-step add/update/set-not-null`) : L(r, "needs-backfill", "NOT NULL column on a table whose row count is unknown", { fix: `declare \`${t.name}: <type>().backfill(sql\`...\`)\` OR \`.default(value)\` so existing rows survive the migration` });
926
- }, Tt = (e, t, n) => {
934
+ }, Dt = (e, t, n) => {
927
935
  let r = {
928
936
  kind: "drop-column",
929
937
  table: e,
930
938
  column: t.name
931
939
  };
932
940
  return n?.dropped ? L(r, "lossy", `column dropped via \`${t.name}: dropped()\` marker — intentional`) : L(r, "lossy", "column missing from declared schema", { fix: `if intentional, add \`${t.name}: dropped()\` to the schema. If a typo, restore the field` });
933
- }, Et = (e, t, n, r) => L({
941
+ }, Ot = (e, t, n, r) => L({
934
942
  kind: "create-table",
935
943
  table: e,
936
944
  columns: t,
937
945
  indexes: n,
938
946
  ...r && r.length > 0 ? { primaryKey: r } : {}
939
- }, "safe", "new table — no data to preserve"), Dt = (e) => L({
947
+ }, "safe", "new table — no data to preserve"), kt = (e) => L({
940
948
  kind: "drop-table",
941
949
  table: e
942
- }, "lossy", "table missing from declared schema", { fix: "if intentional, set VOLTRO_DESTRUCTIVE_OK=1 OR add a file-based migration. If a typo, restore the table declaration" }), Ot = 5e4, kt = (e, t, n, r) => {
950
+ }, "lossy", "table missing from declared schema", { fix: "if intentional, set VOLTRO_DESTRUCTIVE_OK=1 OR add a file-based migration. If a typo, restore the table declaration" }), At = 5e4, jt = (e, t, n, r) => {
943
951
  let i = (n ?? 0) >= r, a;
944
952
  return a = t.unique ? t.columns.length === 1 ? {
945
953
  kind: "add-unique",
@@ -955,7 +963,7 @@ BEGIN
955
963
  table: e,
956
964
  index: t
957
965
  }, i ? L(a, "online-required", `online build on ${n} rows — CONCURRENTLY / INPLACE / WITH(ONLINE=ON) depending on dialect`) : L(a, "safe", t.unique ? t.columns.length === 1 ? "add unique constraint" : "add composite UNIQUE constraint" : "add B-tree index");
958
- }, At = (e, t) => t.unique && t.columns.length > 1 ? L({
966
+ }, Mt = (e, t) => t.unique && t.columns.length > 1 ? L({
959
967
  kind: "drop-unique-composite",
960
968
  table: e,
961
969
  name: t.name
@@ -963,7 +971,7 @@ BEGIN
963
971
  kind: "drop-index",
964
972
  table: e,
965
973
  index: t.name
966
- }, "safe", "drop index (no data loss — index is derived data)"), jt = (e, t) => {
974
+ }, "safe", "drop index (no data loss — index is derived data)"), Nt = (e, t) => {
967
975
  if (e === "reference") return "text";
968
976
  switch (t) {
969
977
  case "sqlite":
@@ -971,7 +979,7 @@ BEGIN
971
979
  case "mssql": return e === "json" ? "text" : e;
972
980
  default: return e;
973
981
  }
974
- }, Mt = (e, t, n, r, i, a) => {
982
+ }, Pt = (e, t, n, r, i, a) => {
975
983
  let o = [];
976
984
  if (t.nullable !== n.nullable) {
977
985
  let n = {
@@ -994,7 +1002,7 @@ BEGIN
994
1002
  table: e,
995
1003
  column: t.name
996
1004
  }, "safe", `drop unique constraint on ${e}.${t.name} — constraint is derived metadata, no data loss`));
997
- if (jt(t.type, r) !== jt(n.type, r)) {
1005
+ if (Nt(t.type, r) !== Nt(n.type, r)) {
998
1006
  let r = t.narrowedFrom;
999
1007
  if (r && r.from === n.type) {
1000
1008
  let i = {
@@ -1017,6 +1025,16 @@ BEGIN
1017
1025
  o.push(L(r, "lossy", `type change ${n.type} → ${t.type} on ${e}.${t.name} may not be value-preserving`, { fix: `acknowledge it on the column: \`.narrowedFrom('${n.type}', { using: '${t.name}::${t.type}' })\` (drop \`using\` if the cast is implicit), or use a file-based migration` }));
1018
1026
  }
1019
1027
  }
1028
+ if (t.type === "text" && n.type === "text" && !u(r ?? "postgres") && t.maxLength !== n.maxLength) {
1029
+ let r = t.maxLength === void 0 || n.maxLength !== void 0 && t.maxLength > n.maxLength, i = n.maxLength === void 0 ? "unbounded" : `varchar(${n.maxLength})`, a = t.maxLength === void 0 ? "unbounded" : `varchar(${t.maxLength})`;
1030
+ o.push(L({
1031
+ kind: "alter-column-type",
1032
+ table: e,
1033
+ column: t.name,
1034
+ from: "text",
1035
+ to: "text"
1036
+ }, r ? "safe" : "needs-backfill", r ? `text length ${i} → ${a} on ${e}.${t.name} — widening, no data can be lost` : `text length ${i} → ${a} on ${e}.${t.name} — NARROWING; the ALTER fails if any existing value is longer than ${String(t.maxLength)}`, r ? void 0 : { fix: `check first: SELECT COUNT(*) FROM ${e} WHERE LENGTH(${t.name}) > ${String(t.maxLength)}` }));
1037
+ }
1020
1038
  if (!_t(t, n)) {
1021
1039
  let n = {
1022
1040
  kind: "alter-column-default",
@@ -1033,7 +1051,7 @@ BEGIN
1033
1051
  table: e,
1034
1052
  column: t.name
1035
1053
  }, "safe", `drop stale enum CHECK on ${e}.${t.name}`));
1036
- let r = bt(e, t);
1054
+ let r = St(e, t);
1037
1055
  r && o.push(r);
1038
1056
  }
1039
1057
  if (JSON.stringify(I(t.references)) !== JSON.stringify(I(n.references)) && (n.references && o.push(L({
@@ -1056,7 +1074,7 @@ BEGIN
1056
1074
  }, "lossy", r === "delete" ? `add FK ${e}.${t.name} → ${n}: orphanPolicy 'delete' first DELETES rows whose ${t.name} points at a missing ${n}` : `add FK ${e}.${t.name} → ${n}: orphanPolicy 'null' first NULLs ${t.name} where it points at a missing ${n}`)) : o.push(L(i, "needs-backfill", `add FK ${e}.${t.name} → ${n} — existing rows must already reference a valid ${n} (else set orphanPolicy:'null'/'delete')`));
1057
1075
  }
1058
1076
  return o;
1059
- }, Nt = (e, t, n) => {
1077
+ }, Ft = (e, t, n) => {
1060
1078
  let r = [], i = /* @__PURE__ */ new Set(), a = /* @__PURE__ */ new Set(), o = new Set(n.removed.map((e) => e.name)), s = new Set(n.added.map((e) => e.name));
1061
1079
  for (let [n, c] of Object.entries(t)) {
1062
1080
  let t = c.renamedFrom;
@@ -1072,7 +1090,7 @@ BEGIN
1072
1090
  consumedAddedNames: i,
1073
1091
  consumedRemovedNames: a
1074
1092
  };
1075
- }, Pt = (e) => {
1093
+ }, It = (e) => {
1076
1094
  let t = {
1077
1095
  safe: 0,
1078
1096
  needsDefault: 0,
@@ -1107,37 +1125,37 @@ BEGIN
1107
1125
  break;
1108
1126
  }
1109
1127
  return t;
1110
- }, Ft = (e) => {
1111
- let t = N(e.declared, e.dialect), n = ht(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? Ot, a = [];
1128
+ }, Lt = (e) => {
1129
+ let t = N(e.declared, e.dialect), n = ht(e.declared, t), r = new Map(e.live.tables.map((e) => [e.name, e])), i = e.onlineAfter ?? At, a = [];
1112
1130
  for (let e of t.tables) if (!r.has(e.name)) {
1113
- a.push(Et(e.name, e.columns, e.indexes, e.primaryKey));
1131
+ a.push(Ot(e.name, e.columns, e.indexes, e.primaryKey));
1114
1132
  for (let t of e.columns) {
1115
- let n = bt(e.name, t);
1133
+ let n = St(e.name, t);
1116
1134
  n && a.push(n);
1117
1135
  }
1118
1136
  }
1119
1137
  let o = new Set(e.ignoreTables ?? []);
1120
- for (let t of e.live.tables) n.has(t.name) || P(t.name) || dt(t.name) || o.has(t.name) || a.push(Dt(t.name));
1138
+ for (let t of e.live.tables) n.has(t.name) || P(t.name) || dt(t.name) || o.has(t.name) || a.push(kt(t.name));
1121
1139
  for (let o of t.tables) {
1122
1140
  let t = r.get(o.name);
1123
1141
  if (!t) continue;
1124
- let s = n.get(o.name), c = St(o, t), l = Ct(o, t), u = Nt(s.table, s.columnDefs, c);
1142
+ let s = n.get(o.name), c = wt(o, t, e.dialect), l = Tt(o, t), u = Ft(s.table, s.columnDefs, c);
1125
1143
  a.push(...u.ops);
1126
1144
  for (let e of c.removed) {
1127
1145
  if (u.consumedRemovedNames.has(e.name) || dt(e.name)) continue;
1128
1146
  let t = s.columnDefs[e.name];
1129
- a.push(Tt(o.name, e, t));
1147
+ a.push(Dt(o.name, e, t));
1130
1148
  }
1131
1149
  for (let e of c.added) {
1132
1150
  if (u.consumedAddedNames.has(e.name)) continue;
1133
1151
  let t = s.columnDefs[e.name];
1134
- a.push(wt(o.name, e, t));
1135
- let n = bt(o.name, e);
1152
+ a.push(Et(o.name, e, t));
1153
+ let n = St(o.name, e);
1136
1154
  n && a.push(n);
1137
1155
  }
1138
- for (let e of l.added) a.push(kt(o.name, e, t.rowCount, i));
1139
- for (let e of l.removed) a.push(At(o.name, e));
1140
- for (let { declared: n, live: r } of c.changed) a.push(...Mt(o.name, n, r, e.dialect, t.rowCount, i));
1156
+ for (let e of l.added) a.push(jt(o.name, e, t.rowCount, i));
1157
+ for (let e of l.removed) a.push(Mt(o.name, e));
1158
+ for (let { declared: n, live: r } of c.changed) a.push(...Pt(o.name, n, r, e.dialect, t.rowCount, i));
1141
1159
  }
1142
1160
  let s = new Set(a.flatMap((e) => e.op.kind === "create-table" ? [e.op.table] : [])), c = new Map(t.tables.map((e) => [e.name, e])), l = (e) => {
1143
1161
  let t = c.get(e);
@@ -1145,7 +1163,7 @@ BEGIN
1145
1163
  column: e.name,
1146
1164
  target: e.references.table
1147
1165
  }] : []) : [];
1148
- }, u = S([...s], l), d = [];
1166
+ }, u = re([...s], l), d = [];
1149
1167
  for (let e of t.tables) if (s.has(e.name)) for (let t of e.columns) !t.references || !u.has(x(e.name, t.name)) || d.push(L({
1150
1168
  kind: "add-foreign-key",
1151
1169
  table: e.name,
@@ -1219,9 +1237,9 @@ BEGIN
1219
1237
  operations: v,
1220
1238
  fromFingerprint: j(e.live),
1221
1239
  toFingerprint: j(t),
1222
- summary: Pt(v)
1240
+ summary: It(v)
1223
1241
  };
1224
- }, It = (e) => {
1242
+ }, Rt = (e) => {
1225
1243
  let t = /[`"[]?([A-Za-z_][A-Za-z0-9_]*)[`"\]]?\s*(?:in\b|=)/i.exec(e);
1226
1244
  if (!t) return null;
1227
1245
  let n = [...e.matchAll(/'((?:[^']|'')*)'/g)].map((e) => e[1].replace(/''/g, "'"));
@@ -1229,7 +1247,7 @@ BEGIN
1229
1247
  column: t[1],
1230
1248
  values: n
1231
1249
  };
1232
- }, Lt = (e, t) => {
1250
+ }, zt = (e, t) => {
1233
1251
  if (t === "vector") return "vector";
1234
1252
  switch (e) {
1235
1253
  case "text":
@@ -1264,25 +1282,25 @@ BEGIN
1264
1282
  case "SET DEFAULT": return "noAction";
1265
1283
  default: return "noAction";
1266
1284
  }
1267
- }, Rt = (e, t) => {
1285
+ }, Bt = (e, t) => {
1268
1286
  let n = e !== void 0 && e !== "" ? Number(e) : NaN;
1269
1287
  return Number.isInteger(n) && n > 0 ? n : t;
1270
- }, zt = () => Rt(process.env.VOLTRO_INTROSPECT_BATCH, 20), Bt = 300, Vt = () => {
1288
+ }, Vt = () => Bt(process.env.VOLTRO_INTROSPECT_BATCH, 20), Ht = 300, Ut = () => {
1271
1289
  let e = process.env.VOLTRO_INTROSPECT_TIMEOUT_MS;
1272
- return e !== void 0 && e.trim() === "0" ? 0 : Rt(e, 3e4);
1273
- }, Ht = (e, t) => {
1290
+ return e !== void 0 && e.trim() === "0" ? 0 : Bt(e, 3e4);
1291
+ }, Wt = (e, t) => {
1274
1292
  let n = Number.isFinite(t) && t >= 1 ? Math.floor(t) : 1, r = [];
1275
1293
  for (let t = 0; t < e.length; t += n) r.push(e.slice(t, t + n));
1276
1294
  return r;
1277
- }, Ut = (e) => {
1278
- let t = Vt(), n = d.gen(function* () {
1295
+ }, Gt = (e) => {
1296
+ let t = Ut(), n = d.gen(function* () {
1279
1297
  t > 0 && (yield* e.unsafe(`SET LOCAL statement_timeout = ${t}`));
1280
- let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = zt(), a = (e, t) => d.gen(function* () {
1298
+ let n = (t) => e.unsafe("(" + t.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ") + ")"), r = (t) => e.unsafe(String(Math.max(0, Math.trunc(t)))), i = Vt(), a = (e, t) => d.gen(function* () {
1281
1299
  let r = [];
1282
- for (let a of Ht(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1300
+ for (let a of Wt(e, i)) a.length !== 0 && r.push(...yield* t(n(a)));
1283
1301
  return r;
1284
1302
  }), o = [];
1285
- for (let t = 0;; t += Bt) {
1303
+ for (let t = 0;; t += Ht) {
1286
1304
  let n = yield* e`
1287
1305
  SELECT c.relname AS table_name,
1288
1306
  COALESCE(c.reltuples::bigint, 0) AS row_count
@@ -1290,14 +1308,15 @@ BEGIN
1290
1308
  JOIN pg_namespace n ON n.oid = c.relnamespace
1291
1309
  WHERE n.nspname = current_schema() AND c.relkind = 'r'
1292
1310
  ORDER BY c.relname
1293
- LIMIT ${r(Bt)} OFFSET ${r(t)}
1311
+ LIMIT ${r(Ht)} OFFSET ${r(t)}
1294
1312
  `;
1295
- if (o.push(...n), n.length < Bt) break;
1313
+ if (o.push(...n), n.length < Ht) break;
1296
1314
  }
1297
1315
  let s = /* @__PURE__ */ new Set(), c = [];
1298
1316
  for (let e of o) s.has(e.table_name) || (s.add(e.table_name), c.push(e));
1299
1317
  let l = c.map((e) => e.table_name), u = yield* a(l, (t) => e`
1300
- SELECT table_name, column_name, data_type, udt_name, is_nullable, column_default
1318
+ SELECT table_name, column_name, data_type, udt_name, is_nullable, column_default,
1319
+ character_maximum_length
1301
1320
  FROM information_schema.columns
1302
1321
  WHERE table_schema = current_schema() AND table_name IN ${t}
1303
1322
  ORDER BY table_name, ordinal_position
@@ -1422,10 +1441,10 @@ BEGIN
1422
1441
  let n = t.get(e.index_name);
1423
1442
  n || (n = [], t.set(e.index_name, n)), n.push(e);
1424
1443
  }
1425
- let S = [];
1444
+ let re = [];
1426
1445
  for (let e of c) {
1427
1446
  let t = /* @__PURE__ */ new Set(), n = (_.get(e.table_name) ?? []).filter((e) => t.has(e.column_name) ? !1 : (t.add(e.column_name), !0)), r = v.get(e.table_name) ?? /* @__PURE__ */ new Set(), i = te.get(e.table_name) ?? /* @__PURE__ */ new Set(), a = ne.get(e.table_name) ?? [], o = new Map(a.map((e) => [e.source_column, e])), s = new Set(n.filter((e) => e.udt_name === "tsvector").map((e) => e.column_name)), c = n.filter((e) => !s.has(e.column_name)).map((t) => {
1428
- let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = a ? "reference" : n && t.column_name === "id" ? "id" : Lt(t.data_type, t.udt_name), c = a ? {
1447
+ let n = r.has(t.column_name) && r.size === 1, a = o.get(t.column_name), s = a ? "reference" : n && t.column_name === "id" ? "id" : zt(t.data_type, t.udt_name), c = a ? {
1429
1448
  table: a.target_table,
1430
1449
  column: a.target_column,
1431
1450
  onDelete: R(a.delete_rule),
@@ -1434,6 +1453,7 @@ BEGIN
1434
1453
  return {
1435
1454
  name: t.column_name,
1436
1455
  type: s,
1456
+ ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
1437
1457
  nullable: t.is_nullable === "YES",
1438
1458
  unique: i.has(t.column_name) || n && t.column_name === "id",
1439
1459
  hasDefault: t.column_default !== null,
@@ -1465,20 +1485,20 @@ BEGIN
1465
1485
  unique: !0
1466
1486
  });
1467
1487
  let d = Number(e.row_count ?? 0);
1468
- S.push({
1488
+ re.push({
1469
1489
  name: e.table_name,
1470
1490
  columns: c,
1471
1491
  indexes: l,
1472
1492
  ...d > 0 ? { rowCount: d } : {}
1473
1493
  });
1474
1494
  }
1475
- return { tables: S };
1495
+ return { tables: re };
1476
1496
  });
1477
1497
  return (t > 0 ? e.withTransaction(n) : n).pipe(d.catchAll((e) => {
1478
1498
  let n = `${String(e)} ${String(e.cause ?? "")}`.toLowerCase();
1479
1499
  return n.includes("statement timeout") || n.includes("57014") ? d.die(/* @__PURE__ */ Error(`schema introspection exceeded VOLTRO_INTROSPECT_TIMEOUT_MS (${t}ms) — the schema is very large / FK-dense or the database is slow. Raise VOLTRO_INTROSPECT_TIMEOUT_MS, set it to 0 to disable the ceiling, or use DB_DIRECT_URL for a non-pooler connection.`)) : d.fail(e);
1480
1500
  }));
1481
- }, Wt = (e, t) => {
1501
+ }, Kt = (e, t) => {
1482
1502
  switch (e.toLowerCase()) {
1483
1503
  case "varchar":
1484
1504
  case "char":
@@ -1514,13 +1534,14 @@ BEGIN
1514
1534
  let t = e, n = {};
1515
1535
  for (let e of Object.keys(t)) n[e.toLowerCase()] = t[e];
1516
1536
  return n;
1517
- }), Gt = (e) => d.gen(function* () {
1537
+ }), qt = (e) => d.gen(function* () {
1518
1538
  let t = z(yield* e`
1519
1539
  SELECT table_name, COALESCE(table_rows, 0) AS table_rows
1520
1540
  FROM information_schema.tables
1521
1541
  WHERE table_schema = DATABASE() AND table_type = 'BASE TABLE'
1522
1542
  ORDER BY table_name`), n = z(yield* e`
1523
- SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key
1543
+ SELECT table_name, column_name, data_type, column_type, is_nullable, column_default, column_key,
1544
+ character_maximum_length
1524
1545
  FROM information_schema.columns
1525
1546
  WHERE table_schema = DATABASE()
1526
1547
  ORDER BY table_name, ordinal_position`), r = z(yield* e`
@@ -1547,7 +1568,7 @@ BEGIN
1547
1568
  o.add(`${e.table_name}.${t[1]}`);
1548
1569
  continue;
1549
1570
  }
1550
- let n = It(e.check_clause);
1571
+ let n = Rt(e.check_clause);
1551
1572
  n && s.set(`${e.table_name}.${n.column}`, n.values);
1552
1573
  }
1553
1574
  let c = /* @__PURE__ */ new Map(), l = /* @__PURE__ */ new Map(), u = /* @__PURE__ */ new Map();
@@ -1570,7 +1591,7 @@ BEGIN
1570
1591
  let t = c.get(e.table_name) ?? [], n = l.get(e.table_name) ?? [], r = new Map(n.map((e) => [e.source_column, e])), i = t.filter((e) => e.column_key === "PRI").map((e) => e.column_name), a = /* @__PURE__ */ new Set(), d = u.get(e.table_name);
1571
1592
  if (d) for (let e of d.values()) e.length === 1 && e[0].non_unique === 0 && a.add(e[0].column_name);
1572
1593
  let p = t.map((t) => {
1573
- let n = i.includes(t.column_name) && i.length === 1, c = r.get(t.column_name), l = c ? "reference" : n && t.column_name === "id" ? "id" : o.has(`${e.table_name}.${t.column_name}`) ? "json" : Wt(t.data_type, t.column_type), u = c ? {
1594
+ let n = i.includes(t.column_name) && i.length === 1, c = r.get(t.column_name), l = c ? "reference" : n && t.column_name === "id" ? "id" : o.has(`${e.table_name}.${t.column_name}`) ? "json" : Kt(t.data_type, t.column_type), u = c ? {
1574
1595
  table: c.target_table,
1575
1596
  column: c.target_column,
1576
1597
  onDelete: R(c.delete_rule),
@@ -1580,6 +1601,7 @@ BEGIN
1580
1601
  name: t.column_name,
1581
1602
  type: l,
1582
1603
  nullable: t.is_nullable === "YES",
1604
+ ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
1583
1605
  unique: d,
1584
1606
  hasDefault: f !== null,
1585
1607
  ...f === null ? {} : { defaultValue: f },
@@ -1611,10 +1633,10 @@ BEGIN
1611
1633
  });
1612
1634
  }
1613
1635
  return { tables: f };
1614
- }), Kt = (e) => {
1636
+ }), Jt = (e) => {
1615
1637
  let t = e.toUpperCase();
1616
1638
  return t.includes("INT") ? "integer" : t.includes("REAL") || t.includes("FLOA") || t.includes("DOUB") ? "real" : t.includes("BLOB") ? "bytes" : "text";
1617
- }, qt = (e) => d.gen(function* () {
1639
+ }, Yt = (e) => d.gen(function* () {
1618
1640
  let t = yield* e`
1619
1641
  SELECT name, sql FROM sqlite_master
1620
1642
  WHERE type = 'table' AND name NOT LIKE 'sqlite_%'
@@ -1631,7 +1653,7 @@ BEGIN
1631
1653
  d.set(t.name, r), t.unique === 1 && r.length === 1 && f.add(r[0]);
1632
1654
  }
1633
1655
  let p = o.map((e) => {
1634
- let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Kt(e.type), a = r ? {
1656
+ let n = u.length === 1 && u[0] === e.name, r = l.get(e.name), i = r ? "reference" : n && e.name === "id" ? "id" : Jt(e.type), a = r ? {
1635
1657
  table: r.table,
1636
1658
  column: r.to,
1637
1659
  onDelete: R(r.on_delete),
@@ -1670,7 +1692,7 @@ BEGIN
1670
1692
  });
1671
1693
  }
1672
1694
  return { tables: r };
1673
- }), Jt = (e) => {
1695
+ }), Xt = (e) => {
1674
1696
  switch (e.toLowerCase()) {
1675
1697
  case "int":
1676
1698
  case "smallint":
@@ -1692,12 +1714,13 @@ BEGIN
1692
1714
  case "image": return "bytes";
1693
1715
  default: return "text";
1694
1716
  }
1695
- }, B = (e) => e === !0 || e === 1, Yt = (e) => d.gen(function* () {
1717
+ }, B = (e) => e === !0 || e === 1, Zt = (e) => d.gen(function* () {
1696
1718
  let t = yield* e`
1697
1719
  SELECT TABLE_NAME AS table_name FROM INFORMATION_SCHEMA.TABLES
1698
1720
  WHERE TABLE_TYPE = 'BASE TABLE' ORDER BY TABLE_NAME`, n = yield* e`
1699
1721
  SELECT TABLE_NAME AS table_name, COLUMN_NAME AS column_name, DATA_TYPE AS data_type,
1700
- IS_NULLABLE AS is_nullable, COLUMN_DEFAULT AS column_default
1722
+ IS_NULLABLE AS is_nullable, COLUMN_DEFAULT AS column_default,
1723
+ CHARACTER_MAXIMUM_LENGTH AS character_maximum_length
1701
1724
  FROM INFORMATION_SCHEMA.COLUMNS ORDER BY TABLE_NAME, ORDINAL_POSITION`, r = yield* e`
1702
1725
  SELECT st.name AS source_table, sc.name AS source_column,
1703
1726
  tt.name AS target_table, tc.name AS target_column,
@@ -1752,16 +1775,17 @@ BEGIN
1752
1775
  else B(t[0].is_unique) && t.length === 1 && f.add(t[0].column_name);
1753
1776
  }
1754
1777
  let p = t.map((t) => {
1755
- let n = d.length === 1 && d[0] === t.column_name, i = r.get(t.column_name), a = i ? "reference" : n && t.column_name === "id" ? "id" : Jt(t.data_type), s = i ? {
1778
+ let n = d.length === 1 && d[0] === t.column_name, i = r.get(t.column_name), a = i ? "reference" : n && t.column_name === "id" ? "id" : Xt(t.data_type), s = i ? {
1756
1779
  table: i.target_table,
1757
1780
  column: i.target_column,
1758
- onDelete: Xt(i.delete_rule),
1759
- onUpdate: Xt(i.update_rule)
1760
- } : void 0, c = t.column_default === null ? null : Zt(t.column_default), l = o.get(`${e}.${t.column_name}`);
1781
+ onDelete: Qt(i.delete_rule),
1782
+ onUpdate: Qt(i.update_rule)
1783
+ } : void 0, c = t.column_default === null ? null : $t(t.column_default), l = o.get(`${e}.${t.column_name}`);
1761
1784
  return {
1762
1785
  name: t.column_name,
1763
1786
  type: a,
1764
1787
  nullable: t.is_nullable === "YES",
1788
+ ...V(t.data_type, t.character_maximum_length) === void 0 ? {} : { maxLength: V(t.data_type, t.character_maximum_length) },
1765
1789
  unique: f.has(t.column_name) || n && t.column_name === "id",
1766
1790
  hasDefault: c !== null,
1767
1791
  ...c === null ? {} : { defaultValue: c },
@@ -1790,37 +1814,48 @@ BEGIN
1790
1814
  });
1791
1815
  }
1792
1816
  return { tables: u };
1793
- }), Xt = (e) => {
1817
+ }), Qt = (e) => {
1794
1818
  switch (e.toUpperCase().replace(/_/g, " ")) {
1795
1819
  case "CASCADE": return "cascade";
1796
1820
  case "SET NULL": return "setNull";
1797
1821
  case "SET DEFAULT": return "noAction";
1798
1822
  default: return "noAction";
1799
1823
  }
1800
- }, Zt = (e) => {
1824
+ }, $t = (e) => {
1801
1825
  let t = e.trim();
1802
1826
  for (; t.startsWith("(") && t.endsWith(")");) t = t.slice(1, -1).trim();
1803
1827
  return t.startsWith("N'") && t.endsWith("'") ? t = t.slice(2, -1) : t.startsWith("'") && t.endsWith("'") && (t = t.slice(1, -1)), t;
1804
- }, V = (e) => e.onDialectOrElse({
1805
- mysql: () => Gt(e),
1806
- mssql: () => Yt(e),
1807
- sqlite: () => qt(e),
1808
- orElse: () => Ut(e)
1809
- }), Qt = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, H = (e, t) => {
1810
- if (!e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
1828
+ }, en = /* @__PURE__ */ new Set([
1829
+ "character varying",
1830
+ "varchar",
1831
+ "nvarchar",
1832
+ "char",
1833
+ "character",
1834
+ "nchar"
1835
+ ]), V = (e, t) => {
1836
+ if (!en.has(e.toLowerCase())) return;
1837
+ let n = Number(t);
1838
+ if (!(!Number.isFinite(n) || n <= 0)) return n;
1839
+ }, H = (e) => e.onDialectOrElse({
1840
+ mysql: () => qt(e),
1841
+ mssql: () => Zt(e),
1842
+ sqlite: () => Yt(e),
1843
+ orElse: () => Gt(e)
1844
+ }), tn = (e, t) => `${t}(${e.precision ?? 38}, ${e.scale ?? 0})`, U = (e, t) => {
1845
+ if (!(e.type === "text" && e.maxLength !== void 0) && !e.spatial && e.type !== "vector" && e.type !== "array" && e.type !== "enum") return;
1811
1846
  let n = 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;
1812
1847
  if (n !== void 0) throw Error(`migration applier: cannot render '${e.name}' (${e.type}) — the schema snapshot carries no ${n}. 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.`);
1813
1848
  return D(e, t);
1814
- }, U = (e) => {
1815
- let t = H(e, "postgres");
1816
- return t === void 0 ? $t(e) : t;
1817
- }, $t = (e) => {
1849
+ }, W = (e) => {
1850
+ let t = U(e, "postgres");
1851
+ return t === void 0 ? nn(e) : t;
1852
+ }, nn = (e) => {
1818
1853
  switch (e.type) {
1819
1854
  case "id": return "text";
1820
1855
  case "text": return "text";
1821
1856
  case "integer": return "integer";
1822
1857
  case "real": return "double precision";
1823
- case "decimal": return Qt(e, "NUMERIC");
1858
+ case "decimal": return tn(e, "NUMERIC");
1824
1859
  case "bigint": return "bigint";
1825
1860
  case "boolean": return "boolean";
1826
1861
  case "timestamp": return "timestamptz";
@@ -1834,15 +1869,15 @@ BEGIN
1834
1869
  case "interval": return "interval";
1835
1870
  case "raw": return e.rawDdl ?? "text";
1836
1871
  }
1837
- }, W = (e) => {
1838
- let t = H(e, "mariadb");
1872
+ }, rn = (e) => {
1873
+ let t = U(e, "mariadb");
1839
1874
  if (t !== void 0) return t;
1840
1875
  switch (e.type) {
1841
1876
  case "id": return "VARCHAR(64)";
1842
1877
  case "text": return e.hasDefault && e.defaultValue !== void 0 || e.oneOf && e.oneOf.length > 0 ? "VARCHAR(255)" : "LONGTEXT";
1843
1878
  case "integer": return "INT";
1844
1879
  case "real": return "DOUBLE";
1845
- case "decimal": return Qt(e, "DECIMAL");
1880
+ case "decimal": return tn(e, "DECIMAL");
1846
1881
  case "bigint": return "BIGINT";
1847
1882
  case "boolean": return "TINYINT(1)";
1848
1883
  case "timestamp": return "DATETIME(6)";
@@ -1856,14 +1891,14 @@ BEGIN
1856
1891
  case "interval": return "BIGINT";
1857
1892
  case "raw": return e.rawDdl ?? "LONGTEXT";
1858
1893
  }
1859
- }, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``, en = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, tn = (e) => `ALTER TABLE ${K(e.table)} DROP COLUMN IF EXISTS ${K(e.column)}, ALGORITHM=COPY;`, nn = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, rn = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${kn(t)}`)};`, an = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${on(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, on = (e, t) => {
1894
+ }, G = (e) => `"${e}"`, K = (e) => `\`${e.replace(/`/g, "``")}\``, an = (e, t) => `ALTER TABLE ${t(e.table)} DROP COLUMN IF EXISTS ${t(e.column)};`, on = (e) => `ALTER TABLE ${K(e.table)} DROP COLUMN IF EXISTS ${K(e.column)}, ALGORITHM=COPY;`, sn = (e, t) => `ALTER TABLE ${t(e.table)} RENAME COLUMN ${t(e.from)} TO ${t(e.to)};`, cn = (e, t, n) => `ALTER TABLE ${n(e.table)} RENAME COLUMN ${n(e.column)} TO ${n(`${e.column}${Nn(t)}`)};`, ln = (e, t, n) => e.hasDefault && e.defaultValue !== void 0 ? `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} SET ${un(e, n)};` : `ALTER TABLE ${t(e.table)} ALTER COLUMN ${t(e.column)} DROP DEFAULT;`, un = (e, t) => {
1860
1895
  let n = t(e.defaultValue);
1861
1896
  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.`);
1862
1897
  return n;
1863
- }, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], sn = (e, t, n) => {
1898
+ }, q = (e, t, n) => e.find((e) => e.tableName === t)?.fields[n], dn = (e, t, n) => {
1864
1899
  let r = q(e, t, n);
1865
1900
  return r ? nt(n, r) : void 0;
1866
- }, cn = (e, t, n) => {
1901
+ }, fn = (e, t, n) => {
1867
1902
  let r = n ?? e.nullable, i = ve(e, "mariadb");
1868
1903
  return [
1869
1904
  K(t),
@@ -1871,17 +1906,17 @@ BEGIN
1871
1906
  r ? null : "NOT NULL",
1872
1907
  i
1873
1908
  ].filter(Boolean).join(" ");
1874
- }, ln = (e, t) => e == null ? null : Array.isArray(e) ? un(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" ? O(e, "mysql") : null, un = (e, t, n) => ye(e, t ?? { type: "json" }, n), dn = (e, t) => e == null ? null : Array.isArray(e) ? un(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" ? O(e, "postgres") : null, J = (e, t) => {
1909
+ }, pn = (e, t) => e == null ? null : Array.isArray(e) ? mn(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" ? O(e, "mysql") : null, mn = (e, t, n) => ye(e, t ?? { type: "json" }, n), hn = (e, t) => e == null ? null : Array.isArray(e) ? mn(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" ? O(e, "postgres") : null, J = (e, t) => {
1875
1910
  if (!e.generatedAs) return null;
1876
1911
  let { expr: n, stored: r } = e.generatedAs;
1877
1912
  return t === "postgres" ? `GENERATED ALWAYS AS (${n}) STORED` : t === "mssql" ? `AS (${n})${r ? " PERSISTED" : ""}` : `GENERATED ALWAYS AS (${n}) ${r ? "STORED" : "VIRTUAL"}`;
1878
- }, fn = (e) => {
1913
+ }, gn = (e) => {
1879
1914
  if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "postgres");
1880
1915
  let t = J(e, "postgres");
1881
- if (t) return `${G(e.name)} ${U(e)} ${t}`;
1882
- let n = [G(e.name), U(e)];
1916
+ if (t) return `${G(e.name)} ${W(e)} ${t}`;
1917
+ let n = [G(e.name), W(e)];
1883
1918
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
1884
- let t = dn(e.defaultValue, e);
1919
+ let t = hn(e.defaultValue, e);
1885
1920
  t && n.push(t);
1886
1921
  }
1887
1922
  return e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
@@ -1890,20 +1925,20 @@ BEGIN
1890
1925
  setNull: "SET NULL",
1891
1926
  noAction: "NO ACTION"
1892
1927
  }[e.references.onDelete]}`)), n.join(" ");
1893
- }, pn = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", mn = (e) => {
1894
- let t = e.columns.map((e) => ` ${fn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${pn(e, G)}\n)`];
1895
- for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(Pn).join(", ")})`);
1928
+ }, _n = (e, t) => e.primaryKey && e.primaryKey.length > 0 ? `,\n PRIMARY KEY (${e.primaryKey.map(t).join(", ")})` : "", vn = (e) => {
1929
+ let t = e.columns.map((e) => ` ${gn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${_n(e, G)}\n)`];
1930
+ for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(Rn).join(", ")})`);
1896
1931
  return n;
1897
- }, hn = 191, gn = (e) => {
1898
- let t = W(e).toUpperCase();
1932
+ }, yn = 191, bn = (e) => {
1933
+ let t = rn(e).toUpperCase();
1899
1934
  return t.endsWith("TEXT") || t.endsWith("BLOB");
1900
- }, _n = (e) => {
1935
+ }, xn = (e) => {
1901
1936
  if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "mariadb");
1902
1937
  let t = J(e, "mariadb");
1903
- if (t) return `${K(e.name)} ${W(e)} ${t}`;
1904
- let n = [K(e.name), W(e)];
1905
- if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !gn(e) && n.push("UNIQUE"), e.hasDefault) {
1906
- let t = ln(e.defaultValue, e);
1938
+ if (t) return `${K(e.name)} ${rn(e)} ${t}`;
1939
+ let n = [K(e.name), rn(e)];
1940
+ if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && !bn(e) && n.push("UNIQUE"), e.hasDefault) {
1941
+ let t = pn(e.defaultValue, e);
1907
1942
  t && n.push(t);
1908
1943
  }
1909
1944
  return e.references && (n.push(`REFERENCES ${K(e.references.table)} (${K(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${{
@@ -1912,26 +1947,26 @@ BEGIN
1912
1947
  setNull: "SET NULL",
1913
1948
  noAction: "NO ACTION"
1914
1949
  }[e.references.onDelete]}`)), n.join(" ");
1915
- }, vn = (e) => {
1950
+ }, Sn = (e) => {
1916
1951
  let t = new Map(e.columns.map((e) => [e.name, e])), n = (e) => {
1917
1952
  let n = t.get(e);
1918
- return n && gn(n) ? `${K(e)}(${hn})` : K(e);
1919
- }, r = e.columns.map((e) => ` ${_n(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${r}${pn(e, n)}\n)`];
1920
- for (let t of e.columns) t.unique && t.type !== "id" && gn(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${K(`${e.table}_${t.name}_key`)} ON ${K(e.table)} (${n(t.name)})`);
1953
+ return n && bn(n) ? `${K(e)}(${yn})` : K(e);
1954
+ }, r = e.columns.map((e) => ` ${xn(e)}`).join(",\n"), i = [`CREATE TABLE IF NOT EXISTS ${K(e.table)} (\n${r}${_n(e, n)}\n)`];
1955
+ for (let t of e.columns) t.unique && t.type !== "id" && bn(t) && i.push(`CREATE UNIQUE INDEX IF NOT EXISTS ${K(`${e.table}_${t.name}_key`)} ON ${K(e.table)} (${n(t.name)})`);
1921
1956
  for (let t of e.indexes) t.name !== `${e.table}_pkey` && i.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(t.name)} ON ${K(e.table)} (${t.columns.map(n).join(", ")})`);
1922
1957
  return i;
1923
- }, yn = {
1958
+ }, Cn = {
1924
1959
  cascade: "CASCADE",
1925
1960
  restrict: "RESTRICT",
1926
1961
  setNull: "SET NULL",
1927
1962
  noAction: "NO ACTION"
1928
- }, bn = {
1963
+ }, wn = {
1929
1964
  cascade: "CASCADE",
1930
1965
  restrict: "NO ACTION",
1931
1966
  setNull: "SET NULL",
1932
1967
  noAction: "NO ACTION"
1933
- }, xn = (e) => {
1934
- let t = H(e, "sqlite");
1968
+ }, Tn = (e) => {
1969
+ let t = U(e, "sqlite");
1935
1970
  if (t !== void 0) return t;
1936
1971
  switch (e.type) {
1937
1972
  case "integer":
@@ -1942,29 +1977,29 @@ BEGIN
1942
1977
  case "bytes": return "BLOB";
1943
1978
  default: return "TEXT";
1944
1979
  }
1945
- }, Y = (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" ? O(e, "sqlite") : null, Sn = (e) => {
1980
+ }, Y = (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" ? O(e, "sqlite") : null, En = (e) => {
1946
1981
  if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "sqlite");
1947
1982
  let t = J(e, "sqlite");
1948
- if (t) return `${G(e.name)} ${xn(e)} ${t}`;
1949
- let n = [G(e.name), xn(e)];
1983
+ if (t) return `${G(e.name)} ${Tn(e)} ${t}`;
1984
+ let n = [G(e.name), Tn(e)];
1950
1985
  if (e.type === "id" && n.push("PRIMARY KEY"), e.nullable || n.push("NOT NULL"), e.unique && e.type !== "id" && n.push("UNIQUE"), e.hasDefault) {
1951
1986
  let t = Y(e.defaultValue, "CURRENT_TIMESTAMP");
1952
1987
  t && n.push(t);
1953
1988
  }
1954
- if (e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${yn[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
1989
+ if (e.references && (n.push(`REFERENCES ${G(e.references.table)} (${G(e.references.column)})`), e.references.onDelete && n.push(`ON DELETE ${Cn[e.references.onDelete]}`)), e.oneOf && e.oneOf.length > 0) {
1955
1990
  let t = e.oneOf.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
1956
1991
  n.push(`CHECK (${G(e.name)} IN (${t}))`);
1957
1992
  }
1958
1993
  return n.join(" ");
1959
- }, Cn = (e) => {
1960
- let t = e.columns.map((e) => ` ${Sn(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${pn(e, G)}\n)`];
1994
+ }, Dn = (e) => {
1995
+ let t = e.columns.map((e) => ` ${En(e)}`).join(",\n"), n = [`CREATE TABLE IF NOT EXISTS ${G(e.table)} (\n${t}${_n(e, G)}\n)`];
1961
1996
  for (let t of e.indexes) t.name !== `${e.table}_pkey` && n.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e.table)} (${t.columns.map(G).join(", ")})`);
1962
1997
  return n;
1963
1998
  }, X = (e, t) => {
1964
1999
  let n = t.find((t) => t.tableName === e);
1965
2000
  if (!n) return [];
1966
2001
  let r = N([n]).tables[0], i = `${e}__voltro_rebuild`, a = r.columns.map((e) => G(e.name)).join(", "), o = [
1967
- ...Cn({
2002
+ ...Dn({
1968
2003
  kind: "create-table",
1969
2004
  table: i,
1970
2005
  columns: r.columns,
@@ -1977,25 +2012,25 @@ BEGIN
1977
2012
  ];
1978
2013
  for (let t of r.indexes) t.name !== `${e}_pkey` && o.push(`CREATE ${t.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${G(t.name)} ON ${G(e)} (${t.columns.map(G).join(", ")})`);
1979
2014
  return o;
1980
- }, wn = (e, t, n, r) => {
2015
+ }, On = (e, t, n, r) => {
1981
2016
  let i = r ?? e.nullable;
1982
2017
  return `ALTER TABLE ${Z(n)} ALTER COLUMN ${Z(t)} ${D(e, "mssql")} ${i ? "NULL" : "NOT NULL"};`;
1983
- }, Tn = (e) => {
2018
+ }, kn = (e) => {
1984
2019
  let t = `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 ${Z(e.table)} DROP CONSTRAINT [' + @dc + ']');`;
1985
2020
  if (!e.hasDefault) return t;
1986
2021
  let n = Y(e.defaultValue, "SYSUTCDATETIME()");
1987
2022
  if (!n) return t;
1988
2023
  let r = n.replace(/^DEFAULT\s+/i, "");
1989
2024
  return `${t} ALTER TABLE ${Z(e.table)} ADD DEFAULT ${r} FOR ${Z(e.column)};`;
1990
- }, Z = (e) => `[${e.replace(/]/g, "]]")}]`, En = (e) => {
1991
- let t = H(e, "mssql");
2025
+ }, Z = (e) => `[${e.replace(/]/g, "]]")}]`, An = (e) => {
2026
+ let t = U(e, "mssql");
1992
2027
  if (t !== void 0) return t;
1993
2028
  switch (e.type) {
1994
2029
  case "id":
1995
2030
  case "reference": return "NVARCHAR(64)";
1996
2031
  case "integer": return "INT";
1997
2032
  case "real": return "FLOAT";
1998
- case "decimal": return Qt(e, "DECIMAL");
2033
+ case "decimal": return tn(e, "DECIMAL");
1999
2034
  case "bigint": return "BIGINT";
2000
2035
  case "boolean": return "BIT";
2001
2036
  case "timestamp": return "DATETIME2(6)";
@@ -2003,34 +2038,34 @@ BEGIN
2003
2038
  case "bytes": return "VARBINARY(MAX)";
2004
2039
  default: return "NVARCHAR(MAX)";
2005
2040
  }
2006
- }, Dn = (e, t) => {
2041
+ }, jn = (e, t) => {
2007
2042
  if (e.type === "id" && e.idScheme?.kind === "numeric") return k(e.name, "mssql");
2008
- let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : En(e), r = J(e, "mssql");
2043
+ let n = e.type === "text" && t?.has(e.name) ? "NVARCHAR(450)" : An(e), r = J(e, "mssql");
2009
2044
  if (r) return `${Z(e.name)} ${r}`;
2010
2045
  let i = [Z(e.name), n];
2011
2046
  if (e.type === "id" && i.push("PRIMARY KEY"), e.nullable || i.push("NOT NULL"), e.unique && e.type !== "id" && i.push("UNIQUE"), e.hasDefault) {
2012
2047
  let t = Y(e.defaultValue, "SYSUTCDATETIME()");
2013
2048
  t && i.push(t);
2014
2049
  }
2015
- return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${bn[e.references.onDelete]}`)), i.join(" ");
2016
- }, On = (e) => {
2017
- let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${Dn(e, n)}`).join(",\n"), i = `CREATE TABLE ${Z(e.table)} (\n${r}${pn(e, Z)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2050
+ return e.references && (i.push(`REFERENCES ${Z(e.references.table)} (${Z(e.references.column)})`), e.references.onDelete && i.push(`ON DELETE ${wn[e.references.onDelete]}`)), i.join(" ");
2051
+ }, Mn = (e) => {
2052
+ let t = (e) => e.replace(/'/g, "''"), n = new Set(e.indexes.flatMap((e) => e.columns)), r = e.columns.map((e) => ` ${jn(e, n)}`).join(",\n"), i = `CREATE TABLE ${Z(e.table)} (\n${r}${_n(e, Z)}\n)`, a = [`IF OBJECT_ID(N'${t(e.table)}', N'U') IS NULL EXEC(N'${t(i)}')`];
2018
2053
  for (let n of e.indexes) {
2019
2054
  if (n.name === `${e.table}_pkey`) continue;
2020
2055
  let r = `CREATE ${n.unique ? "UNIQUE " : ""}INDEX ${Z(n.name)} ON ${Z(e.table)} (${n.columns.map(Z).join(", ")})`;
2021
2056
  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)}')`);
2022
2057
  }
2023
2058
  return a;
2024
- }, kn = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, An = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, jn = (e, t, n) => {
2025
- let r = `${e.table}${kn(t)}`;
2059
+ }, Nn = (e) => `__dropped_${e.replace(/[-:T.Z]/g, "").slice(0, 14)}`, Pn = (e, t) => `DROP TABLE IF EXISTS ${t(e.table)};`, Fn = (e, t, n) => {
2060
+ let r = `${e.table}${Nn(t)}`;
2026
2061
  return `ALTER TABLE ${n(e.table)} RENAME TO ${n(r)};`;
2027
- }, Mn = (e, t, n) => {
2062
+ }, In = (e, t, n) => {
2028
2063
  let r = q(e, t, n);
2029
- return r ? gn({ type: r.type }) : !1;
2030
- }, Nn = (e, t, n) => Mn(e, t, n) ? `${K(n)}(${hn})` : K(n), Pn = (e) => e.startsWith("(") ? e : G(e), Fn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map(Pn).join(", ")});`, In = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map((n) => Nn(t, e.table, n)).join(", ")});`, Ln = (e) => `DROP INDEX IF EXISTS ${G(e.index)};`, Rn = (e) => `DROP INDEX ${K(e.index)} ON ${K(e.table)};`, zn = (e) => `DROP INDEX IF EXISTS ${Z(e.index)} ON ${Z(e.table)};`, Bn = (e) => {
2064
+ return r ? bn({ type: r.type }) : !1;
2065
+ }, Ln = (e, t, n) => In(e, t, n) ? `${K(n)}(${yn})` : K(n), Rn = (e) => e.startsWith("(") ? e : G(e), zn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${t ? "CONCURRENTLY " : ""}IF NOT EXISTS ${G(e.index.name)} ON ${G(e.table)} (${e.index.columns.map(Rn).join(", ")});`, Bn = (e, t) => `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX IF NOT EXISTS ${K(e.index.name)} ON ${K(e.table)} (${e.index.columns.map((n) => Ln(t, e.table, n)).join(", ")});`, Vn = (e) => `DROP INDEX IF EXISTS ${G(e.index)};`, Hn = (e) => `DROP INDEX ${K(e.index)} ON ${K(e.table)};`, Un = (e) => `DROP INDEX IF EXISTS ${Z(e.index)} ON ${Z(e.table)};`, Wn = (e) => {
2031
2066
  let t = (e) => e.replace(/'/g, "''"), n = `CREATE ${e.index.unique ? "UNIQUE " : ""}INDEX ${Z(e.index.name)} ON ${Z(e.table)} (${e.index.columns.map(Z).join(", ")})`;
2032
2067
  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)}');`;
2033
- }, Vn = (e, t, n) => {
2068
+ }, Gn = (e, t, n) => {
2034
2069
  let r = n.find((t) => t.tableName === e);
2035
2070
  if (!r) return [];
2036
2071
  let i = [];
@@ -2039,13 +2074,13 @@ BEGIN
2039
2074
  t && t.type === "text" && !t.generatedAs && i.push(`ALTER TABLE ${Z(e)} ALTER COLUMN ${Z(n)} NVARCHAR(450) ${t.nullable ? "NULL" : "NOT NULL"};`);
2040
2075
  }
2041
2076
  return i;
2042
- }, Hn = (e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${G(e.column)});`, Un = (e, t) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${Nn(t, e.table, e.column)});`, Wn = (e) => {
2077
+ }, Kn = (e) => `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(`${e.table}_${e.column}_key`)} UNIQUE (${G(e.column)});`, qn = (e, t) => `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(`${e.table}_${e.column}_key`)} UNIQUE (${Ln(t, e.table, e.column)});`, Jn = (e) => {
2043
2078
  let t = e.fields.map((e) => G(e)).join(", ");
2044
2079
  return `ALTER TABLE ${G(e.table)} ADD CONSTRAINT ${G(e.name)} UNIQUE (${t});`;
2045
- }, Gn = (e, t) => {
2046
- let n = e.fields.map((n) => Nn(t, e.table, n)).join(", ");
2080
+ }, Yn = (e, t) => {
2081
+ let n = e.fields.map((n) => Ln(t, e.table, n)).join(", ");
2047
2082
  return `ALTER TABLE ${K(e.table)} ADD CONSTRAINT ${K(e.name)} UNIQUE (${n});`;
2048
- }, Kn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(e.name)};`, qn = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(e.name)};`, Jn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_key`)};`, Yn = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(`${e.table}_${e.column}_key`)};`, Xn = (e, t) => {
2083
+ }, Xn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(e.name)};`, Zn = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(e.name)};`, Qn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_key`)};`, $n = (e) => `ALTER TABLE ${K(e.table)} DROP INDEX ${K(`${e.table}_${e.column}_key`)};`, er = (e, t) => {
2049
2084
  let n = [], r = t(e.table), i = t(e.column), a = t(e.targetTable), o = t(e.targetColumn);
2050
2085
  if (e.orphanPolicy) {
2051
2086
  let t = `${i} IS NOT NULL AND ${i} NOT IN (SELECT ${o} FROM ${a})`;
@@ -2063,11 +2098,11 @@ BEGIN
2063
2098
  setNull: "SET NULL",
2064
2099
  noAction: "NO ACTION"
2065
2100
  }[e.onDelete]}`), n.push(s.join(" ") + ";"), n;
2066
- }, Zn = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_fkey`)};`, Qn = (e) => `ALTER TABLE ${K(e.table)} DROP FOREIGN KEY ${K(`${e.table}_${e.column}_fkey`)};`, $n = (e, t) => {
2101
+ }, tr = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_fkey`)};`, nr = (e) => `ALTER TABLE ${K(e.table)} DROP FOREIGN KEY ${K(`${e.table}_${e.column}_fkey`)};`, rr = (e, t) => {
2067
2102
  let n = e.values.map((e) => `'${e.replace(/'/g, "''")}'`).join(", ");
2068
2103
  return `ALTER TABLE ${t(e.table)} ADD CONSTRAINT ${t(`${e.table}_${e.column}_check`)} CHECK (${t(e.column)} IN (${n}));`;
2069
- }, er = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_check`)};`, tr = (e) => `ALTER TABLE ${K(e.table)} DROP CHECK ${K(`${e.table}_${e.column}_check`)};`, nr = (e, t, n, r) => {
2070
- let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Z : G, s = a ? W(i) : r === "mssql" ? En(i) : r === "sqlite" ? xn(i) : U(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? ln(e, i) : r === "mssql" ? Y(e, "SYSUTCDATETIME()") : r === "sqlite" ? Y(e, "CURRENT_TIMESTAMP") : dn(e, i), u = J(i, r);
2104
+ }, ir = (e) => `ALTER TABLE ${G(e.table)} DROP CONSTRAINT IF EXISTS ${G(`${e.table}_${e.column}_check`)};`, ar = (e) => `ALTER TABLE ${K(e.table)} DROP CHECK ${K(`${e.table}_${e.column}_check`)};`, or = (e, t, n, r) => {
2105
+ let i = e.column, a = r === "mariadb", o = a ? K : r === "mssql" ? Z : G, s = a ? rn(i) : r === "mssql" ? An(i) : r === "sqlite" ? Tn(i) : W(i), c = r === "mssql" ? "ADD" : "ADD COLUMN", l = (e) => a ? pn(e, i) : r === "mssql" ? Y(e, "SYSUTCDATETIME()") : r === "sqlite" ? Y(e, "CURRENT_TIMESTAMP") : hn(e, i), u = J(i, r);
2071
2106
  if (u) {
2072
2107
  let t = r === "mssql" ? `${o(i.name)} ${u}` : `${o(i.name)} ${s} ${u}`;
2073
2108
  return {
@@ -2095,7 +2130,7 @@ BEGIN
2095
2130
  post: f ? [f] : []
2096
2131
  };
2097
2132
  return d?.sql && (p.backfillKind = "sql", p.backfillSql = d.sql), d?.js && (p.backfillKind = "js", p.backfillJs = d.js), d?.batchSize !== void 0 && (p.batchSize = d.batchSize), d?.sleepMs !== void 0 && (p.sleepMs = d.sleepMs), p;
2098
- }, rr = (e) => {
2133
+ }, sr = (e) => {
2099
2134
  let t = new Map(e.map((e) => [e.tableName, e]));
2100
2135
  return (e, n) => {
2101
2136
  let r = t.get(e);
@@ -2120,21 +2155,21 @@ BEGIN
2120
2155
  })), d.mapError((e) => {
2121
2156
  let r = _(`applier: statement failed (op=${n})`, t, e, 400).trim();
2122
2157
  return Object.assign(e, { message: r });
2123
- }), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }), ir = (e, t, n) => d.gen(function* () {
2124
- let r = process.hrtime.bigint(), i = rr(n.declared), a = t.op;
2158
+ }), d.map(() => void 0)), $ = (e, t, n) => d.forEach(t, (t) => Q(e, t, n), { discard: !0 }), cr = (e, t, n) => d.gen(function* () {
2159
+ let r = process.hrtime.bigint(), i = sr(n.declared), a = t.op;
2125
2160
  switch (a.kind) {
2126
2161
  case "create-table": {
2127
2162
  let t = yield* e.onDialectOrElse({
2128
- mysql: () => d.succeed(vn(a)),
2129
- mssql: () => d.succeed(On(a)),
2130
- sqlite: () => d.succeed(Cn(a)),
2131
- orElse: () => d.succeed(mn(a))
2163
+ mysql: () => d.succeed(Sn(a)),
2164
+ mssql: () => d.succeed(Mn(a)),
2165
+ sqlite: () => d.succeed(Dn(a)),
2166
+ orElse: () => d.succeed(vn(a))
2132
2167
  });
2133
2168
  for (let n of t) yield* Q(e, n, a.kind);
2134
2169
  break;
2135
2170
  }
2136
2171
  case "drop-table": {
2137
- let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? jn(a, n, e) : An(a, e);
2172
+ let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString(), r = (e) => t ? Fn(a, n, e) : Pn(a, e);
2138
2173
  yield* e.onDialectOrElse({
2139
2174
  mysql: () => Q(e, r(K), a.kind),
2140
2175
  orElse: () => Q(e, r(G), a.kind)
@@ -2144,71 +2179,71 @@ BEGIN
2144
2179
  case "drop-column": {
2145
2180
  let t = process.env.VOLTRO_SOFT_DROP === "1", n = (/* @__PURE__ */ new Date()).toISOString();
2146
2181
  yield* e.onDialectOrElse({
2147
- mysql: () => Q(e, t ? rn(a, n, K) : tn(a), a.kind),
2148
- orElse: () => Q(e, t ? rn(a, n, G) : en(a, G), a.kind)
2182
+ mysql: () => Q(e, t ? cn(a, n, K) : on(a), a.kind),
2183
+ orElse: () => Q(e, t ? cn(a, n, G) : an(a, G), a.kind)
2149
2184
  });
2150
2185
  break;
2151
2186
  }
2152
2187
  case "rename-column":
2153
2188
  yield* e.onDialectOrElse({
2154
- mysql: () => Q(e, nn(a, K), a.kind),
2189
+ mysql: () => Q(e, sn(a, K), a.kind),
2155
2190
  mssql: () => Q(e, `EXEC sp_rename N'${a.table.replace(/'/g, "''")}.${a.from.replace(/'/g, "''")}', N'${a.to.replace(/'/g, "''")}', 'COLUMN';`, a.kind),
2156
- orElse: () => Q(e, nn(a, G), a.kind)
2191
+ orElse: () => Q(e, sn(a, G), a.kind)
2157
2192
  });
2158
2193
  break;
2159
2194
  case "add-index":
2160
2195
  yield* e.onDialectOrElse({
2161
- mysql: () => Q(e, In(a, n.declared), a.kind),
2162
- mssql: () => $(e, [...Vn(a.table, a.index.columns, n.declared), Bn(a)], a.kind),
2163
- orElse: () => Q(e, Fn(a, t.classification === "online-required"), a.kind)
2196
+ mysql: () => Q(e, Bn(a, n.declared), a.kind),
2197
+ mssql: () => $(e, [...Gn(a.table, a.index.columns, n.declared), Wn(a)], a.kind),
2198
+ orElse: () => Q(e, zn(a, t.classification === "online-required"), a.kind)
2164
2199
  });
2165
2200
  break;
2166
2201
  case "drop-index":
2167
2202
  yield* e.onDialectOrElse({
2168
- mysql: () => Q(e, Rn(a), a.kind),
2169
- mssql: () => Q(e, zn(a), a.kind),
2170
- orElse: () => Q(e, Ln(a), a.kind)
2203
+ mysql: () => Q(e, Hn(a), a.kind),
2204
+ mssql: () => Q(e, Un(a), a.kind),
2205
+ orElse: () => Q(e, Vn(a), a.kind)
2171
2206
  });
2172
2207
  break;
2173
2208
  case "add-unique":
2174
2209
  yield* e.onDialectOrElse({
2175
- mysql: () => Q(e, Un(a, n.declared), a.kind),
2210
+ mysql: () => Q(e, qn(a, n.declared), a.kind),
2176
2211
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2177
- mssql: () => $(e, [...Vn(a.table, [a.column], n.declared), Hn(a)], a.kind),
2178
- orElse: () => Q(e, Hn(a), a.kind)
2212
+ mssql: () => $(e, [...Gn(a.table, [a.column], n.declared), Kn(a)], a.kind),
2213
+ orElse: () => Q(e, Kn(a), a.kind)
2179
2214
  });
2180
2215
  break;
2181
2216
  case "drop-unique":
2182
2217
  yield* e.onDialectOrElse({
2183
- mysql: () => Q(e, Yn(a), a.kind),
2218
+ mysql: () => Q(e, $n(a), a.kind),
2184
2219
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2185
- orElse: () => Q(e, Jn(a), a.kind)
2220
+ orElse: () => Q(e, Qn(a), a.kind)
2186
2221
  });
2187
2222
  break;
2188
2223
  case "add-unique-composite":
2189
2224
  yield* e.onDialectOrElse({
2190
- mysql: () => Q(e, Gn(a, n.declared), a.kind),
2225
+ mysql: () => Q(e, Yn(a, n.declared), a.kind),
2191
2226
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2192
- mssql: () => $(e, [...Vn(a.table, a.fields, n.declared), Wn(a)], a.kind),
2193
- orElse: () => Q(e, Wn(a), a.kind)
2227
+ mssql: () => $(e, [...Gn(a.table, a.fields, n.declared), Jn(a)], a.kind),
2228
+ orElse: () => Q(e, Jn(a), a.kind)
2194
2229
  });
2195
2230
  break;
2196
2231
  case "drop-unique-composite":
2197
2232
  yield* e.onDialectOrElse({
2198
- mysql: () => Q(e, qn(a), a.kind),
2233
+ mysql: () => Q(e, Zn(a), a.kind),
2199
2234
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2200
- orElse: () => Q(e, Kn(a), a.kind)
2235
+ orElse: () => Q(e, Xn(a), a.kind)
2201
2236
  });
2202
2237
  break;
2203
2238
  case "add-foreign-key":
2204
2239
  yield* e.onDialectOrElse({
2205
- mysql: () => $(e, Xn(a, K), a.kind),
2240
+ mysql: () => $(e, er(a, K), a.kind),
2206
2241
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2207
- orElse: () => $(e, Xn(a, G), a.kind)
2242
+ orElse: () => $(e, er(a, G), a.kind)
2208
2243
  });
2209
2244
  break;
2210
2245
  case "add-column": {
2211
- let n = nr(a, t, i, yield* e.onDialectOrElse({
2246
+ let n = or(a, t, i, yield* e.onDialectOrElse({
2212
2247
  mysql: () => d.succeed("mariadb"),
2213
2248
  mssql: () => d.succeed("mssql"),
2214
2249
  sqlite: () => d.succeed("sqlite"),
@@ -2254,37 +2289,37 @@ BEGIN
2254
2289
  yield* e.onDialectOrElse({
2255
2290
  mysql: () => {
2256
2291
  let t = q(n.declared, a.table, a.column);
2257
- return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${cn(t, a.column, a.toNullable)};`, a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2292
+ return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${fn(t, a.column, a.toNullable)};`, a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-nullability on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2258
2293
  },
2259
2294
  mssql: () => {
2260
2295
  let t = q(n.declared, a.table, a.column);
2261
- return t ? Q(e, wn(t, a.column, a.table, a.toNullable), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${a.table}.${a.column}'.`));
2296
+ return t ? Q(e, On(t, a.column, a.table, a.toNullable), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-nullability on mssql needs the declared column '${a.table}.${a.column}'.`));
2262
2297
  },
2263
2298
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2264
2299
  orElse: () => Q(e, `ALTER TABLE ${G(a.table)} ALTER COLUMN ${G(a.column)} ${a.toNullable ? "DROP NOT NULL" : "SET NOT NULL"};`, a.kind)
2265
2300
  });
2266
2301
  break;
2267
2302
  case "alter-column-default": {
2268
- let t = sn(n.declared, a.table, a.column);
2303
+ let t = dn(n.declared, a.table, a.column);
2269
2304
  yield* e.onDialectOrElse({
2270
- mysql: () => Q(e, an(a, K, (e) => ln(e, t)), a.kind),
2271
- mssql: () => Q(e, Tn(a), a.kind),
2305
+ mysql: () => Q(e, ln(a, K, (e) => pn(e, t)), a.kind),
2306
+ mssql: () => Q(e, kn(a), a.kind),
2272
2307
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2273
- orElse: () => Q(e, an(a, G, (e) => dn(e, t)), a.kind)
2308
+ orElse: () => Q(e, ln(a, G, (e) => hn(e, t)), a.kind)
2274
2309
  });
2275
2310
  break;
2276
2311
  }
2277
2312
  case "alter-column-type": {
2278
- let r = U(sn(n.declared, a.table, a.column) ?? { type: a.to }), i = a.using ? ` USING ${a.using}` : "";
2313
+ let r = W(dn(n.declared, a.table, a.column) ?? { type: a.to }), i = a.using ? ` USING ${a.using}` : "";
2279
2314
  if (t.classification !== "online-required") {
2280
2315
  yield* e.onDialectOrElse({
2281
2316
  mysql: () => {
2282
2317
  let t = q(n.declared, a.table, a.column);
2283
- return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${cn(t, a.column)};`, a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2318
+ return t ? Q(e, `ALTER TABLE ${K(a.table)} MODIFY COLUMN ${fn(t, a.column)};`, a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mariadb needs the declared column '${a.table}.${a.column}' (to render MODIFY COLUMN); it was not in ctx.declared.`));
2284
2319
  },
2285
2320
  mssql: () => {
2286
2321
  let t = q(n.declared, a.table, a.column);
2287
- return t ? Q(e, wn(t, a.column, a.table), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${a.table}.${a.column}'.`));
2322
+ return t ? Q(e, On(t, a.column, a.table), a.kind) : d.die(/* @__PURE__ */ Error(`alter-column-type on mssql needs the declared column '${a.table}.${a.column}'.`));
2288
2323
  },
2289
2324
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2290
2325
  orElse: () => Q(e, `ALTER TABLE ${G(a.table)} ALTER COLUMN ${G(a.column)} TYPE ${r}${i};`, a.kind)
@@ -2308,23 +2343,23 @@ BEGIN
2308
2343
  }
2309
2344
  case "drop-foreign-key":
2310
2345
  yield* e.onDialectOrElse({
2311
- mysql: () => Q(e, Qn(a), a.kind),
2346
+ mysql: () => Q(e, nr(a), a.kind),
2312
2347
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2313
- orElse: () => Q(e, Zn(a), a.kind)
2348
+ orElse: () => Q(e, tr(a), a.kind)
2314
2349
  });
2315
2350
  break;
2316
2351
  case "add-check":
2317
2352
  yield* e.onDialectOrElse({
2318
- mysql: () => Q(e, $n(a, K), a.kind),
2353
+ mysql: () => Q(e, rr(a, K), a.kind),
2319
2354
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2320
- orElse: () => Q(e, $n(a, G), a.kind)
2355
+ orElse: () => Q(e, rr(a, G), a.kind)
2321
2356
  });
2322
2357
  break;
2323
2358
  case "drop-check":
2324
2359
  yield* e.onDialectOrElse({
2325
- mysql: () => Q(e, tr(a), a.kind),
2360
+ mysql: () => Q(e, ar(a), a.kind),
2326
2361
  sqlite: () => $(e, X(a.table, n.declared), a.kind),
2327
- orElse: () => Q(e, er(a), a.kind)
2362
+ orElse: () => Q(e, ir(a), a.kind)
2328
2363
  });
2329
2364
  break;
2330
2365
  }
@@ -2333,10 +2368,10 @@ BEGIN
2333
2368
  status: "applied",
2334
2369
  durationMs: Number((process.hrtime.bigint() - r) / 1000000n)
2335
2370
  };
2336
- }), ar = (e, t, n) => d.gen(function* () {
2371
+ }), lr = (e, t, n) => d.gen(function* () {
2337
2372
  let r = t.operations.filter((e) => e.blocked);
2338
2373
  if (r.length > 0) return yield* d.die(/* @__PURE__ */ Error(`applyPlan: refusing to execute — ${r.length} blocked operations. Run \`voltro db plan\` to see the fixes.`));
2339
- yield* w(e);
2374
+ yield* C(e);
2340
2375
  let i = Date.now(), a = [];
2341
2376
  try {
2342
2377
  let r = yield* e.onDialectOrElse({
@@ -2346,11 +2381,11 @@ BEGIN
2346
2381
  }), i = r ? t.operations.filter((e) => e.classification !== "online-required") : [], o = r ? t.operations.filter((e) => e.classification === "online-required") : t.operations;
2347
2382
  i.length > 0 && (yield* e.withTransaction(d.gen(function* () {
2348
2383
  let e = yield* p.SqlClient;
2349
- for (let t of i) a.push(yield* ir(e, t, n));
2384
+ for (let t of i) a.push(yield* cr(e, t, n));
2350
2385
  })));
2351
- for (let t of o) a.push(yield* ir(e, t, n));
2386
+ for (let t of o) a.push(yield* cr(e, t, n));
2352
2387
  } finally {
2353
- yield* T(e).pipe(d.orDie);
2388
+ yield* w(e).pipe(d.orDie);
2354
2389
  }
2355
2390
  let o = yield* n.replan(e);
2356
2391
  if (o.operations.length > 0) {
@@ -2382,19 +2417,19 @@ BEGIN
2382
2417
  source: n.source,
2383
2418
  ...n.notes ? { notes: n.notes } : {}
2384
2419
  };
2385
- }), or = (e) => e.operations.filter((e) => e.blocked).map((e) => ` - ${e.op.kind} ${"table" in e.op ? `[${e.op.table}]` : ""}: ${e.reason ?? "<no reason>"}\n fix: ${e.blocked?.fix ?? "<no fix>"}`).join("\n"), sr = (e) => e`
2420
+ }), ur = (e) => e.operations.filter((e) => e.blocked).map((e) => ` - ${e.op.kind} ${"table" in e.op ? `[${e.op.table}]` : ""}: ${e.reason ?? "<no reason>"}\n fix: ${e.blocked?.fix ?? "<no fix>"}`).join("\n"), dr = (e) => e`
2386
2421
  SELECT fingerprint
2387
2422
  FROM _voltro_migration_plans
2388
2423
  ORDER BY ${e("appliedAt")} DESC
2389
2424
  LIMIT 1
2390
- `.pipe(d.map((e) => e.length > 0 ? e[0].fingerprint : void 0), d.catchAll(() => d.succeed(void 0))), cr = (e) => e.onDialectOrElse({
2425
+ `.pipe(d.map((e) => e.length > 0 ? e[0].fingerprint : void 0), d.catchAll(() => d.succeed(void 0))), fr = (e) => e.onDialectOrElse({
2391
2426
  pg: () => "postgres",
2392
2427
  mysql: () => "mysql",
2393
2428
  mssql: () => "mssql",
2394
2429
  sqlite: () => "sqlite",
2395
2430
  orElse: () => "sqlite"
2396
- }), lr = (e, t) => d.gen(function* () {
2397
- let n = j(N(t, cr(e))), r = yield* sr(e);
2431
+ }), pr = (e, t) => d.gen(function* () {
2432
+ let n = j(N(t, fr(e))), r = yield* dr(e);
2398
2433
  return r === n ? {
2399
2434
  kind: "up-to-date",
2400
2435
  fingerprint: n
@@ -2403,23 +2438,23 @@ BEGIN
2403
2438
  expected: n,
2404
2439
  ...r === void 0 ? {} : { actual: r }
2405
2440
  };
2406
- }), ur = [
2441
+ }), mr = [
2407
2442
  "pgeagertest_",
2408
2443
  "mig_e2e_",
2409
2444
  "mig_test_",
2410
2445
  "mysqleagertest_",
2411
2446
  "mssqleagertest_",
2412
2447
  "sqliteeagertest_"
2413
- ], dr = (e) => ur.some((t) => e.startsWith(t)), fr = (e, t) => d.gen(function* () {
2448
+ ], hr = (e) => mr.some((t) => e.startsWith(t)), gr = (e, t) => d.gen(function* () {
2414
2449
  if (process.env.VOLTRO_TEST_FIXTURE_GC === "off") return [];
2415
- let n = t.filter((e) => dr(e.name)).map((e) => e.name);
2450
+ let n = t.filter((e) => hr(e.name)).map((e) => e.name);
2416
2451
  if (n.length === 0) return [];
2417
2452
  for (let t of n) yield* e.unsafe(`DROP TABLE IF EXISTS "${t}" CASCADE`).pipe(d.catchAll(() => d.void));
2418
2453
  return n;
2419
- }), pr = () => {
2454
+ }), _r = () => {
2420
2455
  let e = (process.env.VOLTRO_DB_IGNORE_TABLES ?? "").split(",").map((e) => e.trim()).filter((e) => e.length > 0);
2421
2456
  return e.length > 0 ? { ignoreTables: e } : {};
2422
- }, mr = (e) => {
2457
+ }, vr = (e) => {
2423
2458
  if (e === void 0) return;
2424
2459
  let t = e.trim();
2425
2460
  if (t === "") return;
@@ -2429,43 +2464,43 @@ BEGIN
2429
2464
  kind: "tables",
2430
2465
  tables: new Set(n)
2431
2466
  } : void 0;
2432
- }, hr = (e) => typeof e.table == "string" ? e.table : void 0, gr = (e, t = { kind: "all" }) => ({
2467
+ }, yr = (e) => typeof e.table == "string" ? e.table : void 0, br = (e, t = { kind: "all" }) => ({
2433
2468
  ...e,
2434
2469
  operations: e.operations.map((e) => {
2435
2470
  if (!e.blocked || e.classification !== "lossy") return e;
2436
2471
  if (t?.kind === "tables") {
2437
- let n = hr(e.op);
2472
+ let n = yr(e.op);
2438
2473
  if (n === void 0 || !t.tables.has(n)) return e;
2439
2474
  }
2440
2475
  let { blocked: n, ...r } = e;
2441
2476
  return r;
2442
2477
  })
2443
- }), _r = (e, t, n) => t === "postgres" ? st(e, n).pipe(d.flatMap((e) => {
2478
+ }), xr = (e, t, n) => t === "postgres" ? st(e, n).pipe(d.flatMap((e) => {
2444
2479
  let t = ct(e);
2445
2480
  return t === void 0 ? d.void : d.logWarning(`auto-migrate: ${t}`).pipe(d.annotateLogs({ scope: "voltro:migrate" }));
2446
- }), d.catchAll(() => d.void)) : d.void, vr = (e, t, n) => d.gen(function* () {
2447
- let r = cr(e), i = t.filter((e) => !P(e.tableName));
2481
+ }), d.catchAll(() => d.void)) : d.void, Sr = (e, t, n) => d.gen(function* () {
2482
+ let r = fr(e), i = t.filter((e) => !P(e.tableName));
2448
2483
  if (process.env.VOLTRO_MIGRATE_FORCE !== "1") {
2449
2484
  let t = j(N(i, r));
2450
- if ((yield* sr(e)) === t) return yield* _r(e, r, i), {
2485
+ if ((yield* dr(e)) === t) return yield* xr(e, r, i), {
2451
2486
  kind: "up-to-date",
2452
2487
  fingerprint: t
2453
2488
  };
2454
2489
  }
2455
- let a = yield* V(e), o = yield* fr(e, a.tables);
2490
+ let a = yield* H(e), o = yield* gr(e, a.tables);
2456
2491
  o.length > 0 && (yield* d.logInfo(`auto-migrate: reaped ${o.length} test-fixture leftover(s)`).pipe(d.annotateLogs({
2457
2492
  scope: "voltro:migrate",
2458
2493
  count: o.length
2459
- })), a = yield* V(e));
2460
- let s = Ft({
2494
+ })), a = yield* H(e));
2495
+ let s = Lt({
2461
2496
  declared: i,
2462
2497
  live: { tables: a.tables.filter((e) => !P(e.name)) },
2463
2498
  dialect: r,
2464
- ...pr()
2499
+ ..._r()
2465
2500
  });
2466
2501
  if (s.summary.blocked > 0) {
2467
- let e = s.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = mr(process.env.VOLTRO_DESTRUCTIVE_OK);
2468
- if (t === void 0 || !e || (s = gr(s, t), s.operations.some((e) => e.blocked))) return {
2502
+ let e = s.operations.filter((e) => e.blocked).every((e) => e.classification === "lossy"), t = vr(process.env.VOLTRO_DESTRUCTIVE_OK);
2503
+ if (t === void 0 || !e || (s = br(s, t), s.operations.some((e) => e.blocked))) return {
2469
2504
  kind: "refused-blocked",
2470
2505
  plan: s
2471
2506
  };
@@ -2475,27 +2510,27 @@ BEGIN
2475
2510
  fingerprint: s.toFingerprint
2476
2511
  } : {
2477
2512
  kind: "applied",
2478
- applied: yield* ar(e, s, {
2513
+ applied: yield* lr(e, s, {
2479
2514
  declared: t,
2480
2515
  appliedBy: n.appliedBy,
2481
2516
  environment: n.environment === "prod" ? "dev" : n.environment,
2482
2517
  source: "auto-diff",
2483
2518
  replan: (e) => d.gen(function* () {
2484
- let t = yield* V(e);
2485
- return Ft({
2519
+ let t = yield* H(e);
2520
+ return Lt({
2486
2521
  declared: i,
2487
2522
  live: { tables: t.tables.filter((e) => !P(e.name)) },
2488
2523
  dialect: r,
2489
- ...pr()
2524
+ ..._r()
2490
2525
  });
2491
2526
  })
2492
2527
  }),
2493
2528
  plan: s
2494
2529
  };
2495
- }), yr = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? d.succeed({
2530
+ }), Cr = (e, t, n) => process.env.VOLTRO_AUTO_MIGRATE === "0" ? d.succeed({
2496
2531
  kind: "skipped",
2497
2532
  reason: "VOLTRO_AUTO_MIGRATE=0"
2498
- }) : n.environment === "prod" ? lr(e, t) : vr(e, t, n), br = (e, t) => {
2533
+ }) : n.environment === "prod" ? pr(e, t) : Sr(e, t, n), wr = (e, t) => {
2499
2534
  switch (e.kind) {
2500
2535
  case "skipped": return `auto-migrate: skipped (${e.reason})`;
2501
2536
  case "up-to-date": return `auto-migrate: schema up to date (${t}, fingerprint=${M(e.fingerprint)})`;
@@ -2505,7 +2540,7 @@ BEGIN
2505
2540
  }
2506
2541
  case "prod-mismatch": return `auto-migrate: SCHEMA FINGERPRINT MISMATCH — declared=${M(e.expected)}` + (e.actual ? ` live=${M(e.actual)}` : " live=<no _voltro_migration_plans row>") + ". Run `voltro db apply --plan plan.json` from the deploy pipeline before serving.";
2507
2542
  case "refused-blocked": {
2508
- let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean), i = t.filter((e) => e.op.kind === "add-column").length, a = t.filter((e) => e.op.kind === "drop-column").length, o = t.filter((e) => e.classification === "needs-rename-annotation").length, s = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` + or(e.plan), c = [""];
2543
+ let t = e.plan.operations.filter((e) => e.blocked), n = t.filter((e) => e.op.kind === "drop-table").length, r = t.filter((e) => e.op.kind === "drop-table").map((e) => "table" in e.op ? e.op.table : "").filter(Boolean), i = t.filter((e) => e.op.kind === "add-column").length, a = t.filter((e) => e.op.kind === "drop-column").length, o = t.filter((e) => e.classification === "needs-rename-annotation").length, s = `auto-migrate: REFUSED — ${e.plan.summary.blocked} blocked operation(s):\n` + ur(e.plan), c = [""];
2509
2544
  if (n > 0 && c.push(`${n} table(s) exist in the live DB but aren't in your declared schema.`, "This is usually one of three things:", " (a) You're iterating on the schema — the table file got renamed, moved, or temporarily commented out.", " → Restore the declaration. Your data stays intact.", " (b) You want to KEEP the table but NOT manage it with Voltro (a leftover from another tool —", " a Strapi/Rails/legacy migration artifact, or an externally-owned table).", ` → Set \`VOLTRO_DB_IGNORE_TABLES=${r.join(",")}\` (comma-separated).`, " The planner excludes those tables from the diff entirely — it never drops them, and they", " stop blocking your OTHER (additive) changes. This is the fix when a leftover freezes your schema.", " (c) You actually want to drop the table.", ` → Set \`VOLTRO_DESTRUCTIVE_OK=${r.join(",")}\` for ONE run — it acknowledges`, " the data loss for THOSE tables only; every other lossy op in this plan stays blocked.", " (`VOLTRO_DESTRUCTIVE_OK=1` acknowledges all of them, which is rarely what you mean.)", " There is deliberately no `dropped()` marker for a TABLE, unlike for a column: a", " dropped column leaves a slot worth documenting in the declaration, a dropped table", " leaves nothing — the marker would be a dead entry you must remember to delete.", " Soft-drop: set `VOLTRO_SOFT_DROP=1` alongside DESTRUCTIVE_OK to RENAME instead of DROP", " (data survives as `<name>__dropped_<ts>` for ~7d; restorable via `voltro db restore-snapshot`)."), i > 0 && c.push(`${i} required column(s) need a backfill strategy before adding to a populated table.`, " → Annotate the column: `.backfill(sql`<expr>`)` or `.backfill(row => <fn>)` or `.default(<value>)`.", " Existing rows get the backfill value; the column then lands as NOT NULL."), a > 0) {
2510
2545
  let t = /* @__PURE__ */ new Map(), n = /* @__PURE__ */ new Map();
2511
2546
  for (let r of e.plan.operations) {
@@ -2522,7 +2557,7 @@ BEGIN
2522
2557
  return o > 0 && c.push(`${o} column(s) look like renames (one column gone + a new one of same shape appeared).`, " → On the NEW column add `.renamedFrom('<oldName>')` so the planner emits RENAME instead of DROP+ADD."), c.push("", "See `voltro db plan` for the full machine-readable diff."), s + "\n" + c.join("\n");
2523
2558
  }
2524
2559
  }
2525
- }, xr = /* @__PURE__ */ new Set([
2560
+ }, Tr = /* @__PURE__ */ new Set([
2526
2561
  "node_modules",
2527
2562
  "dist",
2528
2563
  "build",
@@ -2531,11 +2566,11 @@ BEGIN
2531
2566
  ".next",
2532
2567
  ".git",
2533
2568
  ".framework"
2534
- ]), Sr = async (e) => {
2569
+ ]), Er = async (e) => {
2535
2570
  let t = [], n = async (e) => {
2536
2571
  let r = await h.readdir(e, { withFileTypes: !0 }).catch(() => []);
2537
2572
  for (let i of r) {
2538
- if (xr.has(i.name)) continue;
2573
+ if (Tr.has(i.name)) continue;
2539
2574
  let r = g(e, i.name);
2540
2575
  i.isDirectory() ? await n(r) : i.isFile() && l.test(i.name) && t.push(r);
2541
2576
  }
@@ -2544,7 +2579,7 @@ BEGIN
2544
2579
  let n = e.split("/").pop() ?? e, r = t.split("/").pop() ?? t;
2545
2580
  return n.localeCompare(r);
2546
2581
  });
2547
- }, Cr = async (e) => {
2582
+ }, Dr = async (e) => {
2548
2583
  let t = [];
2549
2584
  for (let n of e) {
2550
2585
  let e = (await import(ee(n).href)).default;
@@ -2558,11 +2593,11 @@ BEGIN
2558
2593
  });
2559
2594
  }
2560
2595
  return t;
2561
- }, wr = (e) => e`
2596
+ }, Or = (e) => e`
2562
2597
  SELECT ${e("id")}
2563
2598
  FROM ${e("_voltro_migration_plans")}
2564
2599
  WHERE ${e("source")} = 'file'
2565
- `.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))), Tr = (e, t, n, r) => d.gen(function* () {
2600
+ `.pipe(d.map((e) => e.map((e) => e.id)), d.catchAll(() => d.succeed([]))), kr = (e, t, n, r) => d.gen(function* () {
2566
2601
  let i = Date.now(), a = (/* @__PURE__ */ new Date()).toISOString(), o = {
2567
2602
  sql: e,
2568
2603
  log: {
@@ -2595,9 +2630,9 @@ BEGIN
2595
2630
  ${r}, ${n}, ${"file"},
2596
2631
  ${c}, ${a}, ${t.migration.description})
2597
2632
  `, { durationMs: c };
2598
- }), Er = (e, t) => d.gen(function* () {
2633
+ }), Ar = (e, t) => d.gen(function* () {
2599
2634
  let n = yield* d.tryPromise({
2600
- try: () => Sr(g(t, "migrations")),
2635
+ try: () => Er(g(t, "migrations")),
2601
2636
  catch: (e) => e
2602
2637
  });
2603
2638
  if (n.length === 0) return {
@@ -2605,25 +2640,25 @@ BEGIN
2605
2640
  skipped: []
2606
2641
  };
2607
2642
  let r = yield* d.tryPromise({
2608
- try: () => Cr(n),
2643
+ try: () => Dr(n),
2609
2644
  catch: (e) => e
2610
2645
  });
2611
2646
  if (r.length === 0) return {
2612
2647
  pending: [],
2613
2648
  skipped: []
2614
2649
  };
2615
- let i = new Set(yield* wr(e));
2650
+ let i = new Set(yield* Or(e));
2616
2651
  return {
2617
2652
  pending: r.filter((e) => !i.has(e.migration.id)),
2618
2653
  skipped: r.filter((e) => i.has(e.migration.id)).map((e) => e.migration.id)
2619
2654
  };
2620
- }), Dr = (e, t) => Er(e, t).pipe(d.map((e) => e.pending.map((e) => e.migration.id))), Or = (e, t) => d.gen(function* () {
2621
- let { pending: n, skipped: r } = yield* Er(e, t.projectRoot);
2655
+ }), jr = (e, t) => Ar(e, t).pipe(d.map((e) => e.pending.map((e) => e.migration.id))), Mr = (e, t) => d.gen(function* () {
2656
+ let { pending: n, skipped: r } = yield* Ar(e, t.projectRoot);
2622
2657
  if (n.length === 0) return {
2623
2658
  applied: [],
2624
2659
  skipped: r
2625
2660
  };
2626
- yield* w(e);
2661
+ yield* C(e);
2627
2662
  let i = [];
2628
2663
  try {
2629
2664
  for (let r of n) {
@@ -2632,7 +2667,7 @@ BEGIN
2632
2667
  id: r.migration.id,
2633
2668
  file: r.file
2634
2669
  }));
2635
- let { durationMs: n } = yield* Tr(e, r, t.env, t.appliedBy);
2670
+ let { durationMs: n } = yield* kr(e, r, t.env, t.appliedBy);
2636
2671
  i.push({
2637
2672
  id: r.migration.id,
2638
2673
  durationMs: n
@@ -2643,28 +2678,28 @@ BEGIN
2643
2678
  }));
2644
2679
  }
2645
2680
  } finally {
2646
- yield* T(e).pipe(d.orDie);
2681
+ yield* w(e).pipe(d.orDie);
2647
2682
  }
2648
2683
  return {
2649
2684
  applied: i,
2650
2685
  skipped: r
2651
2686
  };
2652
- }), kr = (e, t) => e`
2687
+ }), Nr = (e, t) => e`
2653
2688
  SELECT ${e("id")}
2654
2689
  FROM ${e("_voltro_migration_plans")}
2655
2690
  WHERE ${e("id")} = ${t} AND ${e("source")} = 'file'
2656
2691
  LIMIT 1
2657
- `, Ar = (e, t) => d.gen(function* () {
2658
- if (!(yield* kr(e, t.id))[0]) return yield* d.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
2692
+ `, Pr = (e, t) => d.gen(function* () {
2693
+ if (!(yield* Nr(e, t.id))[0]) return yield* d.fail(/* @__PURE__ */ Error(`rollback: ${t.id} not found in _voltro_migration_plans (file source)`));
2659
2694
  let n = yield* d.tryPromise({
2660
- try: () => Sr(g(t.projectRoot, "migrations")),
2695
+ try: () => Er(g(t.projectRoot, "migrations")),
2661
2696
  catch: (e) => e
2662
2697
  }), r = (yield* d.tryPromise({
2663
- try: () => Cr(n),
2698
+ try: () => Dr(n),
2664
2699
  catch: (e) => e
2665
2700
  })).find((e) => e.migration.id === t.id);
2666
2701
  if (!r) return yield* d.fail(/* @__PURE__ */ Error(`rollback: file for migration ${t.id} not found on disk under ${t.projectRoot}/migrations/`));
2667
- yield* w(e);
2702
+ yield* C(e);
2668
2703
  let i = Date.now();
2669
2704
  try {
2670
2705
  let n = {
@@ -2691,9 +2726,9 @@ BEGIN
2691
2726
  durationMs: o
2692
2727
  };
2693
2728
  } finally {
2694
- yield* T(e).pipe(d.orDie);
2729
+ yield* w(e).pipe(d.orDie);
2695
2730
  }
2696
- }), jr = (e) => d.gen(function* () {
2731
+ }), Fr = (e) => d.gen(function* () {
2697
2732
  let t = yield* p.SqlClient, n = yield* t`
2698
2733
  SELECT id, fingerprint, appliedAt FROM _voltro_migration_plans
2699
2734
  WHERE source = 'auto-diff'
@@ -2738,10 +2773,10 @@ BEGIN
2738
2773
  snapshotFingerprint: e.fingerprint,
2739
2774
  snapshotId: i
2740
2775
  };
2741
- }), Mr = (e, ...t) => ({
2776
+ }), Ir = (e, ...t) => ({
2742
2777
  _tag: "RawSqlFragment",
2743
2778
  strings: [...e],
2744
2779
  values: [...t]
2745
- }), Nr = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
2780
+ }), Lr = (e) => typeof e == "object" && !!e && e._tag === "RawSqlFragment";
2746
2781
  //#endregion
2747
- export { l as FILE_MIGRATION_PATTERN, ot as REACTIVE_TRIGGER_PREFIX, C as VOLTRO_MIGRATION_LOCK_KEY, w as acquireMigrationLock, Je as applyNamespacedSchema, ar as applyPlan, He as applySchema, Ht as chunkTables, N as declaredSnapshot, ye as defaultArrayClause, ve as defaultClause, O as defaultJsonClause, br as describeOutcome, mr as destructiveScope, st as detectReactiveTriggerDrift, en as emitDropColumnDdl, tn as emitDropColumnDdlMysql, Ve as emitFrameworkBootstrapSql, ze as emitNamespaceProvisionDdl, Be as emitNamespacedSchemaSql, A as emitSchemaSql, j as fingerprintSchema, ct as formatReactiveTriggerDrift, pr as ignoreTablesFromEnv, V as introspectSchema, o as isFileMigration, Nr as isRawSqlFragment, Lt as mapPgType, s as migration, k as numericIdSql, It as parseEnumCheck, Dr as pendingFileMigrationIds, Ft as planMigrations, Ye as provisionTenantNamespace, T as releaseMigrationLock, _n as renderColumnMysql, fn as renderColumnPg, Ar as rollbackFileBasedMigration, Or as runFileBasedMigrations, Xe as runFrameworkBootstrap, qe as runMigrate, yr as runPlannedMigrations, M as shortFingerprint, nt as snapshotColumn, Mr as sql, D as sqlType, jr as squashMigrationPlans, gr as unblockLossy, ge as withMigrationLock };
2782
+ export { l as FILE_MIGRATION_PATTERN, ot as REACTIVE_TRIGGER_PREFIX, S as VOLTRO_MIGRATION_LOCK_KEY, C as acquireMigrationLock, Je as applyNamespacedSchema, lr as applyPlan, He as applySchema, Wt as chunkTables, N as declaredSnapshot, ye as defaultArrayClause, ve as defaultClause, O as defaultJsonClause, wr as describeOutcome, vr as destructiveScope, st as detectReactiveTriggerDrift, an as emitDropColumnDdl, on as emitDropColumnDdlMysql, Ve as emitFrameworkBootstrapSql, ze as emitNamespaceProvisionDdl, Be as emitNamespacedSchemaSql, A as emitSchemaSql, j as fingerprintSchema, ct as formatReactiveTriggerDrift, _r as ignoreTablesFromEnv, H as introspectSchema, o as isFileMigration, Lr as isRawSqlFragment, zt as mapPgType, s as migration, k as numericIdSql, Rt as parseEnumCheck, jr as pendingFileMigrationIds, Lt as planMigrations, Ye as provisionTenantNamespace, w as releaseMigrationLock, xn as renderColumnMysql, gn as renderColumnPg, Pr as rollbackFileBasedMigration, Mr as runFileBasedMigrations, Xe as runFrameworkBootstrap, qe as runMigrate, Cr as runPlannedMigrations, M as shortFingerprint, nt as snapshotColumn, Ir as sql, D as sqlType, Fr as squashMigrationPlans, br as unblockLossy, T as withMigrationLock };