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