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.cjs
CHANGED
|
@@ -1483,6 +1483,60 @@ function getFieldTypeInfo(zodType, fieldName) {
|
|
|
1483
1483
|
options
|
|
1484
1484
|
};
|
|
1485
1485
|
}
|
|
1486
|
+
function dedentSql(value) {
|
|
1487
|
+
const lines = value.replace(/\r\n/g, "\n").split("\n");
|
|
1488
|
+
while (lines.length > 0 && lines[0].trim() === "") {
|
|
1489
|
+
lines.shift();
|
|
1490
|
+
}
|
|
1491
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
|
|
1492
|
+
lines.pop();
|
|
1493
|
+
}
|
|
1494
|
+
if (lines.length === 0) {
|
|
1495
|
+
return "";
|
|
1496
|
+
}
|
|
1497
|
+
let minIndent = Infinity;
|
|
1498
|
+
for (const line of lines) {
|
|
1499
|
+
if (line.trim() === "") continue;
|
|
1500
|
+
const indent = line.length - line.trimStart().length;
|
|
1501
|
+
if (indent < minIndent) {
|
|
1502
|
+
minIndent = indent;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
if (!Number.isFinite(minIndent) || minIndent === 0) {
|
|
1506
|
+
return lines.map((line) => line.trimEnd()).join("\n");
|
|
1507
|
+
}
|
|
1508
|
+
return lines.map((line) => line.slice(minIndent).trimEnd()).join("\n");
|
|
1509
|
+
}
|
|
1510
|
+
function stripLeadingComments(query) {
|
|
1511
|
+
let remaining = query.trim();
|
|
1512
|
+
while (remaining.length > 0) {
|
|
1513
|
+
if (remaining.startsWith("--")) {
|
|
1514
|
+
const newline = remaining.indexOf("\n");
|
|
1515
|
+
remaining = newline === -1 ? "" : remaining.slice(newline + 1).trim();
|
|
1516
|
+
continue;
|
|
1517
|
+
}
|
|
1518
|
+
if (remaining.startsWith("/*")) {
|
|
1519
|
+
const end = remaining.indexOf("*/");
|
|
1520
|
+
remaining = end === -1 ? "" : remaining.slice(end + 2).trim();
|
|
1521
|
+
continue;
|
|
1522
|
+
}
|
|
1523
|
+
break;
|
|
1524
|
+
}
|
|
1525
|
+
return remaining;
|
|
1526
|
+
}
|
|
1527
|
+
function validateViewQuery(collectionName, viewQuery) {
|
|
1528
|
+
if (typeof viewQuery !== "string" || viewQuery.trim() === "") {
|
|
1529
|
+
throw new Error(
|
|
1530
|
+
`View collection "${collectionName}" requires a non-empty viewQuery. Provide the SQL SELECT statement backing the view.`
|
|
1531
|
+
);
|
|
1532
|
+
}
|
|
1533
|
+
const body = stripLeadingComments(viewQuery);
|
|
1534
|
+
if (!/^(select|with)\b/i.test(body)) {
|
|
1535
|
+
throw new Error(
|
|
1536
|
+
`View collection "${collectionName}" has an invalid viewQuery: it must start with SELECT or WITH. Received: ${body.slice(0, 40)}${body.length > 40 ? "..." : ""}`
|
|
1537
|
+
);
|
|
1538
|
+
}
|
|
1539
|
+
}
|
|
1486
1540
|
function getCollectionNameFromFile(filePath) {
|
|
1487
1541
|
const filename = path5__namespace.basename(filePath).replace(/\.(ts|js)$/, "");
|
|
1488
1542
|
return toCollectionName(filename);
|
|
@@ -1506,13 +1560,26 @@ function extractCollectionTypeFromSchema(zodSchema) {
|
|
|
1506
1560
|
}
|
|
1507
1561
|
try {
|
|
1508
1562
|
const metadata = JSON.parse(zodSchema.description);
|
|
1509
|
-
if (metadata.type === "base" || metadata.type === "auth") {
|
|
1563
|
+
if (metadata.type === "base" || metadata.type === "auth" || metadata.type === "view") {
|
|
1510
1564
|
return metadata.type;
|
|
1511
1565
|
}
|
|
1512
1566
|
} catch {
|
|
1513
1567
|
}
|
|
1514
1568
|
return null;
|
|
1515
1569
|
}
|
|
1570
|
+
function extractViewQueryFromSchema(zodSchema) {
|
|
1571
|
+
if (!zodSchema.description) {
|
|
1572
|
+
return null;
|
|
1573
|
+
}
|
|
1574
|
+
try {
|
|
1575
|
+
const metadata = JSON.parse(zodSchema.description);
|
|
1576
|
+
if (typeof metadata.viewQuery === "string") {
|
|
1577
|
+
return metadata.viewQuery;
|
|
1578
|
+
}
|
|
1579
|
+
} catch {
|
|
1580
|
+
}
|
|
1581
|
+
return null;
|
|
1582
|
+
}
|
|
1516
1583
|
function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema", "Collection"]) {
|
|
1517
1584
|
const result = {};
|
|
1518
1585
|
if (module.default instanceof zod.z.ZodObject) {
|
|
@@ -1671,6 +1738,15 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1671
1738
|
const rawFields = extractFieldDefinitions(zodSchema);
|
|
1672
1739
|
const explicitType = extractCollectionTypeFromSchema(zodSchema);
|
|
1673
1740
|
const collectionType = explicitType ?? (isAuthCollection(rawFields) ? "auth" : "base");
|
|
1741
|
+
const isView = collectionType === "view";
|
|
1742
|
+
const viewQuery = extractViewQueryFromSchema(zodSchema);
|
|
1743
|
+
if (isView) {
|
|
1744
|
+
validateViewQuery(collectionName, viewQuery);
|
|
1745
|
+
} else if (viewQuery !== null) {
|
|
1746
|
+
console.warn(
|
|
1747
|
+
`[${collectionName}] viewQuery is only used by view collections and will be ignored. Use defineView() or set type: "view" to define a view collection.`
|
|
1748
|
+
);
|
|
1749
|
+
}
|
|
1674
1750
|
const fields = rawFields.filter((f) => !["created", "updated"].includes(f.name)).map(({ name, zodType }) => buildFieldDefinition(name, zodType));
|
|
1675
1751
|
if (collectionType === "auth") {
|
|
1676
1752
|
const authSystemFields = [
|
|
@@ -1730,26 +1806,43 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1730
1806
|
}
|
|
1731
1807
|
}
|
|
1732
1808
|
const indexes = extractIndexes(zodSchema) || [];
|
|
1809
|
+
if (isView && indexes.length > 0) {
|
|
1810
|
+
throw new Error(
|
|
1811
|
+
`View collection "${collectionName}" cannot declare indexes. PocketBase view collections are backed by a SQL query and do not support indexes.`
|
|
1812
|
+
);
|
|
1813
|
+
}
|
|
1733
1814
|
const permissionAnalyzer = new PermissionAnalyzer();
|
|
1734
1815
|
let permissions = void 0;
|
|
1735
1816
|
const schemaDescription = zodSchema.description;
|
|
1736
1817
|
const extractedPermissions = permissionAnalyzer.extractPermissions(schemaDescription);
|
|
1737
1818
|
if (extractedPermissions) {
|
|
1738
1819
|
const resolvedPermissions = permissionAnalyzer.resolvePermissions(extractedPermissions);
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
1748
|
-
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
1820
|
+
if (isView) {
|
|
1821
|
+
for (const ruleType of ["createRule", "updateRule", "deleteRule", "manageRule"]) {
|
|
1822
|
+
if (resolvedPermissions[ruleType]) {
|
|
1823
|
+
console.warn(
|
|
1824
|
+
`[${collectionName}] ${ruleType} is not supported on view collections and will be set to null.`
|
|
1825
|
+
);
|
|
1826
|
+
}
|
|
1827
|
+
resolvedPermissions[ruleType] = null;
|
|
1749
1828
|
}
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1829
|
+
}
|
|
1830
|
+
if (!isView) {
|
|
1831
|
+
const validationResults = permissionAnalyzer.validatePermissions(
|
|
1832
|
+
collectionName,
|
|
1833
|
+
resolvedPermissions,
|
|
1834
|
+
fields,
|
|
1835
|
+
collectionType === "auth"
|
|
1836
|
+
);
|
|
1837
|
+
for (const [ruleType, result] of validationResults) {
|
|
1838
|
+
if (!result.valid) {
|
|
1839
|
+
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
1840
|
+
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
1841
|
+
}
|
|
1842
|
+
if (result.warnings.length > 0) {
|
|
1843
|
+
console.warn(`[${collectionName}] Permission warnings for ${ruleType}:`);
|
|
1844
|
+
result.warnings.forEach((warning) => console.warn(` - ${warning}`));
|
|
1845
|
+
}
|
|
1753
1846
|
}
|
|
1754
1847
|
}
|
|
1755
1848
|
permissions = permissionAnalyzer.mergeWithDefaults(resolvedPermissions);
|
|
@@ -1770,6 +1863,9 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1770
1863
|
},
|
|
1771
1864
|
permissions
|
|
1772
1865
|
};
|
|
1866
|
+
if (isView) {
|
|
1867
|
+
collectionSchema.viewQuery = viewQuery;
|
|
1868
|
+
}
|
|
1773
1869
|
return collectionSchema;
|
|
1774
1870
|
}
|
|
1775
1871
|
var tsxLoaderRegistered = false;
|
|
@@ -2051,8 +2147,9 @@ function convertPocketBaseField(pbField) {
|
|
|
2051
2147
|
}
|
|
2052
2148
|
function convertPocketBaseCollection(pbCollection) {
|
|
2053
2149
|
const fields = [];
|
|
2150
|
+
const isView = pbCollection.type === "view";
|
|
2054
2151
|
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
2055
|
-
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
2152
|
+
if (!isView && pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
2056
2153
|
for (const pbField of pbCollection.fields) {
|
|
2057
2154
|
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
2058
2155
|
const isAuthSystemField = pbCollection.type === "auth" && ["email", "emailVisibility", "verified", "password", "tokenKey"].includes(pbField.name);
|
|
@@ -2072,6 +2169,9 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
2072
2169
|
if (pbCollection.id) {
|
|
2073
2170
|
schema.id = pbCollection.id;
|
|
2074
2171
|
}
|
|
2172
|
+
if (typeof pbCollection.viewQuery === "string") {
|
|
2173
|
+
schema.viewQuery = dedentSql(pbCollection.viewQuery);
|
|
2174
|
+
}
|
|
2075
2175
|
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
2076
2176
|
schema.indexes = pbCollection.indexes;
|
|
2077
2177
|
}
|
|
@@ -2173,6 +2273,24 @@ function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
|
|
|
2173
2273
|
return [];
|
|
2174
2274
|
}
|
|
2175
2275
|
}
|
|
2276
|
+
function skipTemplateLiteral(content, start) {
|
|
2277
|
+
let i = start + 1;
|
|
2278
|
+
while (i < content.length) {
|
|
2279
|
+
const char = content[i];
|
|
2280
|
+
if (char === "\\") {
|
|
2281
|
+
i += 2;
|
|
2282
|
+
continue;
|
|
2283
|
+
}
|
|
2284
|
+
if (char === "`") {
|
|
2285
|
+
return i + 1;
|
|
2286
|
+
}
|
|
2287
|
+
i++;
|
|
2288
|
+
}
|
|
2289
|
+
return i;
|
|
2290
|
+
}
|
|
2291
|
+
function unescapeTemplateLiteral(raw) {
|
|
2292
|
+
return raw.replace(/\\(`|\$\{|\\)/g, "$1");
|
|
2293
|
+
}
|
|
2176
2294
|
function parseMigrationOperationsFromContent(content) {
|
|
2177
2295
|
const collectionsToCreate = [];
|
|
2178
2296
|
const collectionsToDelete = [];
|
|
@@ -2261,6 +2379,10 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
2261
2379
|
while (i < content.length && bCount > 0) {
|
|
2262
2380
|
const char = content[i];
|
|
2263
2381
|
const prev = i > 0 ? content[i - 1] : "";
|
|
2382
|
+
if (!inStr && char === "`") {
|
|
2383
|
+
i = skipTemplateLiteral(content, i);
|
|
2384
|
+
continue;
|
|
2385
|
+
}
|
|
2264
2386
|
if (!inStr && (char === '"' || char === "'")) {
|
|
2265
2387
|
inStr = true;
|
|
2266
2388
|
strChar = char;
|
|
@@ -2450,6 +2572,95 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
2450
2572
|
}
|
|
2451
2573
|
}
|
|
2452
2574
|
}
|
|
2575
|
+
const viewQueryRegex = /(\w+)\.viewQuery\s*=\s*/g;
|
|
2576
|
+
let viewQueryMatch;
|
|
2577
|
+
while ((viewQueryMatch = viewQueryRegex.exec(content)) !== null) {
|
|
2578
|
+
const varInfo = variables.get(viewQueryMatch[1]);
|
|
2579
|
+
if (!varInfo || varInfo.type !== "collection") continue;
|
|
2580
|
+
const valueStart = viewQueryMatch.index + viewQueryMatch[0].length;
|
|
2581
|
+
if (content[valueStart] === "`") {
|
|
2582
|
+
const end = skipTemplateLiteral(content, valueStart);
|
|
2583
|
+
const raw = content.substring(valueStart + 1, end - 1);
|
|
2584
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
2585
|
+
viewQueryRegex.lastIndex = end;
|
|
2586
|
+
} else {
|
|
2587
|
+
const terminator = content.indexOf(";", valueStart);
|
|
2588
|
+
const valueStr = content.substring(valueStart, terminator === -1 ? content.length : terminator);
|
|
2589
|
+
try {
|
|
2590
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(new Function("app", `return ${valueStr}`)(mockApp));
|
|
2591
|
+
} catch {
|
|
2592
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(valueStr.trim());
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
}
|
|
2596
|
+
const unmarshalRegex = /unmarshal\s*\(/g;
|
|
2597
|
+
let unmarshalMatch;
|
|
2598
|
+
while ((unmarshalMatch = unmarshalRegex.exec(content)) !== null) {
|
|
2599
|
+
let i = unmarshalMatch.index + unmarshalMatch[0].length;
|
|
2600
|
+
while (i < content.length && /\s/.test(content[i])) i++;
|
|
2601
|
+
if (content[i] !== "{") continue;
|
|
2602
|
+
const objStart = i;
|
|
2603
|
+
let braceCount = 1;
|
|
2604
|
+
let inStr = false;
|
|
2605
|
+
let strChar = null;
|
|
2606
|
+
i++;
|
|
2607
|
+
while (i < content.length && braceCount > 0) {
|
|
2608
|
+
const ch = content[i];
|
|
2609
|
+
const prev = i > 0 ? content[i - 1] : "";
|
|
2610
|
+
if (!inStr && ch === "`") {
|
|
2611
|
+
i = skipTemplateLiteral(content, i);
|
|
2612
|
+
continue;
|
|
2613
|
+
}
|
|
2614
|
+
if (!inStr && (ch === '"' || ch === "'")) {
|
|
2615
|
+
inStr = true;
|
|
2616
|
+
strChar = ch;
|
|
2617
|
+
} else if (inStr && ch === strChar && prev !== "\\") {
|
|
2618
|
+
inStr = false;
|
|
2619
|
+
strChar = null;
|
|
2620
|
+
}
|
|
2621
|
+
if (!inStr) {
|
|
2622
|
+
if (ch === "{") braceCount++;
|
|
2623
|
+
if (ch === "}") braceCount--;
|
|
2624
|
+
}
|
|
2625
|
+
i++;
|
|
2626
|
+
}
|
|
2627
|
+
if (braceCount !== 0) continue;
|
|
2628
|
+
const objStr = content.substring(objStart, i);
|
|
2629
|
+
while (i < content.length && /[\s,]/.test(content[i])) i++;
|
|
2630
|
+
const varStart = i;
|
|
2631
|
+
while (i < content.length && /\w/.test(content[i])) i++;
|
|
2632
|
+
const colVarName = content.substring(varStart, i);
|
|
2633
|
+
const colInfo = variables.get(colVarName);
|
|
2634
|
+
if (!colInfo || colInfo.type !== "collection") continue;
|
|
2635
|
+
const keyValRegex = /"(\w+Rule)"\s*:\s*([^,}\n]+)/g;
|
|
2636
|
+
let kvMatch;
|
|
2637
|
+
while ((kvMatch = keyValRegex.exec(objStr)) !== null) {
|
|
2638
|
+
const ruleKey = kvMatch[1];
|
|
2639
|
+
const valStr = kvMatch[2].trim();
|
|
2640
|
+
try {
|
|
2641
|
+
const value = new Function("app", `return ${valStr}`)(mockApp);
|
|
2642
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = value;
|
|
2643
|
+
} catch {
|
|
2644
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = valStr;
|
|
2645
|
+
}
|
|
2646
|
+
}
|
|
2647
|
+
const viewQueryKey = objStr.match(/"viewQuery"\s*:\s*/);
|
|
2648
|
+
if (viewQueryKey) {
|
|
2649
|
+
const valueStart = viewQueryKey.index + viewQueryKey[0].length;
|
|
2650
|
+
if (objStr[valueStart] === "`") {
|
|
2651
|
+
const end = skipTemplateLiteral(objStr, valueStart);
|
|
2652
|
+
const raw = objStr.substring(valueStart + 1, end - 1);
|
|
2653
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
2654
|
+
} else {
|
|
2655
|
+
const valStr = objStr.substring(valueStart).replace(/[,}\s]+$/, "");
|
|
2656
|
+
try {
|
|
2657
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(new Function("app", `return ${valStr}`)(mockApp));
|
|
2658
|
+
} catch {
|
|
2659
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(valStr);
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
}
|
|
2663
|
+
}
|
|
2453
2664
|
const idxPushRegex = /(\w+)\.indexes\.push\s*\(/g;
|
|
2454
2665
|
let match;
|
|
2455
2666
|
while ((match = idxPushRegex.exec(content)) !== null) {
|
|
@@ -2579,6 +2790,10 @@ function parseMigrationOperations(migrationContent) {
|
|
|
2579
2790
|
while (i < migrationContent.length && braceCount > 0) {
|
|
2580
2791
|
const char = migrationContent[i];
|
|
2581
2792
|
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
2793
|
+
if (!inString && char === "`") {
|
|
2794
|
+
i = skipTemplateLiteral(migrationContent, i);
|
|
2795
|
+
continue;
|
|
2796
|
+
}
|
|
2582
2797
|
if (!inString && (char === '"' || char === "'")) {
|
|
2583
2798
|
inString = true;
|
|
2584
2799
|
stringChar = char;
|
|
@@ -2914,6 +3129,9 @@ function applyMigrationOperations(snapshot, operations) {
|
|
|
2914
3129
|
collection.indexes = collection.indexes.filter((idx) => !update.indexesToRemove.includes(idx));
|
|
2915
3130
|
}
|
|
2916
3131
|
}
|
|
3132
|
+
if (update.viewQuery !== void 0) {
|
|
3133
|
+
collection.viewQuery = update.viewQuery;
|
|
3134
|
+
}
|
|
2917
3135
|
if (Object.keys(update.rulesToUpdate).length > 0) {
|
|
2918
3136
|
if (!collection.rules) collection.rules = {};
|
|
2919
3137
|
if (!collection.permissions) collection.permissions = {};
|
|
@@ -3533,7 +3751,45 @@ function compareCollectionFields(currentCollection, previousCollection, config,
|
|
|
3533
3751
|
fieldsToRemove = fieldsToRemove.filter((_, index) => !processedRemoveIndices.has(index));
|
|
3534
3752
|
return { fieldsToAdd, fieldsToRemove, fieldsToModify };
|
|
3535
3753
|
}
|
|
3754
|
+
function normalizeSql(query) {
|
|
3755
|
+
if (!query) {
|
|
3756
|
+
return "";
|
|
3757
|
+
}
|
|
3758
|
+
return query.split("\n").map((line) => line.trim()).join(" ").replace(/\s+/g, " ").trim();
|
|
3759
|
+
}
|
|
3760
|
+
function compareViewQuery(currentCollection, previousCollection) {
|
|
3761
|
+
const newValue = currentCollection.viewQuery;
|
|
3762
|
+
if (typeof newValue !== "string") {
|
|
3763
|
+
return void 0;
|
|
3764
|
+
}
|
|
3765
|
+
if (normalizeSql(newValue) === normalizeSql(previousCollection.viewQuery)) {
|
|
3766
|
+
return void 0;
|
|
3767
|
+
}
|
|
3768
|
+
return {
|
|
3769
|
+
oldValue: previousCollection.viewQuery ?? null,
|
|
3770
|
+
newValue
|
|
3771
|
+
};
|
|
3772
|
+
}
|
|
3536
3773
|
function buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName) {
|
|
3774
|
+
const isView = currentCollection.type === "view" || previousCollection.type === "view";
|
|
3775
|
+
if (isView) {
|
|
3776
|
+
return {
|
|
3777
|
+
collection: currentCollection.name,
|
|
3778
|
+
fieldsToAdd: [],
|
|
3779
|
+
fieldsToRemove: [],
|
|
3780
|
+
fieldsToModify: [],
|
|
3781
|
+
indexesToAdd: [],
|
|
3782
|
+
indexesToRemove: [],
|
|
3783
|
+
rulesToUpdate: compareRules(
|
|
3784
|
+
currentCollection.rules,
|
|
3785
|
+
previousCollection.rules,
|
|
3786
|
+
currentCollection.permissions,
|
|
3787
|
+
previousCollection.permissions
|
|
3788
|
+
),
|
|
3789
|
+
permissionsToUpdate: comparePermissions(currentCollection.permissions, previousCollection.permissions),
|
|
3790
|
+
viewQueryUpdate: compareViewQuery(currentCollection, previousCollection)
|
|
3791
|
+
};
|
|
3792
|
+
}
|
|
3537
3793
|
const { fieldsToAdd, fieldsToRemove, fieldsToModify } = compareCollectionFields(
|
|
3538
3794
|
currentCollection,
|
|
3539
3795
|
previousCollection,
|
|
@@ -3565,6 +3821,9 @@ function detectDestructiveChanges(diff, config) {
|
|
|
3565
3821
|
const destructiveChanges = [];
|
|
3566
3822
|
const mergedConfig = mergeConfig3(config);
|
|
3567
3823
|
for (const collection of diff.collectionsToDelete) {
|
|
3824
|
+
if (collection.type === "view") {
|
|
3825
|
+
continue;
|
|
3826
|
+
}
|
|
3568
3827
|
destructiveChanges.push({
|
|
3569
3828
|
type: "collection_delete",
|
|
3570
3829
|
severity: "high",
|
|
@@ -3652,7 +3911,11 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
3652
3911
|
const destructive = [];
|
|
3653
3912
|
const nonDestructive = [];
|
|
3654
3913
|
for (const collection of diff.collectionsToDelete) {
|
|
3655
|
-
|
|
3914
|
+
if (collection.type === "view") {
|
|
3915
|
+
nonDestructive.push(`Delete view collection: ${collection.name}`);
|
|
3916
|
+
} else {
|
|
3917
|
+
destructive.push(`Delete collection: ${collection.name}`);
|
|
3918
|
+
}
|
|
3656
3919
|
}
|
|
3657
3920
|
for (const collection of diff.collectionsToCreate) {
|
|
3658
3921
|
nonDestructive.push(`Create collection: ${collection.name}`);
|
|
@@ -3687,6 +3950,9 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
3687
3950
|
for (const rule of modification.rulesToUpdate) {
|
|
3688
3951
|
nonDestructive.push(`Update rule: ${collectionName}.${rule.ruleType}`);
|
|
3689
3952
|
}
|
|
3953
|
+
if (modification.viewQueryUpdate) {
|
|
3954
|
+
nonDestructive.push(`Update view query: ${collectionName}`);
|
|
3955
|
+
}
|
|
3690
3956
|
}
|
|
3691
3957
|
return { destructive, nonDestructive };
|
|
3692
3958
|
}
|
|
@@ -3699,6 +3965,7 @@ function generateChangeSummary(diff, config) {
|
|
|
3699
3965
|
let indexChanges = 0;
|
|
3700
3966
|
let ruleChanges = 0;
|
|
3701
3967
|
let permissionChanges = 0;
|
|
3968
|
+
let viewQueryChanges = 0;
|
|
3702
3969
|
for (const modification of diff.collectionsToModify) {
|
|
3703
3970
|
fieldsToAdd += modification.fieldsToAdd.length;
|
|
3704
3971
|
fieldsToRemove += modification.fieldsToRemove.length;
|
|
@@ -3706,6 +3973,9 @@ function generateChangeSummary(diff, config) {
|
|
|
3706
3973
|
indexChanges += modification.indexesToAdd.length + modification.indexesToRemove.length;
|
|
3707
3974
|
ruleChanges += modification.rulesToUpdate.length;
|
|
3708
3975
|
permissionChanges += modification.permissionsToUpdate.length;
|
|
3976
|
+
if (modification.viewQueryUpdate) {
|
|
3977
|
+
viewQueryChanges += 1;
|
|
3978
|
+
}
|
|
3709
3979
|
}
|
|
3710
3980
|
return {
|
|
3711
3981
|
totalChanges: diff.collectionsToCreate.length + diff.collectionsToDelete.length + diff.collectionsToModify.length,
|
|
@@ -3718,6 +3988,7 @@ function generateChangeSummary(diff, config) {
|
|
|
3718
3988
|
indexChanges,
|
|
3719
3989
|
ruleChanges,
|
|
3720
3990
|
permissionChanges,
|
|
3991
|
+
viewQueryChanges,
|
|
3721
3992
|
destructiveChanges,
|
|
3722
3993
|
nonDestructiveChanges: nonDestructive
|
|
3723
3994
|
};
|
|
@@ -3747,12 +4018,11 @@ function filterDiff(diff, options) {
|
|
|
3747
4018
|
});
|
|
3748
4019
|
let collectionsToDelete = diff.collectionsToDelete;
|
|
3749
4020
|
if (skipDestructive) {
|
|
3750
|
-
collectionsToDelete =
|
|
3751
|
-
} else {
|
|
3752
|
-
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
3753
|
-
return matchesPattern(col.name, patterns);
|
|
3754
|
-
});
|
|
4021
|
+
collectionsToDelete = collectionsToDelete.filter((col) => col.type === "view");
|
|
3755
4022
|
}
|
|
4023
|
+
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
4024
|
+
return matchesPattern(col.name, patterns);
|
|
4025
|
+
});
|
|
3756
4026
|
const collectionsToModify = diff.collectionsToModify.map((mod) => {
|
|
3757
4027
|
const collectionMatches = matchesPattern(mod.collection, patterns);
|
|
3758
4028
|
const fieldsToAdd = mod.fieldsToAdd.filter((field) => {
|
|
@@ -3777,6 +4047,7 @@ function filterDiff(diff, options) {
|
|
|
3777
4047
|
const indexesToRemove = collectionMatches ? mod.indexesToRemove : [];
|
|
3778
4048
|
const rulesToUpdate = collectionMatches ? mod.rulesToUpdate : [];
|
|
3779
4049
|
const permissionsToUpdate = collectionMatches ? mod.permissionsToUpdate : [];
|
|
4050
|
+
const viewQueryUpdate = collectionMatches ? mod.viewQueryUpdate : void 0;
|
|
3780
4051
|
return {
|
|
3781
4052
|
...mod,
|
|
3782
4053
|
fieldsToAdd,
|
|
@@ -3785,10 +4056,11 @@ function filterDiff(diff, options) {
|
|
|
3785
4056
|
indexesToAdd,
|
|
3786
4057
|
indexesToRemove,
|
|
3787
4058
|
rulesToUpdate,
|
|
3788
|
-
permissionsToUpdate
|
|
4059
|
+
permissionsToUpdate,
|
|
4060
|
+
viewQueryUpdate
|
|
3789
4061
|
};
|
|
3790
4062
|
}).filter((mod) => {
|
|
3791
|
-
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;
|
|
4063
|
+
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;
|
|
3792
4064
|
});
|
|
3793
4065
|
return {
|
|
3794
4066
|
...diff,
|
|
@@ -3800,7 +4072,7 @@ function filterDiff(diff, options) {
|
|
|
3800
4072
|
|
|
3801
4073
|
// src/migration/diff/index.ts
|
|
3802
4074
|
function hasChanges(modification) {
|
|
3803
|
-
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;
|
|
4075
|
+
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;
|
|
3804
4076
|
}
|
|
3805
4077
|
function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
3806
4078
|
const collectionIdToName = /* @__PURE__ */ new Map();
|
|
@@ -4015,6 +4287,13 @@ function formatValue(value) {
|
|
|
4015
4287
|
}
|
|
4016
4288
|
return String(value);
|
|
4017
4289
|
}
|
|
4290
|
+
function formatSqlTemplate(query, indent = " ") {
|
|
4291
|
+
const escaped = query.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
4292
|
+
const body = escaped.split("\n").map((line) => line.trim() === "" ? "" : `${indent}${line}`).join("\n");
|
|
4293
|
+
return `\`
|
|
4294
|
+
${body}
|
|
4295
|
+
${indent.slice(0, -2)}\``;
|
|
4296
|
+
}
|
|
4018
4297
|
function getFieldConstructorName(fieldType) {
|
|
4019
4298
|
const constructorMap = {
|
|
4020
4299
|
text: "TextField",
|
|
@@ -4053,6 +4332,36 @@ function getSystemFields() {
|
|
|
4053
4332
|
}
|
|
4054
4333
|
];
|
|
4055
4334
|
}
|
|
4335
|
+
function getSystemTimestampFields() {
|
|
4336
|
+
return [
|
|
4337
|
+
{
|
|
4338
|
+
name: "created",
|
|
4339
|
+
id: "autodate2990389176",
|
|
4340
|
+
type: "autodate",
|
|
4341
|
+
required: false,
|
|
4342
|
+
options: {
|
|
4343
|
+
hidden: false,
|
|
4344
|
+
onCreate: true,
|
|
4345
|
+
onUpdate: false,
|
|
4346
|
+
presentable: false,
|
|
4347
|
+
system: true
|
|
4348
|
+
}
|
|
4349
|
+
},
|
|
4350
|
+
{
|
|
4351
|
+
name: "updated",
|
|
4352
|
+
id: "autodate3332085495",
|
|
4353
|
+
type: "autodate",
|
|
4354
|
+
required: false,
|
|
4355
|
+
options: {
|
|
4356
|
+
hidden: false,
|
|
4357
|
+
onCreate: true,
|
|
4358
|
+
onUpdate: true,
|
|
4359
|
+
presentable: false,
|
|
4360
|
+
system: true
|
|
4361
|
+
}
|
|
4362
|
+
}
|
|
4363
|
+
];
|
|
4364
|
+
}
|
|
4056
4365
|
function getAuthSystemFields() {
|
|
4057
4366
|
return [
|
|
4058
4367
|
{
|
|
@@ -4345,6 +4654,15 @@ function generateCollectionRules(rules, collectionType = "base") {
|
|
|
4345
4654
|
if (!rules) {
|
|
4346
4655
|
return "";
|
|
4347
4656
|
}
|
|
4657
|
+
if (collectionType === "view") {
|
|
4658
|
+
return [
|
|
4659
|
+
`"listRule": ${formatValue(rules.listRule ?? null)}`,
|
|
4660
|
+
`"viewRule": ${formatValue(rules.viewRule ?? null)}`,
|
|
4661
|
+
`"createRule": null`,
|
|
4662
|
+
`"updateRule": null`,
|
|
4663
|
+
`"deleteRule": null`
|
|
4664
|
+
].join(",\n ");
|
|
4665
|
+
}
|
|
4348
4666
|
const parts = [];
|
|
4349
4667
|
if (rules.listRule !== void 0) {
|
|
4350
4668
|
parts.push(`"listRule": ${formatValue(rules.listRule)}`);
|
|
@@ -4370,6 +4688,15 @@ function generateCollectionPermissions(permissions, collectionType = "base") {
|
|
|
4370
4688
|
if (!permissions) {
|
|
4371
4689
|
return "";
|
|
4372
4690
|
}
|
|
4691
|
+
if (collectionType === "view") {
|
|
4692
|
+
return [
|
|
4693
|
+
`"listRule": ${formatValue(permissions.listRule ?? null)}`,
|
|
4694
|
+
`"viewRule": ${formatValue(permissions.viewRule ?? null)}`,
|
|
4695
|
+
`"createRule": null`,
|
|
4696
|
+
`"updateRule": null`,
|
|
4697
|
+
`"deleteRule": null`
|
|
4698
|
+
].join(",\n ");
|
|
4699
|
+
}
|
|
4373
4700
|
const parts = [];
|
|
4374
4701
|
if (permissions.listRule !== void 0) {
|
|
4375
4702
|
parts.push(`"listRule": ${formatValue(permissions.listRule)}`);
|
|
@@ -4407,6 +4734,28 @@ function generatePermissionUpdate(collectionName, ruleType, newValue, varName, i
|
|
|
4407
4734
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
4408
4735
|
return lines.join("\n");
|
|
4409
4736
|
}
|
|
4737
|
+
function generateViewQueryUpdate(collectionName, viewQuery, varName, isLast = false, collectionIdMap) {
|
|
4738
|
+
const lines = [];
|
|
4739
|
+
const collectionVar = varName || `collection_${collectionName}_viewQuery`;
|
|
4740
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
4741
|
+
lines.push(` unmarshal({`);
|
|
4742
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(viewQuery, " ")},`);
|
|
4743
|
+
lines.push(` }, ${collectionVar})`);
|
|
4744
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
4745
|
+
return lines.join("\n");
|
|
4746
|
+
}
|
|
4747
|
+
function generateGroupedRuleUpdates(collectionName, entries, varSuffix, isLast = false, collectionIdMap) {
|
|
4748
|
+
const collectionVar = `collection_${collectionName}_${varSuffix}`;
|
|
4749
|
+
const lines = [];
|
|
4750
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
4751
|
+
lines.push(` unmarshal({`);
|
|
4752
|
+
for (const entry of entries) {
|
|
4753
|
+
lines.push(` "${entry.ruleType}": ${formatValue(entry.value)},`);
|
|
4754
|
+
}
|
|
4755
|
+
lines.push(` }, ${collectionVar})`);
|
|
4756
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
4757
|
+
return lines.join("\n");
|
|
4758
|
+
}
|
|
4410
4759
|
|
|
4411
4760
|
// src/migration/generator/collections.ts
|
|
4412
4761
|
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
@@ -4425,16 +4774,24 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
|
|
|
4425
4774
|
} else if (rulesCode) {
|
|
4426
4775
|
lines.push(` ${rulesCode},`);
|
|
4427
4776
|
}
|
|
4777
|
+
if (collection.type === "view") {
|
|
4778
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(collection.viewQuery ?? "")},`);
|
|
4779
|
+
lines.push(` });`);
|
|
4780
|
+
lines.push(``);
|
|
4781
|
+
lines.push(isLast ? ` return app.save(${varName});` : ` app.save(${varName});`);
|
|
4782
|
+
return lines.join("\n");
|
|
4783
|
+
}
|
|
4428
4784
|
const systemFieldNames = ["created", "updated", "id"];
|
|
4429
4785
|
if (collection.type === "auth") {
|
|
4430
4786
|
systemFieldNames.push(...getAuthSystemFields().map((f) => f.name));
|
|
4431
4787
|
}
|
|
4432
4788
|
const userFields = collection.fields.filter((f) => !systemFieldNames.includes(f.name));
|
|
4433
|
-
const allFields = [...getSystemFields()
|
|
4789
|
+
const allFields = [...getSystemFields()];
|
|
4434
4790
|
if (collection.type === "auth") {
|
|
4435
4791
|
allFields.push(...getAuthSystemFields());
|
|
4436
4792
|
}
|
|
4437
4793
|
allFields.push(...userFields);
|
|
4794
|
+
allFields.push(...getSystemTimestampFields());
|
|
4438
4795
|
lines.push(` "fields": ${generateFieldsArray(allFields, collectionIdMap)},`);
|
|
4439
4796
|
let allIndexes = [...collection.indexes || []];
|
|
4440
4797
|
if (collection.type === "auth") {
|
|
@@ -4464,7 +4821,21 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
4464
4821
|
const modification = operation.modifications;
|
|
4465
4822
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
4466
4823
|
let operationCount = 0;
|
|
4467
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
4824
|
+
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);
|
|
4825
|
+
if (modification.viewQueryUpdate) {
|
|
4826
|
+
operationCount++;
|
|
4827
|
+
const isLast = operationCount === totalOperations;
|
|
4828
|
+
lines.push(
|
|
4829
|
+
generateViewQueryUpdate(
|
|
4830
|
+
collectionName,
|
|
4831
|
+
modification.viewQueryUpdate.newValue,
|
|
4832
|
+
void 0,
|
|
4833
|
+
isLast,
|
|
4834
|
+
collectionIdMap
|
|
4835
|
+
)
|
|
4836
|
+
);
|
|
4837
|
+
if (!isLast) lines.push("");
|
|
4838
|
+
}
|
|
4468
4839
|
for (let i = 0; i < modification.fieldsToAdd.length; i++) {
|
|
4469
4840
|
const field = modification.fieldsToAdd[i];
|
|
4470
4841
|
operationCount++;
|
|
@@ -4504,23 +4875,29 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
4504
4875
|
if (!isLast) lines.push("");
|
|
4505
4876
|
}
|
|
4506
4877
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
4507
|
-
|
|
4508
|
-
|
|
4878
|
+
operationCount++;
|
|
4879
|
+
const isLast = operationCount === totalOperations;
|
|
4880
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
4881
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.newValue }));
|
|
4882
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
4883
|
+
} else {
|
|
4884
|
+
const permission = modification.permissionsToUpdate[0];
|
|
4509
4885
|
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
4510
|
-
|
|
4511
|
-
lines.push(
|
|
4512
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap)
|
|
4513
|
-
);
|
|
4514
|
-
if (!isLast) lines.push("");
|
|
4886
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap));
|
|
4515
4887
|
}
|
|
4888
|
+
if (!isLast) lines.push("");
|
|
4516
4889
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
4517
|
-
|
|
4518
|
-
|
|
4890
|
+
operationCount++;
|
|
4891
|
+
const isLast = operationCount === totalOperations;
|
|
4892
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
4893
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.newValue }));
|
|
4894
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
4895
|
+
} else {
|
|
4896
|
+
const rule = modification.rulesToUpdate[0];
|
|
4519
4897
|
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
4520
|
-
const isLast = operationCount === totalOperations;
|
|
4521
4898
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast, collectionIdMap));
|
|
4522
|
-
if (!isLast) lines.push("");
|
|
4523
4899
|
}
|
|
4900
|
+
if (!isLast) lines.push("");
|
|
4524
4901
|
}
|
|
4525
4902
|
} else if (operation.type === "delete") {
|
|
4526
4903
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
|
|
@@ -4559,25 +4936,45 @@ function generateOperationDownMigration(operation, collectionIdMap) {
|
|
|
4559
4936
|
const modification = operation.modifications;
|
|
4560
4937
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
4561
4938
|
let operationCount = 0;
|
|
4562
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
4939
|
+
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);
|
|
4940
|
+
if (modification.viewQueryUpdate) {
|
|
4941
|
+
operationCount++;
|
|
4942
|
+
const isLast = operationCount === totalOperations;
|
|
4943
|
+
lines.push(
|
|
4944
|
+
generateViewQueryUpdate(
|
|
4945
|
+
collectionName,
|
|
4946
|
+
modification.viewQueryUpdate.oldValue ?? "",
|
|
4947
|
+
`collection_${collectionName}_revert_viewQuery`,
|
|
4948
|
+
isLast,
|
|
4949
|
+
collectionIdMap
|
|
4950
|
+
)
|
|
4951
|
+
);
|
|
4952
|
+
if (!isLast) lines.push("");
|
|
4953
|
+
}
|
|
4563
4954
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
4564
|
-
|
|
4565
|
-
|
|
4955
|
+
operationCount++;
|
|
4956
|
+
const isLast = operationCount === totalOperations;
|
|
4957
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
4958
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.oldValue }));
|
|
4959
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
4960
|
+
} else {
|
|
4961
|
+
const permission = modification.permissionsToUpdate[0];
|
|
4566
4962
|
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
4567
|
-
|
|
4568
|
-
lines.push(
|
|
4569
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap)
|
|
4570
|
-
);
|
|
4571
|
-
if (!isLast) lines.push("");
|
|
4963
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap));
|
|
4572
4964
|
}
|
|
4965
|
+
if (!isLast) lines.push("");
|
|
4573
4966
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
4574
|
-
|
|
4575
|
-
|
|
4967
|
+
operationCount++;
|
|
4968
|
+
const isLast = operationCount === totalOperations;
|
|
4969
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
4970
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.oldValue }));
|
|
4971
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
4972
|
+
} else {
|
|
4973
|
+
const rule = modification.rulesToUpdate[0];
|
|
4576
4974
|
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
4577
|
-
const isLast = operationCount === totalOperations;
|
|
4578
4975
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast, collectionIdMap));
|
|
4579
|
-
if (!isLast) lines.push("");
|
|
4580
4976
|
}
|
|
4977
|
+
if (!isLast) lines.push("");
|
|
4581
4978
|
}
|
|
4582
4979
|
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
4583
4980
|
operationCount++;
|
|
@@ -4684,6 +5081,19 @@ function generateUpMigration(diff) {
|
|
|
4684
5081
|
lines.push(` // Modify existing collections`);
|
|
4685
5082
|
for (const modification of diff.collectionsToModify) {
|
|
4686
5083
|
const collectionName = modification.collection;
|
|
5084
|
+
if (modification.viewQueryUpdate) {
|
|
5085
|
+
lines.push(` // Update the view query of ${collectionName}`);
|
|
5086
|
+
lines.push(
|
|
5087
|
+
generateViewQueryUpdate(
|
|
5088
|
+
collectionName,
|
|
5089
|
+
modification.viewQueryUpdate.newValue,
|
|
5090
|
+
void 0,
|
|
5091
|
+
false,
|
|
5092
|
+
collectionIdMap
|
|
5093
|
+
)
|
|
5094
|
+
);
|
|
5095
|
+
lines.push(``);
|
|
5096
|
+
}
|
|
4687
5097
|
if (modification.fieldsToAdd.length > 0) {
|
|
4688
5098
|
lines.push(` // Add fields to ${collectionName}`);
|
|
4689
5099
|
for (let i = 0; i < modification.fieldsToAdd.length; i++) {
|
|
@@ -4729,20 +5139,26 @@ function generateUpMigration(diff) {
|
|
|
4729
5139
|
}
|
|
4730
5140
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
4731
5141
|
lines.push(` // Update permissions for ${collectionName}`);
|
|
4732
|
-
|
|
5142
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
5143
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.newValue }));
|
|
5144
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", false, collectionIdMap));
|
|
5145
|
+
} else {
|
|
5146
|
+
const permission = modification.permissionsToUpdate[0];
|
|
4733
5147
|
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
4734
|
-
lines.push(
|
|
4735
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, false, collectionIdMap)
|
|
4736
|
-
);
|
|
4737
|
-
lines.push(``);
|
|
5148
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, false, collectionIdMap));
|
|
4738
5149
|
}
|
|
5150
|
+
lines.push(``);
|
|
4739
5151
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
4740
5152
|
lines.push(` // Update rules for ${collectionName}`);
|
|
4741
|
-
|
|
5153
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
5154
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.newValue }));
|
|
5155
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", false, collectionIdMap));
|
|
5156
|
+
} else {
|
|
5157
|
+
const rule = modification.rulesToUpdate[0];
|
|
4742
5158
|
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
4743
5159
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, false, collectionIdMap));
|
|
4744
|
-
lines.push(``);
|
|
4745
5160
|
}
|
|
5161
|
+
lines.push(``);
|
|
4746
5162
|
}
|
|
4747
5163
|
}
|
|
4748
5164
|
}
|
|
@@ -4814,22 +5230,41 @@ function generateDownMigration(diff) {
|
|
|
4814
5230
|
lines.push(` // Revert modifications`);
|
|
4815
5231
|
for (const modification of diff.collectionsToModify) {
|
|
4816
5232
|
const collectionName = modification.collection;
|
|
5233
|
+
if (modification.viewQueryUpdate) {
|
|
5234
|
+
lines.push(` // Restore the view query of ${collectionName}`);
|
|
5235
|
+
lines.push(
|
|
5236
|
+
generateViewQueryUpdate(
|
|
5237
|
+
collectionName,
|
|
5238
|
+
modification.viewQueryUpdate.oldValue ?? "",
|
|
5239
|
+
`collection_${collectionName}_revert_viewQuery`,
|
|
5240
|
+
false,
|
|
5241
|
+
collectionIdMap
|
|
5242
|
+
)
|
|
5243
|
+
);
|
|
5244
|
+
lines.push(``);
|
|
5245
|
+
}
|
|
4817
5246
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
4818
5247
|
lines.push(` // Revert permissions for ${collectionName}`);
|
|
4819
|
-
|
|
5248
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
5249
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.oldValue }));
|
|
5250
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", false, collectionIdMap));
|
|
5251
|
+
} else {
|
|
5252
|
+
const permission = modification.permissionsToUpdate[0];
|
|
4820
5253
|
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
4821
|
-
lines.push(
|
|
4822
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, false, collectionIdMap)
|
|
4823
|
-
);
|
|
4824
|
-
lines.push(``);
|
|
5254
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, false, collectionIdMap));
|
|
4825
5255
|
}
|
|
5256
|
+
lines.push(``);
|
|
4826
5257
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
4827
5258
|
lines.push(` // Revert rules for ${collectionName}`);
|
|
4828
|
-
|
|
5259
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
5260
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.oldValue }));
|
|
5261
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", false, collectionIdMap));
|
|
5262
|
+
} else {
|
|
5263
|
+
const rule = modification.rulesToUpdate[0];
|
|
4829
5264
|
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
4830
5265
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, false, collectionIdMap));
|
|
4831
|
-
lines.push(``);
|
|
4832
5266
|
}
|
|
5267
|
+
lines.push(``);
|
|
4833
5268
|
}
|
|
4834
5269
|
if (modification.indexesToRemove.length > 0) {
|
|
4835
5270
|
lines.push(` // Restore indexes to ${collectionName}`);
|
|
@@ -5159,6 +5594,9 @@ var MigrationGenerator = class {
|
|
|
5159
5594
|
function detectCollectionDeletions(diff) {
|
|
5160
5595
|
const changes = [];
|
|
5161
5596
|
for (const collection of diff.collectionsToDelete) {
|
|
5597
|
+
if (collection.type === "view") {
|
|
5598
|
+
continue;
|
|
5599
|
+
}
|
|
5162
5600
|
changes.push({
|
|
5163
5601
|
type: "collection_deletion" /* COLLECTION_DELETION */,
|
|
5164
5602
|
description: `Delete collection: ${collection.name}`,
|