pocketbase-zod-schema 0.2.5 → 0.3.1
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/CHANGELOG.md +16 -0
- package/dist/cli/index.cjs +497 -298
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +2 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.js +497 -298
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/migrate.cjs +497 -298
- package/dist/cli/migrate.cjs.map +1 -1
- package/dist/cli/migrate.js +497 -298
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/utils/index.d.cts +2 -2
- package/dist/cli/utils/index.d.ts +2 -2
- package/dist/{fields-YjcpBXVp.d.cts → fields-RVj26U-O.d.cts} +17 -0
- package/dist/{fields-YjcpBXVp.d.ts → fields-RVj26U-O.d.ts} +17 -0
- package/dist/index.cjs +575 -155
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +576 -144
- package/dist/index.js.map +1 -1
- package/dist/migration/analyzer.cjs +12 -2
- package/dist/migration/analyzer.cjs.map +1 -1
- package/dist/migration/analyzer.d.cts +2 -2
- package/dist/migration/analyzer.d.ts +2 -2
- package/dist/migration/analyzer.js +12 -2
- package/dist/migration/analyzer.js.map +1 -1
- package/dist/migration/diff.cjs +150 -24
- package/dist/migration/diff.cjs.map +1 -1
- package/dist/migration/diff.d.cts +4 -4
- package/dist/migration/diff.d.ts +4 -4
- package/dist/migration/diff.js +150 -24
- package/dist/migration/diff.js.map +1 -1
- package/dist/migration/generator.cjs +360 -46
- package/dist/migration/generator.cjs.map +1 -1
- package/dist/migration/generator.d.cts +59 -12
- package/dist/migration/generator.d.ts +59 -12
- package/dist/migration/generator.js +356 -47
- package/dist/migration/generator.js.map +1 -1
- package/dist/migration/index.cjs +561 -90
- package/dist/migration/index.cjs.map +1 -1
- package/dist/migration/index.d.cts +3 -3
- package/dist/migration/index.d.ts +3 -3
- package/dist/migration/index.js +561 -90
- package/dist/migration/index.js.map +1 -1
- package/dist/migration/snapshot.cjs +51 -18
- package/dist/migration/snapshot.cjs.map +1 -1
- package/dist/migration/snapshot.d.cts +2 -2
- package/dist/migration/snapshot.d.ts +2 -2
- package/dist/migration/snapshot.js +51 -18
- package/dist/migration/snapshot.js.map +1 -1
- package/dist/migration/utils/index.cjs +66 -0
- package/dist/migration/utils/index.cjs.map +1 -1
- package/dist/migration/utils/index.d.cts +39 -202
- package/dist/migration/utils/index.d.ts +39 -202
- package/dist/migration/utils/index.js +65 -1
- package/dist/migration/utils/index.js.map +1 -1
- package/dist/schema.cjs +0 -61
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +2 -86
- package/dist/schema.d.ts +2 -86
- package/dist/schema.js +1 -50
- package/dist/schema.js.map +1 -1
- package/dist/type-mapper-CZzVeDj7.d.ts +208 -0
- package/dist/type-mapper-DaBe-1ph.d.cts +208 -0
- package/dist/{types-LFBGHl9Y.d.ts → types-CUVzgZ9k.d.ts} +33 -2
- package/dist/{types-mhQXWNi3.d.cts → types-D-Fsdn_O.d.cts} +33 -2
- package/package.json +1 -1
package/dist/migration/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var fs3 = require('fs');
|
|
4
4
|
var path = require('path');
|
|
5
5
|
var zod = require('zod');
|
|
6
|
+
var crypto = require('crypto');
|
|
6
7
|
|
|
7
8
|
function _interopNamespace(e) {
|
|
8
9
|
if (e && e.__esModule) return e;
|
|
@@ -1581,12 +1582,22 @@ function isAuthCollection(fields) {
|
|
|
1581
1582
|
function buildFieldDefinition(fieldName, zodType) {
|
|
1582
1583
|
const fieldMetadata = extractFieldMetadata(zodType.description);
|
|
1583
1584
|
if (fieldMetadata) {
|
|
1584
|
-
|
|
1585
|
+
let required2;
|
|
1586
|
+
if (fieldMetadata.type === "number") {
|
|
1587
|
+
if (fieldMetadata.options?.required !== void 0) {
|
|
1588
|
+
required2 = fieldMetadata.options.required;
|
|
1589
|
+
} else {
|
|
1590
|
+
required2 = false;
|
|
1591
|
+
}
|
|
1592
|
+
} else {
|
|
1593
|
+
required2 = isFieldRequired(zodType);
|
|
1594
|
+
}
|
|
1595
|
+
const { required: _required, ...options2 } = fieldMetadata.options || {};
|
|
1585
1596
|
const fieldDef2 = {
|
|
1586
1597
|
name: fieldName,
|
|
1587
1598
|
type: fieldMetadata.type,
|
|
1588
1599
|
required: required2,
|
|
1589
|
-
options:
|
|
1600
|
+
options: Object.keys(options2).length > 0 ? options2 : void 0
|
|
1590
1601
|
};
|
|
1591
1602
|
if (fieldMetadata.type === "relation") {
|
|
1592
1603
|
const relationMetadata2 = extractRelationMetadata(zodType.description);
|
|
@@ -1785,7 +1796,7 @@ var SchemaAnalyzer = class {
|
|
|
1785
1796
|
var SNAPSHOT_VERSION = "1.0.0";
|
|
1786
1797
|
function resolveCollectionIdToName(collectionId) {
|
|
1787
1798
|
if (collectionId === "_pb_users_auth_") {
|
|
1788
|
-
return "
|
|
1799
|
+
return "users";
|
|
1789
1800
|
}
|
|
1790
1801
|
const nameMatch = collectionId.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
1791
1802
|
if (nameMatch) {
|
|
@@ -1793,6 +1804,39 @@ function resolveCollectionIdToName(collectionId) {
|
|
|
1793
1804
|
}
|
|
1794
1805
|
return collectionId;
|
|
1795
1806
|
}
|
|
1807
|
+
function extractFieldOptions2(pbField) {
|
|
1808
|
+
const options = {};
|
|
1809
|
+
if (pbField.options && typeof pbField.options === "object") {
|
|
1810
|
+
Object.assign(options, pbField.options);
|
|
1811
|
+
}
|
|
1812
|
+
const directOptionKeys = [
|
|
1813
|
+
"min",
|
|
1814
|
+
"max",
|
|
1815
|
+
"pattern",
|
|
1816
|
+
"noDecimal",
|
|
1817
|
+
// text/number fields
|
|
1818
|
+
"values",
|
|
1819
|
+
"maxSelect",
|
|
1820
|
+
// select fields
|
|
1821
|
+
"mimeTypes",
|
|
1822
|
+
"maxSize",
|
|
1823
|
+
"thumbs",
|
|
1824
|
+
"protected",
|
|
1825
|
+
// file fields
|
|
1826
|
+
"onCreate",
|
|
1827
|
+
"onUpdate",
|
|
1828
|
+
// autodate fields
|
|
1829
|
+
"exceptDomains",
|
|
1830
|
+
"onlyDomains"
|
|
1831
|
+
// email/url fields
|
|
1832
|
+
];
|
|
1833
|
+
for (const key of directOptionKeys) {
|
|
1834
|
+
if (pbField[key] !== void 0) {
|
|
1835
|
+
options[key] = pbField[key];
|
|
1836
|
+
}
|
|
1837
|
+
}
|
|
1838
|
+
return options;
|
|
1839
|
+
}
|
|
1796
1840
|
function convertPocketBaseCollection(pbCollection) {
|
|
1797
1841
|
const fields = [];
|
|
1798
1842
|
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
@@ -1810,23 +1854,19 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
1810
1854
|
type: pbField.type,
|
|
1811
1855
|
required: pbField.required || false
|
|
1812
1856
|
};
|
|
1813
|
-
field.options = pbField
|
|
1814
|
-
if (pbField.type === "select") {
|
|
1815
|
-
if (pbField.values && Array.isArray(pbField.values)) {
|
|
1816
|
-
field.options.values = pbField.values;
|
|
1817
|
-
} else if (pbField.options?.values && Array.isArray(pbField.options.values)) {
|
|
1818
|
-
field.options.values = pbField.options.values;
|
|
1819
|
-
}
|
|
1820
|
-
}
|
|
1857
|
+
field.options = extractFieldOptions2(pbField);
|
|
1821
1858
|
if (pbField.type === "relation") {
|
|
1822
1859
|
const collectionId = pbField.collectionId || pbField.options?.collectionId || "";
|
|
1823
|
-
const collectionName = resolveCollectionIdToName(collectionId);
|
|
1860
|
+
const collectionName = resolveCollectionIdToName(collectionId || "");
|
|
1824
1861
|
field.relation = {
|
|
1825
1862
|
collection: collectionName,
|
|
1826
1863
|
cascadeDelete: pbField.cascadeDelete ?? pbField.options?.cascadeDelete ?? false,
|
|
1827
1864
|
maxSelect: pbField.maxSelect ?? pbField.options?.maxSelect,
|
|
1828
1865
|
minSelect: pbField.minSelect ?? pbField.options?.minSelect
|
|
1829
1866
|
};
|
|
1867
|
+
delete field.options.maxSelect;
|
|
1868
|
+
delete field.options.minSelect;
|
|
1869
|
+
delete field.options.cascadeDelete;
|
|
1830
1870
|
}
|
|
1831
1871
|
const hasOnlyValues = Object.keys(field.options).length === 1 && field.options.values !== void 0;
|
|
1832
1872
|
if (Object.keys(field.options).length === 0) {
|
|
@@ -1840,17 +1880,21 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
1840
1880
|
type: pbCollection.type || "base",
|
|
1841
1881
|
fields
|
|
1842
1882
|
};
|
|
1883
|
+
if (pbCollection.id) {
|
|
1884
|
+
schema.id = pbCollection.id;
|
|
1885
|
+
}
|
|
1843
1886
|
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
1844
1887
|
schema.indexes = pbCollection.indexes;
|
|
1845
1888
|
}
|
|
1846
|
-
const
|
|
1847
|
-
if (
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1889
|
+
const hasAnyRule = pbCollection.listRule !== void 0 || pbCollection.viewRule !== void 0 || pbCollection.createRule !== void 0 || pbCollection.updateRule !== void 0 || pbCollection.deleteRule !== void 0 || pbCollection.manageRule !== void 0;
|
|
1890
|
+
if (hasAnyRule) {
|
|
1891
|
+
const rules = {};
|
|
1892
|
+
if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
|
|
1893
|
+
if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
|
|
1894
|
+
if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
|
|
1895
|
+
if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
|
|
1896
|
+
if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
|
|
1897
|
+
if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
|
|
1854
1898
|
schema.rules = rules;
|
|
1855
1899
|
schema.permissions = { ...rules };
|
|
1856
1900
|
}
|
|
@@ -2582,6 +2626,67 @@ var SnapshotManager = class {
|
|
|
2582
2626
|
return validateSnapshot(snapshot);
|
|
2583
2627
|
}
|
|
2584
2628
|
};
|
|
2629
|
+
function generateCollectionId() {
|
|
2630
|
+
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
2631
|
+
const idLength = 15;
|
|
2632
|
+
const bytes = crypto.randomBytes(idLength);
|
|
2633
|
+
let id = "pb_";
|
|
2634
|
+
for (let i = 0; i < idLength; i++) {
|
|
2635
|
+
const index = bytes[i] % chars.length;
|
|
2636
|
+
id += chars[index];
|
|
2637
|
+
}
|
|
2638
|
+
return id;
|
|
2639
|
+
}
|
|
2640
|
+
var CollectionIdRegistry = class {
|
|
2641
|
+
ids;
|
|
2642
|
+
constructor() {
|
|
2643
|
+
this.ids = /* @__PURE__ */ new Set();
|
|
2644
|
+
}
|
|
2645
|
+
/**
|
|
2646
|
+
* Generates a unique collection ID for a given collection name
|
|
2647
|
+
* Retries up to 10 times if collision occurs (extremely rare)
|
|
2648
|
+
* Special case: returns "_pb_users_auth_" for users collection
|
|
2649
|
+
*
|
|
2650
|
+
* @param collectionName - The name of the collection (optional)
|
|
2651
|
+
* @returns A unique collection ID
|
|
2652
|
+
* @throws Error if unable to generate unique ID after max attempts
|
|
2653
|
+
*/
|
|
2654
|
+
generate(collectionName) {
|
|
2655
|
+
if (collectionName && collectionName.toLowerCase() === "users") {
|
|
2656
|
+
const usersId = "_pb_users_auth_";
|
|
2657
|
+
if (!this.has(usersId)) {
|
|
2658
|
+
this.register(usersId);
|
|
2659
|
+
}
|
|
2660
|
+
return usersId;
|
|
2661
|
+
}
|
|
2662
|
+
const maxAttempts = 10;
|
|
2663
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
2664
|
+
const id = generateCollectionId();
|
|
2665
|
+
if (!this.has(id)) {
|
|
2666
|
+
this.register(id);
|
|
2667
|
+
return id;
|
|
2668
|
+
}
|
|
2669
|
+
}
|
|
2670
|
+
throw new Error("Failed to generate unique collection ID after maximum attempts");
|
|
2671
|
+
}
|
|
2672
|
+
/**
|
|
2673
|
+
* Checks if an ID has already been registered
|
|
2674
|
+
*
|
|
2675
|
+
* @param id - The collection ID to check
|
|
2676
|
+
* @returns True if the ID exists in the registry
|
|
2677
|
+
*/
|
|
2678
|
+
has(id) {
|
|
2679
|
+
return this.ids.has(id);
|
|
2680
|
+
}
|
|
2681
|
+
/**
|
|
2682
|
+
* Registers a collection ID in the registry
|
|
2683
|
+
*
|
|
2684
|
+
* @param id - The collection ID to register
|
|
2685
|
+
*/
|
|
2686
|
+
register(id) {
|
|
2687
|
+
this.ids.add(id);
|
|
2688
|
+
}
|
|
2689
|
+
};
|
|
2585
2690
|
|
|
2586
2691
|
// src/migration/diff.ts
|
|
2587
2692
|
var DEFAULT_CONFIG3 = {
|
|
@@ -2735,18 +2840,49 @@ function compareFieldConstraints(currentField, previousField) {
|
|
|
2735
2840
|
}
|
|
2736
2841
|
return changes;
|
|
2737
2842
|
}
|
|
2843
|
+
function normalizeOptionValue(key, value, fieldType) {
|
|
2844
|
+
if (key === "maxSelect" && value === 1 && (fieldType === "select" || fieldType === "file")) {
|
|
2845
|
+
return void 0;
|
|
2846
|
+
}
|
|
2847
|
+
if (key === "maxSize" && value === 0 && fieldType === "file") {
|
|
2848
|
+
return void 0;
|
|
2849
|
+
}
|
|
2850
|
+
if (fieldType === "file") {
|
|
2851
|
+
if (key === "mimeTypes" && Array.isArray(value) && value.length === 0) {
|
|
2852
|
+
return void 0;
|
|
2853
|
+
}
|
|
2854
|
+
if (key === "thumbs" && Array.isArray(value) && value.length === 0) {
|
|
2855
|
+
return void 0;
|
|
2856
|
+
}
|
|
2857
|
+
if (key === "protected" && value === false) {
|
|
2858
|
+
return void 0;
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
if (fieldType === "autodate") {
|
|
2862
|
+
if (key === "onCreate" && value === true) {
|
|
2863
|
+
return void 0;
|
|
2864
|
+
}
|
|
2865
|
+
if (key === "onUpdate" && value === false) {
|
|
2866
|
+
return void 0;
|
|
2867
|
+
}
|
|
2868
|
+
}
|
|
2869
|
+
return value;
|
|
2870
|
+
}
|
|
2738
2871
|
function compareFieldOptions(currentField, previousField) {
|
|
2739
2872
|
const changes = [];
|
|
2740
2873
|
const currentOptions = currentField.options || {};
|
|
2741
2874
|
const previousOptions = previousField.options || {};
|
|
2742
2875
|
const allKeys = /* @__PURE__ */ new Set([...Object.keys(currentOptions), ...Object.keys(previousOptions)]);
|
|
2876
|
+
const fieldType = currentField.type;
|
|
2743
2877
|
for (const key of allKeys) {
|
|
2744
2878
|
const currentValue = currentOptions[key];
|
|
2745
2879
|
const previousValue = previousOptions[key];
|
|
2746
|
-
|
|
2880
|
+
const normalizedCurrent = normalizeOptionValue(key, currentValue, fieldType);
|
|
2881
|
+
const normalizedPrevious = normalizeOptionValue(key, previousValue, fieldType);
|
|
2882
|
+
if (normalizedCurrent === void 0 && normalizedPrevious === void 0) {
|
|
2747
2883
|
continue;
|
|
2748
2884
|
}
|
|
2749
|
-
if (!areValuesEqual(
|
|
2885
|
+
if (!areValuesEqual(normalizedCurrent, normalizedPrevious)) {
|
|
2750
2886
|
changes.push({
|
|
2751
2887
|
property: `options.${key}`,
|
|
2752
2888
|
oldValue: previousValue,
|
|
@@ -2756,7 +2892,7 @@ function compareFieldOptions(currentField, previousField) {
|
|
|
2756
2892
|
}
|
|
2757
2893
|
return changes;
|
|
2758
2894
|
}
|
|
2759
|
-
function compareRelationConfigurations(currentField, previousField) {
|
|
2895
|
+
function compareRelationConfigurations(currentField, previousField, collectionIdToName) {
|
|
2760
2896
|
const changes = [];
|
|
2761
2897
|
const currentRelation = currentField.relation;
|
|
2762
2898
|
const previousRelation = previousField.relation;
|
|
@@ -2768,8 +2904,8 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
2768
2904
|
}
|
|
2769
2905
|
const normalizeCollection = (collection) => {
|
|
2770
2906
|
if (!collection) return collection;
|
|
2771
|
-
if (
|
|
2772
|
-
return
|
|
2907
|
+
if (collectionIdToName && collectionIdToName.has(collection)) {
|
|
2908
|
+
return collectionIdToName.get(collection);
|
|
2773
2909
|
}
|
|
2774
2910
|
const nameMatch = collection.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
2775
2911
|
if (nameMatch) {
|
|
@@ -2779,13 +2915,11 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
2779
2915
|
};
|
|
2780
2916
|
const normalizedCurrent = normalizeCollection(currentRelation.collection);
|
|
2781
2917
|
const normalizedPrevious = normalizeCollection(previousRelation.collection);
|
|
2782
|
-
if (normalizedCurrent !== normalizedPrevious) {
|
|
2918
|
+
if (normalizedCurrent.toLowerCase() !== normalizedPrevious.toLowerCase()) {
|
|
2783
2919
|
changes.push({
|
|
2784
2920
|
property: "relation.collection",
|
|
2785
|
-
oldValue:
|
|
2786
|
-
|
|
2787
|
-
newValue: normalizedCurrent
|
|
2788
|
-
// Use normalized value for clarity
|
|
2921
|
+
oldValue: previousRelation.collection,
|
|
2922
|
+
newValue: currentRelation.collection
|
|
2789
2923
|
});
|
|
2790
2924
|
}
|
|
2791
2925
|
if (currentRelation.cascadeDelete !== previousRelation.cascadeDelete) {
|
|
@@ -2795,14 +2929,20 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
2795
2929
|
newValue: currentRelation.cascadeDelete
|
|
2796
2930
|
});
|
|
2797
2931
|
}
|
|
2798
|
-
|
|
2932
|
+
const normalizeMax = (val) => val === 1 ? null : val;
|
|
2933
|
+
const currentMax = normalizeMax(currentRelation.maxSelect);
|
|
2934
|
+
const previousMax = normalizeMax(previousRelation.maxSelect);
|
|
2935
|
+
if (currentMax != previousMax) {
|
|
2799
2936
|
changes.push({
|
|
2800
2937
|
property: "relation.maxSelect",
|
|
2801
2938
|
oldValue: previousRelation.maxSelect,
|
|
2802
2939
|
newValue: currentRelation.maxSelect
|
|
2803
2940
|
});
|
|
2804
2941
|
}
|
|
2805
|
-
|
|
2942
|
+
const normalizeMin = (val) => val === 0 ? null : val;
|
|
2943
|
+
const currentMin = normalizeMin(currentRelation.minSelect);
|
|
2944
|
+
const previousMin = normalizeMin(previousRelation.minSelect);
|
|
2945
|
+
if (currentMin != previousMin) {
|
|
2806
2946
|
changes.push({
|
|
2807
2947
|
property: "relation.minSelect",
|
|
2808
2948
|
oldValue: previousRelation.minSelect,
|
|
@@ -2811,7 +2951,7 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
2811
2951
|
}
|
|
2812
2952
|
return changes;
|
|
2813
2953
|
}
|
|
2814
|
-
function detectFieldChanges(currentField, previousField) {
|
|
2954
|
+
function detectFieldChanges(currentField, previousField, collectionIdToName) {
|
|
2815
2955
|
const changes = [];
|
|
2816
2956
|
const typeChange = compareFieldTypes(currentField, previousField);
|
|
2817
2957
|
if (typeChange) {
|
|
@@ -2820,7 +2960,7 @@ function detectFieldChanges(currentField, previousField) {
|
|
|
2820
2960
|
changes.push(...compareFieldConstraints(currentField, previousField));
|
|
2821
2961
|
changes.push(...compareFieldOptions(currentField, previousField));
|
|
2822
2962
|
if (currentField.type === "relation" && previousField.type === "relation") {
|
|
2823
|
-
changes.push(...compareRelationConfigurations(currentField, previousField));
|
|
2963
|
+
changes.push(...compareRelationConfigurations(currentField, previousField, collectionIdToName));
|
|
2824
2964
|
}
|
|
2825
2965
|
return changes;
|
|
2826
2966
|
}
|
|
@@ -2831,7 +2971,7 @@ function compareIndexes(currentIndexes = [], previousIndexes = []) {
|
|
|
2831
2971
|
const indexesToRemove = previousIndexes.filter((idx) => !currentSet.has(idx));
|
|
2832
2972
|
return { indexesToAdd, indexesToRemove };
|
|
2833
2973
|
}
|
|
2834
|
-
function compareRules(currentRules, previousRules) {
|
|
2974
|
+
function compareRules(currentRules, previousRules, currentPermissions, previousPermissions) {
|
|
2835
2975
|
const updates = [];
|
|
2836
2976
|
const ruleTypes = [
|
|
2837
2977
|
"listRule",
|
|
@@ -2842,8 +2982,8 @@ function compareRules(currentRules, previousRules) {
|
|
|
2842
2982
|
"manageRule"
|
|
2843
2983
|
];
|
|
2844
2984
|
for (const ruleType of ruleTypes) {
|
|
2845
|
-
const currentValue = currentRules?.[ruleType] ?? null;
|
|
2846
|
-
const previousValue = previousRules?.[ruleType] ?? null;
|
|
2985
|
+
const currentValue = currentRules?.[ruleType] ?? currentPermissions?.[ruleType] ?? null;
|
|
2986
|
+
const previousValue = previousRules?.[ruleType] ?? previousPermissions?.[ruleType] ?? null;
|
|
2847
2987
|
if (currentValue !== previousValue) {
|
|
2848
2988
|
updates.push({
|
|
2849
2989
|
ruleType,
|
|
@@ -2870,7 +3010,7 @@ function comparePermissions(currentPermissions, previousPermissions) {
|
|
|
2870
3010
|
}
|
|
2871
3011
|
return changes;
|
|
2872
3012
|
}
|
|
2873
|
-
function compareCollectionFields(currentCollection, previousCollection, config) {
|
|
3013
|
+
function compareCollectionFields(currentCollection, previousCollection, config, collectionIdToName) {
|
|
2874
3014
|
let fieldsToAdd = findNewFields(currentCollection.fields, previousCollection.fields);
|
|
2875
3015
|
const fieldsToRemove = findRemovedFields(currentCollection.fields, previousCollection.fields);
|
|
2876
3016
|
const fieldsToModify = [];
|
|
@@ -2880,7 +3020,7 @@ function compareCollectionFields(currentCollection, previousCollection, config)
|
|
|
2880
3020
|
}
|
|
2881
3021
|
const matchedFields = matchFieldsByName(currentCollection.fields, previousCollection.fields);
|
|
2882
3022
|
for (const [currentField, previousField] of matchedFields) {
|
|
2883
|
-
const changes = detectFieldChanges(currentField, previousField);
|
|
3023
|
+
const changes = detectFieldChanges(currentField, previousField, collectionIdToName);
|
|
2884
3024
|
if (changes.length > 0) {
|
|
2885
3025
|
fieldsToModify.push({
|
|
2886
3026
|
fieldName: currentField.name,
|
|
@@ -2892,14 +3032,20 @@ function compareCollectionFields(currentCollection, previousCollection, config)
|
|
|
2892
3032
|
}
|
|
2893
3033
|
return { fieldsToAdd, fieldsToRemove, fieldsToModify };
|
|
2894
3034
|
}
|
|
2895
|
-
function buildCollectionModification(currentCollection, previousCollection, config) {
|
|
3035
|
+
function buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName) {
|
|
2896
3036
|
const { fieldsToAdd, fieldsToRemove, fieldsToModify } = compareCollectionFields(
|
|
2897
3037
|
currentCollection,
|
|
2898
3038
|
previousCollection,
|
|
2899
|
-
config
|
|
3039
|
+
config,
|
|
3040
|
+
collectionIdToName
|
|
2900
3041
|
);
|
|
2901
3042
|
const { indexesToAdd, indexesToRemove } = compareIndexes(currentCollection.indexes, previousCollection.indexes);
|
|
2902
|
-
const rulesToUpdate = compareRules(
|
|
3043
|
+
const rulesToUpdate = compareRules(
|
|
3044
|
+
currentCollection.rules,
|
|
3045
|
+
previousCollection.rules,
|
|
3046
|
+
currentCollection.permissions,
|
|
3047
|
+
previousCollection.permissions
|
|
3048
|
+
);
|
|
2903
3049
|
const permissionsToUpdate = comparePermissions(currentCollection.permissions, previousCollection.permissions);
|
|
2904
3050
|
return {
|
|
2905
3051
|
collection: currentCollection.name,
|
|
@@ -2916,6 +3062,14 @@ function hasChanges(modification) {
|
|
|
2916
3062
|
return modification.fieldsToAdd.length > 0 || modification.fieldsToRemove.length > 0 || modification.fieldsToModify.length > 0 || modification.indexesToAdd.length > 0 || modification.indexesToRemove.length > 0 || modification.rulesToUpdate.length > 0 || modification.permissionsToUpdate.length > 0;
|
|
2917
3063
|
}
|
|
2918
3064
|
function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
3065
|
+
const collectionIdToName = /* @__PURE__ */ new Map();
|
|
3066
|
+
if (previousSnapshot) {
|
|
3067
|
+
for (const [name, collection] of previousSnapshot.collections) {
|
|
3068
|
+
if (collection.id) {
|
|
3069
|
+
collectionIdToName.set(collection.id, name);
|
|
3070
|
+
}
|
|
3071
|
+
}
|
|
3072
|
+
}
|
|
2919
3073
|
const collectionsToCreate = findNewCollections(currentSchema, previousSnapshot);
|
|
2920
3074
|
const collectionsToDelete = findRemovedCollections(currentSchema, previousSnapshot);
|
|
2921
3075
|
const filteredCollectionsToCreate = collectionsToCreate.filter(
|
|
@@ -2924,16 +3078,28 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
|
2924
3078
|
const filteredCollectionsToDelete = collectionsToDelete.filter(
|
|
2925
3079
|
(collection) => !isSystemCollection(collection.name, config)
|
|
2926
3080
|
);
|
|
3081
|
+
const registry = new CollectionIdRegistry();
|
|
3082
|
+
const collectionsWithIds = filteredCollectionsToCreate.map((collection) => {
|
|
3083
|
+
if (collection.id) {
|
|
3084
|
+
registry.register(collection.id);
|
|
3085
|
+
return collection;
|
|
3086
|
+
}
|
|
3087
|
+
const id = registry.generate(collection.name);
|
|
3088
|
+
return {
|
|
3089
|
+
...collection,
|
|
3090
|
+
id
|
|
3091
|
+
};
|
|
3092
|
+
});
|
|
2927
3093
|
const collectionsToModify = [];
|
|
2928
3094
|
const matchedCollections = matchCollectionsByName(currentSchema, previousSnapshot);
|
|
2929
3095
|
for (const [currentCollection, previousCollection] of matchedCollections) {
|
|
2930
|
-
const modification = buildCollectionModification(currentCollection, previousCollection, config);
|
|
3096
|
+
const modification = buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName);
|
|
2931
3097
|
if (hasChanges(modification)) {
|
|
2932
3098
|
collectionsToModify.push(modification);
|
|
2933
3099
|
}
|
|
2934
3100
|
}
|
|
2935
3101
|
return {
|
|
2936
|
-
collectionsToCreate:
|
|
3102
|
+
collectionsToCreate: collectionsWithIds,
|
|
2937
3103
|
collectionsToDelete: filteredCollectionsToDelete,
|
|
2938
3104
|
collectionsToModify
|
|
2939
3105
|
};
|
|
@@ -3169,6 +3335,49 @@ function generateTimestamp(config) {
|
|
|
3169
3335
|
}
|
|
3170
3336
|
return Math.floor(Date.now() / 1e3).toString();
|
|
3171
3337
|
}
|
|
3338
|
+
function splitDiffByCollection(diff, baseTimestamp) {
|
|
3339
|
+
const operations = [];
|
|
3340
|
+
let currentTimestamp = parseInt(baseTimestamp, 10);
|
|
3341
|
+
for (const collection of diff.collectionsToCreate) {
|
|
3342
|
+
operations.push({
|
|
3343
|
+
type: "create",
|
|
3344
|
+
collection,
|
|
3345
|
+
timestamp: currentTimestamp.toString()
|
|
3346
|
+
});
|
|
3347
|
+
currentTimestamp += 1;
|
|
3348
|
+
}
|
|
3349
|
+
for (const modification of diff.collectionsToModify) {
|
|
3350
|
+
operations.push({
|
|
3351
|
+
type: "modify",
|
|
3352
|
+
collection: modification.collection,
|
|
3353
|
+
modifications: modification,
|
|
3354
|
+
timestamp: currentTimestamp.toString()
|
|
3355
|
+
});
|
|
3356
|
+
currentTimestamp += 1;
|
|
3357
|
+
}
|
|
3358
|
+
for (const collection of diff.collectionsToDelete) {
|
|
3359
|
+
operations.push({
|
|
3360
|
+
type: "delete",
|
|
3361
|
+
collection: collection.name || collection,
|
|
3362
|
+
// Handle both object and string
|
|
3363
|
+
timestamp: currentTimestamp.toString()
|
|
3364
|
+
});
|
|
3365
|
+
currentTimestamp += 1;
|
|
3366
|
+
}
|
|
3367
|
+
return operations;
|
|
3368
|
+
}
|
|
3369
|
+
function generateCollectionMigrationFilename(operation) {
|
|
3370
|
+
const timestamp = operation.timestamp;
|
|
3371
|
+
const operationType = operation.type === "modify" ? "updated" : operation.type === "create" ? "created" : "deleted";
|
|
3372
|
+
let collectionName;
|
|
3373
|
+
if (typeof operation.collection === "string") {
|
|
3374
|
+
collectionName = operation.collection;
|
|
3375
|
+
} else {
|
|
3376
|
+
collectionName = operation.collection.name;
|
|
3377
|
+
}
|
|
3378
|
+
const sanitizedName = collectionName.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase();
|
|
3379
|
+
return `${timestamp}_${operationType}_${sanitizedName}.js`;
|
|
3380
|
+
}
|
|
3172
3381
|
function generateMigrationDescription(diff) {
|
|
3173
3382
|
const parts = [];
|
|
3174
3383
|
if (diff.collectionsToCreate.length > 0) {
|
|
@@ -3276,14 +3485,13 @@ function formatValue(value) {
|
|
|
3276
3485
|
return "null";
|
|
3277
3486
|
}
|
|
3278
3487
|
if (typeof value === "string") {
|
|
3279
|
-
return
|
|
3488
|
+
return JSON.stringify(value);
|
|
3280
3489
|
}
|
|
3281
3490
|
if (typeof value === "number" || typeof value === "boolean") {
|
|
3282
3491
|
return String(value);
|
|
3283
3492
|
}
|
|
3284
3493
|
if (Array.isArray(value)) {
|
|
3285
|
-
|
|
3286
|
-
return `[${items}]`;
|
|
3494
|
+
return JSON.stringify(value).replace(/","/g, '", "');
|
|
3287
3495
|
}
|
|
3288
3496
|
if (typeof value === "object") {
|
|
3289
3497
|
const entries = Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
|
|
@@ -3291,7 +3499,7 @@ function formatValue(value) {
|
|
|
3291
3499
|
}
|
|
3292
3500
|
return String(value);
|
|
3293
3501
|
}
|
|
3294
|
-
function generateFieldDefinitionObject(field) {
|
|
3502
|
+
function generateFieldDefinitionObject(field, collectionIdMap) {
|
|
3295
3503
|
const parts = [];
|
|
3296
3504
|
parts.push(` name: "${field.name}"`);
|
|
3297
3505
|
parts.push(` type: "${field.type}"`);
|
|
@@ -3299,34 +3507,47 @@ function generateFieldDefinitionObject(field) {
|
|
|
3299
3507
|
if (field.unique !== void 0) {
|
|
3300
3508
|
parts.push(` unique: ${field.unique}`);
|
|
3301
3509
|
}
|
|
3510
|
+
if (field.type === "select") {
|
|
3511
|
+
const maxSelect = field.options?.maxSelect ?? 1;
|
|
3512
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
3513
|
+
const values = field.options?.values ?? [];
|
|
3514
|
+
parts.push(` values: ${formatValue(values)}`);
|
|
3515
|
+
}
|
|
3302
3516
|
if (field.options && Object.keys(field.options).length > 0) {
|
|
3303
3517
|
for (const [key, value] of Object.entries(field.options)) {
|
|
3518
|
+
if (field.type === "select" && (key === "maxSelect" || key === "values")) {
|
|
3519
|
+
continue;
|
|
3520
|
+
}
|
|
3304
3521
|
parts.push(` ${key}: ${formatValue(value)}`);
|
|
3305
3522
|
}
|
|
3306
3523
|
}
|
|
3307
3524
|
if (field.relation) {
|
|
3308
3525
|
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
}
|
|
3317
|
-
if (field.relation.cascadeDelete !== void 0) {
|
|
3318
|
-
parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
|
|
3526
|
+
let collectionIdValue;
|
|
3527
|
+
if (isUsersCollection) {
|
|
3528
|
+
collectionIdValue = '"_pb_users_auth_"';
|
|
3529
|
+
} else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
|
|
3530
|
+
collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
|
|
3531
|
+
} else {
|
|
3532
|
+
collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
3319
3533
|
}
|
|
3534
|
+
parts.push(` collectionId: ${collectionIdValue}`);
|
|
3535
|
+
const maxSelect = field.relation.maxSelect ?? 1;
|
|
3536
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
3537
|
+
const minSelect = field.relation.minSelect ?? null;
|
|
3538
|
+
parts.push(` minSelect: ${minSelect}`);
|
|
3539
|
+
const cascadeDelete = field.relation.cascadeDelete ?? false;
|
|
3540
|
+
parts.push(` cascadeDelete: ${cascadeDelete}`);
|
|
3320
3541
|
}
|
|
3321
3542
|
return ` {
|
|
3322
3543
|
${parts.join(",\n")},
|
|
3323
3544
|
}`;
|
|
3324
3545
|
}
|
|
3325
|
-
function generateFieldsArray(fields) {
|
|
3546
|
+
function generateFieldsArray(fields, collectionIdMap) {
|
|
3326
3547
|
if (fields.length === 0) {
|
|
3327
3548
|
return "[]";
|
|
3328
3549
|
}
|
|
3329
|
-
const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field));
|
|
3550
|
+
const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field, collectionIdMap));
|
|
3330
3551
|
return `[
|
|
3331
3552
|
${fieldObjects.join(",\n")},
|
|
3332
3553
|
]`;
|
|
@@ -3385,7 +3606,7 @@ function generateIndexesArray(indexes) {
|
|
|
3385
3606
|
if (!indexes || indexes.length === 0) {
|
|
3386
3607
|
return "[]";
|
|
3387
3608
|
}
|
|
3388
|
-
const indexStrings = indexes.map((idx) =>
|
|
3609
|
+
const indexStrings = indexes.map((idx) => JSON.stringify(idx));
|
|
3389
3610
|
return `[
|
|
3390
3611
|
${indexStrings.join(",\n ")},
|
|
3391
3612
|
]`;
|
|
@@ -3439,9 +3660,12 @@ function getSystemFields() {
|
|
|
3439
3660
|
}
|
|
3440
3661
|
];
|
|
3441
3662
|
}
|
|
3442
|
-
function generateCollectionCreation(collection, varName = "collection", isLast = false) {
|
|
3663
|
+
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
3443
3664
|
const lines = [];
|
|
3444
3665
|
lines.push(` const ${varName} = new Collection({`);
|
|
3666
|
+
if (collection.id) {
|
|
3667
|
+
lines.push(` id: ${formatValue(collection.id)},`);
|
|
3668
|
+
}
|
|
3445
3669
|
lines.push(` name: "${collection.name}",`);
|
|
3446
3670
|
lines.push(` type: "${collection.type}",`);
|
|
3447
3671
|
const permissionsCode = generateCollectionPermissions(collection.permissions);
|
|
@@ -3453,7 +3677,7 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
|
|
|
3453
3677
|
}
|
|
3454
3678
|
const systemFields = getSystemFields();
|
|
3455
3679
|
const allFields = [...systemFields, ...collection.fields];
|
|
3456
|
-
lines.push(` fields: ${generateFieldsArray(allFields)},`);
|
|
3680
|
+
lines.push(` fields: ${generateFieldsArray(allFields, collectionIdMap)},`);
|
|
3457
3681
|
lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
|
|
3458
3682
|
lines.push(` });`);
|
|
3459
3683
|
lines.push(``);
|
|
@@ -3475,42 +3699,59 @@ function getFieldConstructorName(fieldType) {
|
|
|
3475
3699
|
};
|
|
3476
3700
|
return constructorMap[fieldType] || "TextField";
|
|
3477
3701
|
}
|
|
3478
|
-
function generateFieldConstructorOptions(field) {
|
|
3702
|
+
function generateFieldConstructorOptions(field, collectionIdMap) {
|
|
3479
3703
|
const parts = [];
|
|
3480
3704
|
parts.push(` name: "${field.name}"`);
|
|
3481
3705
|
parts.push(` required: ${field.required}`);
|
|
3482
3706
|
if (field.unique !== void 0) {
|
|
3483
3707
|
parts.push(` unique: ${field.unique}`);
|
|
3484
3708
|
}
|
|
3709
|
+
if (field.type === "select") {
|
|
3710
|
+
const maxSelect = field.options?.maxSelect ?? 1;
|
|
3711
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
3712
|
+
const values = field.options?.values ?? [];
|
|
3713
|
+
parts.push(` values: ${formatValue(values)}`);
|
|
3714
|
+
}
|
|
3485
3715
|
if (field.options && Object.keys(field.options).length > 0) {
|
|
3486
3716
|
for (const [key, value] of Object.entries(field.options)) {
|
|
3487
|
-
|
|
3717
|
+
if (field.type === "select" && (key === "maxSelect" || key === "values")) {
|
|
3718
|
+
continue;
|
|
3719
|
+
}
|
|
3720
|
+
if (field.type === "number" && key === "noDecimal") {
|
|
3721
|
+
parts.push(` onlyInt: ${formatValue(value)}`);
|
|
3722
|
+
} else {
|
|
3723
|
+
parts.push(` ${key}: ${formatValue(value)}`);
|
|
3724
|
+
}
|
|
3488
3725
|
}
|
|
3489
3726
|
}
|
|
3490
3727
|
if (field.relation && field.type === "relation") {
|
|
3491
3728
|
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
3492
|
-
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
|
|
3496
|
-
|
|
3497
|
-
|
|
3498
|
-
|
|
3499
|
-
}
|
|
3500
|
-
if (field.relation.cascadeDelete !== void 0) {
|
|
3501
|
-
parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
|
|
3729
|
+
let collectionIdValue;
|
|
3730
|
+
if (isUsersCollection) {
|
|
3731
|
+
collectionIdValue = '"_pb_users_auth_"';
|
|
3732
|
+
} else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
|
|
3733
|
+
collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
|
|
3734
|
+
} else {
|
|
3735
|
+
collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
3502
3736
|
}
|
|
3737
|
+
parts.push(` collectionId: ${collectionIdValue}`);
|
|
3738
|
+
const maxSelect = field.relation.maxSelect ?? 1;
|
|
3739
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
3740
|
+
const minSelect = field.relation.minSelect ?? null;
|
|
3741
|
+
parts.push(` minSelect: ${minSelect}`);
|
|
3742
|
+
const cascadeDelete = field.relation.cascadeDelete ?? false;
|
|
3743
|
+
parts.push(` cascadeDelete: ${cascadeDelete}`);
|
|
3503
3744
|
}
|
|
3504
3745
|
return parts.join(",\n");
|
|
3505
3746
|
}
|
|
3506
|
-
function generateFieldAddition(collectionName, field, varName, isLast = false) {
|
|
3747
|
+
function generateFieldAddition(collectionName, field, varName, isLast = false, collectionIdMap) {
|
|
3507
3748
|
const lines = [];
|
|
3508
3749
|
const constructorName = getFieldConstructorName(field.type);
|
|
3509
3750
|
const collectionVar = varName || `collection_${collectionName}_${field.name}`;
|
|
3510
3751
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
3511
3752
|
lines.push(``);
|
|
3512
3753
|
lines.push(` ${collectionVar}.fields.add(new ${constructorName}({`);
|
|
3513
|
-
lines.push(generateFieldConstructorOptions(field));
|
|
3754
|
+
lines.push(generateFieldConstructorOptions(field, collectionIdMap));
|
|
3514
3755
|
lines.push(` }));`);
|
|
3515
3756
|
lines.push(``);
|
|
3516
3757
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
@@ -3560,7 +3801,7 @@ function generateIndexAddition(collectionName, index, varName, isLast = false) {
|
|
|
3560
3801
|
const lines = [];
|
|
3561
3802
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
3562
3803
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
3563
|
-
lines.push(` ${collectionVar}.indexes.push(
|
|
3804
|
+
lines.push(` ${collectionVar}.indexes.push(${JSON.stringify(index)});`);
|
|
3564
3805
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3565
3806
|
return lines.join("\n");
|
|
3566
3807
|
}
|
|
@@ -3569,7 +3810,7 @@ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
|
|
|
3569
3810
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
3570
3811
|
const indexVar = `${collectionVar}_indexToRemove`;
|
|
3571
3812
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
3572
|
-
lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx ===
|
|
3813
|
+
lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === ${JSON.stringify(index)});`);
|
|
3573
3814
|
lines.push(` if (${indexVar} !== -1) {`);
|
|
3574
3815
|
lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
|
|
3575
3816
|
lines.push(` }`);
|
|
@@ -3598,16 +3839,213 @@ function generateCollectionDeletion(collectionName, varName = "collection", isLa
|
|
|
3598
3839
|
lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
|
|
3599
3840
|
return lines.join("\n");
|
|
3600
3841
|
}
|
|
3842
|
+
function generateOperationUpMigration(operation, collectionIdMap) {
|
|
3843
|
+
const lines = [];
|
|
3844
|
+
if (operation.type === "create") {
|
|
3845
|
+
const collection = operation.collection;
|
|
3846
|
+
const varName = `collection_${collection.name}`;
|
|
3847
|
+
lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
|
|
3848
|
+
} else if (operation.type === "modify") {
|
|
3849
|
+
const modification = operation.modifications;
|
|
3850
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
3851
|
+
let operationCount = 0;
|
|
3852
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
|
|
3853
|
+
for (const field of modification.fieldsToAdd) {
|
|
3854
|
+
operationCount++;
|
|
3855
|
+
const varName = `collection_${collectionName}_add_${field.name}`;
|
|
3856
|
+
const isLast = operationCount === totalOperations;
|
|
3857
|
+
lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
|
|
3858
|
+
if (!isLast) lines.push("");
|
|
3859
|
+
}
|
|
3860
|
+
for (const fieldMod of modification.fieldsToModify) {
|
|
3861
|
+
operationCount++;
|
|
3862
|
+
const varName = `collection_${collectionName}_modify_${fieldMod.fieldName}`;
|
|
3863
|
+
const isLast = operationCount === totalOperations;
|
|
3864
|
+
lines.push(generateFieldModification(collectionName, fieldMod, varName, isLast));
|
|
3865
|
+
if (!isLast) lines.push("");
|
|
3866
|
+
}
|
|
3867
|
+
for (const field of modification.fieldsToRemove) {
|
|
3868
|
+
operationCount++;
|
|
3869
|
+
const varName = `collection_${collectionName}_remove_${field.name}`;
|
|
3870
|
+
const isLast = operationCount === totalOperations;
|
|
3871
|
+
lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
|
|
3872
|
+
if (!isLast) lines.push("");
|
|
3873
|
+
}
|
|
3874
|
+
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
3875
|
+
operationCount++;
|
|
3876
|
+
const index = modification.indexesToAdd[i];
|
|
3877
|
+
const varName = `collection_${collectionName}_addidx_${i}`;
|
|
3878
|
+
const isLast = operationCount === totalOperations;
|
|
3879
|
+
lines.push(generateIndexAddition(collectionName, index, varName, isLast));
|
|
3880
|
+
if (!isLast) lines.push("");
|
|
3881
|
+
}
|
|
3882
|
+
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
3883
|
+
operationCount++;
|
|
3884
|
+
const index = modification.indexesToRemove[i];
|
|
3885
|
+
const varName = `collection_${collectionName}_rmidx_${i}`;
|
|
3886
|
+
const isLast = operationCount === totalOperations;
|
|
3887
|
+
lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
|
|
3888
|
+
if (!isLast) lines.push("");
|
|
3889
|
+
}
|
|
3890
|
+
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
3891
|
+
for (const permission of modification.permissionsToUpdate) {
|
|
3892
|
+
operationCount++;
|
|
3893
|
+
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
3894
|
+
const isLast = operationCount === totalOperations;
|
|
3895
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast));
|
|
3896
|
+
if (!isLast) lines.push("");
|
|
3897
|
+
}
|
|
3898
|
+
} else if (modification.rulesToUpdate.length > 0) {
|
|
3899
|
+
for (const rule of modification.rulesToUpdate) {
|
|
3900
|
+
operationCount++;
|
|
3901
|
+
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
3902
|
+
const isLast = operationCount === totalOperations;
|
|
3903
|
+
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast));
|
|
3904
|
+
if (!isLast) lines.push("");
|
|
3905
|
+
}
|
|
3906
|
+
}
|
|
3907
|
+
} else if (operation.type === "delete") {
|
|
3908
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
|
|
3909
|
+
const varName = `collection_${collectionName}`;
|
|
3910
|
+
lines.push(generateCollectionDeletion(collectionName, varName, true));
|
|
3911
|
+
}
|
|
3912
|
+
let code = lines.join("\n");
|
|
3913
|
+
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
3914
|
+
const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
|
|
3915
|
+
const saveMatches = [...code.matchAll(savePattern)];
|
|
3916
|
+
const deleteMatches = [...code.matchAll(deletePattern)];
|
|
3917
|
+
const allMatches = [
|
|
3918
|
+
...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
|
|
3919
|
+
...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
|
|
3920
|
+
].sort((a, b) => b.index - a.index);
|
|
3921
|
+
if (allMatches.length > 0) {
|
|
3922
|
+
const lastMatch = allMatches[0];
|
|
3923
|
+
if (lastMatch.type === "save") {
|
|
3924
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.save(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
3925
|
+
} else {
|
|
3926
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.delete(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
3927
|
+
}
|
|
3928
|
+
}
|
|
3929
|
+
return code;
|
|
3930
|
+
}
|
|
3931
|
+
function generateOperationDownMigration(operation, collectionIdMap) {
|
|
3932
|
+
const lines = [];
|
|
3933
|
+
if (operation.type === "create") {
|
|
3934
|
+
const collection = operation.collection;
|
|
3935
|
+
const varName = `collection_${collection.name}`;
|
|
3936
|
+
lines.push(generateCollectionDeletion(collection.name, varName, true));
|
|
3937
|
+
} else if (operation.type === "modify") {
|
|
3938
|
+
const modification = operation.modifications;
|
|
3939
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
3940
|
+
let operationCount = 0;
|
|
3941
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
|
|
3942
|
+
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
3943
|
+
for (const permission of modification.permissionsToUpdate) {
|
|
3944
|
+
operationCount++;
|
|
3945
|
+
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
3946
|
+
const isLast = operationCount === totalOperations;
|
|
3947
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast));
|
|
3948
|
+
if (!isLast) lines.push("");
|
|
3949
|
+
}
|
|
3950
|
+
} else if (modification.rulesToUpdate.length > 0) {
|
|
3951
|
+
for (const rule of modification.rulesToUpdate) {
|
|
3952
|
+
operationCount++;
|
|
3953
|
+
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
3954
|
+
const isLast = operationCount === totalOperations;
|
|
3955
|
+
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast));
|
|
3956
|
+
if (!isLast) lines.push("");
|
|
3957
|
+
}
|
|
3958
|
+
}
|
|
3959
|
+
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
3960
|
+
operationCount++;
|
|
3961
|
+
const index = modification.indexesToRemove[i];
|
|
3962
|
+
const varName = `collection_${collectionName}_restore_idx_${i}`;
|
|
3963
|
+
const isLast = operationCount === totalOperations;
|
|
3964
|
+
lines.push(generateIndexAddition(collectionName, index, varName, isLast));
|
|
3965
|
+
if (!isLast) lines.push("");
|
|
3966
|
+
}
|
|
3967
|
+
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
3968
|
+
operationCount++;
|
|
3969
|
+
const index = modification.indexesToAdd[i];
|
|
3970
|
+
const varName = `collection_${collectionName}_revert_idx_${i}`;
|
|
3971
|
+
const isLast = operationCount === totalOperations;
|
|
3972
|
+
lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
|
|
3973
|
+
if (!isLast) lines.push("");
|
|
3974
|
+
}
|
|
3975
|
+
for (const field of modification.fieldsToRemove) {
|
|
3976
|
+
operationCount++;
|
|
3977
|
+
const varName = `collection_${collectionName}_restore_${field.name}`;
|
|
3978
|
+
const isLast = operationCount === totalOperations;
|
|
3979
|
+
lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
|
|
3980
|
+
if (!isLast) lines.push("");
|
|
3981
|
+
}
|
|
3982
|
+
for (const fieldMod of modification.fieldsToModify) {
|
|
3983
|
+
operationCount++;
|
|
3984
|
+
const reverseChanges = fieldMod.changes.map((change) => ({
|
|
3985
|
+
property: change.property,
|
|
3986
|
+
oldValue: change.newValue,
|
|
3987
|
+
newValue: change.oldValue
|
|
3988
|
+
}));
|
|
3989
|
+
const reverseMod = {
|
|
3990
|
+
fieldName: fieldMod.fieldName,
|
|
3991
|
+
currentDefinition: fieldMod.newDefinition,
|
|
3992
|
+
newDefinition: fieldMod.currentDefinition,
|
|
3993
|
+
changes: reverseChanges
|
|
3994
|
+
};
|
|
3995
|
+
const varName = `collection_${collectionName}_revert_${fieldMod.fieldName}`;
|
|
3996
|
+
const isLast = operationCount === totalOperations;
|
|
3997
|
+
lines.push(generateFieldModification(collectionName, reverseMod, varName, isLast));
|
|
3998
|
+
if (!isLast) lines.push("");
|
|
3999
|
+
}
|
|
4000
|
+
for (const field of modification.fieldsToAdd) {
|
|
4001
|
+
operationCount++;
|
|
4002
|
+
const varName = `collection_${collectionName}_revert_add_${field.name}`;
|
|
4003
|
+
const isLast = operationCount === totalOperations;
|
|
4004
|
+
lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
|
|
4005
|
+
if (!isLast) lines.push("");
|
|
4006
|
+
}
|
|
4007
|
+
} else if (operation.type === "delete") {
|
|
4008
|
+
const collection = operation.collection;
|
|
4009
|
+
if (typeof collection !== "string") {
|
|
4010
|
+
const varName = `collection_${collection.name}`;
|
|
4011
|
+
lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
|
|
4012
|
+
}
|
|
4013
|
+
}
|
|
4014
|
+
let code = lines.join("\n");
|
|
4015
|
+
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
4016
|
+
const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
|
|
4017
|
+
const saveMatches = [...code.matchAll(savePattern)];
|
|
4018
|
+
const deleteMatches = [...code.matchAll(deletePattern)];
|
|
4019
|
+
const allMatches = [
|
|
4020
|
+
...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
|
|
4021
|
+
...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
|
|
4022
|
+
].sort((a, b) => b.index - a.index);
|
|
4023
|
+
if (allMatches.length > 0) {
|
|
4024
|
+
const lastMatch = allMatches[0];
|
|
4025
|
+
if (lastMatch.type === "save") {
|
|
4026
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.save(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4027
|
+
} else {
|
|
4028
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.delete(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4029
|
+
}
|
|
4030
|
+
}
|
|
4031
|
+
return code;
|
|
4032
|
+
}
|
|
3601
4033
|
function generateUpMigration(diff) {
|
|
3602
4034
|
const lines = [];
|
|
3603
4035
|
lines.push(` // UP MIGRATION`);
|
|
3604
4036
|
lines.push(``);
|
|
4037
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
4038
|
+
for (const collection of diff.collectionsToCreate) {
|
|
4039
|
+
if (collection.id) {
|
|
4040
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4041
|
+
}
|
|
4042
|
+
}
|
|
3605
4043
|
if (diff.collectionsToCreate.length > 0) {
|
|
3606
4044
|
lines.push(` // Create new collections`);
|
|
3607
4045
|
for (let i = 0; i < diff.collectionsToCreate.length; i++) {
|
|
3608
4046
|
const collection = diff.collectionsToCreate[i];
|
|
3609
4047
|
const varName = `collection_${collection.name}_create`;
|
|
3610
|
-
lines.push(generateCollectionCreation(collection, varName));
|
|
4048
|
+
lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
|
|
3611
4049
|
lines.push(``);
|
|
3612
4050
|
}
|
|
3613
4051
|
}
|
|
@@ -3619,7 +4057,7 @@ function generateUpMigration(diff) {
|
|
|
3619
4057
|
lines.push(` // Add fields to ${collectionName}`);
|
|
3620
4058
|
for (const field of modification.fieldsToAdd) {
|
|
3621
4059
|
const varName = `collection_${collectionName}_add_${field.name}`;
|
|
3622
|
-
lines.push(generateFieldAddition(collectionName, field, varName));
|
|
4060
|
+
lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
|
|
3623
4061
|
lines.push(``);
|
|
3624
4062
|
}
|
|
3625
4063
|
}
|
|
@@ -3710,12 +4148,23 @@ function generateDownMigration(diff) {
|
|
|
3710
4148
|
const lines = [];
|
|
3711
4149
|
lines.push(` // DOWN MIGRATION (ROLLBACK)`);
|
|
3712
4150
|
lines.push(``);
|
|
4151
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
4152
|
+
for (const collection of diff.collectionsToCreate) {
|
|
4153
|
+
if (collection.id) {
|
|
4154
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4155
|
+
}
|
|
4156
|
+
}
|
|
4157
|
+
for (const collection of diff.collectionsToDelete) {
|
|
4158
|
+
if (collection.id) {
|
|
4159
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4160
|
+
}
|
|
4161
|
+
}
|
|
3713
4162
|
if (diff.collectionsToDelete.length > 0) {
|
|
3714
4163
|
lines.push(` // Recreate deleted collections`);
|
|
3715
4164
|
for (let i = 0; i < diff.collectionsToDelete.length; i++) {
|
|
3716
4165
|
const collection = diff.collectionsToDelete[i];
|
|
3717
4166
|
const varName = `collection_${collection.name}_recreate`;
|
|
3718
|
-
lines.push(generateCollectionCreation(collection, varName));
|
|
4167
|
+
lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
|
|
3719
4168
|
lines.push(``);
|
|
3720
4169
|
}
|
|
3721
4170
|
}
|
|
@@ -3760,7 +4209,7 @@ function generateDownMigration(diff) {
|
|
|
3760
4209
|
lines.push(` // Restore fields to ${collectionName}`);
|
|
3761
4210
|
for (const field of modification.fieldsToRemove) {
|
|
3762
4211
|
const varName = `collection_${collectionName}_restore_${field.name}`;
|
|
3763
|
-
lines.push(generateFieldAddition(collectionName, field, varName));
|
|
4212
|
+
lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
|
|
3764
4213
|
lines.push(``);
|
|
3765
4214
|
}
|
|
3766
4215
|
}
|
|
@@ -3829,12 +4278,33 @@ function generate(diff, config) {
|
|
|
3829
4278
|
const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
|
|
3830
4279
|
try {
|
|
3831
4280
|
const migrationDir = resolveMigrationDir(normalizedConfig);
|
|
3832
|
-
const
|
|
3833
|
-
|
|
3834
|
-
|
|
3835
|
-
|
|
3836
|
-
const
|
|
3837
|
-
|
|
4281
|
+
const hasChanges2 = diff.collectionsToCreate.length > 0 || diff.collectionsToModify.length > 0 || diff.collectionsToDelete.length > 0;
|
|
4282
|
+
if (!hasChanges2) {
|
|
4283
|
+
return [];
|
|
4284
|
+
}
|
|
4285
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
4286
|
+
for (const collection of diff.collectionsToCreate) {
|
|
4287
|
+
if (collection.id) {
|
|
4288
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4289
|
+
}
|
|
4290
|
+
}
|
|
4291
|
+
for (const collection of diff.collectionsToDelete) {
|
|
4292
|
+
if (collection.id) {
|
|
4293
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4294
|
+
}
|
|
4295
|
+
}
|
|
4296
|
+
const baseTimestamp = generateTimestamp(normalizedConfig);
|
|
4297
|
+
const operations = splitDiffByCollection(diff, baseTimestamp);
|
|
4298
|
+
const filePaths = [];
|
|
4299
|
+
for (const operation of operations) {
|
|
4300
|
+
const upCode = generateOperationUpMigration(operation, collectionIdMap);
|
|
4301
|
+
const downCode = generateOperationDownMigration(operation, collectionIdMap);
|
|
4302
|
+
const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
|
|
4303
|
+
const filename = generateCollectionMigrationFilename(operation);
|
|
4304
|
+
const filePath = writeMigrationFile(migrationDir, filename, content);
|
|
4305
|
+
filePaths.push(filePath);
|
|
4306
|
+
}
|
|
4307
|
+
return filePaths;
|
|
3838
4308
|
} catch (error) {
|
|
3839
4309
|
if (error instanceof MigrationGenerationError || error instanceof FileSystemError) {
|
|
3840
4310
|
throw error;
|
|
@@ -3852,7 +4322,8 @@ var MigrationGenerator = class {
|
|
|
3852
4322
|
this.config = mergeConfig4(config);
|
|
3853
4323
|
}
|
|
3854
4324
|
/**
|
|
3855
|
-
* Generates
|
|
4325
|
+
* Generates migration files from a schema diff
|
|
4326
|
+
* Returns array of file paths (one per collection operation)
|
|
3856
4327
|
*/
|
|
3857
4328
|
generate(diff) {
|
|
3858
4329
|
return generate(diff, this.config);
|