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/cli/migrate.cjs
CHANGED
|
@@ -7,6 +7,7 @@ var fs5 = require('fs');
|
|
|
7
7
|
var path5 = require('path');
|
|
8
8
|
var url = require('url');
|
|
9
9
|
var zod = require('zod');
|
|
10
|
+
var crypto = require('crypto');
|
|
10
11
|
var ora = require('ora');
|
|
11
12
|
|
|
12
13
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -1320,12 +1321,22 @@ function isAuthCollection(fields) {
|
|
|
1320
1321
|
function buildFieldDefinition(fieldName, zodType) {
|
|
1321
1322
|
const fieldMetadata = extractFieldMetadata(zodType.description);
|
|
1322
1323
|
if (fieldMetadata) {
|
|
1323
|
-
|
|
1324
|
+
let required2;
|
|
1325
|
+
if (fieldMetadata.type === "number") {
|
|
1326
|
+
if (fieldMetadata.options?.required !== void 0) {
|
|
1327
|
+
required2 = fieldMetadata.options.required;
|
|
1328
|
+
} else {
|
|
1329
|
+
required2 = false;
|
|
1330
|
+
}
|
|
1331
|
+
} else {
|
|
1332
|
+
required2 = isFieldRequired(zodType);
|
|
1333
|
+
}
|
|
1334
|
+
const { required: _required, ...options2 } = fieldMetadata.options || {};
|
|
1324
1335
|
const fieldDef2 = {
|
|
1325
1336
|
name: fieldName,
|
|
1326
1337
|
type: fieldMetadata.type,
|
|
1327
1338
|
required: required2,
|
|
1328
|
-
options:
|
|
1339
|
+
options: Object.keys(options2).length > 0 ? options2 : void 0
|
|
1329
1340
|
};
|
|
1330
1341
|
if (fieldMetadata.type === "relation") {
|
|
1331
1342
|
const relationMetadata2 = extractRelationMetadata(zodType.description);
|
|
@@ -1495,6 +1506,67 @@ async function buildSchemaDefinition(config) {
|
|
|
1495
1506
|
async function parseSchemaFiles(config) {
|
|
1496
1507
|
return buildSchemaDefinition(config);
|
|
1497
1508
|
}
|
|
1509
|
+
function generateCollectionId() {
|
|
1510
|
+
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
1511
|
+
const idLength = 15;
|
|
1512
|
+
const bytes = crypto.randomBytes(idLength);
|
|
1513
|
+
let id = "pb_";
|
|
1514
|
+
for (let i = 0; i < idLength; i++) {
|
|
1515
|
+
const index = bytes[i] % chars.length;
|
|
1516
|
+
id += chars[index];
|
|
1517
|
+
}
|
|
1518
|
+
return id;
|
|
1519
|
+
}
|
|
1520
|
+
var CollectionIdRegistry = class {
|
|
1521
|
+
ids;
|
|
1522
|
+
constructor() {
|
|
1523
|
+
this.ids = /* @__PURE__ */ new Set();
|
|
1524
|
+
}
|
|
1525
|
+
/**
|
|
1526
|
+
* Generates a unique collection ID for a given collection name
|
|
1527
|
+
* Retries up to 10 times if collision occurs (extremely rare)
|
|
1528
|
+
* Special case: returns "_pb_users_auth_" for users collection
|
|
1529
|
+
*
|
|
1530
|
+
* @param collectionName - The name of the collection (optional)
|
|
1531
|
+
* @returns A unique collection ID
|
|
1532
|
+
* @throws Error if unable to generate unique ID after max attempts
|
|
1533
|
+
*/
|
|
1534
|
+
generate(collectionName) {
|
|
1535
|
+
if (collectionName && collectionName.toLowerCase() === "users") {
|
|
1536
|
+
const usersId = "_pb_users_auth_";
|
|
1537
|
+
if (!this.has(usersId)) {
|
|
1538
|
+
this.register(usersId);
|
|
1539
|
+
}
|
|
1540
|
+
return usersId;
|
|
1541
|
+
}
|
|
1542
|
+
const maxAttempts = 10;
|
|
1543
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
1544
|
+
const id = generateCollectionId();
|
|
1545
|
+
if (!this.has(id)) {
|
|
1546
|
+
this.register(id);
|
|
1547
|
+
return id;
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
throw new Error("Failed to generate unique collection ID after maximum attempts");
|
|
1551
|
+
}
|
|
1552
|
+
/**
|
|
1553
|
+
* Checks if an ID has already been registered
|
|
1554
|
+
*
|
|
1555
|
+
* @param id - The collection ID to check
|
|
1556
|
+
* @returns True if the ID exists in the registry
|
|
1557
|
+
*/
|
|
1558
|
+
has(id) {
|
|
1559
|
+
return this.ids.has(id);
|
|
1560
|
+
}
|
|
1561
|
+
/**
|
|
1562
|
+
* Registers a collection ID in the registry
|
|
1563
|
+
*
|
|
1564
|
+
* @param id - The collection ID to register
|
|
1565
|
+
*/
|
|
1566
|
+
register(id) {
|
|
1567
|
+
this.ids.add(id);
|
|
1568
|
+
}
|
|
1569
|
+
};
|
|
1498
1570
|
|
|
1499
1571
|
// src/migration/diff.ts
|
|
1500
1572
|
var DEFAULT_CONFIG2 = {
|
|
@@ -1637,18 +1709,49 @@ function compareFieldConstraints(currentField, previousField) {
|
|
|
1637
1709
|
}
|
|
1638
1710
|
return changes;
|
|
1639
1711
|
}
|
|
1712
|
+
function normalizeOptionValue(key, value, fieldType) {
|
|
1713
|
+
if (key === "maxSelect" && value === 1 && (fieldType === "select" || fieldType === "file")) {
|
|
1714
|
+
return void 0;
|
|
1715
|
+
}
|
|
1716
|
+
if (key === "maxSize" && value === 0 && fieldType === "file") {
|
|
1717
|
+
return void 0;
|
|
1718
|
+
}
|
|
1719
|
+
if (fieldType === "file") {
|
|
1720
|
+
if (key === "mimeTypes" && Array.isArray(value) && value.length === 0) {
|
|
1721
|
+
return void 0;
|
|
1722
|
+
}
|
|
1723
|
+
if (key === "thumbs" && Array.isArray(value) && value.length === 0) {
|
|
1724
|
+
return void 0;
|
|
1725
|
+
}
|
|
1726
|
+
if (key === "protected" && value === false) {
|
|
1727
|
+
return void 0;
|
|
1728
|
+
}
|
|
1729
|
+
}
|
|
1730
|
+
if (fieldType === "autodate") {
|
|
1731
|
+
if (key === "onCreate" && value === true) {
|
|
1732
|
+
return void 0;
|
|
1733
|
+
}
|
|
1734
|
+
if (key === "onUpdate" && value === false) {
|
|
1735
|
+
return void 0;
|
|
1736
|
+
}
|
|
1737
|
+
}
|
|
1738
|
+
return value;
|
|
1739
|
+
}
|
|
1640
1740
|
function compareFieldOptions(currentField, previousField) {
|
|
1641
1741
|
const changes = [];
|
|
1642
1742
|
const currentOptions = currentField.options || {};
|
|
1643
1743
|
const previousOptions = previousField.options || {};
|
|
1644
1744
|
const allKeys = /* @__PURE__ */ new Set([...Object.keys(currentOptions), ...Object.keys(previousOptions)]);
|
|
1745
|
+
const fieldType = currentField.type;
|
|
1645
1746
|
for (const key of allKeys) {
|
|
1646
1747
|
const currentValue = currentOptions[key];
|
|
1647
1748
|
const previousValue = previousOptions[key];
|
|
1648
|
-
|
|
1749
|
+
const normalizedCurrent = normalizeOptionValue(key, currentValue, fieldType);
|
|
1750
|
+
const normalizedPrevious = normalizeOptionValue(key, previousValue, fieldType);
|
|
1751
|
+
if (normalizedCurrent === void 0 && normalizedPrevious === void 0) {
|
|
1649
1752
|
continue;
|
|
1650
1753
|
}
|
|
1651
|
-
if (!areValuesEqual(
|
|
1754
|
+
if (!areValuesEqual(normalizedCurrent, normalizedPrevious)) {
|
|
1652
1755
|
changes.push({
|
|
1653
1756
|
property: `options.${key}`,
|
|
1654
1757
|
oldValue: previousValue,
|
|
@@ -1658,7 +1761,7 @@ function compareFieldOptions(currentField, previousField) {
|
|
|
1658
1761
|
}
|
|
1659
1762
|
return changes;
|
|
1660
1763
|
}
|
|
1661
|
-
function compareRelationConfigurations(currentField, previousField) {
|
|
1764
|
+
function compareRelationConfigurations(currentField, previousField, collectionIdToName) {
|
|
1662
1765
|
const changes = [];
|
|
1663
1766
|
const currentRelation = currentField.relation;
|
|
1664
1767
|
const previousRelation = previousField.relation;
|
|
@@ -1670,8 +1773,8 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
1670
1773
|
}
|
|
1671
1774
|
const normalizeCollection = (collection) => {
|
|
1672
1775
|
if (!collection) return collection;
|
|
1673
|
-
if (
|
|
1674
|
-
return
|
|
1776
|
+
if (collectionIdToName && collectionIdToName.has(collection)) {
|
|
1777
|
+
return collectionIdToName.get(collection);
|
|
1675
1778
|
}
|
|
1676
1779
|
const nameMatch = collection.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
1677
1780
|
if (nameMatch) {
|
|
@@ -1681,13 +1784,11 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
1681
1784
|
};
|
|
1682
1785
|
const normalizedCurrent = normalizeCollection(currentRelation.collection);
|
|
1683
1786
|
const normalizedPrevious = normalizeCollection(previousRelation.collection);
|
|
1684
|
-
if (normalizedCurrent !== normalizedPrevious) {
|
|
1787
|
+
if (normalizedCurrent.toLowerCase() !== normalizedPrevious.toLowerCase()) {
|
|
1685
1788
|
changes.push({
|
|
1686
1789
|
property: "relation.collection",
|
|
1687
|
-
oldValue:
|
|
1688
|
-
|
|
1689
|
-
newValue: normalizedCurrent
|
|
1690
|
-
// Use normalized value for clarity
|
|
1790
|
+
oldValue: previousRelation.collection,
|
|
1791
|
+
newValue: currentRelation.collection
|
|
1691
1792
|
});
|
|
1692
1793
|
}
|
|
1693
1794
|
if (currentRelation.cascadeDelete !== previousRelation.cascadeDelete) {
|
|
@@ -1697,14 +1798,20 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
1697
1798
|
newValue: currentRelation.cascadeDelete
|
|
1698
1799
|
});
|
|
1699
1800
|
}
|
|
1700
|
-
|
|
1801
|
+
const normalizeMax = (val) => val === 1 ? null : val;
|
|
1802
|
+
const currentMax = normalizeMax(currentRelation.maxSelect);
|
|
1803
|
+
const previousMax = normalizeMax(previousRelation.maxSelect);
|
|
1804
|
+
if (currentMax != previousMax) {
|
|
1701
1805
|
changes.push({
|
|
1702
1806
|
property: "relation.maxSelect",
|
|
1703
1807
|
oldValue: previousRelation.maxSelect,
|
|
1704
1808
|
newValue: currentRelation.maxSelect
|
|
1705
1809
|
});
|
|
1706
1810
|
}
|
|
1707
|
-
|
|
1811
|
+
const normalizeMin = (val) => val === 0 ? null : val;
|
|
1812
|
+
const currentMin = normalizeMin(currentRelation.minSelect);
|
|
1813
|
+
const previousMin = normalizeMin(previousRelation.minSelect);
|
|
1814
|
+
if (currentMin != previousMin) {
|
|
1708
1815
|
changes.push({
|
|
1709
1816
|
property: "relation.minSelect",
|
|
1710
1817
|
oldValue: previousRelation.minSelect,
|
|
@@ -1713,7 +1820,7 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
1713
1820
|
}
|
|
1714
1821
|
return changes;
|
|
1715
1822
|
}
|
|
1716
|
-
function detectFieldChanges(currentField, previousField) {
|
|
1823
|
+
function detectFieldChanges(currentField, previousField, collectionIdToName) {
|
|
1717
1824
|
const changes = [];
|
|
1718
1825
|
const typeChange = compareFieldTypes(currentField, previousField);
|
|
1719
1826
|
if (typeChange) {
|
|
@@ -1722,7 +1829,7 @@ function detectFieldChanges(currentField, previousField) {
|
|
|
1722
1829
|
changes.push(...compareFieldConstraints(currentField, previousField));
|
|
1723
1830
|
changes.push(...compareFieldOptions(currentField, previousField));
|
|
1724
1831
|
if (currentField.type === "relation" && previousField.type === "relation") {
|
|
1725
|
-
changes.push(...compareRelationConfigurations(currentField, previousField));
|
|
1832
|
+
changes.push(...compareRelationConfigurations(currentField, previousField, collectionIdToName));
|
|
1726
1833
|
}
|
|
1727
1834
|
return changes;
|
|
1728
1835
|
}
|
|
@@ -1733,7 +1840,7 @@ function compareIndexes(currentIndexes = [], previousIndexes = []) {
|
|
|
1733
1840
|
const indexesToRemove = previousIndexes.filter((idx) => !currentSet.has(idx));
|
|
1734
1841
|
return { indexesToAdd, indexesToRemove };
|
|
1735
1842
|
}
|
|
1736
|
-
function compareRules(currentRules, previousRules) {
|
|
1843
|
+
function compareRules(currentRules, previousRules, currentPermissions, previousPermissions) {
|
|
1737
1844
|
const updates = [];
|
|
1738
1845
|
const ruleTypes = [
|
|
1739
1846
|
"listRule",
|
|
@@ -1744,8 +1851,8 @@ function compareRules(currentRules, previousRules) {
|
|
|
1744
1851
|
"manageRule"
|
|
1745
1852
|
];
|
|
1746
1853
|
for (const ruleType of ruleTypes) {
|
|
1747
|
-
const currentValue = currentRules?.[ruleType] ?? null;
|
|
1748
|
-
const previousValue = previousRules?.[ruleType] ?? null;
|
|
1854
|
+
const currentValue = currentRules?.[ruleType] ?? currentPermissions?.[ruleType] ?? null;
|
|
1855
|
+
const previousValue = previousRules?.[ruleType] ?? previousPermissions?.[ruleType] ?? null;
|
|
1749
1856
|
if (currentValue !== previousValue) {
|
|
1750
1857
|
updates.push({
|
|
1751
1858
|
ruleType,
|
|
@@ -1772,7 +1879,7 @@ function comparePermissions(currentPermissions, previousPermissions) {
|
|
|
1772
1879
|
}
|
|
1773
1880
|
return changes;
|
|
1774
1881
|
}
|
|
1775
|
-
function compareCollectionFields(currentCollection, previousCollection, config) {
|
|
1882
|
+
function compareCollectionFields(currentCollection, previousCollection, config, collectionIdToName) {
|
|
1776
1883
|
let fieldsToAdd = findNewFields(currentCollection.fields, previousCollection.fields);
|
|
1777
1884
|
const fieldsToRemove = findRemovedFields(currentCollection.fields, previousCollection.fields);
|
|
1778
1885
|
const fieldsToModify = [];
|
|
@@ -1782,7 +1889,7 @@ function compareCollectionFields(currentCollection, previousCollection, config)
|
|
|
1782
1889
|
}
|
|
1783
1890
|
const matchedFields = matchFieldsByName(currentCollection.fields, previousCollection.fields);
|
|
1784
1891
|
for (const [currentField, previousField] of matchedFields) {
|
|
1785
|
-
const changes = detectFieldChanges(currentField, previousField);
|
|
1892
|
+
const changes = detectFieldChanges(currentField, previousField, collectionIdToName);
|
|
1786
1893
|
if (changes.length > 0) {
|
|
1787
1894
|
fieldsToModify.push({
|
|
1788
1895
|
fieldName: currentField.name,
|
|
@@ -1794,14 +1901,20 @@ function compareCollectionFields(currentCollection, previousCollection, config)
|
|
|
1794
1901
|
}
|
|
1795
1902
|
return { fieldsToAdd, fieldsToRemove, fieldsToModify };
|
|
1796
1903
|
}
|
|
1797
|
-
function buildCollectionModification(currentCollection, previousCollection, config) {
|
|
1904
|
+
function buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName) {
|
|
1798
1905
|
const { fieldsToAdd, fieldsToRemove, fieldsToModify } = compareCollectionFields(
|
|
1799
1906
|
currentCollection,
|
|
1800
1907
|
previousCollection,
|
|
1801
|
-
config
|
|
1908
|
+
config,
|
|
1909
|
+
collectionIdToName
|
|
1802
1910
|
);
|
|
1803
1911
|
const { indexesToAdd, indexesToRemove } = compareIndexes(currentCollection.indexes, previousCollection.indexes);
|
|
1804
|
-
const rulesToUpdate = compareRules(
|
|
1912
|
+
const rulesToUpdate = compareRules(
|
|
1913
|
+
currentCollection.rules,
|
|
1914
|
+
previousCollection.rules,
|
|
1915
|
+
currentCollection.permissions,
|
|
1916
|
+
previousCollection.permissions
|
|
1917
|
+
);
|
|
1805
1918
|
const permissionsToUpdate = comparePermissions(currentCollection.permissions, previousCollection.permissions);
|
|
1806
1919
|
return {
|
|
1807
1920
|
collection: currentCollection.name,
|
|
@@ -1818,6 +1931,14 @@ function hasChanges(modification) {
|
|
|
1818
1931
|
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;
|
|
1819
1932
|
}
|
|
1820
1933
|
function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
1934
|
+
const collectionIdToName = /* @__PURE__ */ new Map();
|
|
1935
|
+
if (previousSnapshot) {
|
|
1936
|
+
for (const [name, collection] of previousSnapshot.collections) {
|
|
1937
|
+
if (collection.id) {
|
|
1938
|
+
collectionIdToName.set(collection.id, name);
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1821
1942
|
const collectionsToCreate = findNewCollections(currentSchema, previousSnapshot);
|
|
1822
1943
|
const collectionsToDelete = findRemovedCollections(currentSchema, previousSnapshot);
|
|
1823
1944
|
const filteredCollectionsToCreate = collectionsToCreate.filter(
|
|
@@ -1826,16 +1947,28 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
|
1826
1947
|
const filteredCollectionsToDelete = collectionsToDelete.filter(
|
|
1827
1948
|
(collection) => !isSystemCollection(collection.name, config)
|
|
1828
1949
|
);
|
|
1950
|
+
const registry = new CollectionIdRegistry();
|
|
1951
|
+
const collectionsWithIds = filteredCollectionsToCreate.map((collection) => {
|
|
1952
|
+
if (collection.id) {
|
|
1953
|
+
registry.register(collection.id);
|
|
1954
|
+
return collection;
|
|
1955
|
+
}
|
|
1956
|
+
const id = registry.generate(collection.name);
|
|
1957
|
+
return {
|
|
1958
|
+
...collection,
|
|
1959
|
+
id
|
|
1960
|
+
};
|
|
1961
|
+
});
|
|
1829
1962
|
const collectionsToModify = [];
|
|
1830
1963
|
const matchedCollections = matchCollectionsByName(currentSchema, previousSnapshot);
|
|
1831
1964
|
for (const [currentCollection, previousCollection] of matchedCollections) {
|
|
1832
|
-
const modification = buildCollectionModification(currentCollection, previousCollection, config);
|
|
1965
|
+
const modification = buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName);
|
|
1833
1966
|
if (hasChanges(modification)) {
|
|
1834
1967
|
collectionsToModify.push(modification);
|
|
1835
1968
|
}
|
|
1836
1969
|
}
|
|
1837
1970
|
return {
|
|
1838
|
-
collectionsToCreate:
|
|
1971
|
+
collectionsToCreate: collectionsWithIds,
|
|
1839
1972
|
collectionsToDelete: filteredCollectionsToDelete,
|
|
1840
1973
|
collectionsToModify
|
|
1841
1974
|
};
|
|
@@ -1918,42 +2051,48 @@ function generateTimestamp(config) {
|
|
|
1918
2051
|
}
|
|
1919
2052
|
return Math.floor(Date.now() / 1e3).toString();
|
|
1920
2053
|
}
|
|
1921
|
-
function
|
|
1922
|
-
const
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
if (diff.collectionsToDelete.length === 1) {
|
|
1932
|
-
parts.push(`deleted_${diff.collectionsToDelete[0].name}`);
|
|
1933
|
-
} else {
|
|
1934
|
-
parts.push(`deleted_${diff.collectionsToDelete.length}_collections`);
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
1937
|
-
if (diff.collectionsToModify.length > 0) {
|
|
1938
|
-
if (diff.collectionsToModify.length === 1) {
|
|
1939
|
-
parts.push(`updated_${diff.collectionsToModify[0].collection}`);
|
|
1940
|
-
} else {
|
|
1941
|
-
parts.push(`updated_${diff.collectionsToModify.length}_collections`);
|
|
1942
|
-
}
|
|
2054
|
+
function splitDiffByCollection(diff, baseTimestamp) {
|
|
2055
|
+
const operations = [];
|
|
2056
|
+
let currentTimestamp = parseInt(baseTimestamp, 10);
|
|
2057
|
+
for (const collection of diff.collectionsToCreate) {
|
|
2058
|
+
operations.push({
|
|
2059
|
+
type: "create",
|
|
2060
|
+
collection,
|
|
2061
|
+
timestamp: currentTimestamp.toString()
|
|
2062
|
+
});
|
|
2063
|
+
currentTimestamp += 1;
|
|
1943
2064
|
}
|
|
1944
|
-
|
|
1945
|
-
|
|
2065
|
+
for (const modification of diff.collectionsToModify) {
|
|
2066
|
+
operations.push({
|
|
2067
|
+
type: "modify",
|
|
2068
|
+
collection: modification.collection,
|
|
2069
|
+
modifications: modification,
|
|
2070
|
+
timestamp: currentTimestamp.toString()
|
|
2071
|
+
});
|
|
2072
|
+
currentTimestamp += 1;
|
|
1946
2073
|
}
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
2074
|
+
for (const collection of diff.collectionsToDelete) {
|
|
2075
|
+
operations.push({
|
|
2076
|
+
type: "delete",
|
|
2077
|
+
collection: collection.name || collection,
|
|
2078
|
+
// Handle both object and string
|
|
2079
|
+
timestamp: currentTimestamp.toString()
|
|
2080
|
+
});
|
|
2081
|
+
currentTimestamp += 1;
|
|
1950
2082
|
}
|
|
1951
|
-
return
|
|
2083
|
+
return operations;
|
|
1952
2084
|
}
|
|
1953
|
-
function
|
|
1954
|
-
const timestamp =
|
|
1955
|
-
const
|
|
1956
|
-
|
|
2085
|
+
function generateCollectionMigrationFilename(operation) {
|
|
2086
|
+
const timestamp = operation.timestamp;
|
|
2087
|
+
const operationType = operation.type === "modify" ? "updated" : operation.type === "create" ? "created" : "deleted";
|
|
2088
|
+
let collectionName;
|
|
2089
|
+
if (typeof operation.collection === "string") {
|
|
2090
|
+
collectionName = operation.collection;
|
|
2091
|
+
} else {
|
|
2092
|
+
collectionName = operation.collection.name;
|
|
2093
|
+
}
|
|
2094
|
+
const sanitizedName = collectionName.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase();
|
|
2095
|
+
return `${timestamp}_${operationType}_${sanitizedName}.js`;
|
|
1957
2096
|
}
|
|
1958
2097
|
function createMigrationFileStructure(upCode, downCode, config) {
|
|
1959
2098
|
const mergedConfig = config ? mergeConfig3(config) : DEFAULT_CONFIG3;
|
|
@@ -2025,14 +2164,13 @@ function formatValue(value) {
|
|
|
2025
2164
|
return "null";
|
|
2026
2165
|
}
|
|
2027
2166
|
if (typeof value === "string") {
|
|
2028
|
-
return
|
|
2167
|
+
return JSON.stringify(value);
|
|
2029
2168
|
}
|
|
2030
2169
|
if (typeof value === "number" || typeof value === "boolean") {
|
|
2031
2170
|
return String(value);
|
|
2032
2171
|
}
|
|
2033
2172
|
if (Array.isArray(value)) {
|
|
2034
|
-
|
|
2035
|
-
return `[${items}]`;
|
|
2173
|
+
return JSON.stringify(value).replace(/","/g, '", "');
|
|
2036
2174
|
}
|
|
2037
2175
|
if (typeof value === "object") {
|
|
2038
2176
|
const entries = Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
|
|
@@ -2040,7 +2178,7 @@ function formatValue(value) {
|
|
|
2040
2178
|
}
|
|
2041
2179
|
return String(value);
|
|
2042
2180
|
}
|
|
2043
|
-
function generateFieldDefinitionObject(field) {
|
|
2181
|
+
function generateFieldDefinitionObject(field, collectionIdMap) {
|
|
2044
2182
|
const parts = [];
|
|
2045
2183
|
parts.push(` name: "${field.name}"`);
|
|
2046
2184
|
parts.push(` type: "${field.type}"`);
|
|
@@ -2048,34 +2186,47 @@ function generateFieldDefinitionObject(field) {
|
|
|
2048
2186
|
if (field.unique !== void 0) {
|
|
2049
2187
|
parts.push(` unique: ${field.unique}`);
|
|
2050
2188
|
}
|
|
2189
|
+
if (field.type === "select") {
|
|
2190
|
+
const maxSelect = field.options?.maxSelect ?? 1;
|
|
2191
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
2192
|
+
const values = field.options?.values ?? [];
|
|
2193
|
+
parts.push(` values: ${formatValue(values)}`);
|
|
2194
|
+
}
|
|
2051
2195
|
if (field.options && Object.keys(field.options).length > 0) {
|
|
2052
2196
|
for (const [key, value] of Object.entries(field.options)) {
|
|
2197
|
+
if (field.type === "select" && (key === "maxSelect" || key === "values")) {
|
|
2198
|
+
continue;
|
|
2199
|
+
}
|
|
2053
2200
|
parts.push(` ${key}: ${formatValue(value)}`);
|
|
2054
2201
|
}
|
|
2055
2202
|
}
|
|
2056
2203
|
if (field.relation) {
|
|
2057
2204
|
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
}
|
|
2066
|
-
if (field.relation.cascadeDelete !== void 0) {
|
|
2067
|
-
parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
|
|
2205
|
+
let collectionIdValue;
|
|
2206
|
+
if (isUsersCollection) {
|
|
2207
|
+
collectionIdValue = '"_pb_users_auth_"';
|
|
2208
|
+
} else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
|
|
2209
|
+
collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
|
|
2210
|
+
} else {
|
|
2211
|
+
collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
2068
2212
|
}
|
|
2213
|
+
parts.push(` collectionId: ${collectionIdValue}`);
|
|
2214
|
+
const maxSelect = field.relation.maxSelect ?? 1;
|
|
2215
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
2216
|
+
const minSelect = field.relation.minSelect ?? null;
|
|
2217
|
+
parts.push(` minSelect: ${minSelect}`);
|
|
2218
|
+
const cascadeDelete = field.relation.cascadeDelete ?? false;
|
|
2219
|
+
parts.push(` cascadeDelete: ${cascadeDelete}`);
|
|
2069
2220
|
}
|
|
2070
2221
|
return ` {
|
|
2071
2222
|
${parts.join(",\n")},
|
|
2072
2223
|
}`;
|
|
2073
2224
|
}
|
|
2074
|
-
function generateFieldsArray(fields) {
|
|
2225
|
+
function generateFieldsArray(fields, collectionIdMap) {
|
|
2075
2226
|
if (fields.length === 0) {
|
|
2076
2227
|
return "[]";
|
|
2077
2228
|
}
|
|
2078
|
-
const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field));
|
|
2229
|
+
const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field, collectionIdMap));
|
|
2079
2230
|
return `[
|
|
2080
2231
|
${fieldObjects.join(",\n")},
|
|
2081
2232
|
]`;
|
|
@@ -2134,7 +2285,7 @@ function generateIndexesArray(indexes) {
|
|
|
2134
2285
|
if (!indexes || indexes.length === 0) {
|
|
2135
2286
|
return "[]";
|
|
2136
2287
|
}
|
|
2137
|
-
const indexStrings = indexes.map((idx) =>
|
|
2288
|
+
const indexStrings = indexes.map((idx) => JSON.stringify(idx));
|
|
2138
2289
|
return `[
|
|
2139
2290
|
${indexStrings.join(",\n ")},
|
|
2140
2291
|
]`;
|
|
@@ -2188,9 +2339,12 @@ function getSystemFields() {
|
|
|
2188
2339
|
}
|
|
2189
2340
|
];
|
|
2190
2341
|
}
|
|
2191
|
-
function generateCollectionCreation(collection, varName = "collection", isLast = false) {
|
|
2342
|
+
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
2192
2343
|
const lines = [];
|
|
2193
2344
|
lines.push(` const ${varName} = new Collection({`);
|
|
2345
|
+
if (collection.id) {
|
|
2346
|
+
lines.push(` id: ${formatValue(collection.id)},`);
|
|
2347
|
+
}
|
|
2194
2348
|
lines.push(` name: "${collection.name}",`);
|
|
2195
2349
|
lines.push(` type: "${collection.type}",`);
|
|
2196
2350
|
const permissionsCode = generateCollectionPermissions(collection.permissions);
|
|
@@ -2202,7 +2356,7 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
|
|
|
2202
2356
|
}
|
|
2203
2357
|
const systemFields = getSystemFields();
|
|
2204
2358
|
const allFields = [...systemFields, ...collection.fields];
|
|
2205
|
-
lines.push(` fields: ${generateFieldsArray(allFields)},`);
|
|
2359
|
+
lines.push(` fields: ${generateFieldsArray(allFields, collectionIdMap)},`);
|
|
2206
2360
|
lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
|
|
2207
2361
|
lines.push(` });`);
|
|
2208
2362
|
lines.push(``);
|
|
@@ -2224,42 +2378,59 @@ function getFieldConstructorName(fieldType) {
|
|
|
2224
2378
|
};
|
|
2225
2379
|
return constructorMap[fieldType] || "TextField";
|
|
2226
2380
|
}
|
|
2227
|
-
function generateFieldConstructorOptions(field) {
|
|
2381
|
+
function generateFieldConstructorOptions(field, collectionIdMap) {
|
|
2228
2382
|
const parts = [];
|
|
2229
2383
|
parts.push(` name: "${field.name}"`);
|
|
2230
2384
|
parts.push(` required: ${field.required}`);
|
|
2231
2385
|
if (field.unique !== void 0) {
|
|
2232
2386
|
parts.push(` unique: ${field.unique}`);
|
|
2233
2387
|
}
|
|
2388
|
+
if (field.type === "select") {
|
|
2389
|
+
const maxSelect = field.options?.maxSelect ?? 1;
|
|
2390
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
2391
|
+
const values = field.options?.values ?? [];
|
|
2392
|
+
parts.push(` values: ${formatValue(values)}`);
|
|
2393
|
+
}
|
|
2234
2394
|
if (field.options && Object.keys(field.options).length > 0) {
|
|
2235
2395
|
for (const [key, value] of Object.entries(field.options)) {
|
|
2236
|
-
|
|
2396
|
+
if (field.type === "select" && (key === "maxSelect" || key === "values")) {
|
|
2397
|
+
continue;
|
|
2398
|
+
}
|
|
2399
|
+
if (field.type === "number" && key === "noDecimal") {
|
|
2400
|
+
parts.push(` onlyInt: ${formatValue(value)}`);
|
|
2401
|
+
} else {
|
|
2402
|
+
parts.push(` ${key}: ${formatValue(value)}`);
|
|
2403
|
+
}
|
|
2237
2404
|
}
|
|
2238
2405
|
}
|
|
2239
2406
|
if (field.relation && field.type === "relation") {
|
|
2240
2407
|
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
}
|
|
2249
|
-
if (field.relation.cascadeDelete !== void 0) {
|
|
2250
|
-
parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
|
|
2408
|
+
let collectionIdValue;
|
|
2409
|
+
if (isUsersCollection) {
|
|
2410
|
+
collectionIdValue = '"_pb_users_auth_"';
|
|
2411
|
+
} else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
|
|
2412
|
+
collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
|
|
2413
|
+
} else {
|
|
2414
|
+
collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
2251
2415
|
}
|
|
2416
|
+
parts.push(` collectionId: ${collectionIdValue}`);
|
|
2417
|
+
const maxSelect = field.relation.maxSelect ?? 1;
|
|
2418
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
2419
|
+
const minSelect = field.relation.minSelect ?? null;
|
|
2420
|
+
parts.push(` minSelect: ${minSelect}`);
|
|
2421
|
+
const cascadeDelete = field.relation.cascadeDelete ?? false;
|
|
2422
|
+
parts.push(` cascadeDelete: ${cascadeDelete}`);
|
|
2252
2423
|
}
|
|
2253
2424
|
return parts.join(",\n");
|
|
2254
2425
|
}
|
|
2255
|
-
function generateFieldAddition(collectionName, field, varName, isLast = false) {
|
|
2426
|
+
function generateFieldAddition(collectionName, field, varName, isLast = false, collectionIdMap) {
|
|
2256
2427
|
const lines = [];
|
|
2257
2428
|
const constructorName = getFieldConstructorName(field.type);
|
|
2258
2429
|
const collectionVar = varName || `collection_${collectionName}_${field.name}`;
|
|
2259
2430
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
2260
2431
|
lines.push(``);
|
|
2261
2432
|
lines.push(` ${collectionVar}.fields.add(new ${constructorName}({`);
|
|
2262
|
-
lines.push(generateFieldConstructorOptions(field));
|
|
2433
|
+
lines.push(generateFieldConstructorOptions(field, collectionIdMap));
|
|
2263
2434
|
lines.push(` }));`);
|
|
2264
2435
|
lines.push(``);
|
|
2265
2436
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
@@ -2309,7 +2480,7 @@ function generateIndexAddition(collectionName, index, varName, isLast = false) {
|
|
|
2309
2480
|
const lines = [];
|
|
2310
2481
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
2311
2482
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
2312
|
-
lines.push(` ${collectionVar}.indexes.push(
|
|
2483
|
+
lines.push(` ${collectionVar}.indexes.push(${JSON.stringify(index)});`);
|
|
2313
2484
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
2314
2485
|
return lines.join("\n");
|
|
2315
2486
|
}
|
|
@@ -2318,7 +2489,7 @@ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
|
|
|
2318
2489
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
2319
2490
|
const indexVar = `${collectionVar}_indexToRemove`;
|
|
2320
2491
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
2321
|
-
lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx ===
|
|
2492
|
+
lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === ${JSON.stringify(index)});`);
|
|
2322
2493
|
lines.push(` if (${indexVar} !== -1) {`);
|
|
2323
2494
|
lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
|
|
2324
2495
|
lines.push(` }`);
|
|
@@ -2347,94 +2518,75 @@ function generateCollectionDeletion(collectionName, varName = "collection", isLa
|
|
|
2347
2518
|
lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
|
|
2348
2519
|
return lines.join("\n");
|
|
2349
2520
|
}
|
|
2350
|
-
function
|
|
2521
|
+
function generateOperationUpMigration(operation, collectionIdMap) {
|
|
2351
2522
|
const lines = [];
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
lines.push(
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2523
|
+
if (operation.type === "create") {
|
|
2524
|
+
const collection = operation.collection;
|
|
2525
|
+
const varName = `collection_${collection.name}`;
|
|
2526
|
+
lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
|
|
2527
|
+
} else if (operation.type === "modify") {
|
|
2528
|
+
const modification = operation.modifications;
|
|
2529
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
2530
|
+
let operationCount = 0;
|
|
2531
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
|
|
2532
|
+
for (const field of modification.fieldsToAdd) {
|
|
2533
|
+
operationCount++;
|
|
2534
|
+
const varName = `collection_${collectionName}_add_${field.name}`;
|
|
2535
|
+
const isLast = operationCount === totalOperations;
|
|
2536
|
+
lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
|
|
2537
|
+
if (!isLast) lines.push("");
|
|
2361
2538
|
}
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
if (
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
|
|
2371
|
-
|
|
2372
|
-
|
|
2373
|
-
|
|
2374
|
-
|
|
2375
|
-
|
|
2376
|
-
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
|
|
2390
|
-
|
|
2391
|
-
|
|
2392
|
-
|
|
2393
|
-
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
}
|
|
2400
|
-
if (modification.indexesToRemove.length > 0) {
|
|
2401
|
-
lines.push(` // Remove indexes from ${collectionName}`);
|
|
2402
|
-
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
2403
|
-
const index = modification.indexesToRemove[i];
|
|
2404
|
-
const varName = `collection_${collectionName}_rmidx_${i}`;
|
|
2405
|
-
lines.push(generateIndexRemoval(collectionName, index, varName));
|
|
2406
|
-
lines.push(``);
|
|
2407
|
-
}
|
|
2539
|
+
for (const fieldMod of modification.fieldsToModify) {
|
|
2540
|
+
operationCount++;
|
|
2541
|
+
const varName = `collection_${collectionName}_modify_${fieldMod.fieldName}`;
|
|
2542
|
+
const isLast = operationCount === totalOperations;
|
|
2543
|
+
lines.push(generateFieldModification(collectionName, fieldMod, varName, isLast));
|
|
2544
|
+
if (!isLast) lines.push("");
|
|
2545
|
+
}
|
|
2546
|
+
for (const field of modification.fieldsToRemove) {
|
|
2547
|
+
operationCount++;
|
|
2548
|
+
const varName = `collection_${collectionName}_remove_${field.name}`;
|
|
2549
|
+
const isLast = operationCount === totalOperations;
|
|
2550
|
+
lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
|
|
2551
|
+
if (!isLast) lines.push("");
|
|
2552
|
+
}
|
|
2553
|
+
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
2554
|
+
operationCount++;
|
|
2555
|
+
const index = modification.indexesToAdd[i];
|
|
2556
|
+
const varName = `collection_${collectionName}_addidx_${i}`;
|
|
2557
|
+
const isLast = operationCount === totalOperations;
|
|
2558
|
+
lines.push(generateIndexAddition(collectionName, index, varName, isLast));
|
|
2559
|
+
if (!isLast) lines.push("");
|
|
2560
|
+
}
|
|
2561
|
+
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
2562
|
+
operationCount++;
|
|
2563
|
+
const index = modification.indexesToRemove[i];
|
|
2564
|
+
const varName = `collection_${collectionName}_rmidx_${i}`;
|
|
2565
|
+
const isLast = operationCount === totalOperations;
|
|
2566
|
+
lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
|
|
2567
|
+
if (!isLast) lines.push("");
|
|
2568
|
+
}
|
|
2569
|
+
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
2570
|
+
for (const permission of modification.permissionsToUpdate) {
|
|
2571
|
+
operationCount++;
|
|
2572
|
+
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
2573
|
+
const isLast = operationCount === totalOperations;
|
|
2574
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast));
|
|
2575
|
+
if (!isLast) lines.push("");
|
|
2408
2576
|
}
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
} else if (modification.rulesToUpdate.length > 0) {
|
|
2417
|
-
lines.push(` // Update rules for ${collectionName}`);
|
|
2418
|
-
for (const rule of modification.rulesToUpdate) {
|
|
2419
|
-
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
2420
|
-
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName));
|
|
2421
|
-
lines.push(``);
|
|
2422
|
-
}
|
|
2577
|
+
} else if (modification.rulesToUpdate.length > 0) {
|
|
2578
|
+
for (const rule of modification.rulesToUpdate) {
|
|
2579
|
+
operationCount++;
|
|
2580
|
+
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
2581
|
+
const isLast = operationCount === totalOperations;
|
|
2582
|
+
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast));
|
|
2583
|
+
if (!isLast) lines.push("");
|
|
2423
2584
|
}
|
|
2424
2585
|
}
|
|
2425
|
-
}
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
const collection = diff.collectionsToDelete[i];
|
|
2430
|
-
const varName = `collection_${collection.name}_delete`;
|
|
2431
|
-
lines.push(generateCollectionDeletion(collection.name, varName));
|
|
2432
|
-
lines.push(``);
|
|
2433
|
-
}
|
|
2434
|
-
}
|
|
2435
|
-
if (lines.length === 2) {
|
|
2436
|
-
lines.push(` // No changes detected`);
|
|
2437
|
-
lines.push(``);
|
|
2586
|
+
} else if (operation.type === "delete") {
|
|
2587
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
|
|
2588
|
+
const varName = `collection_${collectionName}`;
|
|
2589
|
+
lines.push(generateCollectionDeletion(collectionName, varName, true));
|
|
2438
2590
|
}
|
|
2439
2591
|
let code = lines.join("\n");
|
|
2440
2592
|
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
@@ -2455,105 +2607,88 @@ function generateUpMigration(diff) {
|
|
|
2455
2607
|
}
|
|
2456
2608
|
return code;
|
|
2457
2609
|
}
|
|
2458
|
-
function
|
|
2610
|
+
function generateOperationDownMigration(operation, collectionIdMap) {
|
|
2459
2611
|
const lines = [];
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
lines.push(
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
|
|
2468
|
-
|
|
2469
|
-
|
|
2470
|
-
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
lines.push(` // Revert permissions for ${collectionName}`);
|
|
2477
|
-
for (const permission of modification.permissionsToUpdate) {
|
|
2478
|
-
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
2479
|
-
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName));
|
|
2480
|
-
lines.push(``);
|
|
2481
|
-
}
|
|
2482
|
-
} else if (modification.rulesToUpdate.length > 0) {
|
|
2483
|
-
lines.push(` // Revert rules for ${collectionName}`);
|
|
2484
|
-
for (const rule of modification.rulesToUpdate) {
|
|
2485
|
-
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
2486
|
-
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName));
|
|
2487
|
-
lines.push(``);
|
|
2488
|
-
}
|
|
2489
|
-
}
|
|
2490
|
-
if (modification.indexesToRemove.length > 0) {
|
|
2491
|
-
lines.push(` // Restore indexes to ${collectionName}`);
|
|
2492
|
-
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
2493
|
-
const index = modification.indexesToRemove[i];
|
|
2494
|
-
const varName = `collection_${collectionName}_restore_idx_${i}`;
|
|
2495
|
-
lines.push(generateIndexAddition(collectionName, index, varName));
|
|
2496
|
-
lines.push(``);
|
|
2497
|
-
}
|
|
2498
|
-
}
|
|
2499
|
-
if (modification.indexesToAdd.length > 0) {
|
|
2500
|
-
lines.push(` // Remove indexes from ${collectionName}`);
|
|
2501
|
-
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
2502
|
-
const index = modification.indexesToAdd[i];
|
|
2503
|
-
const varName = `collection_${collectionName}_revert_idx_${i}`;
|
|
2504
|
-
lines.push(generateIndexRemoval(collectionName, index, varName));
|
|
2505
|
-
lines.push(``);
|
|
2506
|
-
}
|
|
2507
|
-
}
|
|
2508
|
-
if (modification.fieldsToRemove.length > 0) {
|
|
2509
|
-
lines.push(` // Restore fields to ${collectionName}`);
|
|
2510
|
-
for (const field of modification.fieldsToRemove) {
|
|
2511
|
-
const varName = `collection_${collectionName}_restore_${field.name}`;
|
|
2512
|
-
lines.push(generateFieldAddition(collectionName, field, varName));
|
|
2513
|
-
lines.push(``);
|
|
2514
|
-
}
|
|
2612
|
+
if (operation.type === "create") {
|
|
2613
|
+
const collection = operation.collection;
|
|
2614
|
+
const varName = `collection_${collection.name}`;
|
|
2615
|
+
lines.push(generateCollectionDeletion(collection.name, varName, true));
|
|
2616
|
+
} else if (operation.type === "modify") {
|
|
2617
|
+
const modification = operation.modifications;
|
|
2618
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
2619
|
+
let operationCount = 0;
|
|
2620
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
|
|
2621
|
+
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
2622
|
+
for (const permission of modification.permissionsToUpdate) {
|
|
2623
|
+
operationCount++;
|
|
2624
|
+
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
2625
|
+
const isLast = operationCount === totalOperations;
|
|
2626
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast));
|
|
2627
|
+
if (!isLast) lines.push("");
|
|
2515
2628
|
}
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
}));
|
|
2524
|
-
const reverseMod = {
|
|
2525
|
-
fieldName: fieldMod.fieldName,
|
|
2526
|
-
currentDefinition: fieldMod.newDefinition,
|
|
2527
|
-
newDefinition: fieldMod.currentDefinition,
|
|
2528
|
-
changes: reverseChanges
|
|
2529
|
-
};
|
|
2530
|
-
const varName = `collection_${collectionName}_revert_${fieldMod.fieldName}`;
|
|
2531
|
-
lines.push(generateFieldModification(collectionName, reverseMod, varName));
|
|
2532
|
-
lines.push(``);
|
|
2533
|
-
}
|
|
2534
|
-
}
|
|
2535
|
-
if (modification.fieldsToAdd.length > 0) {
|
|
2536
|
-
lines.push(` // Remove added fields from ${collectionName}`);
|
|
2537
|
-
for (const field of modification.fieldsToAdd) {
|
|
2538
|
-
const varName = `collection_${collectionName}_revert_add_${field.name}`;
|
|
2539
|
-
lines.push(generateFieldDeletion(collectionName, field.name, varName));
|
|
2540
|
-
lines.push(``);
|
|
2541
|
-
}
|
|
2629
|
+
} else if (modification.rulesToUpdate.length > 0) {
|
|
2630
|
+
for (const rule of modification.rulesToUpdate) {
|
|
2631
|
+
operationCount++;
|
|
2632
|
+
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
2633
|
+
const isLast = operationCount === totalOperations;
|
|
2634
|
+
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast));
|
|
2635
|
+
if (!isLast) lines.push("");
|
|
2542
2636
|
}
|
|
2543
2637
|
}
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
const
|
|
2549
|
-
|
|
2550
|
-
lines.push(
|
|
2551
|
-
|
|
2638
|
+
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
2639
|
+
operationCount++;
|
|
2640
|
+
const index = modification.indexesToRemove[i];
|
|
2641
|
+
const varName = `collection_${collectionName}_restore_idx_${i}`;
|
|
2642
|
+
const isLast = operationCount === totalOperations;
|
|
2643
|
+
lines.push(generateIndexAddition(collectionName, index, varName, isLast));
|
|
2644
|
+
if (!isLast) lines.push("");
|
|
2645
|
+
}
|
|
2646
|
+
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
2647
|
+
operationCount++;
|
|
2648
|
+
const index = modification.indexesToAdd[i];
|
|
2649
|
+
const varName = `collection_${collectionName}_revert_idx_${i}`;
|
|
2650
|
+
const isLast = operationCount === totalOperations;
|
|
2651
|
+
lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
|
|
2652
|
+
if (!isLast) lines.push("");
|
|
2653
|
+
}
|
|
2654
|
+
for (const field of modification.fieldsToRemove) {
|
|
2655
|
+
operationCount++;
|
|
2656
|
+
const varName = `collection_${collectionName}_restore_${field.name}`;
|
|
2657
|
+
const isLast = operationCount === totalOperations;
|
|
2658
|
+
lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
|
|
2659
|
+
if (!isLast) lines.push("");
|
|
2660
|
+
}
|
|
2661
|
+
for (const fieldMod of modification.fieldsToModify) {
|
|
2662
|
+
operationCount++;
|
|
2663
|
+
const reverseChanges = fieldMod.changes.map((change) => ({
|
|
2664
|
+
property: change.property,
|
|
2665
|
+
oldValue: change.newValue,
|
|
2666
|
+
newValue: change.oldValue
|
|
2667
|
+
}));
|
|
2668
|
+
const reverseMod = {
|
|
2669
|
+
fieldName: fieldMod.fieldName,
|
|
2670
|
+
currentDefinition: fieldMod.newDefinition,
|
|
2671
|
+
newDefinition: fieldMod.currentDefinition,
|
|
2672
|
+
changes: reverseChanges
|
|
2673
|
+
};
|
|
2674
|
+
const varName = `collection_${collectionName}_revert_${fieldMod.fieldName}`;
|
|
2675
|
+
const isLast = operationCount === totalOperations;
|
|
2676
|
+
lines.push(generateFieldModification(collectionName, reverseMod, varName, isLast));
|
|
2677
|
+
if (!isLast) lines.push("");
|
|
2678
|
+
}
|
|
2679
|
+
for (const field of modification.fieldsToAdd) {
|
|
2680
|
+
operationCount++;
|
|
2681
|
+
const varName = `collection_${collectionName}_revert_add_${field.name}`;
|
|
2682
|
+
const isLast = operationCount === totalOperations;
|
|
2683
|
+
lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
|
|
2684
|
+
if (!isLast) lines.push("");
|
|
2685
|
+
}
|
|
2686
|
+
} else if (operation.type === "delete") {
|
|
2687
|
+
const collection = operation.collection;
|
|
2688
|
+
if (typeof collection !== "string") {
|
|
2689
|
+
const varName = `collection_${collection.name}`;
|
|
2690
|
+
lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
|
|
2552
2691
|
}
|
|
2553
|
-
}
|
|
2554
|
-
if (lines.length === 2) {
|
|
2555
|
-
lines.push(` // No changes to revert`);
|
|
2556
|
-
lines.push(``);
|
|
2557
2692
|
}
|
|
2558
2693
|
let code = lines.join("\n");
|
|
2559
2694
|
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
@@ -2578,12 +2713,33 @@ function generate(diff, config) {
|
|
|
2578
2713
|
const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
|
|
2579
2714
|
try {
|
|
2580
2715
|
const migrationDir = resolveMigrationDir(normalizedConfig);
|
|
2581
|
-
const
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
const
|
|
2586
|
-
|
|
2716
|
+
const hasChanges4 = diff.collectionsToCreate.length > 0 || diff.collectionsToModify.length > 0 || diff.collectionsToDelete.length > 0;
|
|
2717
|
+
if (!hasChanges4) {
|
|
2718
|
+
return [];
|
|
2719
|
+
}
|
|
2720
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
2721
|
+
for (const collection of diff.collectionsToCreate) {
|
|
2722
|
+
if (collection.id) {
|
|
2723
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2726
|
+
for (const collection of diff.collectionsToDelete) {
|
|
2727
|
+
if (collection.id) {
|
|
2728
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
const baseTimestamp = generateTimestamp(normalizedConfig);
|
|
2732
|
+
const operations = splitDiffByCollection(diff, baseTimestamp);
|
|
2733
|
+
const filePaths = [];
|
|
2734
|
+
for (const operation of operations) {
|
|
2735
|
+
const upCode = generateOperationUpMigration(operation, collectionIdMap);
|
|
2736
|
+
const downCode = generateOperationDownMigration(operation, collectionIdMap);
|
|
2737
|
+
const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
|
|
2738
|
+
const filename = generateCollectionMigrationFilename(operation);
|
|
2739
|
+
const filePath = writeMigrationFile(migrationDir, filename, content);
|
|
2740
|
+
filePaths.push(filePath);
|
|
2741
|
+
}
|
|
2742
|
+
return filePaths;
|
|
2587
2743
|
} catch (error) {
|
|
2588
2744
|
if (error instanceof MigrationGenerationError || error instanceof FileSystemError) {
|
|
2589
2745
|
throw error;
|
|
@@ -2600,7 +2756,7 @@ function generate(diff, config) {
|
|
|
2600
2756
|
var SNAPSHOT_VERSION = "1.0.0";
|
|
2601
2757
|
function resolveCollectionIdToName(collectionId) {
|
|
2602
2758
|
if (collectionId === "_pb_users_auth_") {
|
|
2603
|
-
return "
|
|
2759
|
+
return "users";
|
|
2604
2760
|
}
|
|
2605
2761
|
const nameMatch = collectionId.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
2606
2762
|
if (nameMatch) {
|
|
@@ -2608,6 +2764,39 @@ function resolveCollectionIdToName(collectionId) {
|
|
|
2608
2764
|
}
|
|
2609
2765
|
return collectionId;
|
|
2610
2766
|
}
|
|
2767
|
+
function extractFieldOptions2(pbField) {
|
|
2768
|
+
const options = {};
|
|
2769
|
+
if (pbField.options && typeof pbField.options === "object") {
|
|
2770
|
+
Object.assign(options, pbField.options);
|
|
2771
|
+
}
|
|
2772
|
+
const directOptionKeys = [
|
|
2773
|
+
"min",
|
|
2774
|
+
"max",
|
|
2775
|
+
"pattern",
|
|
2776
|
+
"noDecimal",
|
|
2777
|
+
// text/number fields
|
|
2778
|
+
"values",
|
|
2779
|
+
"maxSelect",
|
|
2780
|
+
// select fields
|
|
2781
|
+
"mimeTypes",
|
|
2782
|
+
"maxSize",
|
|
2783
|
+
"thumbs",
|
|
2784
|
+
"protected",
|
|
2785
|
+
// file fields
|
|
2786
|
+
"onCreate",
|
|
2787
|
+
"onUpdate",
|
|
2788
|
+
// autodate fields
|
|
2789
|
+
"exceptDomains",
|
|
2790
|
+
"onlyDomains"
|
|
2791
|
+
// email/url fields
|
|
2792
|
+
];
|
|
2793
|
+
for (const key of directOptionKeys) {
|
|
2794
|
+
if (pbField[key] !== void 0) {
|
|
2795
|
+
options[key] = pbField[key];
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2798
|
+
return options;
|
|
2799
|
+
}
|
|
2611
2800
|
function convertPocketBaseCollection(pbCollection) {
|
|
2612
2801
|
const fields = [];
|
|
2613
2802
|
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
@@ -2625,23 +2814,19 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
2625
2814
|
type: pbField.type,
|
|
2626
2815
|
required: pbField.required || false
|
|
2627
2816
|
};
|
|
2628
|
-
field.options = pbField
|
|
2629
|
-
if (pbField.type === "select") {
|
|
2630
|
-
if (pbField.values && Array.isArray(pbField.values)) {
|
|
2631
|
-
field.options.values = pbField.values;
|
|
2632
|
-
} else if (pbField.options?.values && Array.isArray(pbField.options.values)) {
|
|
2633
|
-
field.options.values = pbField.options.values;
|
|
2634
|
-
}
|
|
2635
|
-
}
|
|
2817
|
+
field.options = extractFieldOptions2(pbField);
|
|
2636
2818
|
if (pbField.type === "relation") {
|
|
2637
2819
|
const collectionId = pbField.collectionId || pbField.options?.collectionId || "";
|
|
2638
|
-
const collectionName = resolveCollectionIdToName(collectionId);
|
|
2820
|
+
const collectionName = resolveCollectionIdToName(collectionId || "");
|
|
2639
2821
|
field.relation = {
|
|
2640
2822
|
collection: collectionName,
|
|
2641
2823
|
cascadeDelete: pbField.cascadeDelete ?? pbField.options?.cascadeDelete ?? false,
|
|
2642
2824
|
maxSelect: pbField.maxSelect ?? pbField.options?.maxSelect,
|
|
2643
2825
|
minSelect: pbField.minSelect ?? pbField.options?.minSelect
|
|
2644
2826
|
};
|
|
2827
|
+
delete field.options.maxSelect;
|
|
2828
|
+
delete field.options.minSelect;
|
|
2829
|
+
delete field.options.cascadeDelete;
|
|
2645
2830
|
}
|
|
2646
2831
|
const hasOnlyValues = Object.keys(field.options).length === 1 && field.options.values !== void 0;
|
|
2647
2832
|
if (Object.keys(field.options).length === 0) {
|
|
@@ -2655,17 +2840,21 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
2655
2840
|
type: pbCollection.type || "base",
|
|
2656
2841
|
fields
|
|
2657
2842
|
};
|
|
2843
|
+
if (pbCollection.id) {
|
|
2844
|
+
schema.id = pbCollection.id;
|
|
2845
|
+
}
|
|
2658
2846
|
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
2659
2847
|
schema.indexes = pbCollection.indexes;
|
|
2660
2848
|
}
|
|
2661
|
-
const
|
|
2662
|
-
if (
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
2849
|
+
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;
|
|
2850
|
+
if (hasAnyRule) {
|
|
2851
|
+
const rules = {};
|
|
2852
|
+
if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
|
|
2853
|
+
if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
|
|
2854
|
+
if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
|
|
2855
|
+
if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
|
|
2856
|
+
if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
|
|
2857
|
+
if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
|
|
2669
2858
|
schema.rules = rules;
|
|
2670
2859
|
schema.permissions = { ...rules };
|
|
2671
2860
|
}
|
|
@@ -3604,15 +3793,25 @@ async function executeGenerate(options) {
|
|
|
3604
3793
|
process.exit(1);
|
|
3605
3794
|
}
|
|
3606
3795
|
logSection("\u{1F4DD} Generating Migration");
|
|
3607
|
-
const
|
|
3796
|
+
const migrationPaths = await withProgress(
|
|
3608
3797
|
"Creating migration file...",
|
|
3609
3798
|
() => Promise.resolve(generate(diff, migrationsDir))
|
|
3610
3799
|
);
|
|
3611
|
-
|
|
3800
|
+
if (migrationPaths.length === 0) {
|
|
3801
|
+
logWarning("No migration files were generated (no changes detected).");
|
|
3802
|
+
return;
|
|
3803
|
+
}
|
|
3804
|
+
if (migrationPaths.length === 1) {
|
|
3805
|
+
logSuccess(`Migration file created: ${path5__namespace.basename(migrationPaths[0])}`);
|
|
3806
|
+
} else {
|
|
3807
|
+
logSuccess(`Created ${migrationPaths.length} migration files`);
|
|
3808
|
+
}
|
|
3612
3809
|
logSection("\u2705 Next Steps");
|
|
3613
3810
|
console.log();
|
|
3614
|
-
console.log(" 1. Review the generated migration file:");
|
|
3615
|
-
|
|
3811
|
+
console.log(" 1. Review the generated migration file(s):");
|
|
3812
|
+
migrationPaths.forEach((migrationPath) => {
|
|
3813
|
+
console.log(` ${migrationPath}`);
|
|
3814
|
+
});
|
|
3616
3815
|
console.log();
|
|
3617
3816
|
console.log(" 2. Apply the migration by running PocketBase:");
|
|
3618
3817
|
console.log(" yarn pb");
|