@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 +56 -14
- package/dist/fs.js.map +7 -7
- package/dist/index.js +56 -14
- package/dist/index.js.map +7 -7
- package/dist/inspect-objects.d.ts.map +1 -1
- package/dist/normalize.d.ts +19 -1
- package/dist/normalize.d.ts.map +1 -1
- package/dist/postgres-types.d.ts +24 -0
- package/dist/postgres-types.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -233,6 +233,9 @@ var SCALAR_TO_PG = {
|
|
|
233
233
|
var CANONICAL_EQUIVALENTS = {
|
|
234
234
|
DateTime: ["timestamptz(3)", "timestamptz(6)"]
|
|
235
235
|
};
|
|
236
|
+
var EXACT_CANONICAL_EQUIVALENTS = {
|
|
237
|
+
DateTime: ["timestamptz(6)"]
|
|
238
|
+
};
|
|
236
239
|
var CANONICAL_UDT = {
|
|
237
240
|
text: "String",
|
|
238
241
|
bool: "Boolean",
|
|
@@ -301,13 +304,15 @@ var NATIVE_ALIASES = {
|
|
|
301
304
|
var IMPLICIT_MODIFIERS = {
|
|
302
305
|
bit: "(1)"
|
|
303
306
|
};
|
|
307
|
+
var DEFAULT_PRECISION_SIX = new Set(["timestamp", "time", "timetz"]);
|
|
304
308
|
function normalizeNativeType(params) {
|
|
305
309
|
const compact = params.raw.toLowerCase().replace(/\s+/g, "");
|
|
306
310
|
const match = compact.match(/^([a-z_0-9]+)(\(.*\))?(\[\])?$/);
|
|
307
311
|
if (match === null)
|
|
308
312
|
return compact;
|
|
309
313
|
const base = NATIVE_ALIASES[match[1]] ?? match[1];
|
|
310
|
-
|
|
314
|
+
const modifier = DEFAULT_PRECISION_SIX.has(base) && match[2] === "(6)" ? "" : match[2] ?? IMPLICIT_MODIFIERS[base] ?? "";
|
|
315
|
+
return `${base}${modifier}${match[3] ?? ""}`;
|
|
311
316
|
}
|
|
312
317
|
function parseUnsupportedPostgresType(params) {
|
|
313
318
|
const temporal = /^\s*(time(?:stamp)?)\s*(\(\s*\d+\s*\))?\s+(with|without)\s+time\s+zone\s*((?:\[\s*\]\s*)*)$/i.exec(params.raw);
|
|
@@ -320,7 +325,7 @@ function parseUnsupportedPostgresType(params) {
|
|
|
320
325
|
return NATIVE_ALIASES[base] === undefined ? undefined : parsePostgresTypeName({ raw: normalizeNativeType(params) });
|
|
321
326
|
}
|
|
322
327
|
function columnTypeKey(params) {
|
|
323
|
-
const { field } = params;
|
|
328
|
+
const { field, exact } = params;
|
|
324
329
|
const listSuffix = field.isList ? "[]" : "";
|
|
325
330
|
if (field.isUnsupported === true) {
|
|
326
331
|
const parsed = parseUnsupportedPostgresType({ raw: field.nativeType ?? "" });
|
|
@@ -331,7 +336,7 @@ function columnTypeKey(params) {
|
|
|
331
336
|
const scalar = namespace === undefined || namespace === "pg_catalog" ? scalarForBuiltinType({ name: parsed.name }) : undefined;
|
|
332
337
|
if (scalar !== undefined) {
|
|
333
338
|
const { isUnsupported: _unsupported, nativeTypeIdentity: _identity, ...rest } = field;
|
|
334
|
-
return columnTypeKey({ field: { ...rest, type: scalar, nativeType: `${parsed.name}${parsed.modifier ?? ""}`, isList: parsed.array || field.isList } });
|
|
339
|
+
return columnTypeKey({ field: { ...rest, type: scalar, nativeType: `${parsed.name}${parsed.modifier ?? ""}`, isList: parsed.array || field.isList }, ...exact === undefined ? {} : { exact } });
|
|
335
340
|
}
|
|
336
341
|
return `u:${JSON.stringify([namespace ?? null, parsed.name, parsed.modifier, parsed.array || field.isList])}`;
|
|
337
342
|
}
|
|
@@ -342,12 +347,37 @@ function columnTypeKey(params) {
|
|
|
342
347
|
if (field.nativeType !== undefined) {
|
|
343
348
|
const normalized = normalizeNativeType({ raw: field.nativeType });
|
|
344
349
|
const canonical = normalizeNativeType({ raw: SCALAR_TO_PG[field.type] });
|
|
345
|
-
const
|
|
350
|
+
const equivalents = exact === true ? EXACT_CANONICAL_EQUIVALENTS : CANONICAL_EQUIVALENTS;
|
|
351
|
+
const isCanonical = normalized === canonical || (equivalents[field.type]?.includes(normalized) ?? false);
|
|
346
352
|
if (!isCanonical)
|
|
347
353
|
return `n:${normalized}${listSuffix}`;
|
|
348
354
|
}
|
|
349
355
|
return `s:${field.type}${listSuffix}`;
|
|
350
356
|
}
|
|
357
|
+
function declaresExactColumnType(params) {
|
|
358
|
+
const { field } = params;
|
|
359
|
+
if (field.isUnsupported === true || field.nativeType === undefined || isEnumType2(field.type))
|
|
360
|
+
return false;
|
|
361
|
+
return CANONICAL_EQUIVALENTS[field.type]?.includes(normalizeNativeType({ raw: field.nativeType })) ?? false;
|
|
362
|
+
}
|
|
363
|
+
function timestamptzPrecision(params) {
|
|
364
|
+
const { field } = params;
|
|
365
|
+
if (field.type !== "DateTime" || field.isUnsupported === true)
|
|
366
|
+
return;
|
|
367
|
+
const normalized = field.nativeType === undefined ? "timestamptz" : normalizeNativeType({ raw: field.nativeType });
|
|
368
|
+
if (normalized === "timestamptz")
|
|
369
|
+
return 6;
|
|
370
|
+
const match = /^timestamptz\((\d)\)$/.exec(normalized);
|
|
371
|
+
return match === null ? undefined : Number(match[1]);
|
|
372
|
+
}
|
|
373
|
+
function isTimestamptzPrecisionWidening(params) {
|
|
374
|
+
const { from, to } = params;
|
|
375
|
+
if (from.isList !== to.isList)
|
|
376
|
+
return false;
|
|
377
|
+
const before = timestamptzPrecision({ field: from });
|
|
378
|
+
const after = timestamptzPrecision({ field: to });
|
|
379
|
+
return before !== undefined && after !== undefined && after >= before;
|
|
380
|
+
}
|
|
351
381
|
function isScalarToArrayChange(params) {
|
|
352
382
|
const { from, to } = params;
|
|
353
383
|
if (from.isList || !to.isList)
|
|
@@ -1094,16 +1124,20 @@ function assertStringEnumLabelsFit(params) {
|
|
|
1094
1124
|
}
|
|
1095
1125
|
}
|
|
1096
1126
|
function columnTypeKeyFor(params) {
|
|
1097
|
-
const { field, dialect, enums } = params;
|
|
1127
|
+
const { field, dialect, enums, exact } = params;
|
|
1098
1128
|
switch (dialect) {
|
|
1099
1129
|
case "postgres":
|
|
1100
|
-
return columnTypeKey({ field });
|
|
1130
|
+
return columnTypeKey({ field, ...exact === undefined ? {} : { exact } });
|
|
1101
1131
|
case "sqlite":
|
|
1102
1132
|
return sqliteColumnTypeKey({ field, enums });
|
|
1103
1133
|
case "mysql":
|
|
1104
1134
|
return mysqlColumnTypeKey({ field, enums });
|
|
1105
1135
|
}
|
|
1106
1136
|
}
|
|
1137
|
+
function columnTypeChanged(params) {
|
|
1138
|
+
const { declared, actual } = params;
|
|
1139
|
+
return declared.pinsExactType ? declared.exactTypeKey !== actual.exactTypeKey : declared.typeKey !== actual.typeKey;
|
|
1140
|
+
}
|
|
1107
1141
|
function defaultFingerprintFor(params) {
|
|
1108
1142
|
const { field, dialect } = params;
|
|
1109
1143
|
switch (dialect) {
|
|
@@ -1126,6 +1160,8 @@ function normalizeModel(params) {
|
|
|
1126
1160
|
name,
|
|
1127
1161
|
field,
|
|
1128
1162
|
typeKey: columnTypeKeyFor({ field, dialect, enums }),
|
|
1163
|
+
exactTypeKey: columnTypeKeyFor({ field, dialect, enums, exact: true }),
|
|
1164
|
+
pinsExactType: dialect === "postgres" && declaresExactColumnType({ field }),
|
|
1129
1165
|
nullable: field.isOptional,
|
|
1130
1166
|
defaultKey: defaultFingerprintFor({ field, dialect })
|
|
1131
1167
|
});
|
|
@@ -2199,8 +2235,9 @@ function reverseMapType(params) {
|
|
|
2199
2235
|
function nonCanonicalModifier(params) {
|
|
2200
2236
|
const { column, udt, scalar } = params;
|
|
2201
2237
|
if (column.dataType === "ARRAY" && column.fullType !== null) {
|
|
2202
|
-
const
|
|
2203
|
-
|
|
2238
|
+
const temporal = parseUnsupportedPostgresType({ raw: column.fullType });
|
|
2239
|
+
const element = temporal?.name === "timestamptz" ? `timestamptz${temporal.modifier}` : normalizeNativeType({ raw: column.fullType }).replace(/\[\]$/, "");
|
|
2240
|
+
if (element !== "timestamptz(6)" && /^(numeric|timestamptz)\([\d,]+\)$/.test(element))
|
|
2204
2241
|
return element;
|
|
2205
2242
|
}
|
|
2206
2243
|
if (scalar === "DateTime" && udt === "timestamptz") {
|
|
@@ -2217,9 +2254,9 @@ function nonCanonicalModifier(params) {
|
|
|
2217
2254
|
}
|
|
2218
2255
|
function withModifier(params) {
|
|
2219
2256
|
const { column, udt } = params;
|
|
2220
|
-
if (udt === "varchar" && column.dataType === "ARRAY" && column.fullType !== null) {
|
|
2257
|
+
if ((udt === "varchar" || udt === "bpchar" || udt === "bit" || udt === "varbit") && column.dataType === "ARRAY" && column.fullType !== null) {
|
|
2221
2258
|
const elementType = normalizeNativeType({ raw: column.fullType }).replace(/\[\]$/, "");
|
|
2222
|
-
if (/^varchar\(\d+\)$/.test(elementType))
|
|
2259
|
+
if (/^(varchar|char|bit|varbit)\(\d+\)$/.test(elementType))
|
|
2223
2260
|
return elementType;
|
|
2224
2261
|
}
|
|
2225
2262
|
if ((udt === "varchar" || udt === "bpchar") && column.charMaxLength !== null) {
|
|
@@ -2229,6 +2266,10 @@ function withModifier(params) {
|
|
|
2229
2266
|
return "char";
|
|
2230
2267
|
if ((udt === "bit" || udt === "varbit") && column.charMaxLength !== null)
|
|
2231
2268
|
return `${udt}(${column.charMaxLength})`;
|
|
2269
|
+
if ((udt === "timestamp" || udt === "time" || udt === "timetz") && column.dataType === "ARRAY" && column.fullType !== null) {
|
|
2270
|
+
const element = parseUnsupportedPostgresType({ raw: column.fullType });
|
|
2271
|
+
return element === undefined || element.modifier === "" || element.modifier === "(6)" ? udt : `${udt}${element.modifier}`;
|
|
2272
|
+
}
|
|
2232
2273
|
if ((udt === "timestamp" || udt === "time" || udt === "timetz") && column.datetimePrecision !== null && column.datetimePrecision !== 6) {
|
|
2233
2274
|
return `${udt}(${column.datetimePrecision})`;
|
|
2234
2275
|
}
|
|
@@ -3944,7 +3985,8 @@ async function verifySchemaObjects(params) {
|
|
|
3944
3985
|
pin("primaryKey", desired.pk, live.pk);
|
|
3945
3986
|
for (const [column, field] of desired.columns) {
|
|
3946
3987
|
const stored = live.columns.get(column);
|
|
3947
|
-
|
|
3988
|
+
const exactType = field.pinsExactType;
|
|
3989
|
+
pin(`columns.${column}.type`, exactType ? field.exactTypeKey : field.typeKey, exactType ? stored?.exactTypeKey : stored?.typeKey);
|
|
3948
3990
|
pin(`columns.${column}.nullable`, field.nullable, stored?.nullable);
|
|
3949
3991
|
if (params.dialect === "mysql" && field.field.collation !== undefined) {
|
|
3950
3992
|
pin(`columns.${column}.collation`, field.field.collation.toLowerCase(), stored?.field.collation?.toLowerCase());
|
|
@@ -6051,7 +6093,7 @@ function diffOneTable(params) {
|
|
|
6051
6093
|
continue;
|
|
6052
6094
|
}
|
|
6053
6095
|
const changes = [];
|
|
6054
|
-
if (
|
|
6096
|
+
if (columnTypeChanged({ declared: column, actual: before }))
|
|
6055
6097
|
changes.push("type");
|
|
6056
6098
|
if (before.nullable !== column.nullable)
|
|
6057
6099
|
changes.push("nullability");
|
|
@@ -6074,7 +6116,7 @@ function diffOneTable(params) {
|
|
|
6074
6116
|
assertStringEnumLabelsFit({ field: column.field, values, dialect, table });
|
|
6075
6117
|
}
|
|
6076
6118
|
}
|
|
6077
|
-
let narrowingType = changes.includes("type") && !isScalarToArrayChange({ from: before.field, to: column.field }) && !(storageChange && column.field.type === "String");
|
|
6119
|
+
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");
|
|
6078
6120
|
if (dialect !== "postgres" && changes.includes("type") && isEnumType6(before.field.type) && isEnumType6(column.field.type)) {
|
|
6079
6121
|
const fromValues = resolveEnumValues({ name: before.field.type.enum, enums: fromEnums });
|
|
6080
6122
|
const toValues = resolveEnumValues({ name: column.field.type.enum, enums: toEnums });
|
|
@@ -10886,4 +10928,4 @@ export {
|
|
|
10886
10928
|
withMigrationReference
|
|
10887
10929
|
};
|
|
10888
10930
|
|
|
10889
|
-
//# debugId=
|
|
10931
|
+
//# debugId=CC107738F16DF7A964756E2164756E21
|