pocketbase-zod-schema 0.7.0 → 0.7.2
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/dist/cli/index.cjs +449 -50
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +1 -1
- package/dist/cli/index.d.ts +1 -1
- package/dist/cli/index.js +449 -50
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/migrate.cjs +455 -53
- package/dist/cli/migrate.cjs.map +1 -1
- package/dist/cli/migrate.js +455 -53
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/utils/index.cjs +8 -1
- package/dist/cli/utils/index.cjs.map +1 -1
- package/dist/cli/utils/index.d.cts +1 -1
- package/dist/cli/utils/index.d.ts +1 -1
- package/dist/cli/utils/index.js +8 -1
- package/dist/cli/utils/index.js.map +1 -1
- package/dist/index.cjs +90 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +87 -2
- package/dist/index.js.map +1 -1
- package/dist/migration/analyzer.cjs +87 -14
- package/dist/migration/analyzer.cjs.map +1 -1
- package/dist/migration/analyzer.d.cts +12 -4
- package/dist/migration/analyzer.d.ts +12 -4
- package/dist/migration/analyzer.js +87 -15
- package/dist/migration/analyzer.js.map +1 -1
- package/dist/migration/diff.cjs +64 -9
- package/dist/migration/diff.cjs.map +1 -1
- package/dist/migration/diff.d.cts +12 -2
- package/dist/migration/diff.d.ts +12 -2
- package/dist/migration/diff.js +64 -10
- package/dist/migration/diff.js.map +1 -1
- package/dist/migration/generator.cjs +206 -39
- package/dist/migration/generator.cjs.map +1 -1
- package/dist/migration/generator.d.cts +54 -2
- package/dist/migration/generator.d.ts +54 -2
- package/dist/migration/generator.js +203 -40
- package/dist/migration/generator.js.map +1 -1
- package/dist/migration/index.cjs +501 -63
- package/dist/migration/index.cjs.map +1 -1
- package/dist/migration/index.d.cts +2 -2
- package/dist/migration/index.d.ts +2 -2
- package/dist/migration/index.js +501 -63
- package/dist/migration/index.js.map +1 -1
- package/dist/migration/snapshot.cjs +147 -1
- package/dist/migration/snapshot.cjs.map +1 -1
- package/dist/migration/snapshot.d.cts +3 -1
- package/dist/migration/snapshot.d.ts +3 -1
- package/dist/migration/snapshot.js +147 -1
- package/dist/migration/snapshot.js.map +1 -1
- package/dist/migration/utils/index.d.cts +1 -1
- package/dist/migration/utils/index.d.ts +1 -1
- package/dist/schema.cjs +90 -1
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +128 -2
- package/dist/schema.d.ts +128 -2
- package/dist/schema.js +87 -2
- package/dist/schema.js.map +1 -1
- package/dist/server.cjs +545 -65
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +2 -2
- package/dist/server.d.ts +2 -2
- package/dist/server.js +542 -66
- package/dist/server.js.map +1 -1
- package/dist/{types-CWHV6ATd.d.cts → types-CnzfX6JH.d.cts} +20 -2
- package/dist/{types-C2nGWHLV.d.ts → types-Do3jyFBm.d.ts} +20 -2
- package/package.json +1 -1
package/dist/migration/index.js
CHANGED
|
@@ -1460,6 +1460,60 @@ function getFieldTypeInfo(zodType, fieldName) {
|
|
|
1460
1460
|
options
|
|
1461
1461
|
};
|
|
1462
1462
|
}
|
|
1463
|
+
function dedentSql(value) {
|
|
1464
|
+
const lines = value.replace(/\r\n/g, "\n").split("\n");
|
|
1465
|
+
while (lines.length > 0 && lines[0].trim() === "") {
|
|
1466
|
+
lines.shift();
|
|
1467
|
+
}
|
|
1468
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
|
|
1469
|
+
lines.pop();
|
|
1470
|
+
}
|
|
1471
|
+
if (lines.length === 0) {
|
|
1472
|
+
return "";
|
|
1473
|
+
}
|
|
1474
|
+
let minIndent = Infinity;
|
|
1475
|
+
for (const line of lines) {
|
|
1476
|
+
if (line.trim() === "") continue;
|
|
1477
|
+
const indent = line.length - line.trimStart().length;
|
|
1478
|
+
if (indent < minIndent) {
|
|
1479
|
+
minIndent = indent;
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
if (!Number.isFinite(minIndent) || minIndent === 0) {
|
|
1483
|
+
return lines.map((line) => line.trimEnd()).join("\n");
|
|
1484
|
+
}
|
|
1485
|
+
return lines.map((line) => line.slice(minIndent).trimEnd()).join("\n");
|
|
1486
|
+
}
|
|
1487
|
+
function stripLeadingComments(query) {
|
|
1488
|
+
let remaining = query.trim();
|
|
1489
|
+
while (remaining.length > 0) {
|
|
1490
|
+
if (remaining.startsWith("--")) {
|
|
1491
|
+
const newline = remaining.indexOf("\n");
|
|
1492
|
+
remaining = newline === -1 ? "" : remaining.slice(newline + 1).trim();
|
|
1493
|
+
continue;
|
|
1494
|
+
}
|
|
1495
|
+
if (remaining.startsWith("/*")) {
|
|
1496
|
+
const end = remaining.indexOf("*/");
|
|
1497
|
+
remaining = end === -1 ? "" : remaining.slice(end + 2).trim();
|
|
1498
|
+
continue;
|
|
1499
|
+
}
|
|
1500
|
+
break;
|
|
1501
|
+
}
|
|
1502
|
+
return remaining;
|
|
1503
|
+
}
|
|
1504
|
+
function validateViewQuery(collectionName, viewQuery) {
|
|
1505
|
+
if (typeof viewQuery !== "string" || viewQuery.trim() === "") {
|
|
1506
|
+
throw new Error(
|
|
1507
|
+
`View collection "${collectionName}" requires a non-empty viewQuery. Provide the SQL SELECT statement backing the view.`
|
|
1508
|
+
);
|
|
1509
|
+
}
|
|
1510
|
+
const body = stripLeadingComments(viewQuery);
|
|
1511
|
+
if (!/^(select|with)\b/i.test(body)) {
|
|
1512
|
+
throw new Error(
|
|
1513
|
+
`View collection "${collectionName}" has an invalid viewQuery: it must start with SELECT or WITH. Received: ${body.slice(0, 40)}${body.length > 40 ? "..." : ""}`
|
|
1514
|
+
);
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1463
1517
|
function getCollectionNameFromFile(filePath) {
|
|
1464
1518
|
const filename = path5.basename(filePath).replace(/\.(ts|js)$/, "");
|
|
1465
1519
|
return toCollectionName(filename);
|
|
@@ -1483,13 +1537,26 @@ function extractCollectionTypeFromSchema(zodSchema) {
|
|
|
1483
1537
|
}
|
|
1484
1538
|
try {
|
|
1485
1539
|
const metadata = JSON.parse(zodSchema.description);
|
|
1486
|
-
if (metadata.type === "base" || metadata.type === "auth") {
|
|
1540
|
+
if (metadata.type === "base" || metadata.type === "auth" || metadata.type === "view") {
|
|
1487
1541
|
return metadata.type;
|
|
1488
1542
|
}
|
|
1489
1543
|
} catch {
|
|
1490
1544
|
}
|
|
1491
1545
|
return null;
|
|
1492
1546
|
}
|
|
1547
|
+
function extractViewQueryFromSchema(zodSchema) {
|
|
1548
|
+
if (!zodSchema.description) {
|
|
1549
|
+
return null;
|
|
1550
|
+
}
|
|
1551
|
+
try {
|
|
1552
|
+
const metadata = JSON.parse(zodSchema.description);
|
|
1553
|
+
if (typeof metadata.viewQuery === "string") {
|
|
1554
|
+
return metadata.viewQuery;
|
|
1555
|
+
}
|
|
1556
|
+
} catch {
|
|
1557
|
+
}
|
|
1558
|
+
return null;
|
|
1559
|
+
}
|
|
1493
1560
|
function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema", "Collection"]) {
|
|
1494
1561
|
const result = {};
|
|
1495
1562
|
if (module.default instanceof z.ZodObject) {
|
|
@@ -1648,6 +1715,15 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1648
1715
|
const rawFields = extractFieldDefinitions(zodSchema);
|
|
1649
1716
|
const explicitType = extractCollectionTypeFromSchema(zodSchema);
|
|
1650
1717
|
const collectionType = explicitType ?? (isAuthCollection(rawFields) ? "auth" : "base");
|
|
1718
|
+
const isView = collectionType === "view";
|
|
1719
|
+
const viewQuery = extractViewQueryFromSchema(zodSchema);
|
|
1720
|
+
if (isView) {
|
|
1721
|
+
validateViewQuery(collectionName, viewQuery);
|
|
1722
|
+
} else if (viewQuery !== null) {
|
|
1723
|
+
console.warn(
|
|
1724
|
+
`[${collectionName}] viewQuery is only used by view collections and will be ignored. Use defineView() or set type: "view" to define a view collection.`
|
|
1725
|
+
);
|
|
1726
|
+
}
|
|
1651
1727
|
const fields = rawFields.filter((f) => !["created", "updated"].includes(f.name)).map(({ name, zodType }) => buildFieldDefinition(name, zodType));
|
|
1652
1728
|
if (collectionType === "auth") {
|
|
1653
1729
|
const authSystemFields = [
|
|
@@ -1707,26 +1783,43 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1707
1783
|
}
|
|
1708
1784
|
}
|
|
1709
1785
|
const indexes = extractIndexes(zodSchema) || [];
|
|
1786
|
+
if (isView && indexes.length > 0) {
|
|
1787
|
+
throw new Error(
|
|
1788
|
+
`View collection "${collectionName}" cannot declare indexes. PocketBase view collections are backed by a SQL query and do not support indexes.`
|
|
1789
|
+
);
|
|
1790
|
+
}
|
|
1710
1791
|
const permissionAnalyzer = new PermissionAnalyzer();
|
|
1711
1792
|
let permissions = void 0;
|
|
1712
1793
|
const schemaDescription = zodSchema.description;
|
|
1713
1794
|
const extractedPermissions = permissionAnalyzer.extractPermissions(schemaDescription);
|
|
1714
1795
|
if (extractedPermissions) {
|
|
1715
1796
|
const resolvedPermissions = permissionAnalyzer.resolvePermissions(extractedPermissions);
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
1725
|
-
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
1797
|
+
if (isView) {
|
|
1798
|
+
for (const ruleType of ["createRule", "updateRule", "deleteRule", "manageRule"]) {
|
|
1799
|
+
if (resolvedPermissions[ruleType]) {
|
|
1800
|
+
console.warn(
|
|
1801
|
+
`[${collectionName}] ${ruleType} is not supported on view collections and will be set to null.`
|
|
1802
|
+
);
|
|
1803
|
+
}
|
|
1804
|
+
resolvedPermissions[ruleType] = null;
|
|
1726
1805
|
}
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1806
|
+
}
|
|
1807
|
+
if (!isView) {
|
|
1808
|
+
const validationResults = permissionAnalyzer.validatePermissions(
|
|
1809
|
+
collectionName,
|
|
1810
|
+
resolvedPermissions,
|
|
1811
|
+
fields,
|
|
1812
|
+
collectionType === "auth"
|
|
1813
|
+
);
|
|
1814
|
+
for (const [ruleType, result] of validationResults) {
|
|
1815
|
+
if (!result.valid) {
|
|
1816
|
+
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
1817
|
+
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
1818
|
+
}
|
|
1819
|
+
if (result.warnings.length > 0) {
|
|
1820
|
+
console.warn(`[${collectionName}] Permission warnings for ${ruleType}:`);
|
|
1821
|
+
result.warnings.forEach((warning) => console.warn(` - ${warning}`));
|
|
1822
|
+
}
|
|
1730
1823
|
}
|
|
1731
1824
|
}
|
|
1732
1825
|
permissions = permissionAnalyzer.mergeWithDefaults(resolvedPermissions);
|
|
@@ -1747,6 +1840,9 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1747
1840
|
},
|
|
1748
1841
|
permissions
|
|
1749
1842
|
};
|
|
1843
|
+
if (isView) {
|
|
1844
|
+
collectionSchema.viewQuery = viewQuery;
|
|
1845
|
+
}
|
|
1750
1846
|
return collectionSchema;
|
|
1751
1847
|
}
|
|
1752
1848
|
var tsxLoaderRegistered = false;
|
|
@@ -2028,8 +2124,9 @@ function convertPocketBaseField(pbField) {
|
|
|
2028
2124
|
}
|
|
2029
2125
|
function convertPocketBaseCollection(pbCollection) {
|
|
2030
2126
|
const fields = [];
|
|
2127
|
+
const isView = pbCollection.type === "view";
|
|
2031
2128
|
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
2032
|
-
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
2129
|
+
if (!isView && pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
2033
2130
|
for (const pbField of pbCollection.fields) {
|
|
2034
2131
|
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
2035
2132
|
const isAuthSystemField = pbCollection.type === "auth" && ["email", "emailVisibility", "verified", "password", "tokenKey"].includes(pbField.name);
|
|
@@ -2049,6 +2146,9 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
2049
2146
|
if (pbCollection.id) {
|
|
2050
2147
|
schema.id = pbCollection.id;
|
|
2051
2148
|
}
|
|
2149
|
+
if (typeof pbCollection.viewQuery === "string") {
|
|
2150
|
+
schema.viewQuery = dedentSql(pbCollection.viewQuery);
|
|
2151
|
+
}
|
|
2052
2152
|
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
2053
2153
|
schema.indexes = pbCollection.indexes;
|
|
2054
2154
|
}
|
|
@@ -2150,6 +2250,24 @@ function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
|
|
|
2150
2250
|
return [];
|
|
2151
2251
|
}
|
|
2152
2252
|
}
|
|
2253
|
+
function skipTemplateLiteral(content, start) {
|
|
2254
|
+
let i = start + 1;
|
|
2255
|
+
while (i < content.length) {
|
|
2256
|
+
const char = content[i];
|
|
2257
|
+
if (char === "\\") {
|
|
2258
|
+
i += 2;
|
|
2259
|
+
continue;
|
|
2260
|
+
}
|
|
2261
|
+
if (char === "`") {
|
|
2262
|
+
return i + 1;
|
|
2263
|
+
}
|
|
2264
|
+
i++;
|
|
2265
|
+
}
|
|
2266
|
+
return i;
|
|
2267
|
+
}
|
|
2268
|
+
function unescapeTemplateLiteral(raw) {
|
|
2269
|
+
return raw.replace(/\\(`|\$\{|\\)/g, "$1");
|
|
2270
|
+
}
|
|
2153
2271
|
function parseMigrationOperationsFromContent(content) {
|
|
2154
2272
|
const collectionsToCreate = [];
|
|
2155
2273
|
const collectionsToDelete = [];
|
|
@@ -2238,6 +2356,10 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
2238
2356
|
while (i < content.length && bCount > 0) {
|
|
2239
2357
|
const char = content[i];
|
|
2240
2358
|
const prev = i > 0 ? content[i - 1] : "";
|
|
2359
|
+
if (!inStr && char === "`") {
|
|
2360
|
+
i = skipTemplateLiteral(content, i);
|
|
2361
|
+
continue;
|
|
2362
|
+
}
|
|
2241
2363
|
if (!inStr && (char === '"' || char === "'")) {
|
|
2242
2364
|
inStr = true;
|
|
2243
2365
|
strChar = char;
|
|
@@ -2427,6 +2549,95 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
2427
2549
|
}
|
|
2428
2550
|
}
|
|
2429
2551
|
}
|
|
2552
|
+
const viewQueryRegex = /(\w+)\.viewQuery\s*=\s*/g;
|
|
2553
|
+
let viewQueryMatch;
|
|
2554
|
+
while ((viewQueryMatch = viewQueryRegex.exec(content)) !== null) {
|
|
2555
|
+
const varInfo = variables.get(viewQueryMatch[1]);
|
|
2556
|
+
if (!varInfo || varInfo.type !== "collection") continue;
|
|
2557
|
+
const valueStart = viewQueryMatch.index + viewQueryMatch[0].length;
|
|
2558
|
+
if (content[valueStart] === "`") {
|
|
2559
|
+
const end = skipTemplateLiteral(content, valueStart);
|
|
2560
|
+
const raw = content.substring(valueStart + 1, end - 1);
|
|
2561
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
2562
|
+
viewQueryRegex.lastIndex = end;
|
|
2563
|
+
} else {
|
|
2564
|
+
const terminator = content.indexOf(";", valueStart);
|
|
2565
|
+
const valueStr = content.substring(valueStart, terminator === -1 ? content.length : terminator);
|
|
2566
|
+
try {
|
|
2567
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(new Function("app", `return ${valueStr}`)(mockApp));
|
|
2568
|
+
} catch {
|
|
2569
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(valueStr.trim());
|
|
2570
|
+
}
|
|
2571
|
+
}
|
|
2572
|
+
}
|
|
2573
|
+
const unmarshalRegex = /unmarshal\s*\(/g;
|
|
2574
|
+
let unmarshalMatch;
|
|
2575
|
+
while ((unmarshalMatch = unmarshalRegex.exec(content)) !== null) {
|
|
2576
|
+
let i = unmarshalMatch.index + unmarshalMatch[0].length;
|
|
2577
|
+
while (i < content.length && /\s/.test(content[i])) i++;
|
|
2578
|
+
if (content[i] !== "{") continue;
|
|
2579
|
+
const objStart = i;
|
|
2580
|
+
let braceCount = 1;
|
|
2581
|
+
let inStr = false;
|
|
2582
|
+
let strChar = null;
|
|
2583
|
+
i++;
|
|
2584
|
+
while (i < content.length && braceCount > 0) {
|
|
2585
|
+
const ch = content[i];
|
|
2586
|
+
const prev = i > 0 ? content[i - 1] : "";
|
|
2587
|
+
if (!inStr && ch === "`") {
|
|
2588
|
+
i = skipTemplateLiteral(content, i);
|
|
2589
|
+
continue;
|
|
2590
|
+
}
|
|
2591
|
+
if (!inStr && (ch === '"' || ch === "'")) {
|
|
2592
|
+
inStr = true;
|
|
2593
|
+
strChar = ch;
|
|
2594
|
+
} else if (inStr && ch === strChar && prev !== "\\") {
|
|
2595
|
+
inStr = false;
|
|
2596
|
+
strChar = null;
|
|
2597
|
+
}
|
|
2598
|
+
if (!inStr) {
|
|
2599
|
+
if (ch === "{") braceCount++;
|
|
2600
|
+
if (ch === "}") braceCount--;
|
|
2601
|
+
}
|
|
2602
|
+
i++;
|
|
2603
|
+
}
|
|
2604
|
+
if (braceCount !== 0) continue;
|
|
2605
|
+
const objStr = content.substring(objStart, i);
|
|
2606
|
+
while (i < content.length && /[\s,]/.test(content[i])) i++;
|
|
2607
|
+
const varStart = i;
|
|
2608
|
+
while (i < content.length && /\w/.test(content[i])) i++;
|
|
2609
|
+
const colVarName = content.substring(varStart, i);
|
|
2610
|
+
const colInfo = variables.get(colVarName);
|
|
2611
|
+
if (!colInfo || colInfo.type !== "collection") continue;
|
|
2612
|
+
const keyValRegex = /"(\w+Rule)"\s*:\s*([^,}\n]+)/g;
|
|
2613
|
+
let kvMatch;
|
|
2614
|
+
while ((kvMatch = keyValRegex.exec(objStr)) !== null) {
|
|
2615
|
+
const ruleKey = kvMatch[1];
|
|
2616
|
+
const valStr = kvMatch[2].trim();
|
|
2617
|
+
try {
|
|
2618
|
+
const value = new Function("app", `return ${valStr}`)(mockApp);
|
|
2619
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = value;
|
|
2620
|
+
} catch {
|
|
2621
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = valStr;
|
|
2622
|
+
}
|
|
2623
|
+
}
|
|
2624
|
+
const viewQueryKey = objStr.match(/"viewQuery"\s*:\s*/);
|
|
2625
|
+
if (viewQueryKey) {
|
|
2626
|
+
const valueStart = viewQueryKey.index + viewQueryKey[0].length;
|
|
2627
|
+
if (objStr[valueStart] === "`") {
|
|
2628
|
+
const end = skipTemplateLiteral(objStr, valueStart);
|
|
2629
|
+
const raw = objStr.substring(valueStart + 1, end - 1);
|
|
2630
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
2631
|
+
} else {
|
|
2632
|
+
const valStr = objStr.substring(valueStart).replace(/[,}\s]+$/, "");
|
|
2633
|
+
try {
|
|
2634
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(new Function("app", `return ${valStr}`)(mockApp));
|
|
2635
|
+
} catch {
|
|
2636
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(valStr);
|
|
2637
|
+
}
|
|
2638
|
+
}
|
|
2639
|
+
}
|
|
2640
|
+
}
|
|
2430
2641
|
const idxPushRegex = /(\w+)\.indexes\.push\s*\(/g;
|
|
2431
2642
|
let match;
|
|
2432
2643
|
while ((match = idxPushRegex.exec(content)) !== null) {
|
|
@@ -2556,6 +2767,10 @@ function parseMigrationOperations(migrationContent) {
|
|
|
2556
2767
|
while (i < migrationContent.length && braceCount > 0) {
|
|
2557
2768
|
const char = migrationContent[i];
|
|
2558
2769
|
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
2770
|
+
if (!inString && char === "`") {
|
|
2771
|
+
i = skipTemplateLiteral(migrationContent, i);
|
|
2772
|
+
continue;
|
|
2773
|
+
}
|
|
2559
2774
|
if (!inString && (char === '"' || char === "'")) {
|
|
2560
2775
|
inString = true;
|
|
2561
2776
|
stringChar = char;
|
|
@@ -2891,6 +3106,9 @@ function applyMigrationOperations(snapshot, operations) {
|
|
|
2891
3106
|
collection.indexes = collection.indexes.filter((idx) => !update.indexesToRemove.includes(idx));
|
|
2892
3107
|
}
|
|
2893
3108
|
}
|
|
3109
|
+
if (update.viewQuery !== void 0) {
|
|
3110
|
+
collection.viewQuery = update.viewQuery;
|
|
3111
|
+
}
|
|
2894
3112
|
if (Object.keys(update.rulesToUpdate).length > 0) {
|
|
2895
3113
|
if (!collection.rules) collection.rules = {};
|
|
2896
3114
|
if (!collection.permissions) collection.permissions = {};
|
|
@@ -3510,7 +3728,45 @@ function compareCollectionFields(currentCollection, previousCollection, config,
|
|
|
3510
3728
|
fieldsToRemove = fieldsToRemove.filter((_, index) => !processedRemoveIndices.has(index));
|
|
3511
3729
|
return { fieldsToAdd, fieldsToRemove, fieldsToModify };
|
|
3512
3730
|
}
|
|
3731
|
+
function normalizeSql(query) {
|
|
3732
|
+
if (!query) {
|
|
3733
|
+
return "";
|
|
3734
|
+
}
|
|
3735
|
+
return query.split("\n").map((line) => line.trim()).join(" ").replace(/\s+/g, " ").trim();
|
|
3736
|
+
}
|
|
3737
|
+
function compareViewQuery(currentCollection, previousCollection) {
|
|
3738
|
+
const newValue = currentCollection.viewQuery;
|
|
3739
|
+
if (typeof newValue !== "string") {
|
|
3740
|
+
return void 0;
|
|
3741
|
+
}
|
|
3742
|
+
if (normalizeSql(newValue) === normalizeSql(previousCollection.viewQuery)) {
|
|
3743
|
+
return void 0;
|
|
3744
|
+
}
|
|
3745
|
+
return {
|
|
3746
|
+
oldValue: previousCollection.viewQuery ?? null,
|
|
3747
|
+
newValue
|
|
3748
|
+
};
|
|
3749
|
+
}
|
|
3513
3750
|
function buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName) {
|
|
3751
|
+
const isView = currentCollection.type === "view" || previousCollection.type === "view";
|
|
3752
|
+
if (isView) {
|
|
3753
|
+
return {
|
|
3754
|
+
collection: currentCollection.name,
|
|
3755
|
+
fieldsToAdd: [],
|
|
3756
|
+
fieldsToRemove: [],
|
|
3757
|
+
fieldsToModify: [],
|
|
3758
|
+
indexesToAdd: [],
|
|
3759
|
+
indexesToRemove: [],
|
|
3760
|
+
rulesToUpdate: compareRules(
|
|
3761
|
+
currentCollection.rules,
|
|
3762
|
+
previousCollection.rules,
|
|
3763
|
+
currentCollection.permissions,
|
|
3764
|
+
previousCollection.permissions
|
|
3765
|
+
),
|
|
3766
|
+
permissionsToUpdate: comparePermissions(currentCollection.permissions, previousCollection.permissions),
|
|
3767
|
+
viewQueryUpdate: compareViewQuery(currentCollection, previousCollection)
|
|
3768
|
+
};
|
|
3769
|
+
}
|
|
3514
3770
|
const { fieldsToAdd, fieldsToRemove, fieldsToModify } = compareCollectionFields(
|
|
3515
3771
|
currentCollection,
|
|
3516
3772
|
previousCollection,
|
|
@@ -3542,6 +3798,9 @@ function detectDestructiveChanges(diff, config) {
|
|
|
3542
3798
|
const destructiveChanges = [];
|
|
3543
3799
|
const mergedConfig = mergeConfig3(config);
|
|
3544
3800
|
for (const collection of diff.collectionsToDelete) {
|
|
3801
|
+
if (collection.type === "view") {
|
|
3802
|
+
continue;
|
|
3803
|
+
}
|
|
3545
3804
|
destructiveChanges.push({
|
|
3546
3805
|
type: "collection_delete",
|
|
3547
3806
|
severity: "high",
|
|
@@ -3629,7 +3888,11 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
3629
3888
|
const destructive = [];
|
|
3630
3889
|
const nonDestructive = [];
|
|
3631
3890
|
for (const collection of diff.collectionsToDelete) {
|
|
3632
|
-
|
|
3891
|
+
if (collection.type === "view") {
|
|
3892
|
+
nonDestructive.push(`Delete view collection: ${collection.name}`);
|
|
3893
|
+
} else {
|
|
3894
|
+
destructive.push(`Delete collection: ${collection.name}`);
|
|
3895
|
+
}
|
|
3633
3896
|
}
|
|
3634
3897
|
for (const collection of diff.collectionsToCreate) {
|
|
3635
3898
|
nonDestructive.push(`Create collection: ${collection.name}`);
|
|
@@ -3664,6 +3927,9 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
3664
3927
|
for (const rule of modification.rulesToUpdate) {
|
|
3665
3928
|
nonDestructive.push(`Update rule: ${collectionName}.${rule.ruleType}`);
|
|
3666
3929
|
}
|
|
3930
|
+
if (modification.viewQueryUpdate) {
|
|
3931
|
+
nonDestructive.push(`Update view query: ${collectionName}`);
|
|
3932
|
+
}
|
|
3667
3933
|
}
|
|
3668
3934
|
return { destructive, nonDestructive };
|
|
3669
3935
|
}
|
|
@@ -3676,6 +3942,7 @@ function generateChangeSummary(diff, config) {
|
|
|
3676
3942
|
let indexChanges = 0;
|
|
3677
3943
|
let ruleChanges = 0;
|
|
3678
3944
|
let permissionChanges = 0;
|
|
3945
|
+
let viewQueryChanges = 0;
|
|
3679
3946
|
for (const modification of diff.collectionsToModify) {
|
|
3680
3947
|
fieldsToAdd += modification.fieldsToAdd.length;
|
|
3681
3948
|
fieldsToRemove += modification.fieldsToRemove.length;
|
|
@@ -3683,6 +3950,9 @@ function generateChangeSummary(diff, config) {
|
|
|
3683
3950
|
indexChanges += modification.indexesToAdd.length + modification.indexesToRemove.length;
|
|
3684
3951
|
ruleChanges += modification.rulesToUpdate.length;
|
|
3685
3952
|
permissionChanges += modification.permissionsToUpdate.length;
|
|
3953
|
+
if (modification.viewQueryUpdate) {
|
|
3954
|
+
viewQueryChanges += 1;
|
|
3955
|
+
}
|
|
3686
3956
|
}
|
|
3687
3957
|
return {
|
|
3688
3958
|
totalChanges: diff.collectionsToCreate.length + diff.collectionsToDelete.length + diff.collectionsToModify.length,
|
|
@@ -3695,6 +3965,7 @@ function generateChangeSummary(diff, config) {
|
|
|
3695
3965
|
indexChanges,
|
|
3696
3966
|
ruleChanges,
|
|
3697
3967
|
permissionChanges,
|
|
3968
|
+
viewQueryChanges,
|
|
3698
3969
|
destructiveChanges,
|
|
3699
3970
|
nonDestructiveChanges: nonDestructive
|
|
3700
3971
|
};
|
|
@@ -3724,12 +3995,11 @@ function filterDiff(diff, options) {
|
|
|
3724
3995
|
});
|
|
3725
3996
|
let collectionsToDelete = diff.collectionsToDelete;
|
|
3726
3997
|
if (skipDestructive) {
|
|
3727
|
-
collectionsToDelete =
|
|
3728
|
-
} else {
|
|
3729
|
-
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
3730
|
-
return matchesPattern(col.name, patterns);
|
|
3731
|
-
});
|
|
3998
|
+
collectionsToDelete = collectionsToDelete.filter((col) => col.type === "view");
|
|
3732
3999
|
}
|
|
4000
|
+
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
4001
|
+
return matchesPattern(col.name, patterns);
|
|
4002
|
+
});
|
|
3733
4003
|
const collectionsToModify = diff.collectionsToModify.map((mod) => {
|
|
3734
4004
|
const collectionMatches = matchesPattern(mod.collection, patterns);
|
|
3735
4005
|
const fieldsToAdd = mod.fieldsToAdd.filter((field) => {
|
|
@@ -3754,6 +4024,7 @@ function filterDiff(diff, options) {
|
|
|
3754
4024
|
const indexesToRemove = collectionMatches ? mod.indexesToRemove : [];
|
|
3755
4025
|
const rulesToUpdate = collectionMatches ? mod.rulesToUpdate : [];
|
|
3756
4026
|
const permissionsToUpdate = collectionMatches ? mod.permissionsToUpdate : [];
|
|
4027
|
+
const viewQueryUpdate = collectionMatches ? mod.viewQueryUpdate : void 0;
|
|
3757
4028
|
return {
|
|
3758
4029
|
...mod,
|
|
3759
4030
|
fieldsToAdd,
|
|
@@ -3762,10 +4033,11 @@ function filterDiff(diff, options) {
|
|
|
3762
4033
|
indexesToAdd,
|
|
3763
4034
|
indexesToRemove,
|
|
3764
4035
|
rulesToUpdate,
|
|
3765
|
-
permissionsToUpdate
|
|
4036
|
+
permissionsToUpdate,
|
|
4037
|
+
viewQueryUpdate
|
|
3766
4038
|
};
|
|
3767
4039
|
}).filter((mod) => {
|
|
3768
|
-
return mod.fieldsToAdd.length > 0 || mod.fieldsToRemove.length > 0 || mod.fieldsToModify.length > 0 || mod.indexesToAdd.length > 0 || mod.indexesToRemove.length > 0 || mod.rulesToUpdate.length > 0 || mod.permissionsToUpdate.length > 0;
|
|
4040
|
+
return mod.fieldsToAdd.length > 0 || mod.fieldsToRemove.length > 0 || mod.fieldsToModify.length > 0 || mod.indexesToAdd.length > 0 || mod.indexesToRemove.length > 0 || mod.rulesToUpdate.length > 0 || mod.permissionsToUpdate.length > 0 || mod.viewQueryUpdate !== void 0;
|
|
3769
4041
|
});
|
|
3770
4042
|
return {
|
|
3771
4043
|
...diff,
|
|
@@ -3777,7 +4049,7 @@ function filterDiff(diff, options) {
|
|
|
3777
4049
|
|
|
3778
4050
|
// src/migration/diff/index.ts
|
|
3779
4051
|
function hasChanges(modification) {
|
|
3780
|
-
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;
|
|
4052
|
+
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 || modification.viewQueryUpdate !== void 0;
|
|
3781
4053
|
}
|
|
3782
4054
|
function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
3783
4055
|
const collectionIdToName = /* @__PURE__ */ new Map();
|
|
@@ -3992,6 +4264,13 @@ function formatValue(value) {
|
|
|
3992
4264
|
}
|
|
3993
4265
|
return String(value);
|
|
3994
4266
|
}
|
|
4267
|
+
function formatSqlTemplate(query, indent = " ") {
|
|
4268
|
+
const escaped = query.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
4269
|
+
const body = escaped.split("\n").map((line) => line.trim() === "" ? "" : `${indent}${line}`).join("\n");
|
|
4270
|
+
return `\`
|
|
4271
|
+
${body}
|
|
4272
|
+
${indent.slice(0, -2)}\``;
|
|
4273
|
+
}
|
|
3995
4274
|
function getFieldConstructorName(fieldType) {
|
|
3996
4275
|
const constructorMap = {
|
|
3997
4276
|
text: "TextField",
|
|
@@ -4030,6 +4309,36 @@ function getSystemFields() {
|
|
|
4030
4309
|
}
|
|
4031
4310
|
];
|
|
4032
4311
|
}
|
|
4312
|
+
function getSystemTimestampFields() {
|
|
4313
|
+
return [
|
|
4314
|
+
{
|
|
4315
|
+
name: "created",
|
|
4316
|
+
id: "autodate2990389176",
|
|
4317
|
+
type: "autodate",
|
|
4318
|
+
required: false,
|
|
4319
|
+
options: {
|
|
4320
|
+
hidden: false,
|
|
4321
|
+
onCreate: true,
|
|
4322
|
+
onUpdate: false,
|
|
4323
|
+
presentable: false,
|
|
4324
|
+
system: true
|
|
4325
|
+
}
|
|
4326
|
+
},
|
|
4327
|
+
{
|
|
4328
|
+
name: "updated",
|
|
4329
|
+
id: "autodate3332085495",
|
|
4330
|
+
type: "autodate",
|
|
4331
|
+
required: false,
|
|
4332
|
+
options: {
|
|
4333
|
+
hidden: false,
|
|
4334
|
+
onCreate: true,
|
|
4335
|
+
onUpdate: true,
|
|
4336
|
+
presentable: false,
|
|
4337
|
+
system: true
|
|
4338
|
+
}
|
|
4339
|
+
}
|
|
4340
|
+
];
|
|
4341
|
+
}
|
|
4033
4342
|
function getAuthSystemFields() {
|
|
4034
4343
|
return [
|
|
4035
4344
|
{
|
|
@@ -4322,6 +4631,15 @@ function generateCollectionRules(rules, collectionType = "base") {
|
|
|
4322
4631
|
if (!rules) {
|
|
4323
4632
|
return "";
|
|
4324
4633
|
}
|
|
4634
|
+
if (collectionType === "view") {
|
|
4635
|
+
return [
|
|
4636
|
+
`"listRule": ${formatValue(rules.listRule ?? null)}`,
|
|
4637
|
+
`"viewRule": ${formatValue(rules.viewRule ?? null)}`,
|
|
4638
|
+
`"createRule": null`,
|
|
4639
|
+
`"updateRule": null`,
|
|
4640
|
+
`"deleteRule": null`
|
|
4641
|
+
].join(",\n ");
|
|
4642
|
+
}
|
|
4325
4643
|
const parts = [];
|
|
4326
4644
|
if (rules.listRule !== void 0) {
|
|
4327
4645
|
parts.push(`"listRule": ${formatValue(rules.listRule)}`);
|
|
@@ -4347,6 +4665,15 @@ function generateCollectionPermissions(permissions, collectionType = "base") {
|
|
|
4347
4665
|
if (!permissions) {
|
|
4348
4666
|
return "";
|
|
4349
4667
|
}
|
|
4668
|
+
if (collectionType === "view") {
|
|
4669
|
+
return [
|
|
4670
|
+
`"listRule": ${formatValue(permissions.listRule ?? null)}`,
|
|
4671
|
+
`"viewRule": ${formatValue(permissions.viewRule ?? null)}`,
|
|
4672
|
+
`"createRule": null`,
|
|
4673
|
+
`"updateRule": null`,
|
|
4674
|
+
`"deleteRule": null`
|
|
4675
|
+
].join(",\n ");
|
|
4676
|
+
}
|
|
4350
4677
|
const parts = [];
|
|
4351
4678
|
if (permissions.listRule !== void 0) {
|
|
4352
4679
|
parts.push(`"listRule": ${formatValue(permissions.listRule)}`);
|
|
@@ -4384,6 +4711,28 @@ function generatePermissionUpdate(collectionName, ruleType, newValue, varName, i
|
|
|
4384
4711
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
4385
4712
|
return lines.join("\n");
|
|
4386
4713
|
}
|
|
4714
|
+
function generateViewQueryUpdate(collectionName, viewQuery, varName, isLast = false, collectionIdMap) {
|
|
4715
|
+
const lines = [];
|
|
4716
|
+
const collectionVar = varName || `collection_${collectionName}_viewQuery`;
|
|
4717
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
4718
|
+
lines.push(` unmarshal({`);
|
|
4719
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(viewQuery, " ")},`);
|
|
4720
|
+
lines.push(` }, ${collectionVar})`);
|
|
4721
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
4722
|
+
return lines.join("\n");
|
|
4723
|
+
}
|
|
4724
|
+
function generateGroupedRuleUpdates(collectionName, entries, varSuffix, isLast = false, collectionIdMap) {
|
|
4725
|
+
const collectionVar = `collection_${collectionName}_${varSuffix}`;
|
|
4726
|
+
const lines = [];
|
|
4727
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
4728
|
+
lines.push(` unmarshal({`);
|
|
4729
|
+
for (const entry of entries) {
|
|
4730
|
+
lines.push(` "${entry.ruleType}": ${formatValue(entry.value)},`);
|
|
4731
|
+
}
|
|
4732
|
+
lines.push(` }, ${collectionVar})`);
|
|
4733
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
4734
|
+
return lines.join("\n");
|
|
4735
|
+
}
|
|
4387
4736
|
|
|
4388
4737
|
// src/migration/generator/collections.ts
|
|
4389
4738
|
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
@@ -4402,16 +4751,24 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
|
|
|
4402
4751
|
} else if (rulesCode) {
|
|
4403
4752
|
lines.push(` ${rulesCode},`);
|
|
4404
4753
|
}
|
|
4754
|
+
if (collection.type === "view") {
|
|
4755
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(collection.viewQuery ?? "")},`);
|
|
4756
|
+
lines.push(` });`);
|
|
4757
|
+
lines.push(``);
|
|
4758
|
+
lines.push(isLast ? ` return app.save(${varName});` : ` app.save(${varName});`);
|
|
4759
|
+
return lines.join("\n");
|
|
4760
|
+
}
|
|
4405
4761
|
const systemFieldNames = ["created", "updated", "id"];
|
|
4406
4762
|
if (collection.type === "auth") {
|
|
4407
4763
|
systemFieldNames.push(...getAuthSystemFields().map((f) => f.name));
|
|
4408
4764
|
}
|
|
4409
4765
|
const userFields = collection.fields.filter((f) => !systemFieldNames.includes(f.name));
|
|
4410
|
-
const allFields = [...getSystemFields()
|
|
4766
|
+
const allFields = [...getSystemFields()];
|
|
4411
4767
|
if (collection.type === "auth") {
|
|
4412
4768
|
allFields.push(...getAuthSystemFields());
|
|
4413
4769
|
}
|
|
4414
4770
|
allFields.push(...userFields);
|
|
4771
|
+
allFields.push(...getSystemTimestampFields());
|
|
4415
4772
|
lines.push(` "fields": ${generateFieldsArray(allFields, collectionIdMap)},`);
|
|
4416
4773
|
let allIndexes = [...collection.indexes || []];
|
|
4417
4774
|
if (collection.type === "auth") {
|
|
@@ -4441,7 +4798,21 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
4441
4798
|
const modification = operation.modifications;
|
|
4442
4799
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
4443
4800
|
let operationCount = 0;
|
|
4444
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
4801
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + (modification.viewQueryUpdate ? 1 : 0) + (modification.permissionsToUpdate.length > 0 ? 1 : modification.rulesToUpdate.length > 0 ? 1 : 0);
|
|
4802
|
+
if (modification.viewQueryUpdate) {
|
|
4803
|
+
operationCount++;
|
|
4804
|
+
const isLast = operationCount === totalOperations;
|
|
4805
|
+
lines.push(
|
|
4806
|
+
generateViewQueryUpdate(
|
|
4807
|
+
collectionName,
|
|
4808
|
+
modification.viewQueryUpdate.newValue,
|
|
4809
|
+
void 0,
|
|
4810
|
+
isLast,
|
|
4811
|
+
collectionIdMap
|
|
4812
|
+
)
|
|
4813
|
+
);
|
|
4814
|
+
if (!isLast) lines.push("");
|
|
4815
|
+
}
|
|
4445
4816
|
for (let i = 0; i < modification.fieldsToAdd.length; i++) {
|
|
4446
4817
|
const field = modification.fieldsToAdd[i];
|
|
4447
4818
|
operationCount++;
|
|
@@ -4481,23 +4852,29 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
4481
4852
|
if (!isLast) lines.push("");
|
|
4482
4853
|
}
|
|
4483
4854
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
4484
|
-
|
|
4485
|
-
|
|
4855
|
+
operationCount++;
|
|
4856
|
+
const isLast = operationCount === totalOperations;
|
|
4857
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
4858
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.newValue }));
|
|
4859
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
4860
|
+
} else {
|
|
4861
|
+
const permission = modification.permissionsToUpdate[0];
|
|
4486
4862
|
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
4487
|
-
|
|
4488
|
-
lines.push(
|
|
4489
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap)
|
|
4490
|
-
);
|
|
4491
|
-
if (!isLast) lines.push("");
|
|
4863
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap));
|
|
4492
4864
|
}
|
|
4865
|
+
if (!isLast) lines.push("");
|
|
4493
4866
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
4494
|
-
|
|
4495
|
-
|
|
4867
|
+
operationCount++;
|
|
4868
|
+
const isLast = operationCount === totalOperations;
|
|
4869
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
4870
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.newValue }));
|
|
4871
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
4872
|
+
} else {
|
|
4873
|
+
const rule = modification.rulesToUpdate[0];
|
|
4496
4874
|
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
4497
|
-
const isLast = operationCount === totalOperations;
|
|
4498
4875
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast, collectionIdMap));
|
|
4499
|
-
if (!isLast) lines.push("");
|
|
4500
4876
|
}
|
|
4877
|
+
if (!isLast) lines.push("");
|
|
4501
4878
|
}
|
|
4502
4879
|
} else if (operation.type === "delete") {
|
|
4503
4880
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
|
|
@@ -4536,25 +4913,45 @@ function generateOperationDownMigration(operation, collectionIdMap) {
|
|
|
4536
4913
|
const modification = operation.modifications;
|
|
4537
4914
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
4538
4915
|
let operationCount = 0;
|
|
4539
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
4916
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + (modification.viewQueryUpdate ? 1 : 0) + (modification.permissionsToUpdate.length > 0 ? 1 : modification.rulesToUpdate.length > 0 ? 1 : 0);
|
|
4917
|
+
if (modification.viewQueryUpdate) {
|
|
4918
|
+
operationCount++;
|
|
4919
|
+
const isLast = operationCount === totalOperations;
|
|
4920
|
+
lines.push(
|
|
4921
|
+
generateViewQueryUpdate(
|
|
4922
|
+
collectionName,
|
|
4923
|
+
modification.viewQueryUpdate.oldValue ?? "",
|
|
4924
|
+
`collection_${collectionName}_revert_viewQuery`,
|
|
4925
|
+
isLast,
|
|
4926
|
+
collectionIdMap
|
|
4927
|
+
)
|
|
4928
|
+
);
|
|
4929
|
+
if (!isLast) lines.push("");
|
|
4930
|
+
}
|
|
4540
4931
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
4541
|
-
|
|
4542
|
-
|
|
4932
|
+
operationCount++;
|
|
4933
|
+
const isLast = operationCount === totalOperations;
|
|
4934
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
4935
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.oldValue }));
|
|
4936
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
4937
|
+
} else {
|
|
4938
|
+
const permission = modification.permissionsToUpdate[0];
|
|
4543
4939
|
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
4544
|
-
|
|
4545
|
-
lines.push(
|
|
4546
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap)
|
|
4547
|
-
);
|
|
4548
|
-
if (!isLast) lines.push("");
|
|
4940
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap));
|
|
4549
4941
|
}
|
|
4942
|
+
if (!isLast) lines.push("");
|
|
4550
4943
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
4551
|
-
|
|
4552
|
-
|
|
4944
|
+
operationCount++;
|
|
4945
|
+
const isLast = operationCount === totalOperations;
|
|
4946
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
4947
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.oldValue }));
|
|
4948
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
4949
|
+
} else {
|
|
4950
|
+
const rule = modification.rulesToUpdate[0];
|
|
4553
4951
|
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
4554
|
-
const isLast = operationCount === totalOperations;
|
|
4555
4952
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast, collectionIdMap));
|
|
4556
|
-
if (!isLast) lines.push("");
|
|
4557
4953
|
}
|
|
4954
|
+
if (!isLast) lines.push("");
|
|
4558
4955
|
}
|
|
4559
4956
|
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
4560
4957
|
operationCount++;
|
|
@@ -4661,6 +5058,19 @@ function generateUpMigration(diff) {
|
|
|
4661
5058
|
lines.push(` // Modify existing collections`);
|
|
4662
5059
|
for (const modification of diff.collectionsToModify) {
|
|
4663
5060
|
const collectionName = modification.collection;
|
|
5061
|
+
if (modification.viewQueryUpdate) {
|
|
5062
|
+
lines.push(` // Update the view query of ${collectionName}`);
|
|
5063
|
+
lines.push(
|
|
5064
|
+
generateViewQueryUpdate(
|
|
5065
|
+
collectionName,
|
|
5066
|
+
modification.viewQueryUpdate.newValue,
|
|
5067
|
+
void 0,
|
|
5068
|
+
false,
|
|
5069
|
+
collectionIdMap
|
|
5070
|
+
)
|
|
5071
|
+
);
|
|
5072
|
+
lines.push(``);
|
|
5073
|
+
}
|
|
4664
5074
|
if (modification.fieldsToAdd.length > 0) {
|
|
4665
5075
|
lines.push(` // Add fields to ${collectionName}`);
|
|
4666
5076
|
for (let i = 0; i < modification.fieldsToAdd.length; i++) {
|
|
@@ -4706,20 +5116,26 @@ function generateUpMigration(diff) {
|
|
|
4706
5116
|
}
|
|
4707
5117
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
4708
5118
|
lines.push(` // Update permissions for ${collectionName}`);
|
|
4709
|
-
|
|
5119
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
5120
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.newValue }));
|
|
5121
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", false, collectionIdMap));
|
|
5122
|
+
} else {
|
|
5123
|
+
const permission = modification.permissionsToUpdate[0];
|
|
4710
5124
|
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
4711
|
-
lines.push(
|
|
4712
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, false, collectionIdMap)
|
|
4713
|
-
);
|
|
4714
|
-
lines.push(``);
|
|
5125
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, false, collectionIdMap));
|
|
4715
5126
|
}
|
|
5127
|
+
lines.push(``);
|
|
4716
5128
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
4717
5129
|
lines.push(` // Update rules for ${collectionName}`);
|
|
4718
|
-
|
|
5130
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
5131
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.newValue }));
|
|
5132
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", false, collectionIdMap));
|
|
5133
|
+
} else {
|
|
5134
|
+
const rule = modification.rulesToUpdate[0];
|
|
4719
5135
|
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
4720
5136
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, false, collectionIdMap));
|
|
4721
|
-
lines.push(``);
|
|
4722
5137
|
}
|
|
5138
|
+
lines.push(``);
|
|
4723
5139
|
}
|
|
4724
5140
|
}
|
|
4725
5141
|
}
|
|
@@ -4791,22 +5207,41 @@ function generateDownMigration(diff) {
|
|
|
4791
5207
|
lines.push(` // Revert modifications`);
|
|
4792
5208
|
for (const modification of diff.collectionsToModify) {
|
|
4793
5209
|
const collectionName = modification.collection;
|
|
5210
|
+
if (modification.viewQueryUpdate) {
|
|
5211
|
+
lines.push(` // Restore the view query of ${collectionName}`);
|
|
5212
|
+
lines.push(
|
|
5213
|
+
generateViewQueryUpdate(
|
|
5214
|
+
collectionName,
|
|
5215
|
+
modification.viewQueryUpdate.oldValue ?? "",
|
|
5216
|
+
`collection_${collectionName}_revert_viewQuery`,
|
|
5217
|
+
false,
|
|
5218
|
+
collectionIdMap
|
|
5219
|
+
)
|
|
5220
|
+
);
|
|
5221
|
+
lines.push(``);
|
|
5222
|
+
}
|
|
4794
5223
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
4795
5224
|
lines.push(` // Revert permissions for ${collectionName}`);
|
|
4796
|
-
|
|
5225
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
5226
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.oldValue }));
|
|
5227
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", false, collectionIdMap));
|
|
5228
|
+
} else {
|
|
5229
|
+
const permission = modification.permissionsToUpdate[0];
|
|
4797
5230
|
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
4798
|
-
lines.push(
|
|
4799
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, false, collectionIdMap)
|
|
4800
|
-
);
|
|
4801
|
-
lines.push(``);
|
|
5231
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, false, collectionIdMap));
|
|
4802
5232
|
}
|
|
5233
|
+
lines.push(``);
|
|
4803
5234
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
4804
5235
|
lines.push(` // Revert rules for ${collectionName}`);
|
|
4805
|
-
|
|
5236
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
5237
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.oldValue }));
|
|
5238
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", false, collectionIdMap));
|
|
5239
|
+
} else {
|
|
5240
|
+
const rule = modification.rulesToUpdate[0];
|
|
4806
5241
|
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
4807
5242
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, false, collectionIdMap));
|
|
4808
|
-
lines.push(``);
|
|
4809
5243
|
}
|
|
5244
|
+
lines.push(``);
|
|
4810
5245
|
}
|
|
4811
5246
|
if (modification.indexesToRemove.length > 0) {
|
|
4812
5247
|
lines.push(` // Restore indexes to ${collectionName}`);
|
|
@@ -5136,6 +5571,9 @@ var MigrationGenerator = class {
|
|
|
5136
5571
|
function detectCollectionDeletions(diff) {
|
|
5137
5572
|
const changes = [];
|
|
5138
5573
|
for (const collection of diff.collectionsToDelete) {
|
|
5574
|
+
if (collection.type === "view") {
|
|
5575
|
+
continue;
|
|
5576
|
+
}
|
|
5139
5577
|
changes.push({
|
|
5140
5578
|
type: "collection_deletion" /* COLLECTION_DELETION */,
|
|
5141
5579
|
description: `Delete collection: ${collection.name}`,
|