relq 1.0.104 → 1.0.106
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.
|
@@ -157,6 +157,35 @@ async function runPush(config, projectRoot, opts = {}) {
|
|
|
157
157
|
const diff = (0, schema_diff_1.diffSchemas)((0, schema_hash_1.normalizeSchema)(dbSchema), (0, schema_hash_1.normalizeSchema)(desiredSchema));
|
|
158
158
|
let filteredDiff = (0, schema_diff_1.filterDiff)(diff, ignorePatterns.map(pat => pat.raw));
|
|
159
159
|
const dbParsedSchema = await (0, ast_transformer_1.introspectedToParsedSchema)(dbSchema);
|
|
160
|
+
const snapshot = (0, snapshot_manager_1.loadSnapshot)(snapshotPath);
|
|
161
|
+
if (snapshot) {
|
|
162
|
+
const snapTables = Object.values(snapshot.tables || {});
|
|
163
|
+
for (const dbTable of dbParsedSchema.tables) {
|
|
164
|
+
const snapTable = snapTables.find(s => s.name === dbTable.name);
|
|
165
|
+
if (!snapTable)
|
|
166
|
+
continue;
|
|
167
|
+
if (snapTable.trackingId)
|
|
168
|
+
dbTable.trackingId = snapTable.trackingId;
|
|
169
|
+
const snapCols = Object.values(snapTable.columns || {});
|
|
170
|
+
for (const dbCol of dbTable.columns) {
|
|
171
|
+
const snapCol = snapCols.find(s => s.name === dbCol.name);
|
|
172
|
+
if (snapCol?.trackingId)
|
|
173
|
+
dbCol.trackingId = snapCol.trackingId;
|
|
174
|
+
}
|
|
175
|
+
const snapIdxs = Object.values(snapTable.indexes || {});
|
|
176
|
+
for (const dbIdx of dbTable.indexes) {
|
|
177
|
+
const snapIdx = snapIdxs.find(s => s.name === dbIdx.name);
|
|
178
|
+
if (snapIdx?.trackingId)
|
|
179
|
+
dbIdx.trackingId = snapIdx.trackingId;
|
|
180
|
+
}
|
|
181
|
+
const snapCons = Object.values(snapTable.constraints || {});
|
|
182
|
+
for (const dbCon of dbTable.constraints) {
|
|
183
|
+
const snapCon = snapCons.find(s => s.name === dbCon.name);
|
|
184
|
+
if (snapCon?.trackingId)
|
|
185
|
+
dbCon.trackingId = snapCon.trackingId;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
160
189
|
const desiredASTCopy = { ...desiredAST };
|
|
161
190
|
if (!includeFunctions) {
|
|
162
191
|
dbParsedSchema.functions = [];
|
|
@@ -176,7 +205,20 @@ async function runPush(config, projectRoot, opts = {}) {
|
|
|
176
205
|
}
|
|
177
206
|
console.log('');
|
|
178
207
|
console.log(`${colors_1.colors.bold('Changes to push:')}`);
|
|
208
|
+
const renamedFromNames = new Set(comparison.renamed.tables.map(r => r.from));
|
|
209
|
+
const renamedToNames = new Set(comparison.renamed.tables.map(r => r.to));
|
|
210
|
+
for (const rename of comparison.renamed.tables) {
|
|
211
|
+
console.log(` ${colors_1.colors.cyan('→')} ${colors_1.colors.bold(rename.from)} → ${colors_1.colors.bold(rename.to)} ${colors_1.colors.muted('(rename)')}`);
|
|
212
|
+
}
|
|
213
|
+
for (const rename of comparison.renamed.columns) {
|
|
214
|
+
console.log(` ${colors_1.colors.cyan('→')} ${colors_1.colors.bold(rename.table)}.${rename.from} → ${rename.to} ${colors_1.colors.muted('(rename column)')}`);
|
|
215
|
+
}
|
|
216
|
+
for (const rename of comparison.renamed.indexes) {
|
|
217
|
+
console.log(` ${colors_1.colors.cyan('→')} index ${rename.from} → ${rename.to} ${colors_1.colors.muted('(rename index)')}`);
|
|
218
|
+
}
|
|
179
219
|
for (const table of filteredDiff.tables) {
|
|
220
|
+
if (renamedFromNames.has(table.name) || renamedToNames.has(table.name))
|
|
221
|
+
continue;
|
|
180
222
|
if (table.type === 'added') {
|
|
181
223
|
console.log(` ${colors_1.colors.green('+')} ${colors_1.colors.bold(table.name)} ${colors_1.colors.muted('(new table)')}`);
|
|
182
224
|
for (const col of table.columns || []) {
|
|
@@ -273,8 +315,11 @@ async function runPush(config, projectRoot, opts = {}) {
|
|
|
273
315
|
|| comparison.removed.triggers.length > 0;
|
|
274
316
|
if ((0, schema_diff_1.hasDestructiveChanges)(filteredDiff) || hasNonTableDestructive) {
|
|
275
317
|
const destructiveItems = [];
|
|
276
|
-
for (const t of (0, schema_diff_1.getDestructiveTables)(filteredDiff))
|
|
318
|
+
for (const t of (0, schema_diff_1.getDestructiveTables)(filteredDiff)) {
|
|
319
|
+
if (renamedFromNames.has(t) || renamedToNames.has(t))
|
|
320
|
+
continue;
|
|
277
321
|
destructiveItems.push(t);
|
|
322
|
+
}
|
|
278
323
|
for (const e of comparison.removed.enums)
|
|
279
324
|
destructiveItems.push(`enum ${e.name}`);
|
|
280
325
|
for (const d of comparison.removed.domains)
|
|
@@ -289,33 +334,35 @@ async function runPush(config, projectRoot, opts = {}) {
|
|
|
289
334
|
destructiveItems.push(`function ${f.name}`);
|
|
290
335
|
for (const tr of comparison.removed.triggers)
|
|
291
336
|
destructiveItems.push(`trigger ${tr.name}`);
|
|
292
|
-
(
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
console.log('');
|
|
297
|
-
if (!force && !skipPrompt) {
|
|
298
|
-
const proceed = await p.confirm({
|
|
299
|
-
message: 'Include destructive changes?',
|
|
300
|
-
initialValue: false,
|
|
301
|
-
});
|
|
302
|
-
if (p.isCancel(proceed)) {
|
|
303
|
-
(0, ui_1.fatal)('Operation cancelled by user');
|
|
337
|
+
if (destructiveItems.length > 0) {
|
|
338
|
+
(0, ui_1.warning)('Destructive changes detected:');
|
|
339
|
+
for (const item of destructiveItems) {
|
|
340
|
+
console.log(` ${colors_1.colors.red('-')} ${item}`);
|
|
304
341
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
if (!
|
|
315
|
-
|
|
316
|
-
|
|
342
|
+
console.log('');
|
|
343
|
+
if (!force && !skipPrompt) {
|
|
344
|
+
const proceed = await p.confirm({
|
|
345
|
+
message: 'Include destructive changes?',
|
|
346
|
+
initialValue: false,
|
|
347
|
+
});
|
|
348
|
+
if (p.isCancel(proceed)) {
|
|
349
|
+
(0, ui_1.fatal)('Operation cancelled by user');
|
|
350
|
+
}
|
|
351
|
+
if (!proceed) {
|
|
352
|
+
filteredDiff = (0, schema_diff_1.stripDestructiveChanges)(filteredDiff);
|
|
353
|
+
comparison.removed.enums = [];
|
|
354
|
+
comparison.removed.domains = [];
|
|
355
|
+
comparison.removed.sequences = [];
|
|
356
|
+
comparison.removed.compositeTypes = [];
|
|
357
|
+
comparison.removed.views = [];
|
|
358
|
+
comparison.removed.functions = [];
|
|
359
|
+
comparison.removed.triggers = [];
|
|
360
|
+
if (!filteredDiff.hasChanges && !comparison.hasChanges) {
|
|
361
|
+
p.log.info('No non-destructive changes to push.');
|
|
362
|
+
process.exit(0);
|
|
363
|
+
}
|
|
364
|
+
p.log.info('Destructive changes excluded. Continuing with safe changes only.');
|
|
317
365
|
}
|
|
318
|
-
p.log.info('Destructive changes excluded. Continuing with safe changes only.');
|
|
319
366
|
}
|
|
320
367
|
}
|
|
321
368
|
}
|
|
@@ -1069,7 +1069,7 @@ function compareColumnProperties(oldCol, newCol) {
|
|
|
1069
1069
|
if (oldCol.isUnique !== newCol.isUnique) {
|
|
1070
1070
|
changes.push({ field: 'unique', from: oldCol.isUnique, to: newCol.isUnique });
|
|
1071
1071
|
}
|
|
1072
|
-
if (oldCol.defaultValue
|
|
1072
|
+
if (!defaultsEqual(oldCol.defaultValue, newCol.defaultValue)) {
|
|
1073
1073
|
changes.push({ field: 'default', from: oldCol.defaultValue, to: newCol.defaultValue });
|
|
1074
1074
|
}
|
|
1075
1075
|
const oldLength = oldCol.typeParams?.length;
|
|
@@ -1089,6 +1089,24 @@ function compareColumnProperties(oldCol, newCol) {
|
|
|
1089
1089
|
}
|
|
1090
1090
|
return changes;
|
|
1091
1091
|
}
|
|
1092
|
+
function defaultsEqual(a, b) {
|
|
1093
|
+
if (a === b)
|
|
1094
|
+
return true;
|
|
1095
|
+
if (a == null && b == null)
|
|
1096
|
+
return true;
|
|
1097
|
+
if (a == null || b == null)
|
|
1098
|
+
return false;
|
|
1099
|
+
return normalizeDefault(a) === normalizeDefault(b);
|
|
1100
|
+
}
|
|
1101
|
+
function normalizeDefault(val) {
|
|
1102
|
+
let v = val.trim();
|
|
1103
|
+
v = v.replace(/::[\w\s]+(\[\])?$/i, '');
|
|
1104
|
+
const upper = v.toUpperCase();
|
|
1105
|
+
if (upper === 'NOW()' || upper === 'CURRENT_TIMESTAMP' || upper === 'CURRENT_TIMESTAMP()') {
|
|
1106
|
+
return 'CURRENT_TIMESTAMP';
|
|
1107
|
+
}
|
|
1108
|
+
return v;
|
|
1109
|
+
}
|
|
1092
1110
|
function compareTableIndexes(oldTable, newTable, tableName, result) {
|
|
1093
1111
|
const oldByName = new Map(oldTable.indexes.map(i => [i.name, i]));
|
|
1094
1112
|
const newByName = new Map(newTable.indexes.map(i => [i.name, i]));
|
|
@@ -14,7 +14,7 @@ import { validateForDialect, formatDialectErrors } from "../utils/dialect-valida
|
|
|
14
14
|
import { validateSchemaFile, formatValidationErrors } from "../utils/schema-validator.js";
|
|
15
15
|
import { loadRelqignore } from "../utils/relqignore.js";
|
|
16
16
|
import { isInitialized } from "../utils/repo-manager.js";
|
|
17
|
-
import { saveSnapshot } from "../utils/snapshot-manager.js";
|
|
17
|
+
import { loadSnapshot, saveSnapshot } from "../utils/snapshot-manager.js";
|
|
18
18
|
import { loadSchemaFile } from "../utils/schema-loader.js";
|
|
19
19
|
import { diffSchemas, filterDiff, hasDestructiveChanges, getDestructiveTables, stripDestructiveChanges, formatCategorizedSummary, compareSchemas } from "../utils/schema-diff.js";
|
|
20
20
|
import { normalizeSchema } from "../utils/schema-hash.js";
|
|
@@ -121,6 +121,35 @@ export async function runPush(config, projectRoot, opts = {}) {
|
|
|
121
121
|
const diff = diffSchemas(normalizeSchema(dbSchema), normalizeSchema(desiredSchema));
|
|
122
122
|
let filteredDiff = filterDiff(diff, ignorePatterns.map(pat => pat.raw));
|
|
123
123
|
const dbParsedSchema = await introspectedToParsedSchema(dbSchema);
|
|
124
|
+
const snapshot = loadSnapshot(snapshotPath);
|
|
125
|
+
if (snapshot) {
|
|
126
|
+
const snapTables = Object.values(snapshot.tables || {});
|
|
127
|
+
for (const dbTable of dbParsedSchema.tables) {
|
|
128
|
+
const snapTable = snapTables.find(s => s.name === dbTable.name);
|
|
129
|
+
if (!snapTable)
|
|
130
|
+
continue;
|
|
131
|
+
if (snapTable.trackingId)
|
|
132
|
+
dbTable.trackingId = snapTable.trackingId;
|
|
133
|
+
const snapCols = Object.values(snapTable.columns || {});
|
|
134
|
+
for (const dbCol of dbTable.columns) {
|
|
135
|
+
const snapCol = snapCols.find(s => s.name === dbCol.name);
|
|
136
|
+
if (snapCol?.trackingId)
|
|
137
|
+
dbCol.trackingId = snapCol.trackingId;
|
|
138
|
+
}
|
|
139
|
+
const snapIdxs = Object.values(snapTable.indexes || {});
|
|
140
|
+
for (const dbIdx of dbTable.indexes) {
|
|
141
|
+
const snapIdx = snapIdxs.find(s => s.name === dbIdx.name);
|
|
142
|
+
if (snapIdx?.trackingId)
|
|
143
|
+
dbIdx.trackingId = snapIdx.trackingId;
|
|
144
|
+
}
|
|
145
|
+
const snapCons = Object.values(snapTable.constraints || {});
|
|
146
|
+
for (const dbCon of dbTable.constraints) {
|
|
147
|
+
const snapCon = snapCons.find(s => s.name === dbCon.name);
|
|
148
|
+
if (snapCon?.trackingId)
|
|
149
|
+
dbCon.trackingId = snapCon.trackingId;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
124
153
|
const desiredASTCopy = { ...desiredAST };
|
|
125
154
|
if (!includeFunctions) {
|
|
126
155
|
dbParsedSchema.functions = [];
|
|
@@ -140,7 +169,20 @@ export async function runPush(config, projectRoot, opts = {}) {
|
|
|
140
169
|
}
|
|
141
170
|
console.log('');
|
|
142
171
|
console.log(`${colors.bold('Changes to push:')}`);
|
|
172
|
+
const renamedFromNames = new Set(comparison.renamed.tables.map(r => r.from));
|
|
173
|
+
const renamedToNames = new Set(comparison.renamed.tables.map(r => r.to));
|
|
174
|
+
for (const rename of comparison.renamed.tables) {
|
|
175
|
+
console.log(` ${colors.cyan('→')} ${colors.bold(rename.from)} → ${colors.bold(rename.to)} ${colors.muted('(rename)')}`);
|
|
176
|
+
}
|
|
177
|
+
for (const rename of comparison.renamed.columns) {
|
|
178
|
+
console.log(` ${colors.cyan('→')} ${colors.bold(rename.table)}.${rename.from} → ${rename.to} ${colors.muted('(rename column)')}`);
|
|
179
|
+
}
|
|
180
|
+
for (const rename of comparison.renamed.indexes) {
|
|
181
|
+
console.log(` ${colors.cyan('→')} index ${rename.from} → ${rename.to} ${colors.muted('(rename index)')}`);
|
|
182
|
+
}
|
|
143
183
|
for (const table of filteredDiff.tables) {
|
|
184
|
+
if (renamedFromNames.has(table.name) || renamedToNames.has(table.name))
|
|
185
|
+
continue;
|
|
144
186
|
if (table.type === 'added') {
|
|
145
187
|
console.log(` ${colors.green('+')} ${colors.bold(table.name)} ${colors.muted('(new table)')}`);
|
|
146
188
|
for (const col of table.columns || []) {
|
|
@@ -237,8 +279,11 @@ export async function runPush(config, projectRoot, opts = {}) {
|
|
|
237
279
|
|| comparison.removed.triggers.length > 0;
|
|
238
280
|
if (hasDestructiveChanges(filteredDiff) || hasNonTableDestructive) {
|
|
239
281
|
const destructiveItems = [];
|
|
240
|
-
for (const t of getDestructiveTables(filteredDiff))
|
|
282
|
+
for (const t of getDestructiveTables(filteredDiff)) {
|
|
283
|
+
if (renamedFromNames.has(t) || renamedToNames.has(t))
|
|
284
|
+
continue;
|
|
241
285
|
destructiveItems.push(t);
|
|
286
|
+
}
|
|
242
287
|
for (const e of comparison.removed.enums)
|
|
243
288
|
destructiveItems.push(`enum ${e.name}`);
|
|
244
289
|
for (const d of comparison.removed.domains)
|
|
@@ -253,33 +298,35 @@ export async function runPush(config, projectRoot, opts = {}) {
|
|
|
253
298
|
destructiveItems.push(`function ${f.name}`);
|
|
254
299
|
for (const tr of comparison.removed.triggers)
|
|
255
300
|
destructiveItems.push(`trigger ${tr.name}`);
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
console.log('');
|
|
261
|
-
if (!force && !skipPrompt) {
|
|
262
|
-
const proceed = await p.confirm({
|
|
263
|
-
message: 'Include destructive changes?',
|
|
264
|
-
initialValue: false,
|
|
265
|
-
});
|
|
266
|
-
if (p.isCancel(proceed)) {
|
|
267
|
-
fatal('Operation cancelled by user');
|
|
301
|
+
if (destructiveItems.length > 0) {
|
|
302
|
+
warning('Destructive changes detected:');
|
|
303
|
+
for (const item of destructiveItems) {
|
|
304
|
+
console.log(` ${colors.red('-')} ${item}`);
|
|
268
305
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
if (!
|
|
279
|
-
|
|
280
|
-
|
|
306
|
+
console.log('');
|
|
307
|
+
if (!force && !skipPrompt) {
|
|
308
|
+
const proceed = await p.confirm({
|
|
309
|
+
message: 'Include destructive changes?',
|
|
310
|
+
initialValue: false,
|
|
311
|
+
});
|
|
312
|
+
if (p.isCancel(proceed)) {
|
|
313
|
+
fatal('Operation cancelled by user');
|
|
314
|
+
}
|
|
315
|
+
if (!proceed) {
|
|
316
|
+
filteredDiff = stripDestructiveChanges(filteredDiff);
|
|
317
|
+
comparison.removed.enums = [];
|
|
318
|
+
comparison.removed.domains = [];
|
|
319
|
+
comparison.removed.sequences = [];
|
|
320
|
+
comparison.removed.compositeTypes = [];
|
|
321
|
+
comparison.removed.views = [];
|
|
322
|
+
comparison.removed.functions = [];
|
|
323
|
+
comparison.removed.triggers = [];
|
|
324
|
+
if (!filteredDiff.hasChanges && !comparison.hasChanges) {
|
|
325
|
+
p.log.info('No non-destructive changes to push.');
|
|
326
|
+
process.exit(0);
|
|
327
|
+
}
|
|
328
|
+
p.log.info('Destructive changes excluded. Continuing with safe changes only.');
|
|
281
329
|
}
|
|
282
|
-
p.log.info('Destructive changes excluded. Continuing with safe changes only.');
|
|
283
330
|
}
|
|
284
331
|
}
|
|
285
332
|
}
|
|
@@ -1058,7 +1058,7 @@ function compareColumnProperties(oldCol, newCol) {
|
|
|
1058
1058
|
if (oldCol.isUnique !== newCol.isUnique) {
|
|
1059
1059
|
changes.push({ field: 'unique', from: oldCol.isUnique, to: newCol.isUnique });
|
|
1060
1060
|
}
|
|
1061
|
-
if (oldCol.defaultValue
|
|
1061
|
+
if (!defaultsEqual(oldCol.defaultValue, newCol.defaultValue)) {
|
|
1062
1062
|
changes.push({ field: 'default', from: oldCol.defaultValue, to: newCol.defaultValue });
|
|
1063
1063
|
}
|
|
1064
1064
|
const oldLength = oldCol.typeParams?.length;
|
|
@@ -1078,6 +1078,24 @@ function compareColumnProperties(oldCol, newCol) {
|
|
|
1078
1078
|
}
|
|
1079
1079
|
return changes;
|
|
1080
1080
|
}
|
|
1081
|
+
function defaultsEqual(a, b) {
|
|
1082
|
+
if (a === b)
|
|
1083
|
+
return true;
|
|
1084
|
+
if (a == null && b == null)
|
|
1085
|
+
return true;
|
|
1086
|
+
if (a == null || b == null)
|
|
1087
|
+
return false;
|
|
1088
|
+
return normalizeDefault(a) === normalizeDefault(b);
|
|
1089
|
+
}
|
|
1090
|
+
function normalizeDefault(val) {
|
|
1091
|
+
let v = val.trim();
|
|
1092
|
+
v = v.replace(/::[\w\s]+(\[\])?$/i, '');
|
|
1093
|
+
const upper = v.toUpperCase();
|
|
1094
|
+
if (upper === 'NOW()' || upper === 'CURRENT_TIMESTAMP' || upper === 'CURRENT_TIMESTAMP()') {
|
|
1095
|
+
return 'CURRENT_TIMESTAMP';
|
|
1096
|
+
}
|
|
1097
|
+
return v;
|
|
1098
|
+
}
|
|
1081
1099
|
function compareTableIndexes(oldTable, newTable, tableName, result) {
|
|
1082
1100
|
const oldByName = new Map(oldTable.indexes.map(i => [i.name, i]));
|
|
1083
1101
|
const newByName = new Map(newTable.indexes.map(i => [i.name, i]));
|