relq 1.0.2 → 1.0.4

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.
Files changed (92) hide show
  1. package/dist/cjs/cli/commands/add.cjs +403 -27
  2. package/dist/cjs/cli/commands/branch.cjs +13 -23
  3. package/dist/cjs/cli/commands/checkout.cjs +16 -29
  4. package/dist/cjs/cli/commands/cherry-pick.cjs +3 -4
  5. package/dist/cjs/cli/commands/commit.cjs +21 -29
  6. package/dist/cjs/cli/commands/diff.cjs +28 -32
  7. package/dist/cjs/cli/commands/export.cjs +7 -7
  8. package/dist/cjs/cli/commands/fetch.cjs +15 -21
  9. package/dist/cjs/cli/commands/generate.cjs +28 -54
  10. package/dist/cjs/cli/commands/history.cjs +19 -40
  11. package/dist/cjs/cli/commands/import.cjs +34 -41
  12. package/dist/cjs/cli/commands/init.cjs +69 -59
  13. package/dist/cjs/cli/commands/introspect.cjs +4 -8
  14. package/dist/cjs/cli/commands/log.cjs +26 -32
  15. package/dist/cjs/cli/commands/merge.cjs +24 -41
  16. package/dist/cjs/cli/commands/migrate.cjs +12 -25
  17. package/dist/cjs/cli/commands/pull.cjs +216 -106
  18. package/dist/cjs/cli/commands/push.cjs +35 -75
  19. package/dist/cjs/cli/commands/remote.cjs +2 -1
  20. package/dist/cjs/cli/commands/reset.cjs +22 -43
  21. package/dist/cjs/cli/commands/resolve.cjs +12 -14
  22. package/dist/cjs/cli/commands/rollback.cjs +16 -38
  23. package/dist/cjs/cli/commands/stash.cjs +5 -7
  24. package/dist/cjs/cli/commands/status.cjs +5 -10
  25. package/dist/cjs/cli/commands/sync.cjs +30 -50
  26. package/dist/cjs/cli/commands/tag.cjs +3 -4
  27. package/dist/cjs/cli/index.cjs +72 -9
  28. package/dist/cjs/cli/utils/change-tracker.cjs +107 -3
  29. package/dist/cjs/cli/utils/cli-utils.cjs +217 -0
  30. package/dist/cjs/cli/utils/config-loader.cjs +34 -8
  31. package/dist/cjs/cli/utils/fast-introspect.cjs +109 -3
  32. package/dist/cjs/cli/utils/git-utils.cjs +42 -161
  33. package/dist/cjs/cli/utils/pool-manager.cjs +156 -0
  34. package/dist/cjs/cli/utils/project-root.cjs +56 -5
  35. package/dist/cjs/cli/utils/relqignore.cjs +1 -0
  36. package/dist/cjs/cli/utils/repo-manager.cjs +47 -0
  37. package/dist/cjs/cli/utils/schema-comparator.cjs +301 -11
  38. package/dist/cjs/cli/utils/schema-diff.cjs +202 -1
  39. package/dist/cjs/cli/utils/schema-hash.cjs +2 -1
  40. package/dist/cjs/cli/utils/schema-introspect.cjs +7 -3
  41. package/dist/cjs/cli/utils/snapshot-manager.cjs +1 -0
  42. package/dist/cjs/cli/utils/spinner.cjs +14 -106
  43. package/dist/cjs/cli/utils/sql-generator.cjs +10 -2
  44. package/dist/cjs/cli/utils/type-generator.cjs +28 -16
  45. package/dist/config.d.ts +16 -6
  46. package/dist/esm/cli/commands/add.js +372 -29
  47. package/dist/esm/cli/commands/branch.js +14 -24
  48. package/dist/esm/cli/commands/checkout.js +16 -29
  49. package/dist/esm/cli/commands/cherry-pick.js +3 -4
  50. package/dist/esm/cli/commands/commit.js +22 -30
  51. package/dist/esm/cli/commands/diff.js +6 -10
  52. package/dist/esm/cli/commands/export.js +8 -8
  53. package/dist/esm/cli/commands/fetch.js +14 -20
  54. package/dist/esm/cli/commands/generate.js +28 -54
  55. package/dist/esm/cli/commands/history.js +11 -32
  56. package/dist/esm/cli/commands/import.js +35 -42
  57. package/dist/esm/cli/commands/init.js +65 -55
  58. package/dist/esm/cli/commands/introspect.js +4 -8
  59. package/dist/esm/cli/commands/log.js +6 -12
  60. package/dist/esm/cli/commands/merge.js +20 -37
  61. package/dist/esm/cli/commands/migrate.js +12 -25
  62. package/dist/esm/cli/commands/pull.js +204 -94
  63. package/dist/esm/cli/commands/push.js +21 -61
  64. package/dist/esm/cli/commands/remote.js +2 -1
  65. package/dist/esm/cli/commands/reset.js +16 -37
  66. package/dist/esm/cli/commands/resolve.js +13 -15
  67. package/dist/esm/cli/commands/rollback.js +16 -38
  68. package/dist/esm/cli/commands/stash.js +6 -8
  69. package/dist/esm/cli/commands/status.js +6 -11
  70. package/dist/esm/cli/commands/sync.js +30 -50
  71. package/dist/esm/cli/commands/tag.js +3 -4
  72. package/dist/esm/cli/index.js +72 -9
  73. package/dist/esm/cli/utils/change-tracker.js +107 -3
  74. package/dist/esm/cli/utils/cli-utils.js +169 -0
  75. package/dist/esm/cli/utils/config-loader.js +34 -8
  76. package/dist/esm/cli/utils/fast-introspect.js +109 -3
  77. package/dist/esm/cli/utils/git-utils.js +2 -124
  78. package/dist/esm/cli/utils/pool-manager.js +114 -0
  79. package/dist/esm/cli/utils/project-root.js +55 -5
  80. package/dist/esm/cli/utils/relqignore.js +1 -0
  81. package/dist/esm/cli/utils/repo-manager.js +42 -0
  82. package/dist/esm/cli/utils/schema-comparator.js +301 -11
  83. package/dist/esm/cli/utils/schema-diff.js +202 -1
  84. package/dist/esm/cli/utils/schema-hash.js +2 -1
  85. package/dist/esm/cli/utils/schema-introspect.js +7 -3
  86. package/dist/esm/cli/utils/snapshot-manager.js +1 -0
  87. package/dist/esm/cli/utils/spinner.js +1 -101
  88. package/dist/esm/cli/utils/sql-generator.js +10 -2
  89. package/dist/esm/cli/utils/type-generator.js +28 -16
  90. package/dist/index.d.ts +25 -8
  91. package/dist/schema-builder.d.ts +18 -7
  92. package/package.json +1 -1
@@ -6,16 +6,20 @@ exports.compareEnums = compareEnums;
6
6
  exports.compareDomains = compareDomains;
7
7
  exports.compareTables = compareTables;
8
8
  const change_tracker_1 = require("./change-tracker.cjs");
9
+ function arraysEqual(a, b) {
10
+ if (a.length !== b.length)
11
+ return false;
12
+ return a.every((val, idx) => val === b[idx]);
13
+ }
9
14
  function compareSchemas(before, after) {
10
15
  const changes = [];
11
16
  changes.push(...compareExtensions(before.extensions || [], after.extensions || []));
12
17
  changes.push(...compareEnums(before.enums || [], after.enums || []));
13
18
  changes.push(...compareDomains(before.domains || [], after.domains || []));
14
19
  changes.push(...compareCompositeTypes(before.compositeTypes || [], after.compositeTypes || []));
20
+ changes.push(...compareSequences(before.sequences || [], after.sequences || []));
15
21
  changes.push(...compareTables(before.tables, after.tables));
16
- const beforeViews = before.views || [];
17
- const afterViews = after.views || [];
18
- changes.push(...compareViews(beforeViews, afterViews));
22
+ changes.push(...compareViews(before.views || [], after.views || []));
19
23
  changes.push(...compareFunctions(before.functions || [], after.functions || []));
20
24
  changes.push(...compareTriggers(before.triggers || [], after.triggers || []));
21
25
  return changes;
@@ -105,6 +109,38 @@ function compareCompositeTypes(before, after) {
105
109
  }
106
110
  return changes;
107
111
  }
112
+ function compareSequences(before, after) {
113
+ const changes = [];
114
+ const beforeMap = new Map(before.map(s => [s.name, s]));
115
+ const afterMap = new Map(after.map(s => [s.name, s]));
116
+ for (const [name, seq] of afterMap) {
117
+ if (!beforeMap.has(name)) {
118
+ changes.push((0, change_tracker_1.createChange)('CREATE', 'SEQUENCE', name, null, seq));
119
+ }
120
+ else {
121
+ const beforeSeq = beforeMap.get(name);
122
+ if (hasSequenceChanged(beforeSeq, seq)) {
123
+ changes.push((0, change_tracker_1.createChange)('ALTER', 'SEQUENCE', name, beforeSeq, seq));
124
+ }
125
+ }
126
+ }
127
+ for (const [name, seq] of beforeMap) {
128
+ if (!afterMap.has(name)) {
129
+ changes.push((0, change_tracker_1.createChange)('DROP', 'SEQUENCE', name, seq, null));
130
+ }
131
+ }
132
+ return changes;
133
+ }
134
+ function hasSequenceChanged(before, after) {
135
+ return (before.dataType !== after.dataType ||
136
+ before.start !== after.start ||
137
+ before.increment !== after.increment ||
138
+ before.minValue !== after.minValue ||
139
+ before.maxValue !== after.maxValue ||
140
+ before.cache !== after.cache ||
141
+ before.cycle !== after.cycle ||
142
+ before.ownedBy !== after.ownedBy);
143
+ }
108
144
  function compareTables(before, after) {
109
145
  const changes = [];
110
146
  const beforeMap = new Map(before.map(t => [t.name, t]));
@@ -112,12 +148,57 @@ function compareTables(before, after) {
112
148
  for (const [name, table] of afterMap) {
113
149
  if (!beforeMap.has(name)) {
114
150
  changes.push((0, change_tracker_1.createChange)('CREATE', 'TABLE', name, null, tableToChangeData(table)));
151
+ const tableIndexes = table.indexes || [];
152
+ for (const idx of tableIndexes) {
153
+ if (!idx.isPrimary) {
154
+ changes.push((0, change_tracker_1.createChange)('CREATE', 'INDEX', idx.name, null, {
155
+ name: idx.name,
156
+ tableName: name,
157
+ columns: Array.isArray(idx.columns) ? idx.columns : [idx.columns],
158
+ isUnique: idx.isUnique,
159
+ type: idx.type,
160
+ }));
161
+ }
162
+ }
163
+ if (table.isPartitioned && table.partitionType && table.partitionKey) {
164
+ changes.push((0, change_tracker_1.createChange)('CREATE', 'PARTITION', name, null, {
165
+ tableName: name,
166
+ type: table.partitionType,
167
+ key: table.partitionKey,
168
+ }));
169
+ const childPartitions = table.childPartitions || [];
170
+ for (const cp of childPartitions) {
171
+ changes.push((0, change_tracker_1.createChange)('CREATE', 'PARTITION_CHILD', cp.name, null, {
172
+ name: cp.name,
173
+ parentTable: name,
174
+ bound: cp.partitionBound,
175
+ }, name));
176
+ }
177
+ }
178
+ if (table.comment) {
179
+ changes.push((0, change_tracker_1.createChange)('CREATE', 'TABLE_COMMENT', name, null, {
180
+ tableName: name,
181
+ comment: table.comment,
182
+ }, name));
183
+ }
184
+ for (const col of table.columns) {
185
+ if (col.comment) {
186
+ changes.push((0, change_tracker_1.createChange)('CREATE', 'COLUMN_COMMENT', col.name, null, {
187
+ tableName: name,
188
+ columnName: col.name,
189
+ comment: col.comment,
190
+ }, name));
191
+ }
192
+ }
115
193
  }
116
194
  else {
117
195
  const beforeTable = beforeMap.get(name);
118
196
  changes.push(...compareColumns(beforeTable.columns, table.columns, name));
119
197
  changes.push(...compareIndexes(beforeTable.indexes || [], table.indexes || [], name));
120
198
  changes.push(...compareConstraints(beforeTable.constraints || [], table.constraints || [], name));
199
+ changes.push(...compareTableComments(beforeTable, table, name));
200
+ changes.push(...compareColumnComments(beforeTable.columns, table.columns, name));
201
+ changes.push(...comparePartitions(beforeTable, table, name));
121
202
  }
122
203
  }
123
204
  for (const [name, table] of beforeMap) {
@@ -183,10 +264,65 @@ function columnToChangeData(col) {
183
264
  scale: col.scale,
184
265
  };
185
266
  }
267
+ function normalizeDataType(type) {
268
+ if (!type)
269
+ return '';
270
+ let normalized = type.toLowerCase().trim();
271
+ const typeMap = {
272
+ 'int4': 'integer',
273
+ 'int8': 'bigint',
274
+ 'int2': 'smallint',
275
+ 'float4': 'real',
276
+ 'float8': 'double precision',
277
+ 'bool': 'boolean',
278
+ 'timestamptz': 'timestamp',
279
+ 'timetz': 'time',
280
+ '_text': 'text[]',
281
+ '_int4': 'integer[]',
282
+ '_int8': 'bigint[]',
283
+ '_varchar': 'varchar[]',
284
+ '_uuid': 'uuid[]',
285
+ '_bool': 'boolean[]',
286
+ '_jsonb': 'jsonb[]',
287
+ 'character varying': 'varchar',
288
+ 'character': 'char',
289
+ 'double precision': 'doubleprecision',
290
+ };
291
+ if (normalized.startsWith('_') && !typeMap[normalized]) {
292
+ return normalized.substring(1) + '[]';
293
+ }
294
+ return typeMap[normalized] || normalized;
295
+ }
296
+ function normalizeDefault(value) {
297
+ if (value == null)
298
+ return null;
299
+ let normalized = value.trim().toLowerCase();
300
+ normalized = normalized.replace(/array\[\]::([\w\[\]]+)/gi, "'empty_array'");
301
+ normalized = normalized.replace(/::\w+(?:\s+\w+)?(?:\[\])?/g, '');
302
+ normalized = normalized.replace(/^array\[\]$/i, "'empty_array'");
303
+ normalized = normalized.replace(/now\s*\(\s*\)/g, 'now()');
304
+ normalized = normalized.replace(/gen_random_uuid\s*\(\s*\)/g, 'gen_random_uuid()');
305
+ normalized = normalized.replace(/current_date/g, 'current_date');
306
+ normalized = normalized.replace(/current_timestamp/g, 'current_timestamp');
307
+ normalized = normalized.replace(/'\[\]'/g, "'empty_array'");
308
+ normalized = normalized.replace(/'\{\}'/g, "'empty_array'");
309
+ normalized = normalized.replace(/:\s+/g, ':');
310
+ normalized = normalized.replace(/,\s+/g, ',');
311
+ normalized = normalized.replace(/\[\s+/g, '[');
312
+ normalized = normalized.replace(/\s+\]/g, ']');
313
+ normalized = normalized.replace(/\{\s+/g, '{');
314
+ normalized = normalized.replace(/\s+\}/g, '}');
315
+ if (normalized === 'true' || normalized === "'t'" || normalized === 't')
316
+ normalized = 'true';
317
+ if (normalized === 'false' || normalized === "'f'" || normalized === 'f')
318
+ normalized = 'false';
319
+ normalized = normalized.replace(/^'([^']*)'$/, '$1');
320
+ return normalized || null;
321
+ }
186
322
  function hasColumnChanged(before, after) {
187
- return (before.dataType.toLowerCase() !== after.dataType.toLowerCase() ||
323
+ return (normalizeDataType(before.dataType) !== normalizeDataType(after.dataType) ||
188
324
  before.isNullable !== after.isNullable ||
189
- before.defaultValue !== after.defaultValue ||
325
+ normalizeDefault(before.defaultValue) !== normalizeDefault(after.defaultValue) ||
190
326
  before.isPrimaryKey !== after.isPrimaryKey ||
191
327
  before.isUnique !== after.isUnique);
192
328
  }
@@ -218,10 +354,14 @@ function compareIndexes(before, after, tableName) {
218
354
  }
219
355
  function compareConstraints(before, after, tableName) {
220
356
  const changes = [];
221
- const beforeMap = new Map(before.map(c => [c.name, c]));
222
- const afterMap = new Map(after.map(c => [c.name, c]));
223
- for (const [name, con] of afterMap) {
224
- if (!beforeMap.has(name)) {
357
+ const beforeChecks = before.filter(c => c.type?.toUpperCase() === 'CHECK');
358
+ const afterChecks = after.filter(c => c.type?.toUpperCase() === 'CHECK');
359
+ const beforeOther = before.filter(c => c.type?.toUpperCase() !== 'CHECK');
360
+ const afterOther = after.filter(c => c.type?.toUpperCase() !== 'CHECK');
361
+ const beforeOtherMap = new Map(beforeOther.map(c => [c.name, c]));
362
+ const afterOtherMap = new Map(afterOther.map(c => [c.name, c]));
363
+ for (const [name, con] of afterOtherMap) {
364
+ if (!beforeOtherMap.has(name)) {
225
365
  const objectType = constraintTypeToObjectType(con.type);
226
366
  changes.push((0, change_tracker_1.createChange)('CREATE', objectType, name, null, {
227
367
  name: con.name,
@@ -229,8 +369,8 @@ function compareConstraints(before, after, tableName) {
229
369
  }, tableName));
230
370
  }
231
371
  }
232
- for (const [name, con] of beforeMap) {
233
- if (!afterMap.has(name)) {
372
+ for (const [name, con] of beforeOtherMap) {
373
+ if (!afterOtherMap.has(name)) {
234
374
  const objectType = constraintTypeToObjectType(con.type);
235
375
  changes.push((0, change_tracker_1.createChange)('DROP', objectType, name, {
236
376
  name: con.name,
@@ -238,6 +378,59 @@ function compareConstraints(before, after, tableName) {
238
378
  }, null, tableName));
239
379
  }
240
380
  }
381
+ const extractColumnFromCheckDef = (definition) => {
382
+ const enumMatch = definition.match(/\((\w+)\)::text\s*=\s*ANY/i);
383
+ if (enumMatch)
384
+ return enumMatch[1].toLowerCase();
385
+ const compMatch = definition.match(/\(\(?(\w+)\s*(?:>=?|<=?|<>|!=|=)/i);
386
+ if (compMatch)
387
+ return compMatch[1].toLowerCase();
388
+ return null;
389
+ };
390
+ const extractColumnFromCheckName = (name, tableName) => {
391
+ const lower = name.toLowerCase();
392
+ const tablePrefix = tableName.toLowerCase() + '_';
393
+ let colPart = lower.startsWith(tablePrefix) ? lower.slice(tablePrefix.length) : lower;
394
+ if (colPart.startsWith('check_'))
395
+ colPart = colPart.slice(6);
396
+ if (colPart.endsWith('_check'))
397
+ colPart = colPart.slice(0, -6);
398
+ return colPart;
399
+ };
400
+ const beforeChecksByCol = new Map();
401
+ const afterChecksByCol = new Map();
402
+ for (const c of beforeChecks) {
403
+ const col = extractColumnFromCheckDef(c.definition) || extractColumnFromCheckName(c.name, tableName);
404
+ beforeChecksByCol.set(col, c);
405
+ }
406
+ for (const c of afterChecks) {
407
+ const col = extractColumnFromCheckDef(c.definition) || extractColumnFromCheckName(c.name, tableName);
408
+ afterChecksByCol.set(col, c);
409
+ }
410
+ const matchedBefore = new Set();
411
+ const matchedAfter = new Set();
412
+ for (const [col, afterCon] of afterChecksByCol) {
413
+ if (beforeChecksByCol.has(col)) {
414
+ matchedBefore.add(beforeChecksByCol.get(col).name);
415
+ matchedAfter.add(afterCon.name);
416
+ }
417
+ }
418
+ for (const c of afterChecks) {
419
+ if (!matchedAfter.has(c.name)) {
420
+ changes.push((0, change_tracker_1.createChange)('CREATE', 'CHECK', c.name, null, {
421
+ name: c.name,
422
+ definition: c.definition,
423
+ }, tableName));
424
+ }
425
+ }
426
+ for (const c of beforeChecks) {
427
+ if (!matchedBefore.has(c.name)) {
428
+ changes.push((0, change_tracker_1.createChange)('DROP', 'CHECK', c.name, {
429
+ name: c.name,
430
+ definition: c.definition,
431
+ }, null, tableName));
432
+ }
433
+ }
241
434
  return changes;
242
435
  }
243
436
  function constraintTypeToObjectType(type) {
@@ -252,6 +445,103 @@ function constraintTypeToObjectType(type) {
252
445
  return 'EXCLUSION';
253
446
  return 'CONSTRAINT';
254
447
  }
448
+ function compareTableComments(before, after, tableName) {
449
+ const changes = [];
450
+ const beforeComment = before.comment;
451
+ const afterComment = after.comment;
452
+ if (afterComment && !beforeComment) {
453
+ changes.push((0, change_tracker_1.createChange)('CREATE', 'TABLE_COMMENT', tableName, null, {
454
+ tableName,
455
+ comment: afterComment,
456
+ }, tableName));
457
+ }
458
+ else if (!afterComment && beforeComment) {
459
+ changes.push((0, change_tracker_1.createChange)('DROP', 'TABLE_COMMENT', tableName, {
460
+ tableName,
461
+ comment: beforeComment,
462
+ }, null, tableName));
463
+ }
464
+ else if (afterComment && beforeComment && afterComment !== beforeComment) {
465
+ changes.push((0, change_tracker_1.createChange)('ALTER', 'TABLE_COMMENT', tableName, {
466
+ tableName,
467
+ comment: beforeComment,
468
+ }, {
469
+ tableName,
470
+ comment: afterComment,
471
+ }, tableName));
472
+ }
473
+ return changes;
474
+ }
475
+ function compareColumnComments(before, after, tableName) {
476
+ const changes = [];
477
+ const beforeMap = new Map(before.map(c => [c.name, c]));
478
+ const afterMap = new Map(after.map(c => [c.name, c]));
479
+ for (const [name, col] of afterMap) {
480
+ const afterComment = col.comment;
481
+ const beforeCol = beforeMap.get(name);
482
+ const beforeComment = beforeCol ? beforeCol.comment : undefined;
483
+ if (afterComment && !beforeComment) {
484
+ changes.push((0, change_tracker_1.createChange)('CREATE', 'COLUMN_COMMENT', name, null, {
485
+ tableName,
486
+ columnName: name,
487
+ comment: afterComment,
488
+ }, tableName));
489
+ }
490
+ else if (!afterComment && beforeComment) {
491
+ changes.push((0, change_tracker_1.createChange)('DROP', 'COLUMN_COMMENT', name, {
492
+ tableName,
493
+ columnName: name,
494
+ comment: beforeComment,
495
+ }, null, tableName));
496
+ }
497
+ else if (afterComment && beforeComment && afterComment !== beforeComment) {
498
+ changes.push((0, change_tracker_1.createChange)('ALTER', 'COLUMN_COMMENT', name, {
499
+ tableName,
500
+ columnName: name,
501
+ comment: beforeComment,
502
+ }, {
503
+ tableName,
504
+ columnName: name,
505
+ comment: afterComment,
506
+ }, tableName));
507
+ }
508
+ }
509
+ return changes;
510
+ }
511
+ function comparePartitions(before, after, tableName) {
512
+ const changes = [];
513
+ const beforePartitioned = before.isPartitioned;
514
+ const afterPartitioned = after.isPartitioned;
515
+ if (afterPartitioned && !beforePartitioned) {
516
+ changes.push((0, change_tracker_1.createChange)('CREATE', 'PARTITION', tableName, null, {
517
+ tableName,
518
+ type: after.partitionType,
519
+ key: after.partitionKey,
520
+ }));
521
+ }
522
+ else if (!afterPartitioned && beforePartitioned) {
523
+ changes.push((0, change_tracker_1.createChange)('DROP', 'PARTITION', tableName, {
524
+ tableName,
525
+ type: before.partitionType,
526
+ key: before.partitionKey,
527
+ }, null));
528
+ }
529
+ else if (afterPartitioned && beforePartitioned) {
530
+ const keysMatch = arraysEqual(before.partitionKey || [], after.partitionKey || []);
531
+ if (before.partitionType !== after.partitionType || !keysMatch) {
532
+ changes.push((0, change_tracker_1.createChange)('ALTER', 'PARTITION', tableName, {
533
+ tableName,
534
+ type: before.partitionType,
535
+ key: before.partitionKey,
536
+ }, {
537
+ tableName,
538
+ type: after.partitionType,
539
+ key: after.partitionKey,
540
+ }));
541
+ }
542
+ }
543
+ return changes;
544
+ }
255
545
  function compareViews(before, after) {
256
546
  const changes = [];
257
547
  const beforeMap = new Map(before.map(v => [v.name, v]));
@@ -7,6 +7,205 @@ exports.filterDiff = filterDiff;
7
7
  exports.hasDestructiveChanges = hasDestructiveChanges;
8
8
  exports.getDestructiveTables = getDestructiveTables;
9
9
  const spinner_1 = require("./spinner.cjs");
10
+ const TYPE_ALIASES = {
11
+ 'int': 'integer',
12
+ 'int2': 'smallint',
13
+ 'int4': 'integer',
14
+ 'int8': 'bigint',
15
+ 'integer': 'integer',
16
+ 'smallint': 'smallint',
17
+ 'bigint': 'bigint',
18
+ 'serial': 'serial',
19
+ 'serial2': 'smallserial',
20
+ 'serial4': 'serial',
21
+ 'serial8': 'bigserial',
22
+ 'smallserial': 'smallserial',
23
+ 'bigserial': 'bigserial',
24
+ 'float': 'double precision',
25
+ 'float4': 'real',
26
+ 'float8': 'double precision',
27
+ 'real': 'real',
28
+ 'double precision': 'double precision',
29
+ 'decimal': 'numeric',
30
+ 'numeric': 'numeric',
31
+ 'bool': 'boolean',
32
+ 'boolean': 'boolean',
33
+ 'char': 'character',
34
+ 'character': 'character',
35
+ 'bpchar': 'character',
36
+ 'varchar': 'character varying',
37
+ 'character varying': 'character varying',
38
+ 'text': 'text',
39
+ 'name': 'name',
40
+ 'citext': 'citext',
41
+ 'timestamp': 'timestamp without time zone',
42
+ 'timestamp without time zone': 'timestamp without time zone',
43
+ 'timestamptz': 'timestamp with time zone',
44
+ 'timestamp with time zone': 'timestamp with time zone',
45
+ 'date': 'date',
46
+ 'time': 'time without time zone',
47
+ 'time without time zone': 'time without time zone',
48
+ 'timetz': 'time with time zone',
49
+ 'time with time zone': 'time with time zone',
50
+ 'interval': 'interval',
51
+ 'abstime': 'abstime',
52
+ 'reltime': 'reltime',
53
+ 'tinterval': 'tinterval',
54
+ 'bytea': 'bytea',
55
+ 'bit': 'bit',
56
+ 'varbit': 'bit varying',
57
+ 'bit varying': 'bit varying',
58
+ 'uuid': 'uuid',
59
+ 'json': 'json',
60
+ 'jsonb': 'jsonb',
61
+ 'jsonpath': 'jsonpath',
62
+ 'xml': 'xml',
63
+ 'money': 'money',
64
+ 'inet': 'inet',
65
+ 'cidr': 'cidr',
66
+ 'macaddr': 'macaddr',
67
+ 'macaddr8': 'macaddr8',
68
+ 'point': 'point',
69
+ 'line': 'line',
70
+ 'lseg': 'lseg',
71
+ 'box': 'box',
72
+ 'path': 'path',
73
+ 'polygon': 'polygon',
74
+ 'circle': 'circle',
75
+ 'int4range': 'int4range',
76
+ 'int8range': 'int8range',
77
+ 'numrange': 'numrange',
78
+ 'tsrange': 'tsrange',
79
+ 'tstzrange': 'tstzrange',
80
+ 'daterange': 'daterange',
81
+ 'int4multirange': 'int4multirange',
82
+ 'int8multirange': 'int8multirange',
83
+ 'nummultirange': 'nummultirange',
84
+ 'tsmultirange': 'tsmultirange',
85
+ 'tstzmultirange': 'tstzmultirange',
86
+ 'datemultirange': 'datemultirange',
87
+ 'tsvector': 'tsvector',
88
+ 'tsquery': 'tsquery',
89
+ 'gtsvector': 'gtsvector',
90
+ 'oid': 'oid',
91
+ 'regclass': 'regclass',
92
+ 'regcollation': 'regcollation',
93
+ 'regconfig': 'regconfig',
94
+ 'regdictionary': 'regdictionary',
95
+ 'regnamespace': 'regnamespace',
96
+ 'regoper': 'regoper',
97
+ 'regoperator': 'regoperator',
98
+ 'regproc': 'regproc',
99
+ 'regprocedure': 'regprocedure',
100
+ 'regrole': 'regrole',
101
+ 'regtype': 'regtype',
102
+ 'xid': 'xid',
103
+ 'xid8': 'xid8',
104
+ 'cid': 'cid',
105
+ 'tid': 'tid',
106
+ 'aclitem': 'aclitem',
107
+ 'smgr': 'smgr',
108
+ 'unknown': 'unknown',
109
+ 'internal': 'internal',
110
+ 'opaque': 'opaque',
111
+ 'anyelement': 'anyelement',
112
+ 'anyarray': 'anyarray',
113
+ 'anynonarray': 'anynonarray',
114
+ 'anyenum': 'anyenum',
115
+ 'anyrange': 'anyrange',
116
+ 'anymultirange': 'anymultirange',
117
+ 'anycompatible': 'anycompatible',
118
+ 'anycompatiblearray': 'anycompatiblearray',
119
+ 'anycompatiblenonarray': 'anycompatiblenonarray',
120
+ 'anycompatiblerange': 'anycompatiblerange',
121
+ 'anycompatiblemultirange': 'anycompatiblemultirange',
122
+ 'cstring': 'cstring',
123
+ 'record': 'record',
124
+ 'trigger': 'trigger',
125
+ 'event_trigger': 'event_trigger',
126
+ 'pg_lsn': 'pg_lsn',
127
+ 'pg_snapshot': 'pg_snapshot',
128
+ 'txid_snapshot': 'txid_snapshot',
129
+ 'fdw_handler': 'fdw_handler',
130
+ 'index_am_handler': 'index_am_handler',
131
+ 'tsm_handler': 'tsm_handler',
132
+ 'table_am_handler': 'table_am_handler',
133
+ 'language_handler': 'language_handler',
134
+ 'void': 'void',
135
+ 'refcursor': 'refcursor',
136
+ '_int2': 'smallint[]',
137
+ '_int4': 'integer[]',
138
+ '_int8': 'bigint[]',
139
+ '_float4': 'real[]',
140
+ '_float8': 'double precision[]',
141
+ '_numeric': 'numeric[]',
142
+ '_bool': 'boolean[]',
143
+ '_text': 'text[]',
144
+ '_varchar': 'character varying[]',
145
+ '_bpchar': 'character[]',
146
+ '_char': 'character[]',
147
+ '_name': 'name[]',
148
+ '_bytea': 'bytea[]',
149
+ '_bit': 'bit[]',
150
+ '_varbit': 'bit varying[]',
151
+ '_uuid': 'uuid[]',
152
+ '_json': 'json[]',
153
+ '_jsonb': 'jsonb[]',
154
+ '_xml': 'xml[]',
155
+ '_money': 'money[]',
156
+ '_timestamp': 'timestamp without time zone[]',
157
+ '_timestamptz': 'timestamp with time zone[]',
158
+ '_date': 'date[]',
159
+ '_time': 'time without time zone[]',
160
+ '_timetz': 'time with time zone[]',
161
+ '_interval': 'interval[]',
162
+ '_inet': 'inet[]',
163
+ '_cidr': 'cidr[]',
164
+ '_macaddr': 'macaddr[]',
165
+ '_macaddr8': 'macaddr8[]',
166
+ '_point': 'point[]',
167
+ '_line': 'line[]',
168
+ '_lseg': 'lseg[]',
169
+ '_box': 'box[]',
170
+ '_path': 'path[]',
171
+ '_polygon': 'polygon[]',
172
+ '_circle': 'circle[]',
173
+ '_int4range': 'int4range[]',
174
+ '_int8range': 'int8range[]',
175
+ '_numrange': 'numrange[]',
176
+ '_tsrange': 'tsrange[]',
177
+ '_tstzrange': 'tstzrange[]',
178
+ '_daterange': 'daterange[]',
179
+ '_tsvector': 'tsvector[]',
180
+ '_tsquery': 'tsquery[]',
181
+ '_oid': 'oid[]',
182
+ '_regclass': 'regclass[]',
183
+ '_regtype': 'regtype[]',
184
+ '_regproc': 'regproc[]',
185
+ '_xid': 'xid[]',
186
+ '_cid': 'cid[]',
187
+ '_tid': 'tid[]',
188
+ '_aclitem': 'aclitem[]',
189
+ '_cstring': 'cstring[]',
190
+ '_record': 'record[]',
191
+ '_pg_lsn': 'pg_lsn[]',
192
+ '_txid_snapshot': 'txid_snapshot[]',
193
+ '_refcursor': 'refcursor[]',
194
+ '_citext': 'citext[]',
195
+ };
196
+ function normalizeType(type) {
197
+ if (!type)
198
+ return type;
199
+ let normalized = type.toLowerCase().trim();
200
+ if (TYPE_ALIASES[normalized]) {
201
+ return TYPE_ALIASES[normalized];
202
+ }
203
+ normalized = normalized.replace(' without time zone', '');
204
+ if (TYPE_ALIASES[normalized]) {
205
+ return TYPE_ALIASES[normalized];
206
+ }
207
+ return normalized;
208
+ }
10
209
  function diffSchemas(local, remote) {
11
210
  const tables = diffTables(local.tables, remote.tables);
12
211
  const extensions = diffExtensions(local.extensions, remote.extensions);
@@ -83,7 +282,9 @@ function diffColumns(local, remote) {
83
282
  }
84
283
  function compareColumns(local, remote) {
85
284
  const changes = [];
86
- if (local.type !== remote.type) {
285
+ const localType = normalizeType(local.type);
286
+ const remoteType = normalizeType(remote.type);
287
+ if (localType !== remoteType) {
87
288
  changes.push({ field: 'type', from: local.type, to: remote.type });
88
289
  }
89
290
  if (local.nullable !== remote.nullable) {
@@ -62,8 +62,9 @@ function normalizeTable(table) {
62
62
  columns,
63
63
  indexes,
64
64
  constraints,
65
+ isPartitioned: table.isPartitioned,
65
66
  partitionType: table.partitionType,
66
- partitionKey: table.partitionKey?.sort(),
67
+ partitionKey: table.partitionKey ? [...table.partitionKey] : undefined,
67
68
  };
68
69
  }
69
70
  function normalizeColumn(col) {
@@ -68,7 +68,7 @@ async function introspectDatabase(connection, onProgress, options) {
68
68
  WHERE n.nspname = 'public' AND c.relispartition = true;
69
69
  `);
70
70
  const partitionTableNames = new Set(partitionNamesResult.rows.map((r) => r.name));
71
- const nonPartitionTables = tablesResult.rows.filter((r) => !partitionTableNames.has(r.table_name) && !r.table_name.startsWith('_relq'));
71
+ const nonPartitionTables = tablesResult.rows.filter((r) => !partitionTableNames.has(r.table_name) && !r.table_name.startsWith('_relq') && !r.table_name.startsWith('_kuery'));
72
72
  const totalTables = nonPartitionTables.length;
73
73
  let tableIndex = 0;
74
74
  for (let i = 0; i < tablesResult.rows.length; i++) {
@@ -76,9 +76,12 @@ async function introspectDatabase(connection, onProgress, options) {
76
76
  const tableName = row.table_name;
77
77
  const tableSchema = row.table_schema;
78
78
  const rowCount = parseInt(row.row_count) || 0;
79
+ const isInternal = tableName.startsWith('_relq') || tableName.startsWith('_kuery');
80
+ if (isInternal) {
81
+ continue;
82
+ }
79
83
  const isPartition = partitionTableNames.has(tableName);
80
- const isInternal = tableName.startsWith('_relq');
81
- if (!isPartition && !isInternal) {
84
+ if (!isPartition) {
82
85
  tableIndex++;
83
86
  onProgress?.('parsing_table', `${tableName} (${tableIndex}/${totalTables})`);
84
87
  }
@@ -408,6 +411,7 @@ async function introspectDatabase(connection, onProgress, options) {
408
411
  domains: [],
409
412
  compositeTypes: [],
410
413
  sequences: [],
414
+ collations: [],
411
415
  functions,
412
416
  triggers,
413
417
  policies,
@@ -145,6 +145,7 @@ function snapshotToDatabaseSchema(snapshot) {
145
145
  domains: [],
146
146
  compositeTypes: [],
147
147
  sequences: [],
148
+ collations: [],
148
149
  functions: [],
149
150
  triggers: [],
150
151
  policies: [],