pocketbase-zod-schema 0.1.3 → 0.2.0
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 +14 -0
- package/README.md +233 -98
- package/dist/cli/index.cjs +449 -108
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +447 -106
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/migrate.cjs +452 -111
- package/dist/cli/migrate.cjs.map +1 -1
- package/dist/cli/migrate.js +447 -106
- package/dist/cli/migrate.js.map +1 -1
- package/dist/index.cjs +593 -175
- 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 +583 -172
- package/dist/index.js.map +1 -1
- package/dist/migration/analyzer.cjs +44 -6
- package/dist/migration/analyzer.cjs.map +1 -1
- package/dist/migration/analyzer.d.cts +11 -1
- package/dist/migration/analyzer.d.ts +11 -1
- package/dist/migration/analyzer.js +44 -7
- package/dist/migration/analyzer.js.map +1 -1
- package/dist/migration/diff.cjs +21 -3
- package/dist/migration/diff.cjs.map +1 -1
- package/dist/migration/diff.js +21 -3
- package/dist/migration/diff.js.map +1 -1
- package/dist/migration/index.cjs +500 -129
- package/dist/migration/index.cjs.map +1 -1
- package/dist/migration/index.d.cts +1 -1
- package/dist/migration/index.d.ts +1 -1
- package/dist/migration/index.js +499 -129
- package/dist/migration/index.js.map +1 -1
- package/dist/migration/snapshot.cjs +432 -118
- package/dist/migration/snapshot.cjs.map +1 -1
- package/dist/migration/snapshot.d.cts +34 -12
- package/dist/migration/snapshot.d.ts +34 -12
- package/dist/migration/snapshot.js +430 -117
- package/dist/migration/snapshot.js.map +1 -1
- package/dist/mutator.cjs +20 -21
- package/dist/mutator.cjs.map +1 -1
- package/dist/mutator.d.cts +4 -4
- package/dist/mutator.d.ts +4 -4
- package/dist/mutator.js +20 -21
- package/dist/mutator.js.map +1 -1
- package/dist/schema.cjs +69 -10
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +98 -8
- package/dist/schema.d.ts +98 -8
- package/dist/schema.js +62 -9
- package/dist/schema.js.map +1 -1
- package/dist/types.d.cts +5 -2
- package/dist/types.d.ts +5 -2
- package/dist/user-DTJQIj4K.d.cts +149 -0
- package/dist/user-DTJQIj4K.d.ts +149 -0
- package/package.json +3 -3
- package/dist/user-C39DQ40N.d.cts +0 -53
- package/dist/user-C39DQ40N.d.ts +0 -53
package/dist/migration/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import * as
|
|
1
|
+
import * as fs3 from 'fs';
|
|
2
2
|
import * as path from 'path';
|
|
3
3
|
import { z } from 'zod';
|
|
4
4
|
|
|
@@ -130,10 +130,10 @@ var FileSystemError = class _FileSystemError extends MigrationError {
|
|
|
130
130
|
operation;
|
|
131
131
|
code;
|
|
132
132
|
originalError;
|
|
133
|
-
constructor(message,
|
|
133
|
+
constructor(message, path5, operation, code, originalError) {
|
|
134
134
|
super(message);
|
|
135
135
|
this.name = "FileSystemError";
|
|
136
|
-
this.path =
|
|
136
|
+
this.path = path5;
|
|
137
137
|
this.operation = operation;
|
|
138
138
|
this.code = code;
|
|
139
139
|
this.originalError = originalError;
|
|
@@ -1319,6 +1319,16 @@ function getFieldTypeInfo(zodType, fieldName) {
|
|
|
1319
1319
|
}
|
|
1320
1320
|
|
|
1321
1321
|
// src/migration/analyzer.ts
|
|
1322
|
+
var tsxLoaderRegistered = false;
|
|
1323
|
+
async function ensureTsxLoader() {
|
|
1324
|
+
if (tsxLoaderRegistered) return;
|
|
1325
|
+
try {
|
|
1326
|
+
await import('tsx/esm');
|
|
1327
|
+
tsxLoaderRegistered = true;
|
|
1328
|
+
} catch {
|
|
1329
|
+
tsxLoaderRegistered = false;
|
|
1330
|
+
}
|
|
1331
|
+
}
|
|
1322
1332
|
var DEFAULT_CONFIG = {
|
|
1323
1333
|
workspaceRoot: process.cwd(),
|
|
1324
1334
|
excludePatterns: [
|
|
@@ -1356,10 +1366,10 @@ function discoverSchemaFiles(config) {
|
|
|
1356
1366
|
const mergedConfig = mergeConfig(normalizedConfig);
|
|
1357
1367
|
const schemaDir = resolveSchemaDir(normalizedConfig);
|
|
1358
1368
|
try {
|
|
1359
|
-
if (!
|
|
1369
|
+
if (!fs3.existsSync(schemaDir)) {
|
|
1360
1370
|
throw new FileSystemError(`Schema directory not found: ${schemaDir}`, schemaDir, "access", "ENOENT");
|
|
1361
1371
|
}
|
|
1362
|
-
const files =
|
|
1372
|
+
const files = fs3.readdirSync(schemaDir);
|
|
1363
1373
|
const schemaFiles = files.filter((file) => {
|
|
1364
1374
|
const hasValidExtension = mergedConfig.includeExtensions.some((ext) => file.endsWith(ext));
|
|
1365
1375
|
if (!hasValidExtension) return false;
|
|
@@ -1409,31 +1419,44 @@ async function importSchemaModule(filePath, config) {
|
|
|
1409
1419
|
let resolvedPath = null;
|
|
1410
1420
|
const jsPath = `${importPath}.js`;
|
|
1411
1421
|
const tsPath = `${importPath}.ts`;
|
|
1412
|
-
if (
|
|
1422
|
+
if (fs3.existsSync(jsPath)) {
|
|
1413
1423
|
resolvedPath = jsPath;
|
|
1414
|
-
} else if (
|
|
1424
|
+
} else if (fs3.existsSync(tsPath)) {
|
|
1415
1425
|
resolvedPath = tsPath;
|
|
1416
1426
|
} else {
|
|
1417
1427
|
resolvedPath = jsPath;
|
|
1418
1428
|
}
|
|
1429
|
+
if (resolvedPath.endsWith(".ts")) {
|
|
1430
|
+
await ensureTsxLoader();
|
|
1431
|
+
if (!tsxLoaderRegistered) {
|
|
1432
|
+
throw new SchemaParsingError(
|
|
1433
|
+
`Failed to import TypeScript schema file. The 'tsx' package is required to load TypeScript files.
|
|
1434
|
+
Please install tsx: npm install tsx (or yarn add tsx, or pnpm add tsx)
|
|
1435
|
+
Alternatively, compile your schema files to JavaScript first.`,
|
|
1436
|
+
filePath
|
|
1437
|
+
);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1419
1440
|
const fileUrl = new URL(`file://${path.resolve(resolvedPath)}`);
|
|
1420
1441
|
const module = await import(fileUrl.href);
|
|
1421
1442
|
return module;
|
|
1422
1443
|
} catch (error) {
|
|
1423
1444
|
const tsPath = `${filePath}.ts`;
|
|
1424
|
-
const isTypeScriptFile =
|
|
1445
|
+
const isTypeScriptFile = fs3.existsSync(tsPath);
|
|
1446
|
+
if (isTypeScriptFile && error instanceof SchemaParsingError) {
|
|
1447
|
+
throw error;
|
|
1448
|
+
}
|
|
1425
1449
|
if (isTypeScriptFile) {
|
|
1426
1450
|
throw new SchemaParsingError(
|
|
1427
|
-
`Failed to import TypeScript schema file.
|
|
1428
|
-
Please
|
|
1429
|
-
|
|
1430
|
-
2. Use tsx to run the migration tool (e.g., "npx tsx package/dist/cli/migrate.js status" or "tsx package/dist/cli/migrate.js status")`,
|
|
1451
|
+
`Failed to import TypeScript schema file. The 'tsx' package is required to load TypeScript files.
|
|
1452
|
+
Please install tsx: npm install tsx (or yarn add tsx, or pnpm add tsx)
|
|
1453
|
+
Alternatively, compile your schema files to JavaScript first.`,
|
|
1431
1454
|
filePath,
|
|
1432
1455
|
error
|
|
1433
1456
|
);
|
|
1434
1457
|
}
|
|
1435
1458
|
throw new SchemaParsingError(
|
|
1436
|
-
`Failed to import schema module. Make sure the schema files
|
|
1459
|
+
`Failed to import schema module. Make sure the schema files exist and are valid.`,
|
|
1437
1460
|
filePath,
|
|
1438
1461
|
error
|
|
1439
1462
|
);
|
|
@@ -1443,6 +1466,19 @@ function getCollectionNameFromFile(filePath) {
|
|
|
1443
1466
|
const filename = path.basename(filePath).replace(/\.(ts|js)$/, "");
|
|
1444
1467
|
return toCollectionName(filename);
|
|
1445
1468
|
}
|
|
1469
|
+
function extractCollectionNameFromSchema(zodSchema) {
|
|
1470
|
+
if (!zodSchema.description) {
|
|
1471
|
+
return null;
|
|
1472
|
+
}
|
|
1473
|
+
try {
|
|
1474
|
+
const metadata = JSON.parse(zodSchema.description);
|
|
1475
|
+
if (metadata.collectionName && typeof metadata.collectionName === "string") {
|
|
1476
|
+
return metadata.collectionName;
|
|
1477
|
+
}
|
|
1478
|
+
} catch {
|
|
1479
|
+
}
|
|
1480
|
+
return null;
|
|
1481
|
+
}
|
|
1446
1482
|
function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema"]) {
|
|
1447
1483
|
const result = {};
|
|
1448
1484
|
for (const [key, value] of Object.entries(module)) {
|
|
@@ -1605,7 +1641,7 @@ async function buildSchemaDefinition(config) {
|
|
|
1605
1641
|
importPath = normalizedConfig.pathTransformer(filePath);
|
|
1606
1642
|
} else if (mergedConfig.useCompiledFiles) {
|
|
1607
1643
|
const distPath = filePath.replace(/\/src\//, "/dist/");
|
|
1608
|
-
if (
|
|
1644
|
+
if (fs3.existsSync(`${distPath}.js`) || fs3.existsSync(`${distPath}.mjs`)) {
|
|
1609
1645
|
importPath = distPath;
|
|
1610
1646
|
} else {
|
|
1611
1647
|
importPath = filePath;
|
|
@@ -1618,7 +1654,8 @@ async function buildSchemaDefinition(config) {
|
|
|
1618
1654
|
console.warn(`No valid schema found in ${filePath}, skipping...`);
|
|
1619
1655
|
continue;
|
|
1620
1656
|
}
|
|
1621
|
-
const
|
|
1657
|
+
const collectionNameFromSchema = extractCollectionNameFromSchema(zodSchema);
|
|
1658
|
+
const collectionName = collectionNameFromSchema ?? getCollectionNameFromFile(filePath);
|
|
1622
1659
|
const collectionSchema = convertZodSchemaToCollectionSchema(collectionName, zodSchema);
|
|
1623
1660
|
collections.set(collectionName, collectionSchema);
|
|
1624
1661
|
} catch (error) {
|
|
@@ -1661,7 +1698,359 @@ var SchemaAnalyzer = class {
|
|
|
1661
1698
|
return convertZodSchemaToCollectionSchema(name, schema);
|
|
1662
1699
|
}
|
|
1663
1700
|
};
|
|
1701
|
+
|
|
1702
|
+
// src/migration/pocketbase-converter.ts
|
|
1664
1703
|
var SNAPSHOT_VERSION = "1.0.0";
|
|
1704
|
+
function resolveCollectionIdToName(collectionId) {
|
|
1705
|
+
if (collectionId === "_pb_users_auth_") {
|
|
1706
|
+
return "Users";
|
|
1707
|
+
}
|
|
1708
|
+
const nameMatch = collectionId.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
1709
|
+
if (nameMatch) {
|
|
1710
|
+
return nameMatch[1];
|
|
1711
|
+
}
|
|
1712
|
+
return collectionId;
|
|
1713
|
+
}
|
|
1714
|
+
function convertPocketBaseCollection(pbCollection) {
|
|
1715
|
+
const fields = [];
|
|
1716
|
+
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
1717
|
+
const authSystemFieldNames = ["email", "emailVisibility", "verified", "password", "tokenKey"];
|
|
1718
|
+
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
1719
|
+
for (const pbField of pbCollection.fields) {
|
|
1720
|
+
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
1721
|
+
continue;
|
|
1722
|
+
}
|
|
1723
|
+
if (pbCollection.type === "auth" && authSystemFieldNames.includes(pbField.name)) {
|
|
1724
|
+
continue;
|
|
1725
|
+
}
|
|
1726
|
+
const field = {
|
|
1727
|
+
name: pbField.name,
|
|
1728
|
+
type: pbField.type,
|
|
1729
|
+
required: pbField.required || false
|
|
1730
|
+
};
|
|
1731
|
+
field.options = pbField.options ? { ...pbField.options } : {};
|
|
1732
|
+
if (pbField.type === "select") {
|
|
1733
|
+
if (pbField.values && Array.isArray(pbField.values)) {
|
|
1734
|
+
field.options.values = pbField.values;
|
|
1735
|
+
} else if (pbField.options?.values && Array.isArray(pbField.options.values)) {
|
|
1736
|
+
field.options.values = pbField.options.values;
|
|
1737
|
+
}
|
|
1738
|
+
}
|
|
1739
|
+
if (pbField.type === "relation") {
|
|
1740
|
+
const collectionId = pbField.collectionId || pbField.options?.collectionId || "";
|
|
1741
|
+
const collectionName = resolveCollectionIdToName(collectionId);
|
|
1742
|
+
field.relation = {
|
|
1743
|
+
collection: collectionName,
|
|
1744
|
+
cascadeDelete: pbField.cascadeDelete ?? pbField.options?.cascadeDelete ?? false,
|
|
1745
|
+
maxSelect: pbField.maxSelect ?? pbField.options?.maxSelect,
|
|
1746
|
+
minSelect: pbField.minSelect ?? pbField.options?.minSelect
|
|
1747
|
+
};
|
|
1748
|
+
}
|
|
1749
|
+
const hasOnlyValues = Object.keys(field.options).length === 1 && field.options.values !== void 0;
|
|
1750
|
+
if (Object.keys(field.options).length === 0) {
|
|
1751
|
+
delete field.options;
|
|
1752
|
+
} else if (pbField.type === "select" && hasOnlyValues) ;
|
|
1753
|
+
fields.push(field);
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
const schema = {
|
|
1757
|
+
name: pbCollection.name,
|
|
1758
|
+
type: pbCollection.type || "base",
|
|
1759
|
+
fields
|
|
1760
|
+
};
|
|
1761
|
+
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
1762
|
+
schema.indexes = pbCollection.indexes;
|
|
1763
|
+
}
|
|
1764
|
+
const rules = {};
|
|
1765
|
+
if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
|
|
1766
|
+
if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
|
|
1767
|
+
if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
|
|
1768
|
+
if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
|
|
1769
|
+
if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
|
|
1770
|
+
if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
|
|
1771
|
+
if (Object.keys(rules).length > 0) {
|
|
1772
|
+
schema.rules = rules;
|
|
1773
|
+
schema.permissions = { ...rules };
|
|
1774
|
+
}
|
|
1775
|
+
return schema;
|
|
1776
|
+
}
|
|
1777
|
+
function convertPocketBaseMigration(migrationContent) {
|
|
1778
|
+
try {
|
|
1779
|
+
const snapshotMatch = migrationContent.match(/const\s+snapshot\s*=\s*(\[[\s\S]*?\]);/);
|
|
1780
|
+
if (!snapshotMatch) {
|
|
1781
|
+
throw new Error("Could not find snapshot array in migration file");
|
|
1782
|
+
}
|
|
1783
|
+
const snapshotArrayStr = snapshotMatch[1];
|
|
1784
|
+
let snapshotArray;
|
|
1785
|
+
try {
|
|
1786
|
+
snapshotArray = new Function(`return ${snapshotArrayStr}`)();
|
|
1787
|
+
} catch (parseError) {
|
|
1788
|
+
throw new Error(`Failed to parse snapshot array: ${parseError}`);
|
|
1789
|
+
}
|
|
1790
|
+
if (!Array.isArray(snapshotArray)) {
|
|
1791
|
+
throw new Error("Snapshot is not an array");
|
|
1792
|
+
}
|
|
1793
|
+
const collections = /* @__PURE__ */ new Map();
|
|
1794
|
+
for (const pbCollection of snapshotArray) {
|
|
1795
|
+
if (!pbCollection.name) {
|
|
1796
|
+
console.warn("Skipping collection without name");
|
|
1797
|
+
continue;
|
|
1798
|
+
}
|
|
1799
|
+
const schema = convertPocketBaseCollection(pbCollection);
|
|
1800
|
+
collections.set(pbCollection.name, schema);
|
|
1801
|
+
}
|
|
1802
|
+
return {
|
|
1803
|
+
version: SNAPSHOT_VERSION,
|
|
1804
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1805
|
+
collections
|
|
1806
|
+
};
|
|
1807
|
+
} catch (error) {
|
|
1808
|
+
throw new SnapshotError(
|
|
1809
|
+
`Failed to convert PocketBase migration: ${error instanceof Error ? error.message : String(error)}`,
|
|
1810
|
+
void 0,
|
|
1811
|
+
"parse",
|
|
1812
|
+
error instanceof Error ? error : void 0
|
|
1813
|
+
);
|
|
1814
|
+
}
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
// src/migration/migration-parser.ts
|
|
1818
|
+
function extractTimestampFromFilename(filename) {
|
|
1819
|
+
const match = filename.match(/^(\d+)_/);
|
|
1820
|
+
if (match) {
|
|
1821
|
+
return parseInt(match[1], 10);
|
|
1822
|
+
}
|
|
1823
|
+
return null;
|
|
1824
|
+
}
|
|
1825
|
+
function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
|
|
1826
|
+
try {
|
|
1827
|
+
if (!fs3.existsSync(migrationsPath)) {
|
|
1828
|
+
return [];
|
|
1829
|
+
}
|
|
1830
|
+
const files = fs3.readdirSync(migrationsPath);
|
|
1831
|
+
const migrationFiles = [];
|
|
1832
|
+
for (const file of files) {
|
|
1833
|
+
if (file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")) {
|
|
1834
|
+
continue;
|
|
1835
|
+
}
|
|
1836
|
+
if (!file.endsWith(".js")) {
|
|
1837
|
+
continue;
|
|
1838
|
+
}
|
|
1839
|
+
const timestamp = extractTimestampFromFilename(file);
|
|
1840
|
+
if (timestamp && timestamp > snapshotTimestamp) {
|
|
1841
|
+
migrationFiles.push({
|
|
1842
|
+
path: path.join(migrationsPath, file),
|
|
1843
|
+
timestamp
|
|
1844
|
+
});
|
|
1845
|
+
}
|
|
1846
|
+
}
|
|
1847
|
+
migrationFiles.sort((a, b) => a.timestamp - b.timestamp);
|
|
1848
|
+
return migrationFiles.map((f) => f.path);
|
|
1849
|
+
} catch (error) {
|
|
1850
|
+
console.warn(`Error finding migrations after snapshot: ${error}`);
|
|
1851
|
+
return [];
|
|
1852
|
+
}
|
|
1853
|
+
}
|
|
1854
|
+
function parseMigrationOperationsFromContent(content) {
|
|
1855
|
+
const collectionsToCreate = [];
|
|
1856
|
+
const collectionsToDelete = [];
|
|
1857
|
+
try {
|
|
1858
|
+
let searchIndex = 0;
|
|
1859
|
+
while (true) {
|
|
1860
|
+
const collectionStart = content.indexOf("new Collection(", searchIndex);
|
|
1861
|
+
if (collectionStart === -1) {
|
|
1862
|
+
break;
|
|
1863
|
+
}
|
|
1864
|
+
const openParen = collectionStart + "new Collection(".length;
|
|
1865
|
+
let braceCount = 0;
|
|
1866
|
+
let parenCount = 1;
|
|
1867
|
+
let inString = false;
|
|
1868
|
+
let stringChar = null;
|
|
1869
|
+
let i = openParen;
|
|
1870
|
+
while (i < content.length && /\s/.test(content[i])) {
|
|
1871
|
+
i++;
|
|
1872
|
+
}
|
|
1873
|
+
if (content[i] !== "{") {
|
|
1874
|
+
searchIndex = i + 1;
|
|
1875
|
+
continue;
|
|
1876
|
+
}
|
|
1877
|
+
const objectStart = i;
|
|
1878
|
+
braceCount = 1;
|
|
1879
|
+
i++;
|
|
1880
|
+
while (i < content.length && (braceCount > 0 || parenCount > 0)) {
|
|
1881
|
+
const char = content[i];
|
|
1882
|
+
const prevChar = i > 0 ? content[i - 1] : "";
|
|
1883
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
1884
|
+
inString = true;
|
|
1885
|
+
stringChar = char;
|
|
1886
|
+
} else if (inString && char === stringChar && prevChar !== "\\") {
|
|
1887
|
+
inString = false;
|
|
1888
|
+
stringChar = null;
|
|
1889
|
+
}
|
|
1890
|
+
if (!inString) {
|
|
1891
|
+
if (char === "{") braceCount++;
|
|
1892
|
+
if (char === "}") braceCount--;
|
|
1893
|
+
if (char === "(") parenCount++;
|
|
1894
|
+
if (char === ")") parenCount--;
|
|
1895
|
+
}
|
|
1896
|
+
i++;
|
|
1897
|
+
}
|
|
1898
|
+
if (braceCount === 0 && parenCount === 0) {
|
|
1899
|
+
const objectContent = content.substring(objectStart, i - 1);
|
|
1900
|
+
try {
|
|
1901
|
+
const collectionObj = new Function(`return ${objectContent}`)();
|
|
1902
|
+
if (collectionObj && collectionObj.name) {
|
|
1903
|
+
const schema = convertPocketBaseCollection(collectionObj);
|
|
1904
|
+
collectionsToCreate.push(schema);
|
|
1905
|
+
}
|
|
1906
|
+
} catch (error) {
|
|
1907
|
+
console.warn(`Failed to parse collection definition: ${error}`);
|
|
1908
|
+
}
|
|
1909
|
+
}
|
|
1910
|
+
searchIndex = i;
|
|
1911
|
+
}
|
|
1912
|
+
const deleteMatches = content.matchAll(
|
|
1913
|
+
/app\.delete\s*\(\s*(?:collection_\w+|app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\))\s*\)/g
|
|
1914
|
+
);
|
|
1915
|
+
for (const match of deleteMatches) {
|
|
1916
|
+
if (match[1]) {
|
|
1917
|
+
collectionsToDelete.push(match[1]);
|
|
1918
|
+
} else {
|
|
1919
|
+
const varNameMatch = match[0].match(/collection_(\w+)/);
|
|
1920
|
+
if (varNameMatch) {
|
|
1921
|
+
const varName = `collection_${varNameMatch[1]}`;
|
|
1922
|
+
const deleteIndex = content.indexOf(match[0]);
|
|
1923
|
+
const beforeDelete = content.substring(0, deleteIndex);
|
|
1924
|
+
const varDefMatch = beforeDelete.match(
|
|
1925
|
+
new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`, "g")
|
|
1926
|
+
);
|
|
1927
|
+
if (varDefMatch && varDefMatch.length > 0) {
|
|
1928
|
+
const collectionDefMatch = beforeDelete.match(
|
|
1929
|
+
new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`)
|
|
1930
|
+
);
|
|
1931
|
+
if (collectionDefMatch) {
|
|
1932
|
+
try {
|
|
1933
|
+
const collectionDefStr = collectionDefMatch[1];
|
|
1934
|
+
const collectionObj = new Function(`return ${collectionDefStr}`)();
|
|
1935
|
+
if (collectionObj && collectionObj.name) {
|
|
1936
|
+
collectionsToDelete.push(collectionObj.name);
|
|
1937
|
+
}
|
|
1938
|
+
} catch {
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
}
|
|
1944
|
+
}
|
|
1945
|
+
const findAndDeleteMatches = content.matchAll(
|
|
1946
|
+
/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)[\s\S]*?app\.delete/g
|
|
1947
|
+
);
|
|
1948
|
+
for (const match of findAndDeleteMatches) {
|
|
1949
|
+
collectionsToDelete.push(match[1]);
|
|
1950
|
+
}
|
|
1951
|
+
} catch (error) {
|
|
1952
|
+
console.warn(`Failed to parse migration operations from content: ${error}`);
|
|
1953
|
+
}
|
|
1954
|
+
return { collectionsToCreate, collectionsToDelete };
|
|
1955
|
+
}
|
|
1956
|
+
function parseMigrationOperations(migrationContent) {
|
|
1957
|
+
try {
|
|
1958
|
+
const migrateMatch = migrationContent.match(/migrate\s*\(\s*/);
|
|
1959
|
+
if (!migrateMatch) {
|
|
1960
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
1961
|
+
}
|
|
1962
|
+
const startIndex = migrateMatch.index + migrateMatch[0].length;
|
|
1963
|
+
let i = startIndex;
|
|
1964
|
+
let parenCount = 0;
|
|
1965
|
+
let foundFirstParen = false;
|
|
1966
|
+
while (i < migrationContent.length) {
|
|
1967
|
+
const char = migrationContent[i];
|
|
1968
|
+
if (char === "(") {
|
|
1969
|
+
parenCount++;
|
|
1970
|
+
foundFirstParen = true;
|
|
1971
|
+
i++;
|
|
1972
|
+
break;
|
|
1973
|
+
}
|
|
1974
|
+
i++;
|
|
1975
|
+
}
|
|
1976
|
+
if (!foundFirstParen) {
|
|
1977
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
1978
|
+
}
|
|
1979
|
+
let inString = false;
|
|
1980
|
+
let stringChar = null;
|
|
1981
|
+
let foundBrace = false;
|
|
1982
|
+
let braceStart = -1;
|
|
1983
|
+
while (i < migrationContent.length && !foundBrace) {
|
|
1984
|
+
const char = migrationContent[i];
|
|
1985
|
+
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
1986
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
1987
|
+
inString = true;
|
|
1988
|
+
stringChar = char;
|
|
1989
|
+
} else if (inString && char === stringChar && prevChar !== "\\") {
|
|
1990
|
+
inString = false;
|
|
1991
|
+
stringChar = null;
|
|
1992
|
+
}
|
|
1993
|
+
if (!inString) {
|
|
1994
|
+
if (char === "(") parenCount++;
|
|
1995
|
+
if (char === ")") {
|
|
1996
|
+
parenCount--;
|
|
1997
|
+
if (parenCount === 0) {
|
|
1998
|
+
i++;
|
|
1999
|
+
while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
|
|
2000
|
+
i++;
|
|
2001
|
+
}
|
|
2002
|
+
if (i < migrationContent.length - 1 && migrationContent[i] === "=" && migrationContent[i + 1] === ">") {
|
|
2003
|
+
i += 2;
|
|
2004
|
+
while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
|
|
2005
|
+
i++;
|
|
2006
|
+
}
|
|
2007
|
+
if (i < migrationContent.length && migrationContent[i] === "{") {
|
|
2008
|
+
foundBrace = true;
|
|
2009
|
+
braceStart = i + 1;
|
|
2010
|
+
break;
|
|
2011
|
+
}
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
}
|
|
2015
|
+
}
|
|
2016
|
+
i++;
|
|
2017
|
+
}
|
|
2018
|
+
if (!foundBrace || braceStart === -1) {
|
|
2019
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
2020
|
+
}
|
|
2021
|
+
let braceCount = 1;
|
|
2022
|
+
i = braceStart;
|
|
2023
|
+
inString = false;
|
|
2024
|
+
stringChar = null;
|
|
2025
|
+
while (i < migrationContent.length && braceCount > 0) {
|
|
2026
|
+
const char = migrationContent[i];
|
|
2027
|
+
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
2028
|
+
if (!inString && (char === '"' || char === "'")) {
|
|
2029
|
+
inString = true;
|
|
2030
|
+
stringChar = char;
|
|
2031
|
+
} else if (inString && char === stringChar && prevChar !== "\\") {
|
|
2032
|
+
inString = false;
|
|
2033
|
+
stringChar = null;
|
|
2034
|
+
}
|
|
2035
|
+
if (!inString) {
|
|
2036
|
+
if (char === "{") braceCount++;
|
|
2037
|
+
if (char === "}") braceCount--;
|
|
2038
|
+
}
|
|
2039
|
+
i++;
|
|
2040
|
+
}
|
|
2041
|
+
if (braceCount === 0) {
|
|
2042
|
+
const upMigrationContent = migrationContent.substring(braceStart, i - 1);
|
|
2043
|
+
return parseMigrationOperationsFromContent(upMigrationContent);
|
|
2044
|
+
}
|
|
2045
|
+
return parseMigrationOperationsFromContent(migrationContent);
|
|
2046
|
+
} catch (error) {
|
|
2047
|
+
console.warn(`Failed to parse migration operations: ${error}`);
|
|
2048
|
+
return { collectionsToCreate: [], collectionsToDelete: [] };
|
|
2049
|
+
}
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
// src/migration/snapshot.ts
|
|
2053
|
+
var SNAPSHOT_VERSION2 = "1.0.0";
|
|
1665
2054
|
var DEFAULT_SNAPSHOT_FILENAME = ".migration-snapshot.json";
|
|
1666
2055
|
var SNAPSHOT_MIGRATIONS = [
|
|
1667
2056
|
// Add migrations here as the format evolves
|
|
@@ -1676,7 +2065,7 @@ var DEFAULT_CONFIG2 = {
|
|
|
1676
2065
|
snapshotPath: DEFAULT_SNAPSHOT_FILENAME,
|
|
1677
2066
|
workspaceRoot: process.cwd(),
|
|
1678
2067
|
autoMigrate: true,
|
|
1679
|
-
version:
|
|
2068
|
+
version: SNAPSHOT_VERSION2
|
|
1680
2069
|
};
|
|
1681
2070
|
function mergeConfig2(config = {}) {
|
|
1682
2071
|
return {
|
|
@@ -1696,7 +2085,7 @@ function getSnapshotPath(config = {}) {
|
|
|
1696
2085
|
function snapshotExists(config = {}) {
|
|
1697
2086
|
try {
|
|
1698
2087
|
const snapshotPath = getSnapshotPath(config);
|
|
1699
|
-
return
|
|
2088
|
+
return fs3.existsSync(snapshotPath);
|
|
1700
2089
|
} catch {
|
|
1701
2090
|
return false;
|
|
1702
2091
|
}
|
|
@@ -1756,12 +2145,12 @@ function saveSnapshot(schema, config = {}) {
|
|
|
1756
2145
|
const snapshotPath = getSnapshotPath(config);
|
|
1757
2146
|
try {
|
|
1758
2147
|
const snapshotDir = path.dirname(snapshotPath);
|
|
1759
|
-
if (!
|
|
1760
|
-
|
|
2148
|
+
if (!fs3.existsSync(snapshotDir)) {
|
|
2149
|
+
fs3.mkdirSync(snapshotDir, { recursive: true });
|
|
1761
2150
|
}
|
|
1762
2151
|
const snapshotData = addSnapshotMetadata(schema, config);
|
|
1763
2152
|
const jsonContent = JSON.stringify(snapshotData, null, 2);
|
|
1764
|
-
|
|
2153
|
+
fs3.writeFileSync(snapshotPath, jsonContent, "utf-8");
|
|
1765
2154
|
} catch (error) {
|
|
1766
2155
|
handleFileSystemError(error, "write", snapshotPath);
|
|
1767
2156
|
}
|
|
@@ -1856,7 +2245,7 @@ function deserializeSnapshot(data) {
|
|
|
1856
2245
|
function loadSnapshot(config = {}) {
|
|
1857
2246
|
const snapshotPath = getSnapshotPath(config);
|
|
1858
2247
|
try {
|
|
1859
|
-
const jsonContent =
|
|
2248
|
+
const jsonContent = fs3.readFileSync(snapshotPath, "utf-8");
|
|
1860
2249
|
const data = parseAndValidateSnapshot(jsonContent, snapshotPath);
|
|
1861
2250
|
const migratedData = migrateSnapshotFormat(data, config);
|
|
1862
2251
|
return deserializeSnapshot(migratedData);
|
|
@@ -1891,10 +2280,10 @@ function mergeSnapshots(baseSnapshot, customSnapshot) {
|
|
|
1891
2280
|
}
|
|
1892
2281
|
function findLatestSnapshot(migrationsPath) {
|
|
1893
2282
|
try {
|
|
1894
|
-
if (!
|
|
2283
|
+
if (!fs3.existsSync(migrationsPath)) {
|
|
1895
2284
|
return null;
|
|
1896
2285
|
}
|
|
1897
|
-
const files =
|
|
2286
|
+
const files = fs3.readdirSync(migrationsPath);
|
|
1898
2287
|
const snapshotFiles = files.filter(
|
|
1899
2288
|
(file) => file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")
|
|
1900
2289
|
);
|
|
@@ -1912,14 +2301,68 @@ function findLatestSnapshot(migrationsPath) {
|
|
|
1912
2301
|
return null;
|
|
1913
2302
|
}
|
|
1914
2303
|
}
|
|
2304
|
+
function applyMigrationOperations(snapshot, operations) {
|
|
2305
|
+
const updatedCollections = new Map(snapshot.collections);
|
|
2306
|
+
for (const collectionName of operations.collectionsToDelete) {
|
|
2307
|
+
updatedCollections.delete(collectionName);
|
|
2308
|
+
}
|
|
2309
|
+
for (const collection of operations.collectionsToCreate) {
|
|
2310
|
+
updatedCollections.set(collection.name, collection);
|
|
2311
|
+
}
|
|
2312
|
+
return {
|
|
2313
|
+
...snapshot,
|
|
2314
|
+
collections: updatedCollections
|
|
2315
|
+
};
|
|
2316
|
+
}
|
|
2317
|
+
function loadSnapshotWithMigrations(config = {}) {
|
|
2318
|
+
const migrationsPath = config.migrationsPath;
|
|
2319
|
+
if (!migrationsPath) {
|
|
2320
|
+
return null;
|
|
2321
|
+
}
|
|
2322
|
+
if (fs3.existsSync(migrationsPath) && fs3.statSync(migrationsPath).isFile()) {
|
|
2323
|
+
try {
|
|
2324
|
+
const migrationContent = fs3.readFileSync(migrationsPath, "utf-8");
|
|
2325
|
+
return convertPocketBaseMigration(migrationContent);
|
|
2326
|
+
} catch (error) {
|
|
2327
|
+
console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
|
|
2328
|
+
return null;
|
|
2329
|
+
}
|
|
2330
|
+
}
|
|
2331
|
+
const latestSnapshotPath = findLatestSnapshot(migrationsPath);
|
|
2332
|
+
if (!latestSnapshotPath) {
|
|
2333
|
+
return null;
|
|
2334
|
+
}
|
|
2335
|
+
try {
|
|
2336
|
+
const migrationContent = fs3.readFileSync(latestSnapshotPath, "utf-8");
|
|
2337
|
+
let snapshot = convertPocketBaseMigration(migrationContent);
|
|
2338
|
+
const snapshotFilename = path.basename(latestSnapshotPath);
|
|
2339
|
+
const snapshotTimestamp = extractTimestampFromFilename(snapshotFilename);
|
|
2340
|
+
if (snapshotTimestamp) {
|
|
2341
|
+
const migrationFiles = findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp);
|
|
2342
|
+
for (const migrationFile of migrationFiles) {
|
|
2343
|
+
try {
|
|
2344
|
+
const migrationContent2 = fs3.readFileSync(migrationFile, "utf-8");
|
|
2345
|
+
const operations = parseMigrationOperations(migrationContent2);
|
|
2346
|
+
snapshot = applyMigrationOperations(snapshot, operations);
|
|
2347
|
+
} catch (error) {
|
|
2348
|
+
console.warn(`Failed to apply migration ${migrationFile}: ${error}`);
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
return snapshot;
|
|
2353
|
+
} catch (error) {
|
|
2354
|
+
console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
|
|
2355
|
+
return null;
|
|
2356
|
+
}
|
|
2357
|
+
}
|
|
1915
2358
|
function loadSnapshotIfExists(config = {}) {
|
|
1916
2359
|
const migrationsPath = config.migrationsPath;
|
|
1917
2360
|
if (!migrationsPath) {
|
|
1918
2361
|
return null;
|
|
1919
2362
|
}
|
|
1920
|
-
if (
|
|
2363
|
+
if (fs3.existsSync(migrationsPath) && fs3.statSync(migrationsPath).isFile()) {
|
|
1921
2364
|
try {
|
|
1922
|
-
const migrationContent =
|
|
2365
|
+
const migrationContent = fs3.readFileSync(migrationsPath, "utf-8");
|
|
1923
2366
|
return convertPocketBaseMigration(migrationContent);
|
|
1924
2367
|
} catch (error) {
|
|
1925
2368
|
console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
|
|
@@ -1929,7 +2372,7 @@ function loadSnapshotIfExists(config = {}) {
|
|
|
1929
2372
|
const latestSnapshotPath = findLatestSnapshot(migrationsPath);
|
|
1930
2373
|
if (latestSnapshotPath) {
|
|
1931
2374
|
try {
|
|
1932
|
-
const migrationContent =
|
|
2375
|
+
const migrationContent = fs3.readFileSync(latestSnapshotPath, "utf-8");
|
|
1933
2376
|
return convertPocketBaseMigration(migrationContent);
|
|
1934
2377
|
} catch (error) {
|
|
1935
2378
|
console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
|
|
@@ -1938,100 +2381,9 @@ function loadSnapshotIfExists(config = {}) {
|
|
|
1938
2381
|
}
|
|
1939
2382
|
return null;
|
|
1940
2383
|
}
|
|
1941
|
-
function convertPocketBaseCollection(pbCollection) {
|
|
1942
|
-
const fields = [];
|
|
1943
|
-
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
1944
|
-
const authSystemFieldNames = ["email", "emailVisibility", "verified", "password", "tokenKey"];
|
|
1945
|
-
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
1946
|
-
for (const pbField of pbCollection.fields) {
|
|
1947
|
-
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
1948
|
-
continue;
|
|
1949
|
-
}
|
|
1950
|
-
if (pbCollection.type === "auth" && authSystemFieldNames.includes(pbField.name)) {
|
|
1951
|
-
continue;
|
|
1952
|
-
}
|
|
1953
|
-
const field = {
|
|
1954
|
-
name: pbField.name,
|
|
1955
|
-
type: pbField.type,
|
|
1956
|
-
required: pbField.required || false
|
|
1957
|
-
};
|
|
1958
|
-
if (pbField.options) {
|
|
1959
|
-
field.options = pbField.options;
|
|
1960
|
-
}
|
|
1961
|
-
if (pbField.type === "relation") {
|
|
1962
|
-
field.relation = {
|
|
1963
|
-
collection: pbField.options?.collectionId || "",
|
|
1964
|
-
cascadeDelete: pbField.options?.cascadeDelete || false,
|
|
1965
|
-
maxSelect: pbField.options?.maxSelect,
|
|
1966
|
-
minSelect: pbField.options?.minSelect
|
|
1967
|
-
};
|
|
1968
|
-
}
|
|
1969
|
-
fields.push(field);
|
|
1970
|
-
}
|
|
1971
|
-
}
|
|
1972
|
-
const schema = {
|
|
1973
|
-
name: pbCollection.name,
|
|
1974
|
-
type: pbCollection.type || "base",
|
|
1975
|
-
fields
|
|
1976
|
-
};
|
|
1977
|
-
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
1978
|
-
schema.indexes = pbCollection.indexes;
|
|
1979
|
-
}
|
|
1980
|
-
const rules = {};
|
|
1981
|
-
if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
|
|
1982
|
-
if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
|
|
1983
|
-
if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
|
|
1984
|
-
if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
|
|
1985
|
-
if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
|
|
1986
|
-
if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
|
|
1987
|
-
if (Object.keys(rules).length > 0) {
|
|
1988
|
-
schema.rules = rules;
|
|
1989
|
-
schema.permissions = { ...rules };
|
|
1990
|
-
}
|
|
1991
|
-
return schema;
|
|
1992
|
-
}
|
|
1993
|
-
function convertPocketBaseMigration(migrationContent) {
|
|
1994
|
-
try {
|
|
1995
|
-
const snapshotMatch = migrationContent.match(/const\s+snapshot\s*=\s*(\[[\s\S]*?\]);/);
|
|
1996
|
-
if (!snapshotMatch) {
|
|
1997
|
-
throw new Error("Could not find snapshot array in migration file");
|
|
1998
|
-
}
|
|
1999
|
-
const snapshotArrayStr = snapshotMatch[1];
|
|
2000
|
-
let snapshotArray;
|
|
2001
|
-
try {
|
|
2002
|
-
snapshotArray = new Function(`return ${snapshotArrayStr}`)();
|
|
2003
|
-
} catch (parseError) {
|
|
2004
|
-
throw new Error(`Failed to parse snapshot array: ${parseError}`);
|
|
2005
|
-
}
|
|
2006
|
-
if (!Array.isArray(snapshotArray)) {
|
|
2007
|
-
throw new Error("Snapshot is not an array");
|
|
2008
|
-
}
|
|
2009
|
-
const collections = /* @__PURE__ */ new Map();
|
|
2010
|
-
for (const pbCollection of snapshotArray) {
|
|
2011
|
-
if (!pbCollection.name) {
|
|
2012
|
-
console.warn("Skipping collection without name");
|
|
2013
|
-
continue;
|
|
2014
|
-
}
|
|
2015
|
-
const schema = convertPocketBaseCollection(pbCollection);
|
|
2016
|
-
collections.set(pbCollection.name, schema);
|
|
2017
|
-
}
|
|
2018
|
-
return {
|
|
2019
|
-
version: SNAPSHOT_VERSION,
|
|
2020
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2021
|
-
collections
|
|
2022
|
-
};
|
|
2023
|
-
} catch (error) {
|
|
2024
|
-
throw new SnapshotError(
|
|
2025
|
-
`Failed to convert PocketBase migration: ${error instanceof Error ? error.message : String(error)}`,
|
|
2026
|
-
void 0,
|
|
2027
|
-
"parse",
|
|
2028
|
-
error instanceof Error ? error : void 0
|
|
2029
|
-
);
|
|
2030
|
-
}
|
|
2031
|
-
}
|
|
2032
2384
|
function loadBaseMigration(migrationPath) {
|
|
2033
2385
|
try {
|
|
2034
|
-
if (!
|
|
2386
|
+
if (!fs3.existsSync(migrationPath)) {
|
|
2035
2387
|
throw new SnapshotError(
|
|
2036
2388
|
`Base migration file not found: ${migrationPath}
|
|
2037
2389
|
|
|
@@ -2042,7 +2394,7 @@ If the file exists in a different location, update the configuration.`,
|
|
|
2042
2394
|
"read"
|
|
2043
2395
|
);
|
|
2044
2396
|
}
|
|
2045
|
-
const migrationContent =
|
|
2397
|
+
const migrationContent = fs3.readFileSync(migrationPath, "utf-8");
|
|
2046
2398
|
const snapshot = convertPocketBaseMigration(migrationContent);
|
|
2047
2399
|
return snapshot;
|
|
2048
2400
|
} catch (error) {
|
|
@@ -2078,14 +2430,14 @@ Please ensure PocketBase is properly set up by running 'yarn setup'.`,
|
|
|
2078
2430
|
}
|
|
2079
2431
|
}
|
|
2080
2432
|
function getSnapshotVersion() {
|
|
2081
|
-
return
|
|
2433
|
+
return SNAPSHOT_VERSION2;
|
|
2082
2434
|
}
|
|
2083
2435
|
function validateSnapshot(snapshot) {
|
|
2084
2436
|
const issues = [];
|
|
2085
2437
|
if (!snapshot.version) {
|
|
2086
2438
|
issues.push("Missing version field");
|
|
2087
|
-
} else if (compareVersions(snapshot.version,
|
|
2088
|
-
issues.push(`Snapshot version ${snapshot.version} is newer than supported version ${
|
|
2439
|
+
} else if (compareVersions(snapshot.version, SNAPSHOT_VERSION2) > 0) {
|
|
2440
|
+
issues.push(`Snapshot version ${snapshot.version} is newer than supported version ${SNAPSHOT_VERSION2}`);
|
|
2089
2441
|
}
|
|
2090
2442
|
if (!snapshot.timestamp) {
|
|
2091
2443
|
issues.push("Missing timestamp field");
|
|
@@ -2304,6 +2656,9 @@ function compareFieldOptions(currentField, previousField) {
|
|
|
2304
2656
|
for (const key of allKeys) {
|
|
2305
2657
|
const currentValue = currentOptions[key];
|
|
2306
2658
|
const previousValue = previousOptions[key];
|
|
2659
|
+
if (currentValue === void 0 && previousValue === void 0) {
|
|
2660
|
+
continue;
|
|
2661
|
+
}
|
|
2307
2662
|
if (!areValuesEqual(currentValue, previousValue)) {
|
|
2308
2663
|
changes.push({
|
|
2309
2664
|
property: `options.${key}`,
|
|
@@ -2324,11 +2679,26 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
2324
2679
|
if (!currentRelation || !previousRelation) {
|
|
2325
2680
|
return changes;
|
|
2326
2681
|
}
|
|
2327
|
-
|
|
2682
|
+
const normalizeCollection = (collection) => {
|
|
2683
|
+
if (!collection) return collection;
|
|
2684
|
+
if (collection === "_pb_users_auth_") {
|
|
2685
|
+
return "Users";
|
|
2686
|
+
}
|
|
2687
|
+
const nameMatch = collection.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
2688
|
+
if (nameMatch) {
|
|
2689
|
+
return nameMatch[1];
|
|
2690
|
+
}
|
|
2691
|
+
return collection;
|
|
2692
|
+
};
|
|
2693
|
+
const normalizedCurrent = normalizeCollection(currentRelation.collection);
|
|
2694
|
+
const normalizedPrevious = normalizeCollection(previousRelation.collection);
|
|
2695
|
+
if (normalizedCurrent !== normalizedPrevious) {
|
|
2328
2696
|
changes.push({
|
|
2329
2697
|
property: "relation.collection",
|
|
2330
|
-
oldValue:
|
|
2331
|
-
|
|
2698
|
+
oldValue: normalizedPrevious,
|
|
2699
|
+
// Use normalized value for clarity
|
|
2700
|
+
newValue: normalizedCurrent
|
|
2701
|
+
// Use normalized value for clarity
|
|
2332
2702
|
});
|
|
2333
2703
|
}
|
|
2334
2704
|
if (currentRelation.cascadeDelete !== previousRelation.cascadeDelete) {
|
|
@@ -2762,9 +3132,9 @@ function createMigrationFileStructure(upCode, downCode, config) {
|
|
|
2762
3132
|
}
|
|
2763
3133
|
function writeMigrationFile(migrationDir, filename, content) {
|
|
2764
3134
|
try {
|
|
2765
|
-
if (!
|
|
3135
|
+
if (!fs3.existsSync(migrationDir)) {
|
|
2766
3136
|
try {
|
|
2767
|
-
|
|
3137
|
+
fs3.mkdirSync(migrationDir, { recursive: true });
|
|
2768
3138
|
} catch (error) {
|
|
2769
3139
|
const fsError = error;
|
|
2770
3140
|
if (fsError.code === "EACCES" || fsError.code === "EPERM") {
|
|
@@ -2786,7 +3156,7 @@ function writeMigrationFile(migrationDir, filename, content) {
|
|
|
2786
3156
|
}
|
|
2787
3157
|
}
|
|
2788
3158
|
const filePath = path.join(migrationDir, filename);
|
|
2789
|
-
|
|
3159
|
+
fs3.writeFileSync(filePath, content, "utf-8");
|
|
2790
3160
|
return filePath;
|
|
2791
3161
|
} catch (error) {
|
|
2792
3162
|
if (error instanceof FileSystemError) {
|
|
@@ -3369,6 +3739,6 @@ var MigrationGenerator = class {
|
|
|
3369
3739
|
}
|
|
3370
3740
|
};
|
|
3371
3741
|
|
|
3372
|
-
export { CLIUsageError, ConfigurationError, DiffEngine, FIELD_TYPE_INFO, FileSystemError, MigrationError, MigrationGenerationError, MigrationGenerator, POCKETBASE_FIELD_TYPES, SchemaAnalyzer, SchemaParsingError, SnapshotError, SnapshotManager, aggregateChanges, buildFieldDefinition, buildSchemaDefinition, categorizeChangesBySeverity, compare, compareFieldConstraints, compareFieldOptions, compareFieldTypes, comparePermissions, compareRelationConfigurations, convertPocketBaseMigration, convertZodSchemaToCollectionSchema, createMigrationFileStructure, detectDestructiveChanges, detectFieldChanges, discoverSchemaFiles, extractComprehensiveFieldOptions, extractFieldDefinitions, extractFieldOptions, extractIndexes, extractSchemaDefinitions, filterSystemCollections, findLatestSnapshot, findNewCollections, findNewFields, findRemovedCollections, findRemovedFields, generate, generateChangeSummary, generateCollectionCreation, generateCollectionPermissions, generateCollectionRules, generateDownMigration, generateFieldAddition, generateFieldDefinitionObject, generateFieldDeletion, generateFieldModification, generateFieldsArray, generateIndexesArray, generateMigrationDescription, generateMigrationFilename, generatePermissionUpdate, generateTimestamp, generateUpMigration, getArrayElementType, getCollectionNameFromFile, getDefaultValue, getFieldTypeInfo, getMaxSelect, getMinSelect, getSnapshotPath, getSnapshotVersion, getUsersSystemFields, importSchemaModule, isArrayType, isAuthCollection, isEditorField, isFieldRequired, isFileFieldByName, isGeoPointType, isMultipleRelationField, isRelationField, isSingleRelationField, isSystemCollection, loadBaseMigration, loadSnapshot, loadSnapshotIfExists, mapZodArrayType, mapZodBooleanType, mapZodDateType, mapZodEnumType, mapZodNumberType, mapZodRecordType, mapZodStringType, mapZodTypeToPocketBase, matchCollectionsByName, matchFieldsByName, mergeSnapshots, parseSchemaFiles, pluralize, requiresForceFlag, resolveTargetCollection, saveSnapshot, selectSchemaForCollection, singularize, snapshotExists, toCollectionName, unwrapZodType, validateSnapshot, writeMigrationFile };
|
|
3742
|
+
export { CLIUsageError, ConfigurationError, DiffEngine, FIELD_TYPE_INFO, FileSystemError, MigrationError, MigrationGenerationError, MigrationGenerator, POCKETBASE_FIELD_TYPES, SchemaAnalyzer, SchemaParsingError, SnapshotError, SnapshotManager, aggregateChanges, buildFieldDefinition, buildSchemaDefinition, categorizeChangesBySeverity, compare, compareFieldConstraints, compareFieldOptions, compareFieldTypes, comparePermissions, compareRelationConfigurations, convertPocketBaseMigration, convertZodSchemaToCollectionSchema, createMigrationFileStructure, detectDestructiveChanges, detectFieldChanges, discoverSchemaFiles, extractComprehensiveFieldOptions, extractFieldDefinitions, extractFieldOptions, extractIndexes, extractSchemaDefinitions, filterSystemCollections, findLatestSnapshot, findNewCollections, findNewFields, findRemovedCollections, findRemovedFields, generate, generateChangeSummary, generateCollectionCreation, generateCollectionPermissions, generateCollectionRules, generateDownMigration, generateFieldAddition, generateFieldDefinitionObject, generateFieldDeletion, generateFieldModification, generateFieldsArray, generateIndexesArray, generateMigrationDescription, generateMigrationFilename, generatePermissionUpdate, generateTimestamp, generateUpMigration, getArrayElementType, getCollectionNameFromFile, getDefaultValue, getFieldTypeInfo, getMaxSelect, getMinSelect, getSnapshotPath, getSnapshotVersion, getUsersSystemFields, importSchemaModule, isArrayType, isAuthCollection, isEditorField, isFieldRequired, isFileFieldByName, isGeoPointType, isMultipleRelationField, isRelationField, isSingleRelationField, isSystemCollection, loadBaseMigration, loadSnapshot, loadSnapshotIfExists, loadSnapshotWithMigrations, mapZodArrayType, mapZodBooleanType, mapZodDateType, mapZodEnumType, mapZodNumberType, mapZodRecordType, mapZodStringType, mapZodTypeToPocketBase, matchCollectionsByName, matchFieldsByName, mergeSnapshots, parseSchemaFiles, pluralize, requiresForceFlag, resolveTargetCollection, saveSnapshot, selectSchemaForCollection, singularize, snapshotExists, toCollectionName, unwrapZodType, validateSnapshot, writeMigrationFile };
|
|
3373
3743
|
//# sourceMappingURL=index.js.map
|
|
3374
3744
|
//# sourceMappingURL=index.js.map
|