@vibeorm/migrate 2.6.0 → 2.7.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
@@ -172,6 +172,9 @@ var SCALAR_TO_PG = {
172
172
  var CANONICAL_EQUIVALENTS = {
173
173
  DateTime: ["timestamptz(3)", "timestamptz(6)"]
174
174
  };
175
+ var EXACT_CANONICAL_EQUIVALENTS = {
176
+ DateTime: ["timestamptz(6)"]
177
+ };
175
178
  var CANONICAL_UDT = {
176
179
  text: "String",
177
180
  bool: "Boolean",
@@ -240,13 +243,15 @@ var NATIVE_ALIASES = {
240
243
  var IMPLICIT_MODIFIERS = {
241
244
  bit: "(1)"
242
245
  };
246
+ var DEFAULT_PRECISION_SIX = new Set(["timestamp", "time", "timetz"]);
243
247
  function normalizeNativeType(params) {
244
248
  const compact = params.raw.toLowerCase().replace(/\s+/g, "");
245
249
  const match = compact.match(/^([a-z_0-9]+)(\(.*\))?(\[\])?$/);
246
250
  if (match === null)
247
251
  return compact;
248
252
  const base = NATIVE_ALIASES[match[1]] ?? match[1];
249
- return `${base}${match[2] ?? IMPLICIT_MODIFIERS[base] ?? ""}${match[3] ?? ""}`;
253
+ const modifier = DEFAULT_PRECISION_SIX.has(base) && match[2] === "(6)" ? "" : match[2] ?? IMPLICIT_MODIFIERS[base] ?? "";
254
+ return `${base}${modifier}${match[3] ?? ""}`;
250
255
  }
251
256
  function parseUnsupportedPostgresType(params) {
252
257
  const temporal = /^\s*(time(?:stamp)?)\s*(\(\s*\d+\s*\))?\s+(with|without)\s+time\s+zone\s*((?:\[\s*\]\s*)*)$/i.exec(params.raw);
@@ -259,7 +264,7 @@ function parseUnsupportedPostgresType(params) {
259
264
  return NATIVE_ALIASES[base] === undefined ? undefined : parsePostgresTypeName({ raw: normalizeNativeType(params) });
260
265
  }
261
266
  function columnTypeKey(params) {
262
- const { field } = params;
267
+ const { field, exact } = params;
263
268
  const listSuffix = field.isList ? "[]" : "";
264
269
  if (field.isUnsupported === true) {
265
270
  const parsed = parseUnsupportedPostgresType({ raw: field.nativeType ?? "" });
@@ -270,7 +275,7 @@ function columnTypeKey(params) {
270
275
  const scalar = namespace === undefined || namespace === "pg_catalog" ? scalarForBuiltinType({ name: parsed.name }) : undefined;
271
276
  if (scalar !== undefined) {
272
277
  const { isUnsupported: _unsupported, nativeTypeIdentity: _identity, ...rest } = field;
273
- return columnTypeKey({ field: { ...rest, type: scalar, nativeType: `${parsed.name}${parsed.modifier ?? ""}`, isList: parsed.array || field.isList } });
278
+ return columnTypeKey({ field: { ...rest, type: scalar, nativeType: `${parsed.name}${parsed.modifier ?? ""}`, isList: parsed.array || field.isList }, ...exact === undefined ? {} : { exact } });
274
279
  }
275
280
  return `u:${JSON.stringify([namespace ?? null, parsed.name, parsed.modifier, parsed.array || field.isList])}`;
276
281
  }
@@ -281,12 +286,37 @@ function columnTypeKey(params) {
281
286
  if (field.nativeType !== undefined) {
282
287
  const normalized = normalizeNativeType({ raw: field.nativeType });
283
288
  const canonical = normalizeNativeType({ raw: SCALAR_TO_PG[field.type] });
284
- const isCanonical = normalized === canonical || (CANONICAL_EQUIVALENTS[field.type]?.includes(normalized) ?? false);
289
+ const equivalents = exact === true ? EXACT_CANONICAL_EQUIVALENTS : CANONICAL_EQUIVALENTS;
290
+ const isCanonical = normalized === canonical || (equivalents[field.type]?.includes(normalized) ?? false);
285
291
  if (!isCanonical)
286
292
  return `n:${normalized}${listSuffix}`;
287
293
  }
288
294
  return `s:${field.type}${listSuffix}`;
289
295
  }
296
+ function declaresExactColumnType(params) {
297
+ const { field } = params;
298
+ if (field.isUnsupported === true || field.nativeType === undefined || isEnumType(field.type))
299
+ return false;
300
+ return CANONICAL_EQUIVALENTS[field.type]?.includes(normalizeNativeType({ raw: field.nativeType })) ?? false;
301
+ }
302
+ function timestamptzPrecision(params) {
303
+ const { field } = params;
304
+ if (field.type !== "DateTime" || field.isUnsupported === true)
305
+ return;
306
+ const normalized = field.nativeType === undefined ? "timestamptz" : normalizeNativeType({ raw: field.nativeType });
307
+ if (normalized === "timestamptz")
308
+ return 6;
309
+ const match = /^timestamptz\((\d)\)$/.exec(normalized);
310
+ return match === null ? undefined : Number(match[1]);
311
+ }
312
+ function isTimestamptzPrecisionWidening(params) {
313
+ const { from, to } = params;
314
+ if (from.isList !== to.isList)
315
+ return false;
316
+ const before = timestamptzPrecision({ field: from });
317
+ const after = timestamptzPrecision({ field: to });
318
+ return before !== undefined && after !== undefined && after >= before;
319
+ }
290
320
  function isScalarToArrayChange(params) {
291
321
  const { from, to } = params;
292
322
  if (from.isList || !to.isList)
@@ -829,16 +859,20 @@ function assertStringEnumLabelsFit(params) {
829
859
  }
830
860
  }
831
861
  function columnTypeKeyFor(params) {
832
- const { field, dialect, enums } = params;
862
+ const { field, dialect, enums, exact } = params;
833
863
  switch (dialect) {
834
864
  case "postgres":
835
- return columnTypeKey({ field });
865
+ return columnTypeKey({ field, ...exact === undefined ? {} : { exact } });
836
866
  case "sqlite":
837
867
  return sqliteColumnTypeKey({ field, enums });
838
868
  case "mysql":
839
869
  return mysqlColumnTypeKey({ field, enums });
840
870
  }
841
871
  }
872
+ function columnTypeChanged(params) {
873
+ const { declared, actual } = params;
874
+ return declared.pinsExactType ? declared.exactTypeKey !== actual.exactTypeKey : declared.typeKey !== actual.typeKey;
875
+ }
842
876
  function defaultFingerprintFor(params) {
843
877
  const { field, dialect } = params;
844
878
  switch (dialect) {
@@ -861,6 +895,8 @@ function normalizeModel(params) {
861
895
  name,
862
896
  field,
863
897
  typeKey: columnTypeKeyFor({ field, dialect, enums }),
898
+ exactTypeKey: columnTypeKeyFor({ field, dialect, enums, exact: true }),
899
+ pinsExactType: dialect === "postgres" && declaresExactColumnType({ field }),
864
900
  nullable: field.isOptional,
865
901
  defaultKey: defaultFingerprintFor({ field, dialect })
866
902
  });
@@ -2720,8 +2756,9 @@ function reverseMapType(params) {
2720
2756
  function nonCanonicalModifier(params) {
2721
2757
  const { column, udt, scalar } = params;
2722
2758
  if (column.dataType === "ARRAY" && column.fullType !== null) {
2723
- const element = normalizeNativeType({ raw: column.fullType }).replace(/\[\]$/, "");
2724
- if (/^(numeric|timestamptz)\([\d,]+\)$/.test(element))
2759
+ const temporal = parseUnsupportedPostgresType({ raw: column.fullType });
2760
+ const element = temporal?.name === "timestamptz" ? `timestamptz${temporal.modifier}` : normalizeNativeType({ raw: column.fullType }).replace(/\[\]$/, "");
2761
+ if (element !== "timestamptz(6)" && /^(numeric|timestamptz)\([\d,]+\)$/.test(element))
2725
2762
  return element;
2726
2763
  }
2727
2764
  if (scalar === "DateTime" && udt === "timestamptz") {
@@ -2738,9 +2775,9 @@ function nonCanonicalModifier(params) {
2738
2775
  }
2739
2776
  function withModifier(params) {
2740
2777
  const { column, udt } = params;
2741
- if (udt === "varchar" && column.dataType === "ARRAY" && column.fullType !== null) {
2778
+ if ((udt === "varchar" || udt === "bpchar" || udt === "bit" || udt === "varbit") && column.dataType === "ARRAY" && column.fullType !== null) {
2742
2779
  const elementType = normalizeNativeType({ raw: column.fullType }).replace(/\[\]$/, "");
2743
- if (/^varchar\(\d+\)$/.test(elementType))
2780
+ if (/^(varchar|char|bit|varbit)\(\d+\)$/.test(elementType))
2744
2781
  return elementType;
2745
2782
  }
2746
2783
  if ((udt === "varchar" || udt === "bpchar") && column.charMaxLength !== null) {
@@ -2750,6 +2787,10 @@ function withModifier(params) {
2750
2787
  return "char";
2751
2788
  if ((udt === "bit" || udt === "varbit") && column.charMaxLength !== null)
2752
2789
  return `${udt}(${column.charMaxLength})`;
2790
+ if ((udt === "timestamp" || udt === "time" || udt === "timetz") && column.dataType === "ARRAY" && column.fullType !== null) {
2791
+ const element = parseUnsupportedPostgresType({ raw: column.fullType });
2792
+ return element === undefined || element.modifier === "" || element.modifier === "(6)" ? udt : `${udt}${element.modifier}`;
2793
+ }
2753
2794
  if ((udt === "timestamp" || udt === "time" || udt === "timetz") && column.datetimePrecision !== null && column.datetimePrecision !== 6) {
2754
2795
  return `${udt}(${column.datetimePrecision})`;
2755
2796
  }
@@ -4248,7 +4289,8 @@ async function verifySchemaObjects(params) {
4248
4289
  pin("primaryKey", desired.pk, live.pk);
4249
4290
  for (const [column, field] of desired.columns) {
4250
4291
  const stored = live.columns.get(column);
4251
- pin(`columns.${column}.type`, field.typeKey, stored?.typeKey);
4292
+ const exactType = field.pinsExactType;
4293
+ pin(`columns.${column}.type`, exactType ? field.exactTypeKey : field.typeKey, exactType ? stored?.exactTypeKey : stored?.typeKey);
4252
4294
  pin(`columns.${column}.nullable`, field.nullable, stored?.nullable);
4253
4295
  if (params.dialect === "mysql" && field.field.collation !== undefined) {
4254
4296
  pin(`columns.${column}.collation`, field.field.collation.toLowerCase(), stored?.field.collation?.toLowerCase());
@@ -6044,7 +6086,7 @@ function diffOneTable(params) {
6044
6086
  continue;
6045
6087
  }
6046
6088
  const changes = [];
6047
- if (before.typeKey !== column.typeKey)
6089
+ if (columnTypeChanged({ declared: column, actual: before }))
6048
6090
  changes.push("type");
6049
6091
  if (before.nullable !== column.nullable)
6050
6092
  changes.push("nullability");
@@ -6067,7 +6109,7 @@ function diffOneTable(params) {
6067
6109
  assertStringEnumLabelsFit({ field: column.field, values, dialect, table });
6068
6110
  }
6069
6111
  }
6070
- let narrowingType = changes.includes("type") && !isScalarToArrayChange({ from: before.field, to: column.field }) && !(storageChange && column.field.type === "String");
6112
+ let narrowingType = changes.includes("type") && !isScalarToArrayChange({ from: before.field, to: column.field }) && !(dialect === "postgres" && isTimestamptzPrecisionWidening({ from: before.field, to: column.field })) && !(storageChange && column.field.type === "String");
6071
6113
  if (dialect !== "postgres" && changes.includes("type") && isEnumType6(before.field.type) && isEnumType6(column.field.type)) {
6072
6114
  const fromValues = resolveEnumValues({ name: before.field.type.enum, enums: fromEnums });
6073
6115
  const toValues = resolveEnumValues({ name: column.field.type.enum, enums: toEnums });
@@ -8701,4 +8743,4 @@ export {
8701
8743
  splitSqlStatements
8702
8744
  };
8703
8745
 
8704
- //# debugId=91A1E2329350564C64756E2164756E21
8746
+ //# debugId=000F8CFDEDF957F264756E2164756E21