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/cli/index.js
CHANGED
|
@@ -1193,6 +1193,60 @@ function unwrapZodType(zodType) {
|
|
|
1193
1193
|
}
|
|
1194
1194
|
return unwrapped;
|
|
1195
1195
|
}
|
|
1196
|
+
function dedentSql(value) {
|
|
1197
|
+
const lines = value.replace(/\r\n/g, "\n").split("\n");
|
|
1198
|
+
while (lines.length > 0 && lines[0].trim() === "") {
|
|
1199
|
+
lines.shift();
|
|
1200
|
+
}
|
|
1201
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
|
|
1202
|
+
lines.pop();
|
|
1203
|
+
}
|
|
1204
|
+
if (lines.length === 0) {
|
|
1205
|
+
return "";
|
|
1206
|
+
}
|
|
1207
|
+
let minIndent = Infinity;
|
|
1208
|
+
for (const line of lines) {
|
|
1209
|
+
if (line.trim() === "") continue;
|
|
1210
|
+
const indent = line.length - line.trimStart().length;
|
|
1211
|
+
if (indent < minIndent) {
|
|
1212
|
+
minIndent = indent;
|
|
1213
|
+
}
|
|
1214
|
+
}
|
|
1215
|
+
if (!Number.isFinite(minIndent) || minIndent === 0) {
|
|
1216
|
+
return lines.map((line) => line.trimEnd()).join("\n");
|
|
1217
|
+
}
|
|
1218
|
+
return lines.map((line) => line.slice(minIndent).trimEnd()).join("\n");
|
|
1219
|
+
}
|
|
1220
|
+
function stripLeadingComments(query) {
|
|
1221
|
+
let remaining = query.trim();
|
|
1222
|
+
while (remaining.length > 0) {
|
|
1223
|
+
if (remaining.startsWith("--")) {
|
|
1224
|
+
const newline = remaining.indexOf("\n");
|
|
1225
|
+
remaining = newline === -1 ? "" : remaining.slice(newline + 1).trim();
|
|
1226
|
+
continue;
|
|
1227
|
+
}
|
|
1228
|
+
if (remaining.startsWith("/*")) {
|
|
1229
|
+
const end = remaining.indexOf("*/");
|
|
1230
|
+
remaining = end === -1 ? "" : remaining.slice(end + 2).trim();
|
|
1231
|
+
continue;
|
|
1232
|
+
}
|
|
1233
|
+
break;
|
|
1234
|
+
}
|
|
1235
|
+
return remaining;
|
|
1236
|
+
}
|
|
1237
|
+
function validateViewQuery(collectionName, viewQuery) {
|
|
1238
|
+
if (typeof viewQuery !== "string" || viewQuery.trim() === "") {
|
|
1239
|
+
throw new Error(
|
|
1240
|
+
`View collection "${collectionName}" requires a non-empty viewQuery. Provide the SQL SELECT statement backing the view.`
|
|
1241
|
+
);
|
|
1242
|
+
}
|
|
1243
|
+
const body = stripLeadingComments(viewQuery);
|
|
1244
|
+
if (!/^(select|with)\b/i.test(body)) {
|
|
1245
|
+
throw new Error(
|
|
1246
|
+
`View collection "${collectionName}" has an invalid viewQuery: it must start with SELECT or WITH. Received: ${body.slice(0, 40)}${body.length > 40 ? "..." : ""}`
|
|
1247
|
+
);
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1196
1250
|
function getCollectionNameFromFile(filePath) {
|
|
1197
1251
|
const filename = path8.basename(filePath).replace(/\.(ts|js)$/, "");
|
|
1198
1252
|
return toCollectionName(filename);
|
|
@@ -1216,13 +1270,26 @@ function extractCollectionTypeFromSchema(zodSchema) {
|
|
|
1216
1270
|
}
|
|
1217
1271
|
try {
|
|
1218
1272
|
const metadata = JSON.parse(zodSchema.description);
|
|
1219
|
-
if (metadata.type === "base" || metadata.type === "auth") {
|
|
1273
|
+
if (metadata.type === "base" || metadata.type === "auth" || metadata.type === "view") {
|
|
1220
1274
|
return metadata.type;
|
|
1221
1275
|
}
|
|
1222
1276
|
} catch {
|
|
1223
1277
|
}
|
|
1224
1278
|
return null;
|
|
1225
1279
|
}
|
|
1280
|
+
function extractViewQueryFromSchema(zodSchema) {
|
|
1281
|
+
if (!zodSchema.description) {
|
|
1282
|
+
return null;
|
|
1283
|
+
}
|
|
1284
|
+
try {
|
|
1285
|
+
const metadata = JSON.parse(zodSchema.description);
|
|
1286
|
+
if (typeof metadata.viewQuery === "string") {
|
|
1287
|
+
return metadata.viewQuery;
|
|
1288
|
+
}
|
|
1289
|
+
} catch {
|
|
1290
|
+
}
|
|
1291
|
+
return null;
|
|
1292
|
+
}
|
|
1226
1293
|
function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema", "Collection"]) {
|
|
1227
1294
|
const result = {};
|
|
1228
1295
|
if (module.default instanceof z.ZodObject) {
|
|
@@ -1381,6 +1448,15 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1381
1448
|
const rawFields = extractFieldDefinitions(zodSchema);
|
|
1382
1449
|
const explicitType = extractCollectionTypeFromSchema(zodSchema);
|
|
1383
1450
|
const collectionType = explicitType ?? (isAuthCollection(rawFields) ? "auth" : "base");
|
|
1451
|
+
const isView = collectionType === "view";
|
|
1452
|
+
const viewQuery = extractViewQueryFromSchema(zodSchema);
|
|
1453
|
+
if (isView) {
|
|
1454
|
+
validateViewQuery(collectionName, viewQuery);
|
|
1455
|
+
} else if (viewQuery !== null) {
|
|
1456
|
+
console.warn(
|
|
1457
|
+
`[${collectionName}] viewQuery is only used by view collections and will be ignored. Use defineView() or set type: "view" to define a view collection.`
|
|
1458
|
+
);
|
|
1459
|
+
}
|
|
1384
1460
|
const fields = rawFields.filter((f) => !["created", "updated"].includes(f.name)).map(({ name, zodType }) => buildFieldDefinition(name, zodType));
|
|
1385
1461
|
if (collectionType === "auth") {
|
|
1386
1462
|
const authSystemFields = [
|
|
@@ -1440,26 +1516,43 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1440
1516
|
}
|
|
1441
1517
|
}
|
|
1442
1518
|
const indexes = extractIndexes(zodSchema) || [];
|
|
1519
|
+
if (isView && indexes.length > 0) {
|
|
1520
|
+
throw new Error(
|
|
1521
|
+
`View collection "${collectionName}" cannot declare indexes. PocketBase view collections are backed by a SQL query and do not support indexes.`
|
|
1522
|
+
);
|
|
1523
|
+
}
|
|
1443
1524
|
const permissionAnalyzer = new PermissionAnalyzer();
|
|
1444
1525
|
let permissions = void 0;
|
|
1445
1526
|
const schemaDescription = zodSchema.description;
|
|
1446
1527
|
const extractedPermissions = permissionAnalyzer.extractPermissions(schemaDescription);
|
|
1447
1528
|
if (extractedPermissions) {
|
|
1448
1529
|
const resolvedPermissions = permissionAnalyzer.resolvePermissions(extractedPermissions);
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
1458
|
-
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
1530
|
+
if (isView) {
|
|
1531
|
+
for (const ruleType of ["createRule", "updateRule", "deleteRule", "manageRule"]) {
|
|
1532
|
+
if (resolvedPermissions[ruleType]) {
|
|
1533
|
+
console.warn(
|
|
1534
|
+
`[${collectionName}] ${ruleType} is not supported on view collections and will be set to null.`
|
|
1535
|
+
);
|
|
1536
|
+
}
|
|
1537
|
+
resolvedPermissions[ruleType] = null;
|
|
1459
1538
|
}
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1539
|
+
}
|
|
1540
|
+
if (!isView) {
|
|
1541
|
+
const validationResults = permissionAnalyzer.validatePermissions(
|
|
1542
|
+
collectionName,
|
|
1543
|
+
resolvedPermissions,
|
|
1544
|
+
fields,
|
|
1545
|
+
collectionType === "auth"
|
|
1546
|
+
);
|
|
1547
|
+
for (const [ruleType, result] of validationResults) {
|
|
1548
|
+
if (!result.valid) {
|
|
1549
|
+
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
1550
|
+
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
1551
|
+
}
|
|
1552
|
+
if (result.warnings.length > 0) {
|
|
1553
|
+
console.warn(`[${collectionName}] Permission warnings for ${ruleType}:`);
|
|
1554
|
+
result.warnings.forEach((warning) => console.warn(` - ${warning}`));
|
|
1555
|
+
}
|
|
1463
1556
|
}
|
|
1464
1557
|
}
|
|
1465
1558
|
permissions = permissionAnalyzer.mergeWithDefaults(resolvedPermissions);
|
|
@@ -1480,6 +1573,9 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1480
1573
|
},
|
|
1481
1574
|
permissions
|
|
1482
1575
|
};
|
|
1576
|
+
if (isView) {
|
|
1577
|
+
collectionSchema.viewQuery = viewQuery;
|
|
1578
|
+
}
|
|
1483
1579
|
return collectionSchema;
|
|
1484
1580
|
}
|
|
1485
1581
|
var tsxLoaderRegistered = false;
|
|
@@ -1737,8 +1833,9 @@ function convertPocketBaseField(pbField) {
|
|
|
1737
1833
|
}
|
|
1738
1834
|
function convertPocketBaseCollection(pbCollection) {
|
|
1739
1835
|
const fields = [];
|
|
1836
|
+
const isView = pbCollection.type === "view";
|
|
1740
1837
|
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
1741
|
-
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
1838
|
+
if (!isView && pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
1742
1839
|
for (const pbField of pbCollection.fields) {
|
|
1743
1840
|
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
1744
1841
|
const isAuthSystemField = pbCollection.type === "auth" && ["email", "emailVisibility", "verified", "password", "tokenKey"].includes(pbField.name);
|
|
@@ -1758,6 +1855,9 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
1758
1855
|
if (pbCollection.id) {
|
|
1759
1856
|
schema.id = pbCollection.id;
|
|
1760
1857
|
}
|
|
1858
|
+
if (typeof pbCollection.viewQuery === "string") {
|
|
1859
|
+
schema.viewQuery = dedentSql(pbCollection.viewQuery);
|
|
1860
|
+
}
|
|
1761
1861
|
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
1762
1862
|
schema.indexes = pbCollection.indexes;
|
|
1763
1863
|
}
|
|
@@ -1859,6 +1959,24 @@ function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
|
|
|
1859
1959
|
return [];
|
|
1860
1960
|
}
|
|
1861
1961
|
}
|
|
1962
|
+
function skipTemplateLiteral(content, start) {
|
|
1963
|
+
let i = start + 1;
|
|
1964
|
+
while (i < content.length) {
|
|
1965
|
+
const char = content[i];
|
|
1966
|
+
if (char === "\\") {
|
|
1967
|
+
i += 2;
|
|
1968
|
+
continue;
|
|
1969
|
+
}
|
|
1970
|
+
if (char === "`") {
|
|
1971
|
+
return i + 1;
|
|
1972
|
+
}
|
|
1973
|
+
i++;
|
|
1974
|
+
}
|
|
1975
|
+
return i;
|
|
1976
|
+
}
|
|
1977
|
+
function unescapeTemplateLiteral(raw) {
|
|
1978
|
+
return raw.replace(/\\(`|\$\{|\\)/g, "$1");
|
|
1979
|
+
}
|
|
1862
1980
|
function parseMigrationOperationsFromContent(content) {
|
|
1863
1981
|
const collectionsToCreate = [];
|
|
1864
1982
|
const collectionsToDelete = [];
|
|
@@ -1947,6 +2065,10 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
1947
2065
|
while (i < content.length && bCount > 0) {
|
|
1948
2066
|
const char = content[i];
|
|
1949
2067
|
const prev = i > 0 ? content[i - 1] : "";
|
|
2068
|
+
if (!inStr && char === "`") {
|
|
2069
|
+
i = skipTemplateLiteral(content, i);
|
|
2070
|
+
continue;
|
|
2071
|
+
}
|
|
1950
2072
|
if (!inStr && (char === '"' || char === "'")) {
|
|
1951
2073
|
inStr = true;
|
|
1952
2074
|
strChar = char;
|
|
@@ -2136,6 +2258,95 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
2136
2258
|
}
|
|
2137
2259
|
}
|
|
2138
2260
|
}
|
|
2261
|
+
const viewQueryRegex = /(\w+)\.viewQuery\s*=\s*/g;
|
|
2262
|
+
let viewQueryMatch;
|
|
2263
|
+
while ((viewQueryMatch = viewQueryRegex.exec(content)) !== null) {
|
|
2264
|
+
const varInfo = variables.get(viewQueryMatch[1]);
|
|
2265
|
+
if (!varInfo || varInfo.type !== "collection") continue;
|
|
2266
|
+
const valueStart = viewQueryMatch.index + viewQueryMatch[0].length;
|
|
2267
|
+
if (content[valueStart] === "`") {
|
|
2268
|
+
const end = skipTemplateLiteral(content, valueStart);
|
|
2269
|
+
const raw = content.substring(valueStart + 1, end - 1);
|
|
2270
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
2271
|
+
viewQueryRegex.lastIndex = end;
|
|
2272
|
+
} else {
|
|
2273
|
+
const terminator = content.indexOf(";", valueStart);
|
|
2274
|
+
const valueStr = content.substring(valueStart, terminator === -1 ? content.length : terminator);
|
|
2275
|
+
try {
|
|
2276
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(new Function("app", `return ${valueStr}`)(mockApp));
|
|
2277
|
+
} catch {
|
|
2278
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(valueStr.trim());
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
}
|
|
2282
|
+
const unmarshalRegex = /unmarshal\s*\(/g;
|
|
2283
|
+
let unmarshalMatch;
|
|
2284
|
+
while ((unmarshalMatch = unmarshalRegex.exec(content)) !== null) {
|
|
2285
|
+
let i = unmarshalMatch.index + unmarshalMatch[0].length;
|
|
2286
|
+
while (i < content.length && /\s/.test(content[i])) i++;
|
|
2287
|
+
if (content[i] !== "{") continue;
|
|
2288
|
+
const objStart = i;
|
|
2289
|
+
let braceCount = 1;
|
|
2290
|
+
let inStr = false;
|
|
2291
|
+
let strChar = null;
|
|
2292
|
+
i++;
|
|
2293
|
+
while (i < content.length && braceCount > 0) {
|
|
2294
|
+
const ch = content[i];
|
|
2295
|
+
const prev = i > 0 ? content[i - 1] : "";
|
|
2296
|
+
if (!inStr && ch === "`") {
|
|
2297
|
+
i = skipTemplateLiteral(content, i);
|
|
2298
|
+
continue;
|
|
2299
|
+
}
|
|
2300
|
+
if (!inStr && (ch === '"' || ch === "'")) {
|
|
2301
|
+
inStr = true;
|
|
2302
|
+
strChar = ch;
|
|
2303
|
+
} else if (inStr && ch === strChar && prev !== "\\") {
|
|
2304
|
+
inStr = false;
|
|
2305
|
+
strChar = null;
|
|
2306
|
+
}
|
|
2307
|
+
if (!inStr) {
|
|
2308
|
+
if (ch === "{") braceCount++;
|
|
2309
|
+
if (ch === "}") braceCount--;
|
|
2310
|
+
}
|
|
2311
|
+
i++;
|
|
2312
|
+
}
|
|
2313
|
+
if (braceCount !== 0) continue;
|
|
2314
|
+
const objStr = content.substring(objStart, i);
|
|
2315
|
+
while (i < content.length && /[\s,]/.test(content[i])) i++;
|
|
2316
|
+
const varStart = i;
|
|
2317
|
+
while (i < content.length && /\w/.test(content[i])) i++;
|
|
2318
|
+
const colVarName = content.substring(varStart, i);
|
|
2319
|
+
const colInfo = variables.get(colVarName);
|
|
2320
|
+
if (!colInfo || colInfo.type !== "collection") continue;
|
|
2321
|
+
const keyValRegex = /"(\w+Rule)"\s*:\s*([^,}\n]+)/g;
|
|
2322
|
+
let kvMatch;
|
|
2323
|
+
while ((kvMatch = keyValRegex.exec(objStr)) !== null) {
|
|
2324
|
+
const ruleKey = kvMatch[1];
|
|
2325
|
+
const valStr = kvMatch[2].trim();
|
|
2326
|
+
try {
|
|
2327
|
+
const value = new Function("app", `return ${valStr}`)(mockApp);
|
|
2328
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = value;
|
|
2329
|
+
} catch {
|
|
2330
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = valStr;
|
|
2331
|
+
}
|
|
2332
|
+
}
|
|
2333
|
+
const viewQueryKey = objStr.match(/"viewQuery"\s*:\s*/);
|
|
2334
|
+
if (viewQueryKey) {
|
|
2335
|
+
const valueStart = viewQueryKey.index + viewQueryKey[0].length;
|
|
2336
|
+
if (objStr[valueStart] === "`") {
|
|
2337
|
+
const end = skipTemplateLiteral(objStr, valueStart);
|
|
2338
|
+
const raw = objStr.substring(valueStart + 1, end - 1);
|
|
2339
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
2340
|
+
} else {
|
|
2341
|
+
const valStr = objStr.substring(valueStart).replace(/[,}\s]+$/, "");
|
|
2342
|
+
try {
|
|
2343
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(new Function("app", `return ${valStr}`)(mockApp));
|
|
2344
|
+
} catch {
|
|
2345
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(valStr);
|
|
2346
|
+
}
|
|
2347
|
+
}
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2139
2350
|
const idxPushRegex = /(\w+)\.indexes\.push\s*\(/g;
|
|
2140
2351
|
let match;
|
|
2141
2352
|
while ((match = idxPushRegex.exec(content)) !== null) {
|
|
@@ -2265,6 +2476,10 @@ function parseMigrationOperations(migrationContent) {
|
|
|
2265
2476
|
while (i < migrationContent.length && braceCount > 0) {
|
|
2266
2477
|
const char = migrationContent[i];
|
|
2267
2478
|
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
2479
|
+
if (!inString && char === "`") {
|
|
2480
|
+
i = skipTemplateLiteral(migrationContent, i);
|
|
2481
|
+
continue;
|
|
2482
|
+
}
|
|
2268
2483
|
if (!inString && (char === '"' || char === "'")) {
|
|
2269
2484
|
inString = true;
|
|
2270
2485
|
stringChar = char;
|
|
@@ -2372,6 +2587,9 @@ function applyMigrationOperations(snapshot, operations) {
|
|
|
2372
2587
|
collection.indexes = collection.indexes.filter((idx) => !update.indexesToRemove.includes(idx));
|
|
2373
2588
|
}
|
|
2374
2589
|
}
|
|
2590
|
+
if (update.viewQuery !== void 0) {
|
|
2591
|
+
collection.viewQuery = update.viewQuery;
|
|
2592
|
+
}
|
|
2375
2593
|
if (Object.keys(update.rulesToUpdate).length > 0) {
|
|
2376
2594
|
if (!collection.rules) collection.rules = {};
|
|
2377
2595
|
if (!collection.permissions) collection.permissions = {};
|
|
@@ -2835,7 +3053,45 @@ function compareCollectionFields(currentCollection, previousCollection, config,
|
|
|
2835
3053
|
fieldsToRemove = fieldsToRemove.filter((_, index) => !processedRemoveIndices.has(index));
|
|
2836
3054
|
return { fieldsToAdd, fieldsToRemove, fieldsToModify };
|
|
2837
3055
|
}
|
|
3056
|
+
function normalizeSql(query) {
|
|
3057
|
+
if (!query) {
|
|
3058
|
+
return "";
|
|
3059
|
+
}
|
|
3060
|
+
return query.split("\n").map((line) => line.trim()).join(" ").replace(/\s+/g, " ").trim();
|
|
3061
|
+
}
|
|
3062
|
+
function compareViewQuery(currentCollection, previousCollection) {
|
|
3063
|
+
const newValue = currentCollection.viewQuery;
|
|
3064
|
+
if (typeof newValue !== "string") {
|
|
3065
|
+
return void 0;
|
|
3066
|
+
}
|
|
3067
|
+
if (normalizeSql(newValue) === normalizeSql(previousCollection.viewQuery)) {
|
|
3068
|
+
return void 0;
|
|
3069
|
+
}
|
|
3070
|
+
return {
|
|
3071
|
+
oldValue: previousCollection.viewQuery ?? null,
|
|
3072
|
+
newValue
|
|
3073
|
+
};
|
|
3074
|
+
}
|
|
2838
3075
|
function buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName) {
|
|
3076
|
+
const isView = currentCollection.type === "view" || previousCollection.type === "view";
|
|
3077
|
+
if (isView) {
|
|
3078
|
+
return {
|
|
3079
|
+
collection: currentCollection.name,
|
|
3080
|
+
fieldsToAdd: [],
|
|
3081
|
+
fieldsToRemove: [],
|
|
3082
|
+
fieldsToModify: [],
|
|
3083
|
+
indexesToAdd: [],
|
|
3084
|
+
indexesToRemove: [],
|
|
3085
|
+
rulesToUpdate: compareRules(
|
|
3086
|
+
currentCollection.rules,
|
|
3087
|
+
previousCollection.rules,
|
|
3088
|
+
currentCollection.permissions,
|
|
3089
|
+
previousCollection.permissions
|
|
3090
|
+
),
|
|
3091
|
+
permissionsToUpdate: comparePermissions(currentCollection.permissions, previousCollection.permissions),
|
|
3092
|
+
viewQueryUpdate: compareViewQuery(currentCollection, previousCollection)
|
|
3093
|
+
};
|
|
3094
|
+
}
|
|
2839
3095
|
const { fieldsToAdd, fieldsToRemove, fieldsToModify } = compareCollectionFields(
|
|
2840
3096
|
currentCollection,
|
|
2841
3097
|
previousCollection,
|
|
@@ -2867,7 +3123,11 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
2867
3123
|
const destructive = [];
|
|
2868
3124
|
const nonDestructive = [];
|
|
2869
3125
|
for (const collection of diff.collectionsToDelete) {
|
|
2870
|
-
|
|
3126
|
+
if (collection.type === "view") {
|
|
3127
|
+
nonDestructive.push(`Delete view collection: ${collection.name}`);
|
|
3128
|
+
} else {
|
|
3129
|
+
destructive.push(`Delete collection: ${collection.name}`);
|
|
3130
|
+
}
|
|
2871
3131
|
}
|
|
2872
3132
|
for (const collection of diff.collectionsToCreate) {
|
|
2873
3133
|
nonDestructive.push(`Create collection: ${collection.name}`);
|
|
@@ -2902,6 +3162,9 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
2902
3162
|
for (const rule of modification.rulesToUpdate) {
|
|
2903
3163
|
nonDestructive.push(`Update rule: ${collectionName}.${rule.ruleType}`);
|
|
2904
3164
|
}
|
|
3165
|
+
if (modification.viewQueryUpdate) {
|
|
3166
|
+
nonDestructive.push(`Update view query: ${collectionName}`);
|
|
3167
|
+
}
|
|
2905
3168
|
}
|
|
2906
3169
|
return { destructive, nonDestructive };
|
|
2907
3170
|
}
|
|
@@ -2930,12 +3193,11 @@ function filterDiff(diff, options) {
|
|
|
2930
3193
|
});
|
|
2931
3194
|
let collectionsToDelete = diff.collectionsToDelete;
|
|
2932
3195
|
if (skipDestructive) {
|
|
2933
|
-
collectionsToDelete =
|
|
2934
|
-
} else {
|
|
2935
|
-
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
2936
|
-
return matchesPattern(col.name, patterns);
|
|
2937
|
-
});
|
|
3196
|
+
collectionsToDelete = collectionsToDelete.filter((col) => col.type === "view");
|
|
2938
3197
|
}
|
|
3198
|
+
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
3199
|
+
return matchesPattern(col.name, patterns);
|
|
3200
|
+
});
|
|
2939
3201
|
const collectionsToModify = diff.collectionsToModify.map((mod) => {
|
|
2940
3202
|
const collectionMatches = matchesPattern(mod.collection, patterns);
|
|
2941
3203
|
const fieldsToAdd = mod.fieldsToAdd.filter((field) => {
|
|
@@ -2960,6 +3222,7 @@ function filterDiff(diff, options) {
|
|
|
2960
3222
|
const indexesToRemove = collectionMatches ? mod.indexesToRemove : [];
|
|
2961
3223
|
const rulesToUpdate = collectionMatches ? mod.rulesToUpdate : [];
|
|
2962
3224
|
const permissionsToUpdate = collectionMatches ? mod.permissionsToUpdate : [];
|
|
3225
|
+
const viewQueryUpdate = collectionMatches ? mod.viewQueryUpdate : void 0;
|
|
2963
3226
|
return {
|
|
2964
3227
|
...mod,
|
|
2965
3228
|
fieldsToAdd,
|
|
@@ -2968,10 +3231,11 @@ function filterDiff(diff, options) {
|
|
|
2968
3231
|
indexesToAdd,
|
|
2969
3232
|
indexesToRemove,
|
|
2970
3233
|
rulesToUpdate,
|
|
2971
|
-
permissionsToUpdate
|
|
3234
|
+
permissionsToUpdate,
|
|
3235
|
+
viewQueryUpdate
|
|
2972
3236
|
};
|
|
2973
3237
|
}).filter((mod) => {
|
|
2974
|
-
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;
|
|
3238
|
+
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;
|
|
2975
3239
|
});
|
|
2976
3240
|
return {
|
|
2977
3241
|
...diff,
|
|
@@ -2983,7 +3247,7 @@ function filterDiff(diff, options) {
|
|
|
2983
3247
|
|
|
2984
3248
|
// src/migration/diff/index.ts
|
|
2985
3249
|
function hasChanges(modification) {
|
|
2986
|
-
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;
|
|
3250
|
+
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;
|
|
2987
3251
|
}
|
|
2988
3252
|
function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
2989
3253
|
const collectionIdToName = /* @__PURE__ */ new Map();
|
|
@@ -3162,6 +3426,13 @@ function formatValue(value) {
|
|
|
3162
3426
|
}
|
|
3163
3427
|
return String(value);
|
|
3164
3428
|
}
|
|
3429
|
+
function formatSqlTemplate(query, indent = " ") {
|
|
3430
|
+
const escaped = query.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
3431
|
+
const body = escaped.split("\n").map((line) => line.trim() === "" ? "" : `${indent}${line}`).join("\n");
|
|
3432
|
+
return `\`
|
|
3433
|
+
${body}
|
|
3434
|
+
${indent.slice(0, -2)}\``;
|
|
3435
|
+
}
|
|
3165
3436
|
function getFieldConstructorName(fieldType) {
|
|
3166
3437
|
const constructorMap = {
|
|
3167
3438
|
text: "TextField",
|
|
@@ -3200,6 +3471,36 @@ function getSystemFields() {
|
|
|
3200
3471
|
}
|
|
3201
3472
|
];
|
|
3202
3473
|
}
|
|
3474
|
+
function getSystemTimestampFields() {
|
|
3475
|
+
return [
|
|
3476
|
+
{
|
|
3477
|
+
name: "created",
|
|
3478
|
+
id: "autodate2990389176",
|
|
3479
|
+
type: "autodate",
|
|
3480
|
+
required: false,
|
|
3481
|
+
options: {
|
|
3482
|
+
hidden: false,
|
|
3483
|
+
onCreate: true,
|
|
3484
|
+
onUpdate: false,
|
|
3485
|
+
presentable: false,
|
|
3486
|
+
system: true
|
|
3487
|
+
}
|
|
3488
|
+
},
|
|
3489
|
+
{
|
|
3490
|
+
name: "updated",
|
|
3491
|
+
id: "autodate3332085495",
|
|
3492
|
+
type: "autodate",
|
|
3493
|
+
required: false,
|
|
3494
|
+
options: {
|
|
3495
|
+
hidden: false,
|
|
3496
|
+
onCreate: true,
|
|
3497
|
+
onUpdate: true,
|
|
3498
|
+
presentable: false,
|
|
3499
|
+
system: true
|
|
3500
|
+
}
|
|
3501
|
+
}
|
|
3502
|
+
];
|
|
3503
|
+
}
|
|
3203
3504
|
function getAuthSystemFields() {
|
|
3204
3505
|
return [
|
|
3205
3506
|
{
|
|
@@ -3492,6 +3793,15 @@ function generateCollectionRules(rules, collectionType = "base") {
|
|
|
3492
3793
|
if (!rules) {
|
|
3493
3794
|
return "";
|
|
3494
3795
|
}
|
|
3796
|
+
if (collectionType === "view") {
|
|
3797
|
+
return [
|
|
3798
|
+
`"listRule": ${formatValue(rules.listRule ?? null)}`,
|
|
3799
|
+
`"viewRule": ${formatValue(rules.viewRule ?? null)}`,
|
|
3800
|
+
`"createRule": null`,
|
|
3801
|
+
`"updateRule": null`,
|
|
3802
|
+
`"deleteRule": null`
|
|
3803
|
+
].join(",\n ");
|
|
3804
|
+
}
|
|
3495
3805
|
const parts = [];
|
|
3496
3806
|
if (rules.listRule !== void 0) {
|
|
3497
3807
|
parts.push(`"listRule": ${formatValue(rules.listRule)}`);
|
|
@@ -3517,6 +3827,15 @@ function generateCollectionPermissions(permissions, collectionType = "base") {
|
|
|
3517
3827
|
if (!permissions) {
|
|
3518
3828
|
return "";
|
|
3519
3829
|
}
|
|
3830
|
+
if (collectionType === "view") {
|
|
3831
|
+
return [
|
|
3832
|
+
`"listRule": ${formatValue(permissions.listRule ?? null)}`,
|
|
3833
|
+
`"viewRule": ${formatValue(permissions.viewRule ?? null)}`,
|
|
3834
|
+
`"createRule": null`,
|
|
3835
|
+
`"updateRule": null`,
|
|
3836
|
+
`"deleteRule": null`
|
|
3837
|
+
].join(",\n ");
|
|
3838
|
+
}
|
|
3520
3839
|
const parts = [];
|
|
3521
3840
|
if (permissions.listRule !== void 0) {
|
|
3522
3841
|
parts.push(`"listRule": ${formatValue(permissions.listRule)}`);
|
|
@@ -3554,6 +3873,28 @@ function generatePermissionUpdate(collectionName, ruleType, newValue, varName, i
|
|
|
3554
3873
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3555
3874
|
return lines.join("\n");
|
|
3556
3875
|
}
|
|
3876
|
+
function generateViewQueryUpdate(collectionName, viewQuery, varName, isLast = false, collectionIdMap) {
|
|
3877
|
+
const lines = [];
|
|
3878
|
+
const collectionVar = varName || `collection_${collectionName}_viewQuery`;
|
|
3879
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
3880
|
+
lines.push(` unmarshal({`);
|
|
3881
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(viewQuery, " ")},`);
|
|
3882
|
+
lines.push(` }, ${collectionVar})`);
|
|
3883
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3884
|
+
return lines.join("\n");
|
|
3885
|
+
}
|
|
3886
|
+
function generateGroupedRuleUpdates(collectionName, entries, varSuffix, isLast = false, collectionIdMap) {
|
|
3887
|
+
const collectionVar = `collection_${collectionName}_${varSuffix}`;
|
|
3888
|
+
const lines = [];
|
|
3889
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
3890
|
+
lines.push(` unmarshal({`);
|
|
3891
|
+
for (const entry of entries) {
|
|
3892
|
+
lines.push(` "${entry.ruleType}": ${formatValue(entry.value)},`);
|
|
3893
|
+
}
|
|
3894
|
+
lines.push(` }, ${collectionVar})`);
|
|
3895
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3896
|
+
return lines.join("\n");
|
|
3897
|
+
}
|
|
3557
3898
|
|
|
3558
3899
|
// src/migration/generator/collections.ts
|
|
3559
3900
|
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
@@ -3572,16 +3913,24 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
|
|
|
3572
3913
|
} else if (rulesCode) {
|
|
3573
3914
|
lines.push(` ${rulesCode},`);
|
|
3574
3915
|
}
|
|
3916
|
+
if (collection.type === "view") {
|
|
3917
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(collection.viewQuery ?? "")},`);
|
|
3918
|
+
lines.push(` });`);
|
|
3919
|
+
lines.push(``);
|
|
3920
|
+
lines.push(isLast ? ` return app.save(${varName});` : ` app.save(${varName});`);
|
|
3921
|
+
return lines.join("\n");
|
|
3922
|
+
}
|
|
3575
3923
|
const systemFieldNames = ["created", "updated", "id"];
|
|
3576
3924
|
if (collection.type === "auth") {
|
|
3577
3925
|
systemFieldNames.push(...getAuthSystemFields().map((f) => f.name));
|
|
3578
3926
|
}
|
|
3579
3927
|
const userFields = collection.fields.filter((f) => !systemFieldNames.includes(f.name));
|
|
3580
|
-
const allFields = [...getSystemFields()
|
|
3928
|
+
const allFields = [...getSystemFields()];
|
|
3581
3929
|
if (collection.type === "auth") {
|
|
3582
3930
|
allFields.push(...getAuthSystemFields());
|
|
3583
3931
|
}
|
|
3584
3932
|
allFields.push(...userFields);
|
|
3933
|
+
allFields.push(...getSystemTimestampFields());
|
|
3585
3934
|
lines.push(` "fields": ${generateFieldsArray(allFields, collectionIdMap)},`);
|
|
3586
3935
|
let allIndexes = [...collection.indexes || []];
|
|
3587
3936
|
if (collection.type === "auth") {
|
|
@@ -3611,7 +3960,21 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
3611
3960
|
const modification = operation.modifications;
|
|
3612
3961
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
3613
3962
|
let operationCount = 0;
|
|
3614
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
3963
|
+
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);
|
|
3964
|
+
if (modification.viewQueryUpdate) {
|
|
3965
|
+
operationCount++;
|
|
3966
|
+
const isLast = operationCount === totalOperations;
|
|
3967
|
+
lines.push(
|
|
3968
|
+
generateViewQueryUpdate(
|
|
3969
|
+
collectionName,
|
|
3970
|
+
modification.viewQueryUpdate.newValue,
|
|
3971
|
+
void 0,
|
|
3972
|
+
isLast,
|
|
3973
|
+
collectionIdMap
|
|
3974
|
+
)
|
|
3975
|
+
);
|
|
3976
|
+
if (!isLast) lines.push("");
|
|
3977
|
+
}
|
|
3615
3978
|
for (let i = 0; i < modification.fieldsToAdd.length; i++) {
|
|
3616
3979
|
const field = modification.fieldsToAdd[i];
|
|
3617
3980
|
operationCount++;
|
|
@@ -3651,23 +4014,29 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
3651
4014
|
if (!isLast) lines.push("");
|
|
3652
4015
|
}
|
|
3653
4016
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
3654
|
-
|
|
3655
|
-
|
|
4017
|
+
operationCount++;
|
|
4018
|
+
const isLast = operationCount === totalOperations;
|
|
4019
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
4020
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.newValue }));
|
|
4021
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
4022
|
+
} else {
|
|
4023
|
+
const permission = modification.permissionsToUpdate[0];
|
|
3656
4024
|
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
3657
|
-
|
|
3658
|
-
lines.push(
|
|
3659
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap)
|
|
3660
|
-
);
|
|
3661
|
-
if (!isLast) lines.push("");
|
|
4025
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap));
|
|
3662
4026
|
}
|
|
4027
|
+
if (!isLast) lines.push("");
|
|
3663
4028
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
3664
|
-
|
|
3665
|
-
|
|
4029
|
+
operationCount++;
|
|
4030
|
+
const isLast = operationCount === totalOperations;
|
|
4031
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
4032
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.newValue }));
|
|
4033
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
4034
|
+
} else {
|
|
4035
|
+
const rule = modification.rulesToUpdate[0];
|
|
3666
4036
|
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
3667
|
-
const isLast = operationCount === totalOperations;
|
|
3668
4037
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast, collectionIdMap));
|
|
3669
|
-
if (!isLast) lines.push("");
|
|
3670
4038
|
}
|
|
4039
|
+
if (!isLast) lines.push("");
|
|
3671
4040
|
}
|
|
3672
4041
|
} else if (operation.type === "delete") {
|
|
3673
4042
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
|
|
@@ -3706,25 +4075,45 @@ function generateOperationDownMigration(operation, collectionIdMap) {
|
|
|
3706
4075
|
const modification = operation.modifications;
|
|
3707
4076
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
3708
4077
|
let operationCount = 0;
|
|
3709
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
4078
|
+
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);
|
|
4079
|
+
if (modification.viewQueryUpdate) {
|
|
4080
|
+
operationCount++;
|
|
4081
|
+
const isLast = operationCount === totalOperations;
|
|
4082
|
+
lines.push(
|
|
4083
|
+
generateViewQueryUpdate(
|
|
4084
|
+
collectionName,
|
|
4085
|
+
modification.viewQueryUpdate.oldValue ?? "",
|
|
4086
|
+
`collection_${collectionName}_revert_viewQuery`,
|
|
4087
|
+
isLast,
|
|
4088
|
+
collectionIdMap
|
|
4089
|
+
)
|
|
4090
|
+
);
|
|
4091
|
+
if (!isLast) lines.push("");
|
|
4092
|
+
}
|
|
3710
4093
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
3711
|
-
|
|
3712
|
-
|
|
4094
|
+
operationCount++;
|
|
4095
|
+
const isLast = operationCount === totalOperations;
|
|
4096
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
4097
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.oldValue }));
|
|
4098
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
4099
|
+
} else {
|
|
4100
|
+
const permission = modification.permissionsToUpdate[0];
|
|
3713
4101
|
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
3714
|
-
|
|
3715
|
-
lines.push(
|
|
3716
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap)
|
|
3717
|
-
);
|
|
3718
|
-
if (!isLast) lines.push("");
|
|
4102
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap));
|
|
3719
4103
|
}
|
|
4104
|
+
if (!isLast) lines.push("");
|
|
3720
4105
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
3721
|
-
|
|
3722
|
-
|
|
4106
|
+
operationCount++;
|
|
4107
|
+
const isLast = operationCount === totalOperations;
|
|
4108
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
4109
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.oldValue }));
|
|
4110
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
4111
|
+
} else {
|
|
4112
|
+
const rule = modification.rulesToUpdate[0];
|
|
3723
4113
|
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
3724
|
-
const isLast = operationCount === totalOperations;
|
|
3725
4114
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast, collectionIdMap));
|
|
3726
|
-
if (!isLast) lines.push("");
|
|
3727
4115
|
}
|
|
4116
|
+
if (!isLast) lines.push("");
|
|
3728
4117
|
}
|
|
3729
4118
|
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
3730
4119
|
operationCount++;
|
|
@@ -3973,6 +4362,9 @@ function generate(diff, config) {
|
|
|
3973
4362
|
function detectCollectionDeletions(diff) {
|
|
3974
4363
|
const changes = [];
|
|
3975
4364
|
for (const collection of diff.collectionsToDelete) {
|
|
4365
|
+
if (collection.type === "view") {
|
|
4366
|
+
continue;
|
|
4367
|
+
}
|
|
3976
4368
|
changes.push({
|
|
3977
4369
|
type: "collection_deletion" /* COLLECTION_DELETION */,
|
|
3978
4370
|
description: `Delete collection: ${collection.name}`,
|
|
@@ -4386,7 +4778,11 @@ function formatChangeSummary(diff) {
|
|
|
4386
4778
|
lines.push(chalk.green.bold(`\u2713 ${totalCollectionsToCreate} collection(s) to create:`));
|
|
4387
4779
|
for (const collection of diff.collectionsToCreate) {
|
|
4388
4780
|
lines.push(chalk.green(` + ${collection.name} (${collection.type})`));
|
|
4389
|
-
|
|
4781
|
+
if (collection.type === "view") {
|
|
4782
|
+
lines.push(chalk.gray(` fields derived from the view query`));
|
|
4783
|
+
} else {
|
|
4784
|
+
lines.push(chalk.gray(` ${collection.fields.length} field(s)`));
|
|
4785
|
+
}
|
|
4390
4786
|
}
|
|
4391
4787
|
lines.push("");
|
|
4392
4788
|
}
|
|
@@ -4431,6 +4827,9 @@ function formatChangeSummary(diff) {
|
|
|
4431
4827
|
if (modification.rulesToUpdate.length > 0) {
|
|
4432
4828
|
lines.push(chalk.yellow(` ~ ${modification.rulesToUpdate.length} rule(s) to update`));
|
|
4433
4829
|
}
|
|
4830
|
+
if (modification.viewQueryUpdate) {
|
|
4831
|
+
lines.push(chalk.yellow(` ~ view query to update`));
|
|
4832
|
+
}
|
|
4434
4833
|
lines.push("");
|
|
4435
4834
|
}
|
|
4436
4835
|
}
|