relq 1.0.25 → 1.0.27

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 (52) hide show
  1. package/dist/cjs/cli/commands/commit.cjs +80 -0
  2. package/dist/cjs/cli/commands/import.cjs +1 -0
  3. package/dist/cjs/cli/commands/pull.cjs +108 -34
  4. package/dist/cjs/cli/commands/push.cjs +48 -8
  5. package/dist/cjs/cli/commands/rollback.cjs +205 -84
  6. package/dist/cjs/cli/commands/schema-ast.cjs +219 -0
  7. package/dist/cjs/cli/index.cjs +6 -0
  8. package/dist/cjs/cli/utils/ast-codegen.cjs +95 -3
  9. package/dist/cjs/cli/utils/ast-transformer.cjs +12 -0
  10. package/dist/cjs/cli/utils/change-tracker.cjs +135 -0
  11. package/dist/cjs/cli/utils/commit-manager.cjs +54 -0
  12. package/dist/cjs/cli/utils/migration-generator.cjs +319 -0
  13. package/dist/cjs/cli/utils/repo-manager.cjs +99 -3
  14. package/dist/cjs/cli/utils/schema-diff.cjs +390 -0
  15. package/dist/cjs/cli/utils/schema-hash.cjs +4 -0
  16. package/dist/cjs/cli/utils/schema-to-ast.cjs +477 -0
  17. package/dist/cjs/schema-definition/column-types.cjs +50 -4
  18. package/dist/cjs/schema-definition/pg-enum.cjs +10 -0
  19. package/dist/cjs/schema-definition/pg-function.cjs +19 -0
  20. package/dist/cjs/schema-definition/pg-sequence.cjs +22 -1
  21. package/dist/cjs/schema-definition/pg-trigger.cjs +39 -0
  22. package/dist/cjs/schema-definition/pg-view.cjs +17 -0
  23. package/dist/cjs/schema-definition/sql-expressions.cjs +3 -0
  24. package/dist/cjs/schema-definition/table-definition.cjs +4 -0
  25. package/dist/config.d.ts +98 -0
  26. package/dist/esm/cli/commands/commit.js +83 -3
  27. package/dist/esm/cli/commands/import.js +1 -0
  28. package/dist/esm/cli/commands/pull.js +109 -35
  29. package/dist/esm/cli/commands/push.js +49 -9
  30. package/dist/esm/cli/commands/rollback.js +206 -85
  31. package/dist/esm/cli/commands/schema-ast.js +183 -0
  32. package/dist/esm/cli/index.js +6 -0
  33. package/dist/esm/cli/utils/ast-codegen.js +93 -3
  34. package/dist/esm/cli/utils/ast-transformer.js +12 -0
  35. package/dist/esm/cli/utils/change-tracker.js +134 -0
  36. package/dist/esm/cli/utils/commit-manager.js +51 -0
  37. package/dist/esm/cli/utils/migration-generator.js +318 -0
  38. package/dist/esm/cli/utils/repo-manager.js +96 -3
  39. package/dist/esm/cli/utils/schema-diff.js +389 -0
  40. package/dist/esm/cli/utils/schema-hash.js +4 -0
  41. package/dist/esm/cli/utils/schema-to-ast.js +447 -0
  42. package/dist/esm/schema-definition/column-types.js +50 -4
  43. package/dist/esm/schema-definition/pg-enum.js +10 -0
  44. package/dist/esm/schema-definition/pg-function.js +19 -0
  45. package/dist/esm/schema-definition/pg-sequence.js +22 -1
  46. package/dist/esm/schema-definition/pg-trigger.js +39 -0
  47. package/dist/esm/schema-definition/pg-view.js +17 -0
  48. package/dist/esm/schema-definition/sql-expressions.js +3 -0
  49. package/dist/esm/schema-definition/table-definition.js +4 -0
  50. package/dist/index.d.ts +98 -0
  51. package/dist/schema-builder.d.ts +223 -24
  52. package/package.json +1 -1
@@ -475,3 +475,392 @@ export function getDestructiveTables(diff) {
475
475
  }
476
476
  return tables;
477
477
  }
478
+ export function compareSchemas(oldSchema, newSchema) {
479
+ const result = {
480
+ added: {
481
+ tables: [],
482
+ columns: [],
483
+ indexes: [],
484
+ enums: [],
485
+ domains: [],
486
+ compositeTypes: [],
487
+ sequences: [],
488
+ views: [],
489
+ functions: [],
490
+ triggers: [],
491
+ extensions: [],
492
+ },
493
+ removed: {
494
+ tables: [],
495
+ columns: [],
496
+ indexes: [],
497
+ enums: [],
498
+ domains: [],
499
+ compositeTypes: [],
500
+ sequences: [],
501
+ views: [],
502
+ functions: [],
503
+ triggers: [],
504
+ extensions: [],
505
+ },
506
+ renamed: {
507
+ tables: [],
508
+ columns: [],
509
+ indexes: [],
510
+ enums: [],
511
+ sequences: [],
512
+ functions: [],
513
+ },
514
+ modified: {
515
+ tables: [],
516
+ columns: [],
517
+ enums: [],
518
+ },
519
+ hasChanges: false,
520
+ };
521
+ compareTables(oldSchema.tables, newSchema.tables, result);
522
+ compareEnums(oldSchema.enums, newSchema.enums, result);
523
+ const oldExtensions = new Set(oldSchema.extensions);
524
+ const newExtensions = new Set(newSchema.extensions);
525
+ for (const ext of newExtensions) {
526
+ if (!oldExtensions.has(ext)) {
527
+ result.added.extensions.push(ext);
528
+ }
529
+ }
530
+ for (const ext of oldExtensions) {
531
+ if (!newExtensions.has(ext)) {
532
+ result.removed.extensions.push(ext);
533
+ }
534
+ }
535
+ compareByTrackingId(oldSchema.sequences, newSchema.sequences, (item) => item.name, (item) => item.trackingId, (item) => result.added.sequences.push(item), (item) => result.removed.sequences.push(item), (from, to, trackingId) => result.renamed.sequences.push({ from, to, trackingId }));
536
+ compareByTrackingId(oldSchema.functions, newSchema.functions, (item) => item.name, (item) => item.trackingId, (item) => result.added.functions.push(item), (item) => result.removed.functions.push(item), (from, to, trackingId) => result.renamed.functions.push({ from, to, trackingId }));
537
+ compareByName(oldSchema.views, newSchema.views, (item) => item.name, (item) => result.added.views.push(item), (item) => result.removed.views.push(item));
538
+ compareByName(oldSchema.triggers, newSchema.triggers, (item) => item.name, (item) => result.added.triggers.push(item), (item) => result.removed.triggers.push(item));
539
+ compareByName(oldSchema.domains, newSchema.domains, (item) => item.name, (item) => result.added.domains.push(item), (item) => result.removed.domains.push(item));
540
+ compareByName(oldSchema.compositeTypes, newSchema.compositeTypes, (item) => item.name, (item) => result.added.compositeTypes.push(item), (item) => result.removed.compositeTypes.push(item));
541
+ result.hasChanges =
542
+ result.added.tables.length > 0 ||
543
+ result.added.columns.length > 0 ||
544
+ result.added.indexes.length > 0 ||
545
+ result.added.enums.length > 0 ||
546
+ result.added.extensions.length > 0 ||
547
+ result.added.sequences.length > 0 ||
548
+ result.added.functions.length > 0 ||
549
+ result.added.views.length > 0 ||
550
+ result.added.triggers.length > 0 ||
551
+ result.added.domains.length > 0 ||
552
+ result.added.compositeTypes.length > 0 ||
553
+ result.removed.tables.length > 0 ||
554
+ result.removed.columns.length > 0 ||
555
+ result.removed.indexes.length > 0 ||
556
+ result.removed.enums.length > 0 ||
557
+ result.removed.extensions.length > 0 ||
558
+ result.removed.sequences.length > 0 ||
559
+ result.removed.functions.length > 0 ||
560
+ result.removed.views.length > 0 ||
561
+ result.removed.triggers.length > 0 ||
562
+ result.removed.domains.length > 0 ||
563
+ result.removed.compositeTypes.length > 0 ||
564
+ result.renamed.tables.length > 0 ||
565
+ result.renamed.columns.length > 0 ||
566
+ result.renamed.indexes.length > 0 ||
567
+ result.renamed.enums.length > 0 ||
568
+ result.renamed.sequences.length > 0 ||
569
+ result.renamed.functions.length > 0 ||
570
+ result.modified.tables.length > 0 ||
571
+ result.modified.columns.length > 0 ||
572
+ result.modified.enums.length > 0;
573
+ return result;
574
+ }
575
+ function compareTables(oldTables, newTables, result) {
576
+ const oldByName = new Map(oldTables.map(t => [t.name, t]));
577
+ const newByName = new Map(newTables.map(t => [t.name, t]));
578
+ const oldByTrackingId = new Map();
579
+ const newByTrackingId = new Map();
580
+ for (const t of oldTables) {
581
+ if (t.trackingId)
582
+ oldByTrackingId.set(t.trackingId, t);
583
+ }
584
+ for (const t of newTables) {
585
+ if (t.trackingId)
586
+ newByTrackingId.set(t.trackingId, t);
587
+ }
588
+ const processedOld = new Set();
589
+ const processedNew = new Set();
590
+ for (const [trackingId, oldTable] of oldByTrackingId) {
591
+ const newTable = newByTrackingId.get(trackingId);
592
+ if (newTable && newTable.name !== oldTable.name) {
593
+ result.renamed.tables.push({
594
+ from: oldTable.name,
595
+ to: newTable.name,
596
+ trackingId,
597
+ });
598
+ processedOld.add(oldTable.name);
599
+ processedNew.add(newTable.name);
600
+ compareTableColumns(oldTable, newTable, newTable.name, result);
601
+ }
602
+ }
603
+ for (const [name, newTable] of newByName) {
604
+ if (processedNew.has(name))
605
+ continue;
606
+ const oldTable = oldByName.get(name);
607
+ if (oldTable) {
608
+ processedOld.add(name);
609
+ compareTableColumns(oldTable, newTable, name, result);
610
+ }
611
+ else {
612
+ result.added.tables.push(newTable);
613
+ }
614
+ }
615
+ for (const [name, oldTable] of oldByName) {
616
+ if (processedOld.has(name))
617
+ continue;
618
+ if (!newByName.has(name)) {
619
+ result.removed.tables.push(oldTable);
620
+ }
621
+ }
622
+ }
623
+ function compareTableColumns(oldTable, newTable, tableName, result) {
624
+ const oldByName = new Map(oldTable.columns.map(c => [c.name, c]));
625
+ const newByName = new Map(newTable.columns.map(c => [c.name, c]));
626
+ const oldByTrackingId = new Map();
627
+ const newByTrackingId = new Map();
628
+ for (const c of oldTable.columns) {
629
+ if (c.trackingId)
630
+ oldByTrackingId.set(c.trackingId, c);
631
+ }
632
+ for (const c of newTable.columns) {
633
+ if (c.trackingId)
634
+ newByTrackingId.set(c.trackingId, c);
635
+ }
636
+ const processedOld = new Set();
637
+ const processedNew = new Set();
638
+ for (const [trackingId, oldCol] of oldByTrackingId) {
639
+ const newCol = newByTrackingId.get(trackingId);
640
+ if (newCol && newCol.name !== oldCol.name) {
641
+ result.renamed.columns.push({
642
+ table: tableName,
643
+ from: oldCol.name,
644
+ to: newCol.name,
645
+ trackingId,
646
+ });
647
+ processedOld.add(oldCol.name);
648
+ processedNew.add(newCol.name);
649
+ const changes = compareColumnProperties(oldCol, newCol);
650
+ if (changes.length > 0) {
651
+ result.modified.columns.push({
652
+ table: tableName,
653
+ column: newCol.name,
654
+ changes,
655
+ });
656
+ }
657
+ }
658
+ }
659
+ for (const [name, newCol] of newByName) {
660
+ if (processedNew.has(name))
661
+ continue;
662
+ const oldCol = oldByName.get(name);
663
+ if (oldCol) {
664
+ processedOld.add(name);
665
+ const changes = compareColumnProperties(oldCol, newCol);
666
+ if (changes.length > 0) {
667
+ result.modified.columns.push({
668
+ table: tableName,
669
+ column: name,
670
+ changes,
671
+ });
672
+ }
673
+ }
674
+ else {
675
+ result.added.columns.push({ table: tableName, column: newCol });
676
+ }
677
+ }
678
+ for (const [name, oldCol] of oldByName) {
679
+ if (processedOld.has(name))
680
+ continue;
681
+ if (!newByName.has(name)) {
682
+ result.removed.columns.push({ table: tableName, column: oldCol });
683
+ }
684
+ }
685
+ compareTableIndexes(oldTable, newTable, tableName, result);
686
+ }
687
+ function compareColumnProperties(oldCol, newCol) {
688
+ const changes = [];
689
+ const oldType = normalizeType(oldCol.type);
690
+ const newType = normalizeType(newCol.type);
691
+ if (oldType !== newType) {
692
+ changes.push({ field: 'type', from: oldCol.type, to: newCol.type });
693
+ }
694
+ if (oldCol.isNullable !== newCol.isNullable) {
695
+ changes.push({ field: 'nullable', from: oldCol.isNullable, to: newCol.isNullable });
696
+ }
697
+ if (oldCol.isPrimaryKey !== newCol.isPrimaryKey) {
698
+ changes.push({ field: 'primaryKey', from: oldCol.isPrimaryKey, to: newCol.isPrimaryKey });
699
+ }
700
+ if (oldCol.isUnique !== newCol.isUnique) {
701
+ changes.push({ field: 'unique', from: oldCol.isUnique, to: newCol.isUnique });
702
+ }
703
+ if (oldCol.defaultValue !== newCol.defaultValue) {
704
+ changes.push({ field: 'default', from: oldCol.defaultValue, to: newCol.defaultValue });
705
+ }
706
+ return changes;
707
+ }
708
+ function compareTableIndexes(oldTable, newTable, tableName, result) {
709
+ const oldByName = new Map(oldTable.indexes.map(i => [i.name, i]));
710
+ const newByName = new Map(newTable.indexes.map(i => [i.name, i]));
711
+ const oldByTrackingId = new Map();
712
+ const newByTrackingId = new Map();
713
+ for (const i of oldTable.indexes) {
714
+ if (i.trackingId)
715
+ oldByTrackingId.set(i.trackingId, i);
716
+ }
717
+ for (const i of newTable.indexes) {
718
+ if (i.trackingId)
719
+ newByTrackingId.set(i.trackingId, i);
720
+ }
721
+ const processedOld = new Set();
722
+ const processedNew = new Set();
723
+ for (const [trackingId, oldIdx] of oldByTrackingId) {
724
+ const newIdx = newByTrackingId.get(trackingId);
725
+ if (newIdx && newIdx.name !== oldIdx.name) {
726
+ result.renamed.indexes.push({
727
+ table: tableName,
728
+ from: oldIdx.name,
729
+ to: newIdx.name,
730
+ trackingId,
731
+ });
732
+ processedOld.add(oldIdx.name);
733
+ processedNew.add(newIdx.name);
734
+ }
735
+ }
736
+ for (const [name, newIdx] of newByName) {
737
+ if (processedNew.has(name))
738
+ continue;
739
+ if (!oldByName.has(name)) {
740
+ result.added.indexes.push({ table: tableName, index: newIdx });
741
+ }
742
+ }
743
+ for (const [name, oldIdx] of oldByName) {
744
+ if (processedOld.has(name))
745
+ continue;
746
+ if (!newByName.has(name)) {
747
+ result.removed.indexes.push({ table: tableName, index: oldIdx });
748
+ }
749
+ }
750
+ }
751
+ function compareEnums(oldEnums, newEnums, result) {
752
+ const oldByName = new Map(oldEnums.map(e => [e.name, e]));
753
+ const newByName = new Map(newEnums.map(e => [e.name, e]));
754
+ const oldByTrackingId = new Map();
755
+ const newByTrackingId = new Map();
756
+ for (const e of oldEnums) {
757
+ if (e.trackingId)
758
+ oldByTrackingId.set(e.trackingId, e);
759
+ }
760
+ for (const e of newEnums) {
761
+ if (e.trackingId)
762
+ newByTrackingId.set(e.trackingId, e);
763
+ }
764
+ const processedOld = new Set();
765
+ const processedNew = new Set();
766
+ for (const [trackingId, oldEnum] of oldByTrackingId) {
767
+ const newEnum = newByTrackingId.get(trackingId);
768
+ if (newEnum && newEnum.name !== oldEnum.name) {
769
+ result.renamed.enums.push({
770
+ from: oldEnum.name,
771
+ to: newEnum.name,
772
+ trackingId,
773
+ });
774
+ processedOld.add(oldEnum.name);
775
+ processedNew.add(newEnum.name);
776
+ const added = newEnum.values.filter(v => !oldEnum.values.includes(v));
777
+ const removed = oldEnum.values.filter(v => !newEnum.values.includes(v));
778
+ if (added.length > 0 || removed.length > 0) {
779
+ result.modified.enums.push({
780
+ name: newEnum.name,
781
+ changes: { added, removed },
782
+ });
783
+ }
784
+ }
785
+ }
786
+ for (const [name, newEnum] of newByName) {
787
+ if (processedNew.has(name))
788
+ continue;
789
+ const oldEnum = oldByName.get(name);
790
+ if (oldEnum) {
791
+ processedOld.add(name);
792
+ const added = newEnum.values.filter(v => !oldEnum.values.includes(v));
793
+ const removed = oldEnum.values.filter(v => !newEnum.values.includes(v));
794
+ if (added.length > 0 || removed.length > 0) {
795
+ result.modified.enums.push({
796
+ name,
797
+ changes: { added, removed },
798
+ });
799
+ }
800
+ }
801
+ else {
802
+ result.added.enums.push(newEnum);
803
+ }
804
+ }
805
+ for (const [name, oldEnum] of oldByName) {
806
+ if (processedOld.has(name))
807
+ continue;
808
+ if (!newByName.has(name)) {
809
+ result.removed.enums.push(oldEnum);
810
+ }
811
+ }
812
+ }
813
+ function compareByTrackingId(oldItems, newItems, getName, getTrackingId, onAdd, onRemove, onRename) {
814
+ const oldByName = new Map(oldItems.map(item => [getName(item), item]));
815
+ const newByName = new Map(newItems.map(item => [getName(item), item]));
816
+ const oldByTrackingId = new Map();
817
+ const newByTrackingId = new Map();
818
+ for (const item of oldItems) {
819
+ const tid = getTrackingId(item);
820
+ if (tid)
821
+ oldByTrackingId.set(tid, item);
822
+ }
823
+ for (const item of newItems) {
824
+ const tid = getTrackingId(item);
825
+ if (tid)
826
+ newByTrackingId.set(tid, item);
827
+ }
828
+ const processedOld = new Set();
829
+ const processedNew = new Set();
830
+ for (const [trackingId, oldItem] of oldByTrackingId) {
831
+ const newItem = newByTrackingId.get(trackingId);
832
+ if (newItem && getName(newItem) !== getName(oldItem)) {
833
+ onRename(getName(oldItem), getName(newItem), trackingId);
834
+ processedOld.add(getName(oldItem));
835
+ processedNew.add(getName(newItem));
836
+ }
837
+ }
838
+ for (const [name, item] of newByName) {
839
+ if (processedNew.has(name))
840
+ continue;
841
+ if (!oldByName.has(name)) {
842
+ onAdd(item);
843
+ }
844
+ }
845
+ for (const [name, item] of oldByName) {
846
+ if (processedOld.has(name))
847
+ continue;
848
+ if (!newByName.has(name)) {
849
+ onRemove(item);
850
+ }
851
+ }
852
+ }
853
+ function compareByName(oldItems, newItems, getName, onAdd, onRemove) {
854
+ const oldNames = new Set(oldItems.map(getName));
855
+ const newNames = new Set(newItems.map(getName));
856
+ for (const item of newItems) {
857
+ if (!oldNames.has(getName(item))) {
858
+ onAdd(item);
859
+ }
860
+ }
861
+ for (const item of oldItems) {
862
+ if (!newNames.has(getName(item))) {
863
+ onRemove(item);
864
+ }
865
+ }
866
+ }
@@ -26,6 +26,7 @@ function normalizeTable(table) {
26
26
  isPartitioned: table.isPartitioned,
27
27
  partitionType: table.partitionType,
28
28
  partitionKey: table.partitionKey ? [...table.partitionKey] : undefined,
29
+ trackingId: table.trackingId,
29
30
  };
30
31
  }
31
32
  function normalizeColumn(col) {
@@ -37,6 +38,7 @@ function normalizeColumn(col) {
37
38
  isPrimaryKey: col.isPrimaryKey,
38
39
  isUnique: col.isUnique,
39
40
  length: col.maxLength || undefined,
41
+ trackingId: col.trackingId,
40
42
  };
41
43
  }
42
44
  function normalizeIndex(idx) {
@@ -45,6 +47,7 @@ function normalizeIndex(idx) {
45
47
  columns: [...idx.columns].sort(),
46
48
  unique: idx.isUnique,
47
49
  type: idx.type?.toUpperCase(),
50
+ trackingId: idx.trackingId,
48
51
  };
49
52
  }
50
53
  function normalizeConstraint(con) {
@@ -52,6 +55,7 @@ function normalizeConstraint(con) {
52
55
  name: con.name,
53
56
  type: con.type.toUpperCase(),
54
57
  definition: con.definition || undefined,
58
+ trackingId: con.trackingId,
55
59
  };
56
60
  }
57
61
  export function generateSchemaHash(schema) {