@vibeorm/migrate 2.3.0 → 2.5.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/fs.js CHANGED
@@ -116,10 +116,10 @@ function parseMigrationMetadata(params) {
116
116
  }
117
117
 
118
118
  // packages/migrate/src/object-ownership.ts
119
- import { VibeError as VibeError6, sqlObjectKey as sqlObjectKey2, enumStorageOf as enumStorageOf2 } from "@vibeorm/schema";
119
+ import { VibeError as VibeError6, defaultPrimaryKeyName, enumStorageOf as enumStorageOf2, implicitJoinTableObjectNames, postgresGeneratedObjectName, sqlObjectKey as sqlObjectKey2 } from "@vibeorm/schema";
120
120
 
121
121
  // packages/migrate/src/normalize.ts
122
- import { VibeError as VibeError5, enumStorageOf, isEnumType as isEnumType5, unsupportedCapability as unsupportedCapability4 } from "@vibeorm/schema";
122
+ import { VibeError as VibeError5, defaultForeignKeyName, defaultIndexName, enumStorageOf, isEnumType as isEnumType5, unsupportedCapability as unsupportedCapability4 } from "@vibeorm/schema";
123
123
 
124
124
  // packages/migrate/src/relations.ts
125
125
  import { implicitJoinTable, isImplicitManyToManyRelation } from "@vibeorm/schema";
@@ -169,6 +169,49 @@ var SCALAR_TO_PG = {
169
169
  var CANONICAL_EQUIVALENTS = {
170
170
  DateTime: ["timestamptz(3)", "timestamptz(6)"]
171
171
  };
172
+ var CANONICAL_UDT = {
173
+ text: "String",
174
+ bool: "Boolean",
175
+ int4: "Int",
176
+ int8: "BigInt",
177
+ float8: "Float",
178
+ numeric: "Decimal",
179
+ timestamptz: "DateTime",
180
+ jsonb: "Json",
181
+ bytea: "Bytes"
182
+ };
183
+ var NON_CANONICAL_UDT = {
184
+ varchar: "String",
185
+ bpchar: "String",
186
+ uuid: "String",
187
+ bit: "String",
188
+ varbit: "String",
189
+ xml: "String",
190
+ inet: "String",
191
+ citext: "String",
192
+ int2: "Int",
193
+ oid: "Int",
194
+ float4: "Float",
195
+ money: "Decimal",
196
+ timestamp: "DateTime",
197
+ date: "DateTime",
198
+ time: "DateTime",
199
+ timetz: "DateTime",
200
+ json: "Json"
201
+ };
202
+ var SPELLING_TO_UDT = {
203
+ integer: "int4",
204
+ bigint: "int8",
205
+ smallint: "int2",
206
+ boolean: "bool",
207
+ doubleprecision: "float8",
208
+ real: "float4",
209
+ char: "bpchar"
210
+ };
211
+ function scalarForBuiltinType(params) {
212
+ const udt = SPELLING_TO_UDT[params.name] ?? params.name;
213
+ return CANONICAL_UDT[udt] ?? NON_CANONICAL_UDT[udt];
214
+ }
172
215
  var NATIVE_ALIASES = {
173
216
  charactervarying: "varchar",
174
217
  character: "char",
@@ -188,7 +231,11 @@ var NATIVE_ALIASES = {
188
231
  timestampwithtimezone: "timestamptz",
189
232
  timestampwithouttimezone: "timestamp",
190
233
  timewithtimezone: "timetz",
191
- timewithouttimezone: "time"
234
+ timewithouttimezone: "time",
235
+ bitvarying: "varbit"
236
+ };
237
+ var IMPLICIT_MODIFIERS = {
238
+ bit: "(1)"
192
239
  };
193
240
  function normalizeNativeType(params) {
194
241
  const compact = params.raw.toLowerCase().replace(/\s+/g, "");
@@ -196,7 +243,7 @@ function normalizeNativeType(params) {
196
243
  if (match === null)
197
244
  return compact;
198
245
  const base = NATIVE_ALIASES[match[1]] ?? match[1];
199
- return `${base}${match[2] ?? ""}${match[3] ?? ""}`;
246
+ return `${base}${match[2] ?? IMPLICIT_MODIFIERS[base] ?? ""}${match[3] ?? ""}`;
200
247
  }
201
248
  function parseUnsupportedPostgresType(params) {
202
249
  const temporal = /^\s*(time(?:stamp)?)\s*(\(\s*\d+\s*\))?\s+(with|without)\s+time\s+zone\s*((?:\[\s*\]\s*)*)$/i.exec(params.raw);
@@ -217,6 +264,11 @@ function columnTypeKey(params) {
217
264
  return `u:${field.nativeType ?? ""}`;
218
265
  const evidence = field.nativeTypeIdentity;
219
266
  const namespace = evidence !== undefined && evidence.source === field.nativeType ? evidence.namespace : parsed.namespace;
267
+ const scalar = namespace === undefined || namespace === "pg_catalog" ? scalarForBuiltinType({ name: parsed.name }) : undefined;
268
+ if (scalar !== undefined) {
269
+ const { isUnsupported: _unsupported, nativeTypeIdentity: _identity, ...rest } = field;
270
+ return columnTypeKey({ field: { ...rest, type: scalar, nativeType: `${parsed.name}${parsed.modifier ?? ""}`, isList: parsed.array || field.isList } });
271
+ }
220
272
  return `u:${JSON.stringify([namespace ?? null, parsed.name, parsed.modifier, parsed.array || field.isList])}`;
221
273
  }
222
274
  if (isEnumType(field.type)) {
@@ -305,8 +357,12 @@ function defaultFingerprint(params) {
305
357
  }
306
358
  case "enumValue":
307
359
  return `enum:${def.value}`;
308
- case "dbgenerated":
309
- return `db:${def.sql.trim()}`;
360
+ case "dbgenerated": {
361
+ const sql = def.sql.trim();
362
+ if (/^now\(\)$/i.test(sql) || /^current_timestamp(\(\d\))?$/i.test(sql))
363
+ return "now";
364
+ return `db:${sql}`;
365
+ }
310
366
  }
311
367
  }
312
368
  function defaultSql(params) {
@@ -797,8 +853,8 @@ function normalizeModel(params) {
797
853
  });
798
854
  }
799
855
  const pk = normalizePk({ model });
800
- const indexes = normalizeIndexes({ model, table });
801
- const fks = normalizeFks({ model, table, schema });
856
+ const indexes = normalizeIndexes({ model, table, dialect });
857
+ const fks = normalizeFks({ model, table, schema, dialect });
802
858
  const checks = new Map;
803
859
  for (const check of model.checks ?? [])
804
860
  checks.set(check.name, check.expression);
@@ -812,7 +868,7 @@ function normalizePk(params) {
812
868
  return model.fields.filter((field) => field.isId).map((field) => field.dbName ?? field.name);
813
869
  }
814
870
  function normalizeIndexes(params) {
815
- const { model, table } = params;
871
+ const { model, table, dialect } = params;
816
872
  const result = new Map;
817
873
  const add = (index) => {
818
874
  const unique = index.kind === "unique";
@@ -831,7 +887,7 @@ function normalizeIndexes(params) {
831
887
  const key = indexComparisonKey({ unique, kind, columns, where, nullsNotDistinct });
832
888
  if (result.has(key))
833
889
  return;
834
- const name = index.name ?? `${table}_${columns.map((column) => column.name).join("_")}_${unique ? "key" : "idx"}`;
890
+ const name = index.name ?? defaultIndexName({ table, columns: columns.map((column) => column.name), unique, dialect });
835
891
  result.set(key, {
836
892
  key,
837
893
  name,
@@ -1037,7 +1093,7 @@ function normalizeFks(params) {
1037
1093
  continue;
1038
1094
  result.set(key, {
1039
1095
  key,
1040
- constraintName: relation.constraintName ?? `${table}_${columns.join("_")}_fkey`,
1096
+ constraintName: relation.constraintName ?? defaultForeignKeyName({ table, columns, dialect: params.dialect }),
1041
1097
  columns,
1042
1098
  refTable,
1043
1099
  refColumns,
@@ -1180,7 +1236,7 @@ function removalIdentity(params) {
1180
1236
  case "dropForeignKey":
1181
1237
  return { kind: "constraint", constraintType: "foreignKey", table, name: step.constraintName };
1182
1238
  case "dropPrimaryKey":
1183
- return { kind: "constraint", constraintType: "primaryKey", table, name: step.constraintName ?? `${step.table}_pkey` };
1239
+ return { kind: "constraint", constraintType: "primaryKey", table, name: step.constraintName ?? defaultPrimaryKeyName({ table: step.table, dialect: "postgres" }) };
1184
1240
  default:
1185
1241
  return;
1186
1242
  }
@@ -1199,7 +1255,7 @@ function schemaObjectIdentities(params) {
1199
1255
  if (definition.defaultKey !== null)
1200
1256
  result.push({ kind: "columnDefault", table, column });
1201
1257
  if (params.dialect === "postgres" && definition.field.default?.kind === "autoincrement")
1202
- result.push({ kind: "sequence", name: { namespace: params.namespace, name: `${name}_${column}_seq` } });
1258
+ result.push({ kind: "sequence", name: { namespace: params.namespace, name: postgresGeneratedObjectName({ name1: name, name2: column, label: "seq" }) } });
1203
1259
  }
1204
1260
  for (const exclusion of model.model.exclusions ?? [])
1205
1261
  result.push({ kind: "constraint", constraintType: "exclusion", table, name: exclusion.name });
@@ -1213,15 +1269,15 @@ function schemaObjectIdentities(params) {
1213
1269
  for (const fk of model.fks.values())
1214
1270
  result.push({ kind: "constraint", constraintType: "foreignKey", table, name: fk.constraintName });
1215
1271
  if (model.pk.length > 0)
1216
- result.push({ kind: "constraint", constraintType: "primaryKey", table, name: model.model.primaryKeyConstraintName ?? (params.dialect === "mysql" ? "PRIMARY" : `${name}_pkey`) });
1272
+ result.push({ kind: "constraint", constraintType: "primaryKey", table, name: model.model.primaryKeyConstraintName ?? (params.dialect === "mysql" ? "PRIMARY" : defaultPrimaryKeyName({ table: name, dialect: params.dialect })) });
1217
1273
  }
1218
1274
  for (const name of normalized.joinTables.keys()) {
1219
1275
  const table = { namespace: params.namespace, name };
1220
1276
  result.push({ kind: "table", name: table });
1221
- for (const column of ["A", "B"])
1222
- result.push({ kind: "column", table, column }, { kind: "constraint", constraintType: "foreignKey", table, name: `${name}_${column}_fkey` });
1223
- for (const suffix of ["AB_unique", "B_index"])
1224
- result.push({ kind: "index", table, name: `${name}_${suffix}` });
1277
+ const derived = implicitJoinTableObjectNames({ table: name });
1278
+ result.push({ kind: "column", table, column: "A" }, { kind: "constraint", constraintType: "foreignKey", table, name: derived.foreignKeyA });
1279
+ result.push({ kind: "column", table, column: "B" }, { kind: "constraint", constraintType: "foreignKey", table, name: derived.foreignKeyB });
1280
+ result.push({ kind: "index", table, name: derived.uniqueIndex }, { kind: "index", table, name: derived.indexB });
1225
1281
  }
1226
1282
  for (const name of normalized.views.keys())
1227
1283
  result.push({ kind: "view", name: { namespace: params.namespace, name } });
@@ -1296,7 +1352,7 @@ function assertRemovalAuthorization(params) {
1296
1352
  }
1297
1353
 
1298
1354
  // packages/migrate/src/inventory.ts
1299
- import { VibeError as VibeError16, isSqlObjectIdentity as isSqlObjectIdentity2, sqlObjectKey as sqlObjectKey5 } from "@vibeorm/schema";
1355
+ import { VibeError as VibeError16, defaultForeignKeyName as defaultForeignKeyName2, defaultPrimaryKeyName as defaultPrimaryKeyName2, isSqlObjectIdentity as isSqlObjectIdentity2, sqlObjectKey as sqlObjectKey5 } from "@vibeorm/schema";
1300
1356
  import { getSqlDialect as getSqlDialect2, renderMigrationInventory, renderSqliteColumnInventory as renderSqliteColumnInventory2, renderMysqlObjectMembers as renderMysqlObjectMembers2, sqliteTableConstraints as sqliteTableConstraints3, renderSqliteForeignKeyInventory } from "@vibeorm/sql";
1301
1357
 
1302
1358
  // packages/migrate/src/exclusions.ts
@@ -2042,18 +2098,17 @@ async function introspectPostgres(params) {
2042
2098
  if (params.inTransaction !== true)
2043
2099
  await executor({ text: "BEGIN" });
2044
2100
  try {
2045
- const savedPath = params.inTransaction === true ? await executor(renderRlsReadinessQuery({ dialect: postgresDialect6, query: "readSearchPath" })) : undefined;
2046
- const searchPath = savedPath?.[0]?.searchPath;
2047
- if (params.inTransaction === true && typeof searchPath !== "string")
2101
+ const savedPath = await executor(renderRlsReadinessQuery({ dialect: postgresDialect6, query: "readSearchPath" }));
2102
+ const searchPath = savedPath[0]?.searchPath;
2103
+ if (typeof searchPath !== "string")
2048
2104
  throw new VibeError12({ code: "VIBE_MIGRATION", message: "Cannot read the migration search_path" });
2049
2105
  const matched = await verifyPostgresRls({ executor, ...params.rlsSchema === undefined ? {} : { schema: params.rlsSchema }, ...params.requireInstalledRls === undefined ? {} : { requireInstalled: params.requireInstalledRls } }).then((verified) => verified, (error) => {
2050
2106
  if (error instanceof VibeError12)
2051
2107
  throw error;
2052
2108
  throw new VibeError12({ code: "VIBE_MIGRATION", message: "Native RLS verification could not complete. Check migration privileges and supply the deployed schema as previousSchema/rlsSchema before changing referenced columns.", meta: { reason: "rls-verification-unavailable" }, cause: error });
2053
2109
  });
2110
+ await executor(renderRlsReadinessQuery({ dialect: postgresDialect6, query: "setSearchPath", searchPath }));
2054
2111
  const physical = await introspectPhysicalPostgres({ executor });
2055
- if (typeof searchPath === "string")
2056
- await executor(renderRlsReadinessQuery({ dialect: postgresDialect6, query: "setSearchPath", searchPath }));
2057
2112
  return projectPostgresRls({ physical, ...params.rlsSchema === undefined ? {} : { declared: params.rlsSchema }, matched });
2058
2113
  } finally {
2059
2114
  if (params.inTransaction !== true)
@@ -2330,27 +2385,6 @@ function buildField(params) {
2330
2385
  ...mapped.isUnsupported === true ? { isUnsupported: true } : {}
2331
2386
  };
2332
2387
  }
2333
- var CANONICAL_UDT = {
2334
- text: "String",
2335
- bool: "Boolean",
2336
- int4: "Int",
2337
- int8: "BigInt",
2338
- float8: "Float",
2339
- numeric: "Decimal",
2340
- timestamptz: "DateTime",
2341
- jsonb: "Json",
2342
- bytea: "Bytes"
2343
- };
2344
- var NON_CANONICAL_UDT = {
2345
- varchar: "String",
2346
- bpchar: "String",
2347
- uuid: "String",
2348
- int2: "Int",
2349
- float4: "Float",
2350
- timestamp: "DateTime",
2351
- date: "DateTime",
2352
- json: "Json"
2353
- };
2354
2388
  function reverseMapType(params) {
2355
2389
  const { column, enumNames } = params;
2356
2390
  const isList = column.dataType === "ARRAY";
@@ -2406,8 +2440,10 @@ function withModifier(params) {
2406
2440
  }
2407
2441
  if (udt === "bpchar")
2408
2442
  return "char";
2409
- if (udt === "timestamp" && column.datetimePrecision !== null && column.datetimePrecision !== 6) {
2410
- return `timestamp(${column.datetimePrecision})`;
2443
+ if ((udt === "bit" || udt === "varbit") && column.charMaxLength !== null)
2444
+ return `${udt}(${column.charMaxLength})`;
2445
+ if ((udt === "timestamp" || udt === "time" || udt === "timetz") && column.datetimePrecision !== null && column.datetimePrecision !== 6) {
2446
+ return `${udt}(${column.datetimePrecision})`;
2411
2447
  }
2412
2448
  return udt;
2413
2449
  }
@@ -4157,7 +4193,7 @@ async function inspectMigrationInventory(params) {
4157
4193
  for (const constraint of clauses) {
4158
4194
  if (constraint.type === "check")
4159
4195
  continue;
4160
- const name = constraint.named ? constraint.name : constraint.type === "primaryKey" ? `${qualified.name}_pkey` : constraint.type === "foreignKey" ? `${qualified.name}_${constraint.columns.join("_")}_fkey` : constraint.name;
4196
+ const name = constraint.named ? constraint.name : constraint.type === "primaryKey" ? defaultPrimaryKeyName2({ table: qualified.name, dialect: "sqlite" }) : constraint.type === "foreignKey" ? defaultForeignKeyName2({ table: qualified.name, columns: constraint.columns, dialect: "sqlite" }) : constraint.name;
4161
4197
  objects.push({ identity: { kind: "constraint", constraintType: constraint.type, table: qualified, name }, ...constraint.type === "unique" && !constraint.named ? { inspectionUnavailable: "sqlite-anonymous-unique-constraint" } : {} });
4162
4198
  }
4163
4199
  const checks = parseSqliteNamedChecks({ tableSql: row.definition });
@@ -4168,7 +4204,7 @@ async function inspectMigrationInventory(params) {
4168
4204
  const query = renderSqliteColumnInventory2({ dialect: getSqlDialect2({ dialect: params.dialect }), namespace: params.namespace, table: name });
4169
4205
  const columns = await params.executor({ text: query.text, values: [...query.values] });
4170
4206
  if (columns.some((column) => Number(column.pk) > 0) && !clauses.some((clause) => clause.type === "primaryKey"))
4171
- objects.push({ identity: { kind: "constraint", constraintType: "primaryKey", table: qualified, name: `${qualified.name}_pkey` } });
4207
+ objects.push({ identity: { kind: "constraint", constraintType: "primaryKey", table: qualified, name: defaultPrimaryKeyName2({ table: qualified.name, dialect: "sqlite" }) } });
4172
4208
  const fkQuery = renderSqliteForeignKeyInventory({ dialect: getSqlDialect2({ dialect: params.dialect }), namespace: params.namespace, table: name });
4173
4209
  const foreignKeys = await params.executor({ text: fkQuery.text, values: [...fkQuery.values] });
4174
4210
  const groups = new Map;
@@ -4177,7 +4213,7 @@ async function inspectMigrationInventory(params) {
4177
4213
  for (const fields of groups.values()) {
4178
4214
  if (clauses.some((clause) => clause.type === "foreignKey" && JSON.stringify(clause.columns) === JSON.stringify(fields)))
4179
4215
  continue;
4180
- objects.push({ identity: { kind: "constraint", constraintType: "foreignKey", table: qualified, name: `${qualified.name}_${fields.join("_")}_fkey` }, inspectionUnavailable: "sqlite-inline-foreign-key-definition-unavailable" });
4216
+ objects.push({ identity: { kind: "constraint", constraintType: "foreignKey", table: qualified, name: defaultForeignKeyName2({ table: qualified.name, columns: fields, dialect: "sqlite" }) }, inspectionUnavailable: "sqlite-inline-foreign-key-definition-unavailable" });
4181
4217
  }
4182
4218
  for (const column of columns) {
4183
4219
  objects.push({ identity: { kind: "column", table: qualified, column: String(column.name) } });
@@ -5638,7 +5674,7 @@ import { VibeError as VibeError31, sqlObjectKey as sqlObjectKey9 } from "@vibeor
5638
5674
 
5639
5675
  // packages/migrate/src/ddl/postgres.ts
5640
5676
  import { renderExclusionSetup } from "@vibeorm/sql";
5641
- import { VibeError as VibeError28, isEnumType as isEnumType7 } from "@vibeorm/schema";
5677
+ import { VibeError as VibeError28, defaultPrimaryKeyName as defaultPrimaryKeyName3, implicitJoinTableObjectNames as implicitJoinTableObjectNames2, isEnumType as isEnumType7 } from "@vibeorm/schema";
5642
5678
  import { postgresDialect as postgresDialect8, renderRlsPolicyPath } from "@vibeorm/sql";
5643
5679
  function renderPostgresSteps(params) {
5644
5680
  refuseSameTransactionEnumUse({ steps: params.steps });
@@ -5710,7 +5746,7 @@ function renderStep(params) {
5710
5746
  const lines = step.columns.map((column) => ` ${columnDefSql({ field: column })}`);
5711
5747
  if (step.primaryKey.length > 0) {
5712
5748
  const pkCols = step.primaryKey.map((column) => q2(column)).join(", ");
5713
- lines.push(` CONSTRAINT ${q2(step.primaryKeyConstraintName ?? `${step.table}_pkey`)} PRIMARY KEY (${pkCols})`);
5749
+ lines.push(` CONSTRAINT ${q2(step.primaryKeyConstraintName ?? defaultPrimaryKeyName3({ table: step.table, dialect: "postgres" }))} PRIMARY KEY (${pkCols})`);
5714
5750
  }
5715
5751
  for (const check of step.checks ?? []) {
5716
5752
  lines.push(` CONSTRAINT ${q2(check.name)} CHECK (${check.expression})`);
@@ -5783,25 +5819,26 @@ ${lines.join(`,
5783
5819
  case "createJoinTable": {
5784
5820
  const aType = columnTypeSql({ field: { ...step.a.field, isList: false } });
5785
5821
  const bType = columnTypeSql({ field: { ...step.b.field, isList: false } });
5822
+ const names = implicitJoinTableObjectNames2({ table: step.table });
5786
5823
  return [
5787
5824
  `CREATE TABLE ${publicName(step.table)} (
5788
5825
  "A" ${aType} NOT NULL,
5789
5826
  "B" ${bType} NOT NULL
5790
5827
  );`,
5791
- `CREATE UNIQUE INDEX ${q2(`${step.table}_AB_unique`)} ON ${publicName(step.table)} ("A", "B");`,
5792
- `CREATE INDEX ${q2(`${step.table}_B_index`)} ON ${publicName(step.table)} ("B");`,
5793
- `ALTER TABLE ${publicName(step.table)} ADD CONSTRAINT ${q2(`${step.table}_A_fkey`)} FOREIGN KEY ("A") REFERENCES ${publicName(step.a.table)} (${q2(step.a.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`,
5794
- `ALTER TABLE ${publicName(step.table)} ADD CONSTRAINT ${q2(`${step.table}_B_fkey`)} FOREIGN KEY ("B") REFERENCES ${publicName(step.b.table)} (${q2(step.b.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`
5828
+ `CREATE UNIQUE INDEX ${q2(names.uniqueIndex)} ON ${publicName(step.table)} ("A", "B");`,
5829
+ `CREATE INDEX ${q2(names.indexB)} ON ${publicName(step.table)} ("B");`,
5830
+ `ALTER TABLE ${publicName(step.table)} ADD CONSTRAINT ${q2(names.foreignKeyA)} FOREIGN KEY ("A") REFERENCES ${publicName(step.a.table)} (${q2(step.a.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`,
5831
+ `ALTER TABLE ${publicName(step.table)} ADD CONSTRAINT ${q2(names.foreignKeyB)} FOREIGN KEY ("B") REFERENCES ${publicName(step.b.table)} (${q2(step.b.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`
5795
5832
  ];
5796
5833
  }
5797
5834
  case "addPrimaryKey": {
5798
5835
  const cols = step.columns.map((column) => q2(column)).join(", ");
5799
5836
  return [
5800
- `ALTER TABLE ${publicName(step.table)} ADD CONSTRAINT ${q2(step.constraintName ?? `${step.table}_pkey`)} PRIMARY KEY (${cols});`
5837
+ `ALTER TABLE ${publicName(step.table)} ADD CONSTRAINT ${q2(step.constraintName ?? defaultPrimaryKeyName3({ table: step.table, dialect: "postgres" }))} PRIMARY KEY (${cols});`
5801
5838
  ];
5802
5839
  }
5803
5840
  case "dropPrimaryKey":
5804
- return [`ALTER TABLE ${publicName(step.table)} DROP CONSTRAINT ${q2(step.constraintName ?? `${step.table}_pkey`)};`];
5841
+ return [`ALTER TABLE ${publicName(step.table)} DROP CONSTRAINT ${q2(step.constraintName ?? defaultPrimaryKeyName3({ table: step.table, dialect: "postgres" }))};`];
5805
5842
  }
5806
5843
  }
5807
5844
  function columnDefSql(params) {
@@ -5863,7 +5900,7 @@ function q2(name) {
5863
5900
  }
5864
5901
 
5865
5902
  // packages/migrate/src/ddl/sqlite.ts
5866
- import { VibeError as VibeError29, isEnumType as isEnumType8, unsupportedCapability as unsupportedCapability7 } from "@vibeorm/schema";
5903
+ import { VibeError as VibeError29, implicitJoinTableObjectNames as implicitJoinTableObjectNames3, isEnumType as isEnumType8, unsupportedCapability as unsupportedCapability7 } from "@vibeorm/schema";
5867
5904
  import { sqliteDialect as sqliteDialect3 } from "@vibeorm/sql";
5868
5905
 
5869
5906
  // packages/migrate/src/ddl/drop-order.ts
@@ -6061,12 +6098,13 @@ function renderSqliteSteps(params) {
6061
6098
  case "createJoinTable": {
6062
6099
  const aType = sqliteStorageType({ field: { ...step.a.field, isList: false } });
6063
6100
  const bType = sqliteStorageType({ field: { ...step.b.field, isList: false } });
6101
+ const names = implicitJoinTableObjectNames3({ table: step.table });
6064
6102
  statements.push(`CREATE TABLE ${q3(step.table)} (
6065
6103
  "A" ${aType} NOT NULL,
6066
6104
  "B" ${bType} NOT NULL,
6067
- CONSTRAINT ${q3(`${step.table}_A_fkey`)} FOREIGN KEY ("A") REFERENCES ${q3(step.a.table)} (${q3(step.a.column)}) ON DELETE CASCADE ON UPDATE CASCADE,
6068
- CONSTRAINT ${q3(`${step.table}_B_fkey`)} FOREIGN KEY ("B") REFERENCES ${q3(step.b.table)} (${q3(step.b.column)}) ON DELETE CASCADE ON UPDATE CASCADE
6069
- );`, `CREATE UNIQUE INDEX ${q3(`${step.table}_AB_unique`)} ON ${q3(step.table)} ("A", "B");`, `CREATE INDEX ${q3(`${step.table}_B_index`)} ON ${q3(step.table)} ("B");`);
6105
+ CONSTRAINT ${q3(names.foreignKeyA)} FOREIGN KEY ("A") REFERENCES ${q3(step.a.table)} (${q3(step.a.column)}) ON DELETE CASCADE ON UPDATE CASCADE,
6106
+ CONSTRAINT ${q3(names.foreignKeyB)} FOREIGN KEY ("B") REFERENCES ${q3(step.b.table)} (${q3(step.b.column)}) ON DELETE CASCADE ON UPDATE CASCADE
6107
+ );`, `CREATE UNIQUE INDEX ${q3(names.uniqueIndex)} ON ${q3(step.table)} ("A", "B");`, `CREATE INDEX ${q3(names.indexB)} ON ${q3(step.table)} ("B");`);
6070
6108
  break;
6071
6109
  }
6072
6110
  case "addColumn":
@@ -6432,7 +6470,7 @@ function q3(name) {
6432
6470
  }
6433
6471
 
6434
6472
  // packages/migrate/src/ddl/mysql.ts
6435
- import { VibeError as VibeError30, unsupportedCapability as unsupportedCapability8 } from "@vibeorm/schema";
6473
+ import { VibeError as VibeError30, implicitJoinTableObjectNames as implicitJoinTableObjectNames4, unsupportedCapability as unsupportedCapability8 } from "@vibeorm/schema";
6436
6474
  import { mysqlDialect as mysqlDialect3 } from "@vibeorm/sql";
6437
6475
  function renderMysqlSteps(params) {
6438
6476
  for (const step of params.steps) {
@@ -6611,15 +6649,16 @@ ${lines.join(`,
6611
6649
  case "createJoinTable": {
6612
6650
  const aType = mysqlColumnTypeSql({ field: { ...step.a.field, isList: false }, enums });
6613
6651
  const bType = mysqlColumnTypeSql({ field: { ...step.b.field, isList: false }, enums });
6652
+ const names = implicitJoinTableObjectNames4({ table: step.table });
6614
6653
  return [
6615
6654
  `CREATE TABLE ${q4(step.table)} (
6616
6655
  \`A\` ${aType} NOT NULL,
6617
6656
  \`B\` ${bType} NOT NULL
6618
6657
  );`,
6619
- `CREATE UNIQUE INDEX ${q4(`${step.table}_AB_unique`)} ON ${q4(step.table)} (\`A\`, \`B\`);`,
6620
- `CREATE INDEX ${q4(`${step.table}_B_index`)} ON ${q4(step.table)} (\`B\`);`,
6621
- `ALTER TABLE ${q4(step.table)} ADD CONSTRAINT ${q4(`${step.table}_A_fkey`)} FOREIGN KEY (\`A\`) REFERENCES ${q4(step.a.table)} (${q4(step.a.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`,
6622
- `ALTER TABLE ${q4(step.table)} ADD CONSTRAINT ${q4(`${step.table}_B_fkey`)} FOREIGN KEY (\`B\`) REFERENCES ${q4(step.b.table)} (${q4(step.b.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`
6658
+ `CREATE UNIQUE INDEX ${q4(names.uniqueIndex)} ON ${q4(step.table)} (\`A\`, \`B\`);`,
6659
+ `CREATE INDEX ${q4(names.indexB)} ON ${q4(step.table)} (\`B\`);`,
6660
+ `ALTER TABLE ${q4(step.table)} ADD CONSTRAINT ${q4(names.foreignKeyA)} FOREIGN KEY (\`A\`) REFERENCES ${q4(step.a.table)} (${q4(step.a.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`,
6661
+ `ALTER TABLE ${q4(step.table)} ADD CONSTRAINT ${q4(names.foreignKeyB)} FOREIGN KEY (\`B\`) REFERENCES ${q4(step.b.table)} (${q4(step.b.column)}) ON DELETE CASCADE ON UPDATE CASCADE;`
6623
6662
  ];
6624
6663
  }
6625
6664
  case "addPrimaryKey":
@@ -6756,6 +6795,7 @@ function collectExtensionArtifacts(params) {
6756
6795
  const { schema, dialect, extensions } = params;
6757
6796
  const setup = [];
6758
6797
  const objects = [];
6798
+ const groups = [];
6759
6799
  for (const extension of extensions) {
6760
6800
  const artifactsHook = extension.migrate?.artifacts;
6761
6801
  if (artifactsHook === undefined)
@@ -6763,6 +6803,7 @@ function collectExtensionArtifacts(params) {
6763
6803
  const declarations = extensionDeclarations({ schema, name: extension.name });
6764
6804
  if (Object.keys(declarations).length === 0 && extension.schema?.configOnly !== true)
6765
6805
  continue;
6806
+ const contributed = [];
6766
6807
  for (const artifact of artifactsHook({
6767
6808
  schema,
6768
6809
  dialect,
@@ -6770,10 +6811,19 @@ function collectExtensionArtifacts(params) {
6770
6811
  options: extension.options,
6771
6812
  declarations
6772
6813
  })) {
6773
- (artifact.owns.kind === "postgresExtension" ? setup : objects).push(artifact);
6814
+ if (artifact.owns.kind === "postgresExtension")
6815
+ setup.push(artifact);
6816
+ else {
6817
+ objects.push(artifact);
6818
+ contributed.push(artifact);
6819
+ }
6774
6820
  }
6821
+ groups.push({ extension: extension.name, objects: contributed });
6775
6822
  }
6776
- return { setup, objects };
6823
+ return { setup, objects, groups };
6824
+ }
6825
+ function lastDeclaredSchema(params) {
6826
+ return [...params.migrations].reverse().find((migration) => migration.desiredState !== undefined)?.desiredState?.to.schema;
6777
6827
  }
6778
6828
  function ownedTableNames(params) {
6779
6829
  const exact = new Set;
@@ -6875,6 +6925,36 @@ async function probeInstalledExtensionState(params) {
6875
6925
  function artifactCreateSql(params) {
6876
6926
  return params.artifacts.flatMap((artifact) => [...artifact.create]);
6877
6927
  }
6928
+ function planChangedArtifacts(params) {
6929
+ const previousById = new Map((params.previous?.objects ?? []).map((artifact) => [artifact.id, artifact]));
6930
+ const probedIds = new Set((params.probed ?? []).map((artifact) => artifact.id));
6931
+ const missingIds = new Set(params.missing.map((artifact) => artifact.id));
6932
+ const rebuilt = new Set;
6933
+ for (const group of params.current.groups) {
6934
+ const changed = group.objects.filter((artifact) => {
6935
+ if (missingIds.has(artifact.id))
6936
+ return false;
6937
+ if (probedIds.has(artifact.id))
6938
+ return true;
6939
+ const before = previousById.get(artifact.id);
6940
+ return before !== undefined && JSON.stringify(before.owns) === JSON.stringify(artifact.owns) && JSON.stringify(before.create) !== JSON.stringify(artifact.create);
6941
+ });
6942
+ if (changed.length === 0)
6943
+ continue;
6944
+ const rebuiltColumnTables = new Set(changed.flatMap((artifact) => artifact.owns.kind === "column" ? [artifact.owns.table] : []));
6945
+ for (const artifact of group.objects) {
6946
+ if (missingIds.has(artifact.id))
6947
+ continue;
6948
+ const dependent = (artifact.owns.kind === "index" || artifact.owns.kind === "trigger") && rebuiltColumnTables.has(artifact.owns.table);
6949
+ if (changed.includes(artifact) || dependent)
6950
+ rebuilt.add(artifact.id);
6951
+ }
6952
+ }
6953
+ return params.current.objects.filter((artifact) => rebuilt.has(artifact.id));
6954
+ }
6955
+ function artifactDropSql(params) {
6956
+ return [...params.artifacts].reverse().flatMap((artifact) => [...artifact.drop]);
6957
+ }
6878
6958
  // packages/migrate/src/runner.ts
6879
6959
  function migrationRlsSecurityChanges(params) {
6880
6960
  const source = params.migration.rls;
@@ -7025,6 +7105,7 @@ function generateMigration(params) {
7025
7105
  extensions: params.extensions ?? []
7026
7106
  });
7027
7107
  const allArtifacts = [...artifacts.setup, ...artifacts.objects];
7108
+ const rebuilt = planChangedArtifacts({ previous: collectExtensionArtifacts({ schema: from, dialect, extensions: params.extensions ?? [] }), current: artifacts, missing: [] });
7028
7109
  assertRetainedMigrationObjects({ from: from.migrationObjects ?? [], to: to.migrationObjects ?? [] });
7029
7110
  const strippedFrom = preserveMigrationObjects({ from: stripExtensionArtifacts({ schema: from, artifacts: allArtifacts }), to, objects: [...from.migrationObjects ?? [], ...to.migrationObjects ?? []] });
7030
7111
  const steps = diffSchemas({ from: strippedFrom, to, dialect, ...params.renames === undefined ? {} : { renames: params.renames } });
@@ -7035,6 +7116,7 @@ function generateMigration(params) {
7035
7116
  artifacts: missing.filter((artifact) => artifact.owns.kind === "postgresExtension")
7036
7117
  }),
7037
7118
  ...coreSql,
7119
+ ...artifactDropSql({ artifacts: rebuilt }),
7038
7120
  ...artifactCreateSql({
7039
7121
  artifacts: missing.filter((artifact) => artifact.owns.kind !== "postgresExtension")
7040
7122
  }),
@@ -8020,4 +8102,4 @@ export {
8020
8102
  splitSqlStatements
8021
8103
  };
8022
8104
 
8023
- //# debugId=F0D645556CA0676064756E2164756E21
8105
+ //# debugId=B0F3289A0E0F6E5B64756E2164756E21