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.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as path5 from 'path';
|
|
2
2
|
import * as fs5 from 'fs';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
+
import { randomBytes } from 'crypto';
|
|
4
5
|
import chalk from 'chalk';
|
|
5
6
|
import ora from 'ora';
|
|
6
7
|
|
|
@@ -1288,12 +1289,22 @@ function isAuthCollection(fields) {
|
|
|
1288
1289
|
function buildFieldDefinition(fieldName, zodType) {
|
|
1289
1290
|
const fieldMetadata = extractFieldMetadata(zodType.description);
|
|
1290
1291
|
if (fieldMetadata) {
|
|
1291
|
-
|
|
1292
|
+
let required2;
|
|
1293
|
+
if (fieldMetadata.type === "number") {
|
|
1294
|
+
if (fieldMetadata.options?.required !== void 0) {
|
|
1295
|
+
required2 = fieldMetadata.options.required;
|
|
1296
|
+
} else {
|
|
1297
|
+
required2 = false;
|
|
1298
|
+
}
|
|
1299
|
+
} else {
|
|
1300
|
+
required2 = isFieldRequired(zodType);
|
|
1301
|
+
}
|
|
1302
|
+
const { required: _required, ...options2 } = fieldMetadata.options || {};
|
|
1292
1303
|
const fieldDef2 = {
|
|
1293
1304
|
name: fieldName,
|
|
1294
1305
|
type: fieldMetadata.type,
|
|
1295
1306
|
required: required2,
|
|
1296
|
-
options:
|
|
1307
|
+
options: Object.keys(options2).length > 0 ? options2 : void 0
|
|
1297
1308
|
};
|
|
1298
1309
|
if (fieldMetadata.type === "relation") {
|
|
1299
1310
|
const relationMetadata2 = extractRelationMetadata(zodType.description);
|
|
@@ -1463,6 +1474,67 @@ async function buildSchemaDefinition(config) {
|
|
|
1463
1474
|
async function parseSchemaFiles(config) {
|
|
1464
1475
|
return buildSchemaDefinition(config);
|
|
1465
1476
|
}
|
|
1477
|
+
function generateCollectionId() {
|
|
1478
|
+
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
1479
|
+
const idLength = 15;
|
|
1480
|
+
const bytes = randomBytes(idLength);
|
|
1481
|
+
let id = "pb_";
|
|
1482
|
+
for (let i = 0; i < idLength; i++) {
|
|
1483
|
+
const index = bytes[i] % chars.length;
|
|
1484
|
+
id += chars[index];
|
|
1485
|
+
}
|
|
1486
|
+
return id;
|
|
1487
|
+
}
|
|
1488
|
+
var CollectionIdRegistry = class {
|
|
1489
|
+
ids;
|
|
1490
|
+
constructor() {
|
|
1491
|
+
this.ids = /* @__PURE__ */ new Set();
|
|
1492
|
+
}
|
|
1493
|
+
/**
|
|
1494
|
+
* Generates a unique collection ID for a given collection name
|
|
1495
|
+
* Retries up to 10 times if collision occurs (extremely rare)
|
|
1496
|
+
* Special case: returns "_pb_users_auth_" for users collection
|
|
1497
|
+
*
|
|
1498
|
+
* @param collectionName - The name of the collection (optional)
|
|
1499
|
+
* @returns A unique collection ID
|
|
1500
|
+
* @throws Error if unable to generate unique ID after max attempts
|
|
1501
|
+
*/
|
|
1502
|
+
generate(collectionName) {
|
|
1503
|
+
if (collectionName && collectionName.toLowerCase() === "users") {
|
|
1504
|
+
const usersId = "_pb_users_auth_";
|
|
1505
|
+
if (!this.has(usersId)) {
|
|
1506
|
+
this.register(usersId);
|
|
1507
|
+
}
|
|
1508
|
+
return usersId;
|
|
1509
|
+
}
|
|
1510
|
+
const maxAttempts = 10;
|
|
1511
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
1512
|
+
const id = generateCollectionId();
|
|
1513
|
+
if (!this.has(id)) {
|
|
1514
|
+
this.register(id);
|
|
1515
|
+
return id;
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
throw new Error("Failed to generate unique collection ID after maximum attempts");
|
|
1519
|
+
}
|
|
1520
|
+
/**
|
|
1521
|
+
* Checks if an ID has already been registered
|
|
1522
|
+
*
|
|
1523
|
+
* @param id - The collection ID to check
|
|
1524
|
+
* @returns True if the ID exists in the registry
|
|
1525
|
+
*/
|
|
1526
|
+
has(id) {
|
|
1527
|
+
return this.ids.has(id);
|
|
1528
|
+
}
|
|
1529
|
+
/**
|
|
1530
|
+
* Registers a collection ID in the registry
|
|
1531
|
+
*
|
|
1532
|
+
* @param id - The collection ID to register
|
|
1533
|
+
*/
|
|
1534
|
+
register(id) {
|
|
1535
|
+
this.ids.add(id);
|
|
1536
|
+
}
|
|
1537
|
+
};
|
|
1466
1538
|
|
|
1467
1539
|
// src/migration/diff.ts
|
|
1468
1540
|
var DEFAULT_CONFIG2 = {
|
|
@@ -1605,18 +1677,49 @@ function compareFieldConstraints(currentField, previousField) {
|
|
|
1605
1677
|
}
|
|
1606
1678
|
return changes;
|
|
1607
1679
|
}
|
|
1680
|
+
function normalizeOptionValue(key, value, fieldType) {
|
|
1681
|
+
if (key === "maxSelect" && value === 1 && (fieldType === "select" || fieldType === "file")) {
|
|
1682
|
+
return void 0;
|
|
1683
|
+
}
|
|
1684
|
+
if (key === "maxSize" && value === 0 && fieldType === "file") {
|
|
1685
|
+
return void 0;
|
|
1686
|
+
}
|
|
1687
|
+
if (fieldType === "file") {
|
|
1688
|
+
if (key === "mimeTypes" && Array.isArray(value) && value.length === 0) {
|
|
1689
|
+
return void 0;
|
|
1690
|
+
}
|
|
1691
|
+
if (key === "thumbs" && Array.isArray(value) && value.length === 0) {
|
|
1692
|
+
return void 0;
|
|
1693
|
+
}
|
|
1694
|
+
if (key === "protected" && value === false) {
|
|
1695
|
+
return void 0;
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
if (fieldType === "autodate") {
|
|
1699
|
+
if (key === "onCreate" && value === true) {
|
|
1700
|
+
return void 0;
|
|
1701
|
+
}
|
|
1702
|
+
if (key === "onUpdate" && value === false) {
|
|
1703
|
+
return void 0;
|
|
1704
|
+
}
|
|
1705
|
+
}
|
|
1706
|
+
return value;
|
|
1707
|
+
}
|
|
1608
1708
|
function compareFieldOptions(currentField, previousField) {
|
|
1609
1709
|
const changes = [];
|
|
1610
1710
|
const currentOptions = currentField.options || {};
|
|
1611
1711
|
const previousOptions = previousField.options || {};
|
|
1612
1712
|
const allKeys = /* @__PURE__ */ new Set([...Object.keys(currentOptions), ...Object.keys(previousOptions)]);
|
|
1713
|
+
const fieldType = currentField.type;
|
|
1613
1714
|
for (const key of allKeys) {
|
|
1614
1715
|
const currentValue = currentOptions[key];
|
|
1615
1716
|
const previousValue = previousOptions[key];
|
|
1616
|
-
|
|
1717
|
+
const normalizedCurrent = normalizeOptionValue(key, currentValue, fieldType);
|
|
1718
|
+
const normalizedPrevious = normalizeOptionValue(key, previousValue, fieldType);
|
|
1719
|
+
if (normalizedCurrent === void 0 && normalizedPrevious === void 0) {
|
|
1617
1720
|
continue;
|
|
1618
1721
|
}
|
|
1619
|
-
if (!areValuesEqual(
|
|
1722
|
+
if (!areValuesEqual(normalizedCurrent, normalizedPrevious)) {
|
|
1620
1723
|
changes.push({
|
|
1621
1724
|
property: `options.${key}`,
|
|
1622
1725
|
oldValue: previousValue,
|
|
@@ -1626,7 +1729,7 @@ function compareFieldOptions(currentField, previousField) {
|
|
|
1626
1729
|
}
|
|
1627
1730
|
return changes;
|
|
1628
1731
|
}
|
|
1629
|
-
function compareRelationConfigurations(currentField, previousField) {
|
|
1732
|
+
function compareRelationConfigurations(currentField, previousField, collectionIdToName) {
|
|
1630
1733
|
const changes = [];
|
|
1631
1734
|
const currentRelation = currentField.relation;
|
|
1632
1735
|
const previousRelation = previousField.relation;
|
|
@@ -1638,8 +1741,8 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
1638
1741
|
}
|
|
1639
1742
|
const normalizeCollection = (collection) => {
|
|
1640
1743
|
if (!collection) return collection;
|
|
1641
|
-
if (
|
|
1642
|
-
return
|
|
1744
|
+
if (collectionIdToName && collectionIdToName.has(collection)) {
|
|
1745
|
+
return collectionIdToName.get(collection);
|
|
1643
1746
|
}
|
|
1644
1747
|
const nameMatch = collection.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
1645
1748
|
if (nameMatch) {
|
|
@@ -1649,13 +1752,11 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
1649
1752
|
};
|
|
1650
1753
|
const normalizedCurrent = normalizeCollection(currentRelation.collection);
|
|
1651
1754
|
const normalizedPrevious = normalizeCollection(previousRelation.collection);
|
|
1652
|
-
if (normalizedCurrent !== normalizedPrevious) {
|
|
1755
|
+
if (normalizedCurrent.toLowerCase() !== normalizedPrevious.toLowerCase()) {
|
|
1653
1756
|
changes.push({
|
|
1654
1757
|
property: "relation.collection",
|
|
1655
|
-
oldValue:
|
|
1656
|
-
|
|
1657
|
-
newValue: normalizedCurrent
|
|
1658
|
-
// Use normalized value for clarity
|
|
1758
|
+
oldValue: previousRelation.collection,
|
|
1759
|
+
newValue: currentRelation.collection
|
|
1659
1760
|
});
|
|
1660
1761
|
}
|
|
1661
1762
|
if (currentRelation.cascadeDelete !== previousRelation.cascadeDelete) {
|
|
@@ -1665,14 +1766,20 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
1665
1766
|
newValue: currentRelation.cascadeDelete
|
|
1666
1767
|
});
|
|
1667
1768
|
}
|
|
1668
|
-
|
|
1769
|
+
const normalizeMax = (val) => val === 1 ? null : val;
|
|
1770
|
+
const currentMax = normalizeMax(currentRelation.maxSelect);
|
|
1771
|
+
const previousMax = normalizeMax(previousRelation.maxSelect);
|
|
1772
|
+
if (currentMax != previousMax) {
|
|
1669
1773
|
changes.push({
|
|
1670
1774
|
property: "relation.maxSelect",
|
|
1671
1775
|
oldValue: previousRelation.maxSelect,
|
|
1672
1776
|
newValue: currentRelation.maxSelect
|
|
1673
1777
|
});
|
|
1674
1778
|
}
|
|
1675
|
-
|
|
1779
|
+
const normalizeMin = (val) => val === 0 ? null : val;
|
|
1780
|
+
const currentMin = normalizeMin(currentRelation.minSelect);
|
|
1781
|
+
const previousMin = normalizeMin(previousRelation.minSelect);
|
|
1782
|
+
if (currentMin != previousMin) {
|
|
1676
1783
|
changes.push({
|
|
1677
1784
|
property: "relation.minSelect",
|
|
1678
1785
|
oldValue: previousRelation.minSelect,
|
|
@@ -1681,7 +1788,7 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
1681
1788
|
}
|
|
1682
1789
|
return changes;
|
|
1683
1790
|
}
|
|
1684
|
-
function detectFieldChanges(currentField, previousField) {
|
|
1791
|
+
function detectFieldChanges(currentField, previousField, collectionIdToName) {
|
|
1685
1792
|
const changes = [];
|
|
1686
1793
|
const typeChange = compareFieldTypes(currentField, previousField);
|
|
1687
1794
|
if (typeChange) {
|
|
@@ -1690,7 +1797,7 @@ function detectFieldChanges(currentField, previousField) {
|
|
|
1690
1797
|
changes.push(...compareFieldConstraints(currentField, previousField));
|
|
1691
1798
|
changes.push(...compareFieldOptions(currentField, previousField));
|
|
1692
1799
|
if (currentField.type === "relation" && previousField.type === "relation") {
|
|
1693
|
-
changes.push(...compareRelationConfigurations(currentField, previousField));
|
|
1800
|
+
changes.push(...compareRelationConfigurations(currentField, previousField, collectionIdToName));
|
|
1694
1801
|
}
|
|
1695
1802
|
return changes;
|
|
1696
1803
|
}
|
|
@@ -1701,7 +1808,7 @@ function compareIndexes(currentIndexes = [], previousIndexes = []) {
|
|
|
1701
1808
|
const indexesToRemove = previousIndexes.filter((idx) => !currentSet.has(idx));
|
|
1702
1809
|
return { indexesToAdd, indexesToRemove };
|
|
1703
1810
|
}
|
|
1704
|
-
function compareRules(currentRules, previousRules) {
|
|
1811
|
+
function compareRules(currentRules, previousRules, currentPermissions, previousPermissions) {
|
|
1705
1812
|
const updates = [];
|
|
1706
1813
|
const ruleTypes = [
|
|
1707
1814
|
"listRule",
|
|
@@ -1712,8 +1819,8 @@ function compareRules(currentRules, previousRules) {
|
|
|
1712
1819
|
"manageRule"
|
|
1713
1820
|
];
|
|
1714
1821
|
for (const ruleType of ruleTypes) {
|
|
1715
|
-
const currentValue = currentRules?.[ruleType] ?? null;
|
|
1716
|
-
const previousValue = previousRules?.[ruleType] ?? null;
|
|
1822
|
+
const currentValue = currentRules?.[ruleType] ?? currentPermissions?.[ruleType] ?? null;
|
|
1823
|
+
const previousValue = previousRules?.[ruleType] ?? previousPermissions?.[ruleType] ?? null;
|
|
1717
1824
|
if (currentValue !== previousValue) {
|
|
1718
1825
|
updates.push({
|
|
1719
1826
|
ruleType,
|
|
@@ -1740,7 +1847,7 @@ function comparePermissions(currentPermissions, previousPermissions) {
|
|
|
1740
1847
|
}
|
|
1741
1848
|
return changes;
|
|
1742
1849
|
}
|
|
1743
|
-
function compareCollectionFields(currentCollection, previousCollection, config) {
|
|
1850
|
+
function compareCollectionFields(currentCollection, previousCollection, config, collectionIdToName) {
|
|
1744
1851
|
let fieldsToAdd = findNewFields(currentCollection.fields, previousCollection.fields);
|
|
1745
1852
|
const fieldsToRemove = findRemovedFields(currentCollection.fields, previousCollection.fields);
|
|
1746
1853
|
const fieldsToModify = [];
|
|
@@ -1750,7 +1857,7 @@ function compareCollectionFields(currentCollection, previousCollection, config)
|
|
|
1750
1857
|
}
|
|
1751
1858
|
const matchedFields = matchFieldsByName(currentCollection.fields, previousCollection.fields);
|
|
1752
1859
|
for (const [currentField, previousField] of matchedFields) {
|
|
1753
|
-
const changes = detectFieldChanges(currentField, previousField);
|
|
1860
|
+
const changes = detectFieldChanges(currentField, previousField, collectionIdToName);
|
|
1754
1861
|
if (changes.length > 0) {
|
|
1755
1862
|
fieldsToModify.push({
|
|
1756
1863
|
fieldName: currentField.name,
|
|
@@ -1762,14 +1869,20 @@ function compareCollectionFields(currentCollection, previousCollection, config)
|
|
|
1762
1869
|
}
|
|
1763
1870
|
return { fieldsToAdd, fieldsToRemove, fieldsToModify };
|
|
1764
1871
|
}
|
|
1765
|
-
function buildCollectionModification(currentCollection, previousCollection, config) {
|
|
1872
|
+
function buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName) {
|
|
1766
1873
|
const { fieldsToAdd, fieldsToRemove, fieldsToModify } = compareCollectionFields(
|
|
1767
1874
|
currentCollection,
|
|
1768
1875
|
previousCollection,
|
|
1769
|
-
config
|
|
1876
|
+
config,
|
|
1877
|
+
collectionIdToName
|
|
1770
1878
|
);
|
|
1771
1879
|
const { indexesToAdd, indexesToRemove } = compareIndexes(currentCollection.indexes, previousCollection.indexes);
|
|
1772
|
-
const rulesToUpdate = compareRules(
|
|
1880
|
+
const rulesToUpdate = compareRules(
|
|
1881
|
+
currentCollection.rules,
|
|
1882
|
+
previousCollection.rules,
|
|
1883
|
+
currentCollection.permissions,
|
|
1884
|
+
previousCollection.permissions
|
|
1885
|
+
);
|
|
1773
1886
|
const permissionsToUpdate = comparePermissions(currentCollection.permissions, previousCollection.permissions);
|
|
1774
1887
|
return {
|
|
1775
1888
|
collection: currentCollection.name,
|
|
@@ -1786,6 +1899,14 @@ function hasChanges(modification) {
|
|
|
1786
1899
|
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;
|
|
1787
1900
|
}
|
|
1788
1901
|
function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
1902
|
+
const collectionIdToName = /* @__PURE__ */ new Map();
|
|
1903
|
+
if (previousSnapshot) {
|
|
1904
|
+
for (const [name, collection] of previousSnapshot.collections) {
|
|
1905
|
+
if (collection.id) {
|
|
1906
|
+
collectionIdToName.set(collection.id, name);
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1789
1910
|
const collectionsToCreate = findNewCollections(currentSchema, previousSnapshot);
|
|
1790
1911
|
const collectionsToDelete = findRemovedCollections(currentSchema, previousSnapshot);
|
|
1791
1912
|
const filteredCollectionsToCreate = collectionsToCreate.filter(
|
|
@@ -1794,16 +1915,28 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
|
1794
1915
|
const filteredCollectionsToDelete = collectionsToDelete.filter(
|
|
1795
1916
|
(collection) => !isSystemCollection(collection.name, config)
|
|
1796
1917
|
);
|
|
1918
|
+
const registry = new CollectionIdRegistry();
|
|
1919
|
+
const collectionsWithIds = filteredCollectionsToCreate.map((collection) => {
|
|
1920
|
+
if (collection.id) {
|
|
1921
|
+
registry.register(collection.id);
|
|
1922
|
+
return collection;
|
|
1923
|
+
}
|
|
1924
|
+
const id = registry.generate(collection.name);
|
|
1925
|
+
return {
|
|
1926
|
+
...collection,
|
|
1927
|
+
id
|
|
1928
|
+
};
|
|
1929
|
+
});
|
|
1797
1930
|
const collectionsToModify = [];
|
|
1798
1931
|
const matchedCollections = matchCollectionsByName(currentSchema, previousSnapshot);
|
|
1799
1932
|
for (const [currentCollection, previousCollection] of matchedCollections) {
|
|
1800
|
-
const modification = buildCollectionModification(currentCollection, previousCollection, config);
|
|
1933
|
+
const modification = buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName);
|
|
1801
1934
|
if (hasChanges(modification)) {
|
|
1802
1935
|
collectionsToModify.push(modification);
|
|
1803
1936
|
}
|
|
1804
1937
|
}
|
|
1805
1938
|
return {
|
|
1806
|
-
collectionsToCreate:
|
|
1939
|
+
collectionsToCreate: collectionsWithIds,
|
|
1807
1940
|
collectionsToDelete: filteredCollectionsToDelete,
|
|
1808
1941
|
collectionsToModify
|
|
1809
1942
|
};
|
|
@@ -1886,42 +2019,48 @@ function generateTimestamp(config) {
|
|
|
1886
2019
|
}
|
|
1887
2020
|
return Math.floor(Date.now() / 1e3).toString();
|
|
1888
2021
|
}
|
|
1889
|
-
function
|
|
1890
|
-
const
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
if (diff.collectionsToDelete.length === 1) {
|
|
1900
|
-
parts.push(`deleted_${diff.collectionsToDelete[0].name}`);
|
|
1901
|
-
} else {
|
|
1902
|
-
parts.push(`deleted_${diff.collectionsToDelete.length}_collections`);
|
|
1903
|
-
}
|
|
1904
|
-
}
|
|
1905
|
-
if (diff.collectionsToModify.length > 0) {
|
|
1906
|
-
if (diff.collectionsToModify.length === 1) {
|
|
1907
|
-
parts.push(`updated_${diff.collectionsToModify[0].collection}`);
|
|
1908
|
-
} else {
|
|
1909
|
-
parts.push(`updated_${diff.collectionsToModify.length}_collections`);
|
|
1910
|
-
}
|
|
2022
|
+
function splitDiffByCollection(diff, baseTimestamp) {
|
|
2023
|
+
const operations = [];
|
|
2024
|
+
let currentTimestamp = parseInt(baseTimestamp, 10);
|
|
2025
|
+
for (const collection of diff.collectionsToCreate) {
|
|
2026
|
+
operations.push({
|
|
2027
|
+
type: "create",
|
|
2028
|
+
collection,
|
|
2029
|
+
timestamp: currentTimestamp.toString()
|
|
2030
|
+
});
|
|
2031
|
+
currentTimestamp += 1;
|
|
1911
2032
|
}
|
|
1912
|
-
|
|
1913
|
-
|
|
2033
|
+
for (const modification of diff.collectionsToModify) {
|
|
2034
|
+
operations.push({
|
|
2035
|
+
type: "modify",
|
|
2036
|
+
collection: modification.collection,
|
|
2037
|
+
modifications: modification,
|
|
2038
|
+
timestamp: currentTimestamp.toString()
|
|
2039
|
+
});
|
|
2040
|
+
currentTimestamp += 1;
|
|
1914
2041
|
}
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
2042
|
+
for (const collection of diff.collectionsToDelete) {
|
|
2043
|
+
operations.push({
|
|
2044
|
+
type: "delete",
|
|
2045
|
+
collection: collection.name || collection,
|
|
2046
|
+
// Handle both object and string
|
|
2047
|
+
timestamp: currentTimestamp.toString()
|
|
2048
|
+
});
|
|
2049
|
+
currentTimestamp += 1;
|
|
1918
2050
|
}
|
|
1919
|
-
return
|
|
2051
|
+
return operations;
|
|
1920
2052
|
}
|
|
1921
|
-
function
|
|
1922
|
-
const timestamp =
|
|
1923
|
-
const
|
|
1924
|
-
|
|
2053
|
+
function generateCollectionMigrationFilename(operation) {
|
|
2054
|
+
const timestamp = operation.timestamp;
|
|
2055
|
+
const operationType = operation.type === "modify" ? "updated" : operation.type === "create" ? "created" : "deleted";
|
|
2056
|
+
let collectionName;
|
|
2057
|
+
if (typeof operation.collection === "string") {
|
|
2058
|
+
collectionName = operation.collection;
|
|
2059
|
+
} else {
|
|
2060
|
+
collectionName = operation.collection.name;
|
|
2061
|
+
}
|
|
2062
|
+
const sanitizedName = collectionName.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase();
|
|
2063
|
+
return `${timestamp}_${operationType}_${sanitizedName}.js`;
|
|
1925
2064
|
}
|
|
1926
2065
|
function createMigrationFileStructure(upCode, downCode, config) {
|
|
1927
2066
|
const mergedConfig = config ? mergeConfig3(config) : DEFAULT_CONFIG3;
|
|
@@ -1993,14 +2132,13 @@ function formatValue(value) {
|
|
|
1993
2132
|
return "null";
|
|
1994
2133
|
}
|
|
1995
2134
|
if (typeof value === "string") {
|
|
1996
|
-
return
|
|
2135
|
+
return JSON.stringify(value);
|
|
1997
2136
|
}
|
|
1998
2137
|
if (typeof value === "number" || typeof value === "boolean") {
|
|
1999
2138
|
return String(value);
|
|
2000
2139
|
}
|
|
2001
2140
|
if (Array.isArray(value)) {
|
|
2002
|
-
|
|
2003
|
-
return `[${items}]`;
|
|
2141
|
+
return JSON.stringify(value).replace(/","/g, '", "');
|
|
2004
2142
|
}
|
|
2005
2143
|
if (typeof value === "object") {
|
|
2006
2144
|
const entries = Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
|
|
@@ -2008,7 +2146,7 @@ function formatValue(value) {
|
|
|
2008
2146
|
}
|
|
2009
2147
|
return String(value);
|
|
2010
2148
|
}
|
|
2011
|
-
function generateFieldDefinitionObject(field) {
|
|
2149
|
+
function generateFieldDefinitionObject(field, collectionIdMap) {
|
|
2012
2150
|
const parts = [];
|
|
2013
2151
|
parts.push(` name: "${field.name}"`);
|
|
2014
2152
|
parts.push(` type: "${field.type}"`);
|
|
@@ -2016,34 +2154,47 @@ function generateFieldDefinitionObject(field) {
|
|
|
2016
2154
|
if (field.unique !== void 0) {
|
|
2017
2155
|
parts.push(` unique: ${field.unique}`);
|
|
2018
2156
|
}
|
|
2157
|
+
if (field.type === "select") {
|
|
2158
|
+
const maxSelect = field.options?.maxSelect ?? 1;
|
|
2159
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
2160
|
+
const values = field.options?.values ?? [];
|
|
2161
|
+
parts.push(` values: ${formatValue(values)}`);
|
|
2162
|
+
}
|
|
2019
2163
|
if (field.options && Object.keys(field.options).length > 0) {
|
|
2020
2164
|
for (const [key, value] of Object.entries(field.options)) {
|
|
2165
|
+
if (field.type === "select" && (key === "maxSelect" || key === "values")) {
|
|
2166
|
+
continue;
|
|
2167
|
+
}
|
|
2021
2168
|
parts.push(` ${key}: ${formatValue(value)}`);
|
|
2022
2169
|
}
|
|
2023
2170
|
}
|
|
2024
2171
|
if (field.relation) {
|
|
2025
2172
|
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
}
|
|
2034
|
-
if (field.relation.cascadeDelete !== void 0) {
|
|
2035
|
-
parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
|
|
2173
|
+
let collectionIdValue;
|
|
2174
|
+
if (isUsersCollection) {
|
|
2175
|
+
collectionIdValue = '"_pb_users_auth_"';
|
|
2176
|
+
} else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
|
|
2177
|
+
collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
|
|
2178
|
+
} else {
|
|
2179
|
+
collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
2036
2180
|
}
|
|
2181
|
+
parts.push(` collectionId: ${collectionIdValue}`);
|
|
2182
|
+
const maxSelect = field.relation.maxSelect ?? 1;
|
|
2183
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
2184
|
+
const minSelect = field.relation.minSelect ?? null;
|
|
2185
|
+
parts.push(` minSelect: ${minSelect}`);
|
|
2186
|
+
const cascadeDelete = field.relation.cascadeDelete ?? false;
|
|
2187
|
+
parts.push(` cascadeDelete: ${cascadeDelete}`);
|
|
2037
2188
|
}
|
|
2038
2189
|
return ` {
|
|
2039
2190
|
${parts.join(",\n")},
|
|
2040
2191
|
}`;
|
|
2041
2192
|
}
|
|
2042
|
-
function generateFieldsArray(fields) {
|
|
2193
|
+
function generateFieldsArray(fields, collectionIdMap) {
|
|
2043
2194
|
if (fields.length === 0) {
|
|
2044
2195
|
return "[]";
|
|
2045
2196
|
}
|
|
2046
|
-
const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field));
|
|
2197
|
+
const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field, collectionIdMap));
|
|
2047
2198
|
return `[
|
|
2048
2199
|
${fieldObjects.join(",\n")},
|
|
2049
2200
|
]`;
|
|
@@ -2102,7 +2253,7 @@ function generateIndexesArray(indexes) {
|
|
|
2102
2253
|
if (!indexes || indexes.length === 0) {
|
|
2103
2254
|
return "[]";
|
|
2104
2255
|
}
|
|
2105
|
-
const indexStrings = indexes.map((idx) =>
|
|
2256
|
+
const indexStrings = indexes.map((idx) => JSON.stringify(idx));
|
|
2106
2257
|
return `[
|
|
2107
2258
|
${indexStrings.join(",\n ")},
|
|
2108
2259
|
]`;
|
|
@@ -2156,9 +2307,12 @@ function getSystemFields() {
|
|
|
2156
2307
|
}
|
|
2157
2308
|
];
|
|
2158
2309
|
}
|
|
2159
|
-
function generateCollectionCreation(collection, varName = "collection", isLast = false) {
|
|
2310
|
+
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
2160
2311
|
const lines = [];
|
|
2161
2312
|
lines.push(` const ${varName} = new Collection({`);
|
|
2313
|
+
if (collection.id) {
|
|
2314
|
+
lines.push(` id: ${formatValue(collection.id)},`);
|
|
2315
|
+
}
|
|
2162
2316
|
lines.push(` name: "${collection.name}",`);
|
|
2163
2317
|
lines.push(` type: "${collection.type}",`);
|
|
2164
2318
|
const permissionsCode = generateCollectionPermissions(collection.permissions);
|
|
@@ -2170,7 +2324,7 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
|
|
|
2170
2324
|
}
|
|
2171
2325
|
const systemFields = getSystemFields();
|
|
2172
2326
|
const allFields = [...systemFields, ...collection.fields];
|
|
2173
|
-
lines.push(` fields: ${generateFieldsArray(allFields)},`);
|
|
2327
|
+
lines.push(` fields: ${generateFieldsArray(allFields, collectionIdMap)},`);
|
|
2174
2328
|
lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
|
|
2175
2329
|
lines.push(` });`);
|
|
2176
2330
|
lines.push(``);
|
|
@@ -2192,42 +2346,59 @@ function getFieldConstructorName(fieldType) {
|
|
|
2192
2346
|
};
|
|
2193
2347
|
return constructorMap[fieldType] || "TextField";
|
|
2194
2348
|
}
|
|
2195
|
-
function generateFieldConstructorOptions(field) {
|
|
2349
|
+
function generateFieldConstructorOptions(field, collectionIdMap) {
|
|
2196
2350
|
const parts = [];
|
|
2197
2351
|
parts.push(` name: "${field.name}"`);
|
|
2198
2352
|
parts.push(` required: ${field.required}`);
|
|
2199
2353
|
if (field.unique !== void 0) {
|
|
2200
2354
|
parts.push(` unique: ${field.unique}`);
|
|
2201
2355
|
}
|
|
2356
|
+
if (field.type === "select") {
|
|
2357
|
+
const maxSelect = field.options?.maxSelect ?? 1;
|
|
2358
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
2359
|
+
const values = field.options?.values ?? [];
|
|
2360
|
+
parts.push(` values: ${formatValue(values)}`);
|
|
2361
|
+
}
|
|
2202
2362
|
if (field.options && Object.keys(field.options).length > 0) {
|
|
2203
2363
|
for (const [key, value] of Object.entries(field.options)) {
|
|
2204
|
-
|
|
2364
|
+
if (field.type === "select" && (key === "maxSelect" || key === "values")) {
|
|
2365
|
+
continue;
|
|
2366
|
+
}
|
|
2367
|
+
if (field.type === "number" && key === "noDecimal") {
|
|
2368
|
+
parts.push(` onlyInt: ${formatValue(value)}`);
|
|
2369
|
+
} else {
|
|
2370
|
+
parts.push(` ${key}: ${formatValue(value)}`);
|
|
2371
|
+
}
|
|
2205
2372
|
}
|
|
2206
2373
|
}
|
|
2207
2374
|
if (field.relation && field.type === "relation") {
|
|
2208
2375
|
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
}
|
|
2217
|
-
if (field.relation.cascadeDelete !== void 0) {
|
|
2218
|
-
parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
|
|
2376
|
+
let collectionIdValue;
|
|
2377
|
+
if (isUsersCollection) {
|
|
2378
|
+
collectionIdValue = '"_pb_users_auth_"';
|
|
2379
|
+
} else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
|
|
2380
|
+
collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
|
|
2381
|
+
} else {
|
|
2382
|
+
collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
2219
2383
|
}
|
|
2384
|
+
parts.push(` collectionId: ${collectionIdValue}`);
|
|
2385
|
+
const maxSelect = field.relation.maxSelect ?? 1;
|
|
2386
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
2387
|
+
const minSelect = field.relation.minSelect ?? null;
|
|
2388
|
+
parts.push(` minSelect: ${minSelect}`);
|
|
2389
|
+
const cascadeDelete = field.relation.cascadeDelete ?? false;
|
|
2390
|
+
parts.push(` cascadeDelete: ${cascadeDelete}`);
|
|
2220
2391
|
}
|
|
2221
2392
|
return parts.join(",\n");
|
|
2222
2393
|
}
|
|
2223
|
-
function generateFieldAddition(collectionName, field, varName, isLast = false) {
|
|
2394
|
+
function generateFieldAddition(collectionName, field, varName, isLast = false, collectionIdMap) {
|
|
2224
2395
|
const lines = [];
|
|
2225
2396
|
const constructorName = getFieldConstructorName(field.type);
|
|
2226
2397
|
const collectionVar = varName || `collection_${collectionName}_${field.name}`;
|
|
2227
2398
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
2228
2399
|
lines.push(``);
|
|
2229
2400
|
lines.push(` ${collectionVar}.fields.add(new ${constructorName}({`);
|
|
2230
|
-
lines.push(generateFieldConstructorOptions(field));
|
|
2401
|
+
lines.push(generateFieldConstructorOptions(field, collectionIdMap));
|
|
2231
2402
|
lines.push(` }));`);
|
|
2232
2403
|
lines.push(``);
|
|
2233
2404
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
@@ -2277,7 +2448,7 @@ function generateIndexAddition(collectionName, index, varName, isLast = false) {
|
|
|
2277
2448
|
const lines = [];
|
|
2278
2449
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
2279
2450
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
2280
|
-
lines.push(` ${collectionVar}.indexes.push(
|
|
2451
|
+
lines.push(` ${collectionVar}.indexes.push(${JSON.stringify(index)});`);
|
|
2281
2452
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
2282
2453
|
return lines.join("\n");
|
|
2283
2454
|
}
|
|
@@ -2286,7 +2457,7 @@ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
|
|
|
2286
2457
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
2287
2458
|
const indexVar = `${collectionVar}_indexToRemove`;
|
|
2288
2459
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
2289
|
-
lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx ===
|
|
2460
|
+
lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === ${JSON.stringify(index)});`);
|
|
2290
2461
|
lines.push(` if (${indexVar} !== -1) {`);
|
|
2291
2462
|
lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
|
|
2292
2463
|
lines.push(` }`);
|
|
@@ -2315,94 +2486,75 @@ function generateCollectionDeletion(collectionName, varName = "collection", isLa
|
|
|
2315
2486
|
lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
|
|
2316
2487
|
return lines.join("\n");
|
|
2317
2488
|
}
|
|
2318
|
-
function
|
|
2489
|
+
function generateOperationUpMigration(operation, collectionIdMap) {
|
|
2319
2490
|
const lines = [];
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
lines.push(
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2491
|
+
if (operation.type === "create") {
|
|
2492
|
+
const collection = operation.collection;
|
|
2493
|
+
const varName = `collection_${collection.name}`;
|
|
2494
|
+
lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
|
|
2495
|
+
} else if (operation.type === "modify") {
|
|
2496
|
+
const modification = operation.modifications;
|
|
2497
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
2498
|
+
let operationCount = 0;
|
|
2499
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
|
|
2500
|
+
for (const field of modification.fieldsToAdd) {
|
|
2501
|
+
operationCount++;
|
|
2502
|
+
const varName = `collection_${collectionName}_add_${field.name}`;
|
|
2503
|
+
const isLast = operationCount === totalOperations;
|
|
2504
|
+
lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
|
|
2505
|
+
if (!isLast) lines.push("");
|
|
2329
2506
|
}
|
|
2330
|
-
|
|
2331
|
-
|
|
2332
|
-
|
|
2333
|
-
|
|
2334
|
-
|
|
2335
|
-
if (
|
|
2336
|
-
|
|
2337
|
-
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
|
|
2341
|
-
|
|
2342
|
-
|
|
2343
|
-
|
|
2344
|
-
|
|
2345
|
-
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2352
|
-
|
|
2353
|
-
|
|
2354
|
-
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
2359
|
-
|
|
2360
|
-
|
|
2361
|
-
|
|
2362
|
-
|
|
2363
|
-
|
|
2364
|
-
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
}
|
|
2368
|
-
if (modification.indexesToRemove.length > 0) {
|
|
2369
|
-
lines.push(` // Remove indexes from ${collectionName}`);
|
|
2370
|
-
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
2371
|
-
const index = modification.indexesToRemove[i];
|
|
2372
|
-
const varName = `collection_${collectionName}_rmidx_${i}`;
|
|
2373
|
-
lines.push(generateIndexRemoval(collectionName, index, varName));
|
|
2374
|
-
lines.push(``);
|
|
2375
|
-
}
|
|
2507
|
+
for (const fieldMod of modification.fieldsToModify) {
|
|
2508
|
+
operationCount++;
|
|
2509
|
+
const varName = `collection_${collectionName}_modify_${fieldMod.fieldName}`;
|
|
2510
|
+
const isLast = operationCount === totalOperations;
|
|
2511
|
+
lines.push(generateFieldModification(collectionName, fieldMod, varName, isLast));
|
|
2512
|
+
if (!isLast) lines.push("");
|
|
2513
|
+
}
|
|
2514
|
+
for (const field of modification.fieldsToRemove) {
|
|
2515
|
+
operationCount++;
|
|
2516
|
+
const varName = `collection_${collectionName}_remove_${field.name}`;
|
|
2517
|
+
const isLast = operationCount === totalOperations;
|
|
2518
|
+
lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
|
|
2519
|
+
if (!isLast) lines.push("");
|
|
2520
|
+
}
|
|
2521
|
+
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
2522
|
+
operationCount++;
|
|
2523
|
+
const index = modification.indexesToAdd[i];
|
|
2524
|
+
const varName = `collection_${collectionName}_addidx_${i}`;
|
|
2525
|
+
const isLast = operationCount === totalOperations;
|
|
2526
|
+
lines.push(generateIndexAddition(collectionName, index, varName, isLast));
|
|
2527
|
+
if (!isLast) lines.push("");
|
|
2528
|
+
}
|
|
2529
|
+
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
2530
|
+
operationCount++;
|
|
2531
|
+
const index = modification.indexesToRemove[i];
|
|
2532
|
+
const varName = `collection_${collectionName}_rmidx_${i}`;
|
|
2533
|
+
const isLast = operationCount === totalOperations;
|
|
2534
|
+
lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
|
|
2535
|
+
if (!isLast) lines.push("");
|
|
2536
|
+
}
|
|
2537
|
+
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
2538
|
+
for (const permission of modification.permissionsToUpdate) {
|
|
2539
|
+
operationCount++;
|
|
2540
|
+
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
2541
|
+
const isLast = operationCount === totalOperations;
|
|
2542
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast));
|
|
2543
|
+
if (!isLast) lines.push("");
|
|
2376
2544
|
}
|
|
2377
|
-
|
|
2378
|
-
|
|
2379
|
-
|
|
2380
|
-
|
|
2381
|
-
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
} else if (modification.rulesToUpdate.length > 0) {
|
|
2385
|
-
lines.push(` // Update rules for ${collectionName}`);
|
|
2386
|
-
for (const rule of modification.rulesToUpdate) {
|
|
2387
|
-
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
2388
|
-
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName));
|
|
2389
|
-
lines.push(``);
|
|
2390
|
-
}
|
|
2545
|
+
} else if (modification.rulesToUpdate.length > 0) {
|
|
2546
|
+
for (const rule of modification.rulesToUpdate) {
|
|
2547
|
+
operationCount++;
|
|
2548
|
+
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
2549
|
+
const isLast = operationCount === totalOperations;
|
|
2550
|
+
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast));
|
|
2551
|
+
if (!isLast) lines.push("");
|
|
2391
2552
|
}
|
|
2392
2553
|
}
|
|
2393
|
-
}
|
|
2394
|
-
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
const collection = diff.collectionsToDelete[i];
|
|
2398
|
-
const varName = `collection_${collection.name}_delete`;
|
|
2399
|
-
lines.push(generateCollectionDeletion(collection.name, varName));
|
|
2400
|
-
lines.push(``);
|
|
2401
|
-
}
|
|
2402
|
-
}
|
|
2403
|
-
if (lines.length === 2) {
|
|
2404
|
-
lines.push(` // No changes detected`);
|
|
2405
|
-
lines.push(``);
|
|
2554
|
+
} else if (operation.type === "delete") {
|
|
2555
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
|
|
2556
|
+
const varName = `collection_${collectionName}`;
|
|
2557
|
+
lines.push(generateCollectionDeletion(collectionName, varName, true));
|
|
2406
2558
|
}
|
|
2407
2559
|
let code = lines.join("\n");
|
|
2408
2560
|
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
@@ -2423,105 +2575,88 @@ function generateUpMigration(diff) {
|
|
|
2423
2575
|
}
|
|
2424
2576
|
return code;
|
|
2425
2577
|
}
|
|
2426
|
-
function
|
|
2578
|
+
function generateOperationDownMigration(operation, collectionIdMap) {
|
|
2427
2579
|
const lines = [];
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2431
|
-
lines.push(
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
|
|
2440
|
-
|
|
2441
|
-
|
|
2442
|
-
|
|
2443
|
-
|
|
2444
|
-
lines.push(` // Revert permissions for ${collectionName}`);
|
|
2445
|
-
for (const permission of modification.permissionsToUpdate) {
|
|
2446
|
-
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
2447
|
-
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName));
|
|
2448
|
-
lines.push(``);
|
|
2449
|
-
}
|
|
2450
|
-
} else if (modification.rulesToUpdate.length > 0) {
|
|
2451
|
-
lines.push(` // Revert rules for ${collectionName}`);
|
|
2452
|
-
for (const rule of modification.rulesToUpdate) {
|
|
2453
|
-
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
2454
|
-
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName));
|
|
2455
|
-
lines.push(``);
|
|
2456
|
-
}
|
|
2457
|
-
}
|
|
2458
|
-
if (modification.indexesToRemove.length > 0) {
|
|
2459
|
-
lines.push(` // Restore indexes to ${collectionName}`);
|
|
2460
|
-
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
2461
|
-
const index = modification.indexesToRemove[i];
|
|
2462
|
-
const varName = `collection_${collectionName}_restore_idx_${i}`;
|
|
2463
|
-
lines.push(generateIndexAddition(collectionName, index, varName));
|
|
2464
|
-
lines.push(``);
|
|
2465
|
-
}
|
|
2466
|
-
}
|
|
2467
|
-
if (modification.indexesToAdd.length > 0) {
|
|
2468
|
-
lines.push(` // Remove indexes from ${collectionName}`);
|
|
2469
|
-
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
2470
|
-
const index = modification.indexesToAdd[i];
|
|
2471
|
-
const varName = `collection_${collectionName}_revert_idx_${i}`;
|
|
2472
|
-
lines.push(generateIndexRemoval(collectionName, index, varName));
|
|
2473
|
-
lines.push(``);
|
|
2474
|
-
}
|
|
2475
|
-
}
|
|
2476
|
-
if (modification.fieldsToRemove.length > 0) {
|
|
2477
|
-
lines.push(` // Restore fields to ${collectionName}`);
|
|
2478
|
-
for (const field of modification.fieldsToRemove) {
|
|
2479
|
-
const varName = `collection_${collectionName}_restore_${field.name}`;
|
|
2480
|
-
lines.push(generateFieldAddition(collectionName, field, varName));
|
|
2481
|
-
lines.push(``);
|
|
2482
|
-
}
|
|
2580
|
+
if (operation.type === "create") {
|
|
2581
|
+
const collection = operation.collection;
|
|
2582
|
+
const varName = `collection_${collection.name}`;
|
|
2583
|
+
lines.push(generateCollectionDeletion(collection.name, varName, true));
|
|
2584
|
+
} else if (operation.type === "modify") {
|
|
2585
|
+
const modification = operation.modifications;
|
|
2586
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
2587
|
+
let operationCount = 0;
|
|
2588
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
|
|
2589
|
+
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
2590
|
+
for (const permission of modification.permissionsToUpdate) {
|
|
2591
|
+
operationCount++;
|
|
2592
|
+
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
2593
|
+
const isLast = operationCount === totalOperations;
|
|
2594
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast));
|
|
2595
|
+
if (!isLast) lines.push("");
|
|
2483
2596
|
}
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
}));
|
|
2492
|
-
const reverseMod = {
|
|
2493
|
-
fieldName: fieldMod.fieldName,
|
|
2494
|
-
currentDefinition: fieldMod.newDefinition,
|
|
2495
|
-
newDefinition: fieldMod.currentDefinition,
|
|
2496
|
-
changes: reverseChanges
|
|
2497
|
-
};
|
|
2498
|
-
const varName = `collection_${collectionName}_revert_${fieldMod.fieldName}`;
|
|
2499
|
-
lines.push(generateFieldModification(collectionName, reverseMod, varName));
|
|
2500
|
-
lines.push(``);
|
|
2501
|
-
}
|
|
2502
|
-
}
|
|
2503
|
-
if (modification.fieldsToAdd.length > 0) {
|
|
2504
|
-
lines.push(` // Remove added fields from ${collectionName}`);
|
|
2505
|
-
for (const field of modification.fieldsToAdd) {
|
|
2506
|
-
const varName = `collection_${collectionName}_revert_add_${field.name}`;
|
|
2507
|
-
lines.push(generateFieldDeletion(collectionName, field.name, varName));
|
|
2508
|
-
lines.push(``);
|
|
2509
|
-
}
|
|
2597
|
+
} else if (modification.rulesToUpdate.length > 0) {
|
|
2598
|
+
for (const rule of modification.rulesToUpdate) {
|
|
2599
|
+
operationCount++;
|
|
2600
|
+
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
2601
|
+
const isLast = operationCount === totalOperations;
|
|
2602
|
+
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast));
|
|
2603
|
+
if (!isLast) lines.push("");
|
|
2510
2604
|
}
|
|
2511
2605
|
}
|
|
2512
|
-
|
|
2513
|
-
|
|
2514
|
-
|
|
2515
|
-
|
|
2516
|
-
const
|
|
2517
|
-
|
|
2518
|
-
lines.push(
|
|
2519
|
-
|
|
2606
|
+
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
2607
|
+
operationCount++;
|
|
2608
|
+
const index = modification.indexesToRemove[i];
|
|
2609
|
+
const varName = `collection_${collectionName}_restore_idx_${i}`;
|
|
2610
|
+
const isLast = operationCount === totalOperations;
|
|
2611
|
+
lines.push(generateIndexAddition(collectionName, index, varName, isLast));
|
|
2612
|
+
if (!isLast) lines.push("");
|
|
2613
|
+
}
|
|
2614
|
+
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
2615
|
+
operationCount++;
|
|
2616
|
+
const index = modification.indexesToAdd[i];
|
|
2617
|
+
const varName = `collection_${collectionName}_revert_idx_${i}`;
|
|
2618
|
+
const isLast = operationCount === totalOperations;
|
|
2619
|
+
lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
|
|
2620
|
+
if (!isLast) lines.push("");
|
|
2621
|
+
}
|
|
2622
|
+
for (const field of modification.fieldsToRemove) {
|
|
2623
|
+
operationCount++;
|
|
2624
|
+
const varName = `collection_${collectionName}_restore_${field.name}`;
|
|
2625
|
+
const isLast = operationCount === totalOperations;
|
|
2626
|
+
lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
|
|
2627
|
+
if (!isLast) lines.push("");
|
|
2628
|
+
}
|
|
2629
|
+
for (const fieldMod of modification.fieldsToModify) {
|
|
2630
|
+
operationCount++;
|
|
2631
|
+
const reverseChanges = fieldMod.changes.map((change) => ({
|
|
2632
|
+
property: change.property,
|
|
2633
|
+
oldValue: change.newValue,
|
|
2634
|
+
newValue: change.oldValue
|
|
2635
|
+
}));
|
|
2636
|
+
const reverseMod = {
|
|
2637
|
+
fieldName: fieldMod.fieldName,
|
|
2638
|
+
currentDefinition: fieldMod.newDefinition,
|
|
2639
|
+
newDefinition: fieldMod.currentDefinition,
|
|
2640
|
+
changes: reverseChanges
|
|
2641
|
+
};
|
|
2642
|
+
const varName = `collection_${collectionName}_revert_${fieldMod.fieldName}`;
|
|
2643
|
+
const isLast = operationCount === totalOperations;
|
|
2644
|
+
lines.push(generateFieldModification(collectionName, reverseMod, varName, isLast));
|
|
2645
|
+
if (!isLast) lines.push("");
|
|
2646
|
+
}
|
|
2647
|
+
for (const field of modification.fieldsToAdd) {
|
|
2648
|
+
operationCount++;
|
|
2649
|
+
const varName = `collection_${collectionName}_revert_add_${field.name}`;
|
|
2650
|
+
const isLast = operationCount === totalOperations;
|
|
2651
|
+
lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
|
|
2652
|
+
if (!isLast) lines.push("");
|
|
2653
|
+
}
|
|
2654
|
+
} else if (operation.type === "delete") {
|
|
2655
|
+
const collection = operation.collection;
|
|
2656
|
+
if (typeof collection !== "string") {
|
|
2657
|
+
const varName = `collection_${collection.name}`;
|
|
2658
|
+
lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
|
|
2520
2659
|
}
|
|
2521
|
-
}
|
|
2522
|
-
if (lines.length === 2) {
|
|
2523
|
-
lines.push(` // No changes to revert`);
|
|
2524
|
-
lines.push(``);
|
|
2525
2660
|
}
|
|
2526
2661
|
let code = lines.join("\n");
|
|
2527
2662
|
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
@@ -2546,12 +2681,33 @@ function generate(diff, config) {
|
|
|
2546
2681
|
const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
|
|
2547
2682
|
try {
|
|
2548
2683
|
const migrationDir = resolveMigrationDir(normalizedConfig);
|
|
2549
|
-
const
|
|
2550
|
-
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
const
|
|
2554
|
-
|
|
2684
|
+
const hasChanges4 = diff.collectionsToCreate.length > 0 || diff.collectionsToModify.length > 0 || diff.collectionsToDelete.length > 0;
|
|
2685
|
+
if (!hasChanges4) {
|
|
2686
|
+
return [];
|
|
2687
|
+
}
|
|
2688
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
2689
|
+
for (const collection of diff.collectionsToCreate) {
|
|
2690
|
+
if (collection.id) {
|
|
2691
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
for (const collection of diff.collectionsToDelete) {
|
|
2695
|
+
if (collection.id) {
|
|
2696
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
2697
|
+
}
|
|
2698
|
+
}
|
|
2699
|
+
const baseTimestamp = generateTimestamp(normalizedConfig);
|
|
2700
|
+
const operations = splitDiffByCollection(diff, baseTimestamp);
|
|
2701
|
+
const filePaths = [];
|
|
2702
|
+
for (const operation of operations) {
|
|
2703
|
+
const upCode = generateOperationUpMigration(operation, collectionIdMap);
|
|
2704
|
+
const downCode = generateOperationDownMigration(operation, collectionIdMap);
|
|
2705
|
+
const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
|
|
2706
|
+
const filename = generateCollectionMigrationFilename(operation);
|
|
2707
|
+
const filePath = writeMigrationFile(migrationDir, filename, content);
|
|
2708
|
+
filePaths.push(filePath);
|
|
2709
|
+
}
|
|
2710
|
+
return filePaths;
|
|
2555
2711
|
} catch (error) {
|
|
2556
2712
|
if (error instanceof MigrationGenerationError || error instanceof FileSystemError) {
|
|
2557
2713
|
throw error;
|
|
@@ -2568,7 +2724,7 @@ function generate(diff, config) {
|
|
|
2568
2724
|
var SNAPSHOT_VERSION = "1.0.0";
|
|
2569
2725
|
function resolveCollectionIdToName(collectionId) {
|
|
2570
2726
|
if (collectionId === "_pb_users_auth_") {
|
|
2571
|
-
return "
|
|
2727
|
+
return "users";
|
|
2572
2728
|
}
|
|
2573
2729
|
const nameMatch = collectionId.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
2574
2730
|
if (nameMatch) {
|
|
@@ -2576,6 +2732,39 @@ function resolveCollectionIdToName(collectionId) {
|
|
|
2576
2732
|
}
|
|
2577
2733
|
return collectionId;
|
|
2578
2734
|
}
|
|
2735
|
+
function extractFieldOptions2(pbField) {
|
|
2736
|
+
const options = {};
|
|
2737
|
+
if (pbField.options && typeof pbField.options === "object") {
|
|
2738
|
+
Object.assign(options, pbField.options);
|
|
2739
|
+
}
|
|
2740
|
+
const directOptionKeys = [
|
|
2741
|
+
"min",
|
|
2742
|
+
"max",
|
|
2743
|
+
"pattern",
|
|
2744
|
+
"noDecimal",
|
|
2745
|
+
// text/number fields
|
|
2746
|
+
"values",
|
|
2747
|
+
"maxSelect",
|
|
2748
|
+
// select fields
|
|
2749
|
+
"mimeTypes",
|
|
2750
|
+
"maxSize",
|
|
2751
|
+
"thumbs",
|
|
2752
|
+
"protected",
|
|
2753
|
+
// file fields
|
|
2754
|
+
"onCreate",
|
|
2755
|
+
"onUpdate",
|
|
2756
|
+
// autodate fields
|
|
2757
|
+
"exceptDomains",
|
|
2758
|
+
"onlyDomains"
|
|
2759
|
+
// email/url fields
|
|
2760
|
+
];
|
|
2761
|
+
for (const key of directOptionKeys) {
|
|
2762
|
+
if (pbField[key] !== void 0) {
|
|
2763
|
+
options[key] = pbField[key];
|
|
2764
|
+
}
|
|
2765
|
+
}
|
|
2766
|
+
return options;
|
|
2767
|
+
}
|
|
2579
2768
|
function convertPocketBaseCollection(pbCollection) {
|
|
2580
2769
|
const fields = [];
|
|
2581
2770
|
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
@@ -2593,23 +2782,19 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
2593
2782
|
type: pbField.type,
|
|
2594
2783
|
required: pbField.required || false
|
|
2595
2784
|
};
|
|
2596
|
-
field.options = pbField
|
|
2597
|
-
if (pbField.type === "select") {
|
|
2598
|
-
if (pbField.values && Array.isArray(pbField.values)) {
|
|
2599
|
-
field.options.values = pbField.values;
|
|
2600
|
-
} else if (pbField.options?.values && Array.isArray(pbField.options.values)) {
|
|
2601
|
-
field.options.values = pbField.options.values;
|
|
2602
|
-
}
|
|
2603
|
-
}
|
|
2785
|
+
field.options = extractFieldOptions2(pbField);
|
|
2604
2786
|
if (pbField.type === "relation") {
|
|
2605
2787
|
const collectionId = pbField.collectionId || pbField.options?.collectionId || "";
|
|
2606
|
-
const collectionName = resolveCollectionIdToName(collectionId);
|
|
2788
|
+
const collectionName = resolveCollectionIdToName(collectionId || "");
|
|
2607
2789
|
field.relation = {
|
|
2608
2790
|
collection: collectionName,
|
|
2609
2791
|
cascadeDelete: pbField.cascadeDelete ?? pbField.options?.cascadeDelete ?? false,
|
|
2610
2792
|
maxSelect: pbField.maxSelect ?? pbField.options?.maxSelect,
|
|
2611
2793
|
minSelect: pbField.minSelect ?? pbField.options?.minSelect
|
|
2612
2794
|
};
|
|
2795
|
+
delete field.options.maxSelect;
|
|
2796
|
+
delete field.options.minSelect;
|
|
2797
|
+
delete field.options.cascadeDelete;
|
|
2613
2798
|
}
|
|
2614
2799
|
const hasOnlyValues = Object.keys(field.options).length === 1 && field.options.values !== void 0;
|
|
2615
2800
|
if (Object.keys(field.options).length === 0) {
|
|
@@ -2623,17 +2808,21 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
2623
2808
|
type: pbCollection.type || "base",
|
|
2624
2809
|
fields
|
|
2625
2810
|
};
|
|
2811
|
+
if (pbCollection.id) {
|
|
2812
|
+
schema.id = pbCollection.id;
|
|
2813
|
+
}
|
|
2626
2814
|
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
2627
2815
|
schema.indexes = pbCollection.indexes;
|
|
2628
2816
|
}
|
|
2629
|
-
const
|
|
2630
|
-
if (
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
|
|
2636
|
-
|
|
2817
|
+
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;
|
|
2818
|
+
if (hasAnyRule) {
|
|
2819
|
+
const rules = {};
|
|
2820
|
+
if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
|
|
2821
|
+
if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
|
|
2822
|
+
if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
|
|
2823
|
+
if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
|
|
2824
|
+
if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
|
|
2825
|
+
if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
|
|
2637
2826
|
schema.rules = rules;
|
|
2638
2827
|
schema.permissions = { ...rules };
|
|
2639
2828
|
}
|
|
@@ -3632,15 +3821,25 @@ async function executeGenerate(options) {
|
|
|
3632
3821
|
process.exit(1);
|
|
3633
3822
|
}
|
|
3634
3823
|
logSection("\u{1F4DD} Generating Migration");
|
|
3635
|
-
const
|
|
3824
|
+
const migrationPaths = await withProgress(
|
|
3636
3825
|
"Creating migration file...",
|
|
3637
3826
|
() => Promise.resolve(generate(diff, migrationsDir))
|
|
3638
3827
|
);
|
|
3639
|
-
|
|
3828
|
+
if (migrationPaths.length === 0) {
|
|
3829
|
+
logWarning("No migration files were generated (no changes detected).");
|
|
3830
|
+
return;
|
|
3831
|
+
}
|
|
3832
|
+
if (migrationPaths.length === 1) {
|
|
3833
|
+
logSuccess(`Migration file created: ${path5.basename(migrationPaths[0])}`);
|
|
3834
|
+
} else {
|
|
3835
|
+
logSuccess(`Created ${migrationPaths.length} migration files`);
|
|
3836
|
+
}
|
|
3640
3837
|
logSection("\u2705 Next Steps");
|
|
3641
3838
|
console.log();
|
|
3642
|
-
console.log(" 1. Review the generated migration file:");
|
|
3643
|
-
|
|
3839
|
+
console.log(" 1. Review the generated migration file(s):");
|
|
3840
|
+
migrationPaths.forEach((migrationPath) => {
|
|
3841
|
+
console.log(` ${migrationPath}`);
|
|
3842
|
+
});
|
|
3644
3843
|
console.log();
|
|
3645
3844
|
console.log(" 2. Apply the migration by running PocketBase:");
|
|
3646
3845
|
console.log(" yarn pb");
|