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.cjs
CHANGED
|
@@ -1220,6 +1220,60 @@ function unwrapZodType(zodType) {
|
|
|
1220
1220
|
}
|
|
1221
1221
|
return unwrapped;
|
|
1222
1222
|
}
|
|
1223
|
+
function dedentSql(value) {
|
|
1224
|
+
const lines = value.replace(/\r\n/g, "\n").split("\n");
|
|
1225
|
+
while (lines.length > 0 && lines[0].trim() === "") {
|
|
1226
|
+
lines.shift();
|
|
1227
|
+
}
|
|
1228
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
|
|
1229
|
+
lines.pop();
|
|
1230
|
+
}
|
|
1231
|
+
if (lines.length === 0) {
|
|
1232
|
+
return "";
|
|
1233
|
+
}
|
|
1234
|
+
let minIndent = Infinity;
|
|
1235
|
+
for (const line of lines) {
|
|
1236
|
+
if (line.trim() === "") continue;
|
|
1237
|
+
const indent = line.length - line.trimStart().length;
|
|
1238
|
+
if (indent < minIndent) {
|
|
1239
|
+
minIndent = indent;
|
|
1240
|
+
}
|
|
1241
|
+
}
|
|
1242
|
+
if (!Number.isFinite(minIndent) || minIndent === 0) {
|
|
1243
|
+
return lines.map((line) => line.trimEnd()).join("\n");
|
|
1244
|
+
}
|
|
1245
|
+
return lines.map((line) => line.slice(minIndent).trimEnd()).join("\n");
|
|
1246
|
+
}
|
|
1247
|
+
function stripLeadingComments(query) {
|
|
1248
|
+
let remaining = query.trim();
|
|
1249
|
+
while (remaining.length > 0) {
|
|
1250
|
+
if (remaining.startsWith("--")) {
|
|
1251
|
+
const newline = remaining.indexOf("\n");
|
|
1252
|
+
remaining = newline === -1 ? "" : remaining.slice(newline + 1).trim();
|
|
1253
|
+
continue;
|
|
1254
|
+
}
|
|
1255
|
+
if (remaining.startsWith("/*")) {
|
|
1256
|
+
const end = remaining.indexOf("*/");
|
|
1257
|
+
remaining = end === -1 ? "" : remaining.slice(end + 2).trim();
|
|
1258
|
+
continue;
|
|
1259
|
+
}
|
|
1260
|
+
break;
|
|
1261
|
+
}
|
|
1262
|
+
return remaining;
|
|
1263
|
+
}
|
|
1264
|
+
function validateViewQuery(collectionName, viewQuery) {
|
|
1265
|
+
if (typeof viewQuery !== "string" || viewQuery.trim() === "") {
|
|
1266
|
+
throw new Error(
|
|
1267
|
+
`View collection "${collectionName}" requires a non-empty viewQuery. Provide the SQL SELECT statement backing the view.`
|
|
1268
|
+
);
|
|
1269
|
+
}
|
|
1270
|
+
const body = stripLeadingComments(viewQuery);
|
|
1271
|
+
if (!/^(select|with)\b/i.test(body)) {
|
|
1272
|
+
throw new Error(
|
|
1273
|
+
`View collection "${collectionName}" has an invalid viewQuery: it must start with SELECT or WITH. Received: ${body.slice(0, 40)}${body.length > 40 ? "..." : ""}`
|
|
1274
|
+
);
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1223
1277
|
function getCollectionNameFromFile(filePath) {
|
|
1224
1278
|
const filename = path8__namespace.basename(filePath).replace(/\.(ts|js)$/, "");
|
|
1225
1279
|
return toCollectionName(filename);
|
|
@@ -1243,13 +1297,26 @@ function extractCollectionTypeFromSchema(zodSchema) {
|
|
|
1243
1297
|
}
|
|
1244
1298
|
try {
|
|
1245
1299
|
const metadata = JSON.parse(zodSchema.description);
|
|
1246
|
-
if (metadata.type === "base" || metadata.type === "auth") {
|
|
1300
|
+
if (metadata.type === "base" || metadata.type === "auth" || metadata.type === "view") {
|
|
1247
1301
|
return metadata.type;
|
|
1248
1302
|
}
|
|
1249
1303
|
} catch {
|
|
1250
1304
|
}
|
|
1251
1305
|
return null;
|
|
1252
1306
|
}
|
|
1307
|
+
function extractViewQueryFromSchema(zodSchema) {
|
|
1308
|
+
if (!zodSchema.description) {
|
|
1309
|
+
return null;
|
|
1310
|
+
}
|
|
1311
|
+
try {
|
|
1312
|
+
const metadata = JSON.parse(zodSchema.description);
|
|
1313
|
+
if (typeof metadata.viewQuery === "string") {
|
|
1314
|
+
return metadata.viewQuery;
|
|
1315
|
+
}
|
|
1316
|
+
} catch {
|
|
1317
|
+
}
|
|
1318
|
+
return null;
|
|
1319
|
+
}
|
|
1253
1320
|
function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema", "Collection"]) {
|
|
1254
1321
|
const result = {};
|
|
1255
1322
|
if (module.default instanceof zod.z.ZodObject) {
|
|
@@ -1408,6 +1475,15 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1408
1475
|
const rawFields = extractFieldDefinitions(zodSchema);
|
|
1409
1476
|
const explicitType = extractCollectionTypeFromSchema(zodSchema);
|
|
1410
1477
|
const collectionType = explicitType ?? (isAuthCollection(rawFields) ? "auth" : "base");
|
|
1478
|
+
const isView = collectionType === "view";
|
|
1479
|
+
const viewQuery = extractViewQueryFromSchema(zodSchema);
|
|
1480
|
+
if (isView) {
|
|
1481
|
+
validateViewQuery(collectionName, viewQuery);
|
|
1482
|
+
} else if (viewQuery !== null) {
|
|
1483
|
+
console.warn(
|
|
1484
|
+
`[${collectionName}] viewQuery is only used by view collections and will be ignored. Use defineView() or set type: "view" to define a view collection.`
|
|
1485
|
+
);
|
|
1486
|
+
}
|
|
1411
1487
|
const fields = rawFields.filter((f) => !["created", "updated"].includes(f.name)).map(({ name, zodType }) => buildFieldDefinition(name, zodType));
|
|
1412
1488
|
if (collectionType === "auth") {
|
|
1413
1489
|
const authSystemFields = [
|
|
@@ -1467,26 +1543,43 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1467
1543
|
}
|
|
1468
1544
|
}
|
|
1469
1545
|
const indexes = extractIndexes(zodSchema) || [];
|
|
1546
|
+
if (isView && indexes.length > 0) {
|
|
1547
|
+
throw new Error(
|
|
1548
|
+
`View collection "${collectionName}" cannot declare indexes. PocketBase view collections are backed by a SQL query and do not support indexes.`
|
|
1549
|
+
);
|
|
1550
|
+
}
|
|
1470
1551
|
const permissionAnalyzer = new PermissionAnalyzer();
|
|
1471
1552
|
let permissions = void 0;
|
|
1472
1553
|
const schemaDescription = zodSchema.description;
|
|
1473
1554
|
const extractedPermissions = permissionAnalyzer.extractPermissions(schemaDescription);
|
|
1474
1555
|
if (extractedPermissions) {
|
|
1475
1556
|
const resolvedPermissions = permissionAnalyzer.resolvePermissions(extractedPermissions);
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
1485
|
-
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
1557
|
+
if (isView) {
|
|
1558
|
+
for (const ruleType of ["createRule", "updateRule", "deleteRule", "manageRule"]) {
|
|
1559
|
+
if (resolvedPermissions[ruleType]) {
|
|
1560
|
+
console.warn(
|
|
1561
|
+
`[${collectionName}] ${ruleType} is not supported on view collections and will be set to null.`
|
|
1562
|
+
);
|
|
1563
|
+
}
|
|
1564
|
+
resolvedPermissions[ruleType] = null;
|
|
1486
1565
|
}
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1566
|
+
}
|
|
1567
|
+
if (!isView) {
|
|
1568
|
+
const validationResults = permissionAnalyzer.validatePermissions(
|
|
1569
|
+
collectionName,
|
|
1570
|
+
resolvedPermissions,
|
|
1571
|
+
fields,
|
|
1572
|
+
collectionType === "auth"
|
|
1573
|
+
);
|
|
1574
|
+
for (const [ruleType, result] of validationResults) {
|
|
1575
|
+
if (!result.valid) {
|
|
1576
|
+
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
1577
|
+
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
1578
|
+
}
|
|
1579
|
+
if (result.warnings.length > 0) {
|
|
1580
|
+
console.warn(`[${collectionName}] Permission warnings for ${ruleType}:`);
|
|
1581
|
+
result.warnings.forEach((warning) => console.warn(` - ${warning}`));
|
|
1582
|
+
}
|
|
1490
1583
|
}
|
|
1491
1584
|
}
|
|
1492
1585
|
permissions = permissionAnalyzer.mergeWithDefaults(resolvedPermissions);
|
|
@@ -1507,6 +1600,9 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1507
1600
|
},
|
|
1508
1601
|
permissions
|
|
1509
1602
|
};
|
|
1603
|
+
if (isView) {
|
|
1604
|
+
collectionSchema.viewQuery = viewQuery;
|
|
1605
|
+
}
|
|
1510
1606
|
return collectionSchema;
|
|
1511
1607
|
}
|
|
1512
1608
|
var tsxLoaderRegistered = false;
|
|
@@ -1764,8 +1860,9 @@ function convertPocketBaseField(pbField) {
|
|
|
1764
1860
|
}
|
|
1765
1861
|
function convertPocketBaseCollection(pbCollection) {
|
|
1766
1862
|
const fields = [];
|
|
1863
|
+
const isView = pbCollection.type === "view";
|
|
1767
1864
|
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
1768
|
-
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
1865
|
+
if (!isView && pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
1769
1866
|
for (const pbField of pbCollection.fields) {
|
|
1770
1867
|
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
1771
1868
|
const isAuthSystemField = pbCollection.type === "auth" && ["email", "emailVisibility", "verified", "password", "tokenKey"].includes(pbField.name);
|
|
@@ -1785,6 +1882,9 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
1785
1882
|
if (pbCollection.id) {
|
|
1786
1883
|
schema.id = pbCollection.id;
|
|
1787
1884
|
}
|
|
1885
|
+
if (typeof pbCollection.viewQuery === "string") {
|
|
1886
|
+
schema.viewQuery = dedentSql(pbCollection.viewQuery);
|
|
1887
|
+
}
|
|
1788
1888
|
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
1789
1889
|
schema.indexes = pbCollection.indexes;
|
|
1790
1890
|
}
|
|
@@ -1886,6 +1986,24 @@ function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
|
|
|
1886
1986
|
return [];
|
|
1887
1987
|
}
|
|
1888
1988
|
}
|
|
1989
|
+
function skipTemplateLiteral(content, start) {
|
|
1990
|
+
let i = start + 1;
|
|
1991
|
+
while (i < content.length) {
|
|
1992
|
+
const char = content[i];
|
|
1993
|
+
if (char === "\\") {
|
|
1994
|
+
i += 2;
|
|
1995
|
+
continue;
|
|
1996
|
+
}
|
|
1997
|
+
if (char === "`") {
|
|
1998
|
+
return i + 1;
|
|
1999
|
+
}
|
|
2000
|
+
i++;
|
|
2001
|
+
}
|
|
2002
|
+
return i;
|
|
2003
|
+
}
|
|
2004
|
+
function unescapeTemplateLiteral(raw) {
|
|
2005
|
+
return raw.replace(/\\(`|\$\{|\\)/g, "$1");
|
|
2006
|
+
}
|
|
1889
2007
|
function parseMigrationOperationsFromContent(content) {
|
|
1890
2008
|
const collectionsToCreate = [];
|
|
1891
2009
|
const collectionsToDelete = [];
|
|
@@ -1974,6 +2092,10 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
1974
2092
|
while (i < content.length && bCount > 0) {
|
|
1975
2093
|
const char = content[i];
|
|
1976
2094
|
const prev = i > 0 ? content[i - 1] : "";
|
|
2095
|
+
if (!inStr && char === "`") {
|
|
2096
|
+
i = skipTemplateLiteral(content, i);
|
|
2097
|
+
continue;
|
|
2098
|
+
}
|
|
1977
2099
|
if (!inStr && (char === '"' || char === "'")) {
|
|
1978
2100
|
inStr = true;
|
|
1979
2101
|
strChar = char;
|
|
@@ -2163,6 +2285,95 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
2163
2285
|
}
|
|
2164
2286
|
}
|
|
2165
2287
|
}
|
|
2288
|
+
const viewQueryRegex = /(\w+)\.viewQuery\s*=\s*/g;
|
|
2289
|
+
let viewQueryMatch;
|
|
2290
|
+
while ((viewQueryMatch = viewQueryRegex.exec(content)) !== null) {
|
|
2291
|
+
const varInfo = variables.get(viewQueryMatch[1]);
|
|
2292
|
+
if (!varInfo || varInfo.type !== "collection") continue;
|
|
2293
|
+
const valueStart = viewQueryMatch.index + viewQueryMatch[0].length;
|
|
2294
|
+
if (content[valueStart] === "`") {
|
|
2295
|
+
const end = skipTemplateLiteral(content, valueStart);
|
|
2296
|
+
const raw = content.substring(valueStart + 1, end - 1);
|
|
2297
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
2298
|
+
viewQueryRegex.lastIndex = end;
|
|
2299
|
+
} else {
|
|
2300
|
+
const terminator = content.indexOf(";", valueStart);
|
|
2301
|
+
const valueStr = content.substring(valueStart, terminator === -1 ? content.length : terminator);
|
|
2302
|
+
try {
|
|
2303
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(new Function("app", `return ${valueStr}`)(mockApp));
|
|
2304
|
+
} catch {
|
|
2305
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(valueStr.trim());
|
|
2306
|
+
}
|
|
2307
|
+
}
|
|
2308
|
+
}
|
|
2309
|
+
const unmarshalRegex = /unmarshal\s*\(/g;
|
|
2310
|
+
let unmarshalMatch;
|
|
2311
|
+
while ((unmarshalMatch = unmarshalRegex.exec(content)) !== null) {
|
|
2312
|
+
let i = unmarshalMatch.index + unmarshalMatch[0].length;
|
|
2313
|
+
while (i < content.length && /\s/.test(content[i])) i++;
|
|
2314
|
+
if (content[i] !== "{") continue;
|
|
2315
|
+
const objStart = i;
|
|
2316
|
+
let braceCount = 1;
|
|
2317
|
+
let inStr = false;
|
|
2318
|
+
let strChar = null;
|
|
2319
|
+
i++;
|
|
2320
|
+
while (i < content.length && braceCount > 0) {
|
|
2321
|
+
const ch = content[i];
|
|
2322
|
+
const prev = i > 0 ? content[i - 1] : "";
|
|
2323
|
+
if (!inStr && ch === "`") {
|
|
2324
|
+
i = skipTemplateLiteral(content, i);
|
|
2325
|
+
continue;
|
|
2326
|
+
}
|
|
2327
|
+
if (!inStr && (ch === '"' || ch === "'")) {
|
|
2328
|
+
inStr = true;
|
|
2329
|
+
strChar = ch;
|
|
2330
|
+
} else if (inStr && ch === strChar && prev !== "\\") {
|
|
2331
|
+
inStr = false;
|
|
2332
|
+
strChar = null;
|
|
2333
|
+
}
|
|
2334
|
+
if (!inStr) {
|
|
2335
|
+
if (ch === "{") braceCount++;
|
|
2336
|
+
if (ch === "}") braceCount--;
|
|
2337
|
+
}
|
|
2338
|
+
i++;
|
|
2339
|
+
}
|
|
2340
|
+
if (braceCount !== 0) continue;
|
|
2341
|
+
const objStr = content.substring(objStart, i);
|
|
2342
|
+
while (i < content.length && /[\s,]/.test(content[i])) i++;
|
|
2343
|
+
const varStart = i;
|
|
2344
|
+
while (i < content.length && /\w/.test(content[i])) i++;
|
|
2345
|
+
const colVarName = content.substring(varStart, i);
|
|
2346
|
+
const colInfo = variables.get(colVarName);
|
|
2347
|
+
if (!colInfo || colInfo.type !== "collection") continue;
|
|
2348
|
+
const keyValRegex = /"(\w+Rule)"\s*:\s*([^,}\n]+)/g;
|
|
2349
|
+
let kvMatch;
|
|
2350
|
+
while ((kvMatch = keyValRegex.exec(objStr)) !== null) {
|
|
2351
|
+
const ruleKey = kvMatch[1];
|
|
2352
|
+
const valStr = kvMatch[2].trim();
|
|
2353
|
+
try {
|
|
2354
|
+
const value = new Function("app", `return ${valStr}`)(mockApp);
|
|
2355
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = value;
|
|
2356
|
+
} catch {
|
|
2357
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = valStr;
|
|
2358
|
+
}
|
|
2359
|
+
}
|
|
2360
|
+
const viewQueryKey = objStr.match(/"viewQuery"\s*:\s*/);
|
|
2361
|
+
if (viewQueryKey) {
|
|
2362
|
+
const valueStart = viewQueryKey.index + viewQueryKey[0].length;
|
|
2363
|
+
if (objStr[valueStart] === "`") {
|
|
2364
|
+
const end = skipTemplateLiteral(objStr, valueStart);
|
|
2365
|
+
const raw = objStr.substring(valueStart + 1, end - 1);
|
|
2366
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
2367
|
+
} else {
|
|
2368
|
+
const valStr = objStr.substring(valueStart).replace(/[,}\s]+$/, "");
|
|
2369
|
+
try {
|
|
2370
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(new Function("app", `return ${valStr}`)(mockApp));
|
|
2371
|
+
} catch {
|
|
2372
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(valStr);
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2166
2377
|
const idxPushRegex = /(\w+)\.indexes\.push\s*\(/g;
|
|
2167
2378
|
let match;
|
|
2168
2379
|
while ((match = idxPushRegex.exec(content)) !== null) {
|
|
@@ -2292,6 +2503,10 @@ function parseMigrationOperations(migrationContent) {
|
|
|
2292
2503
|
while (i < migrationContent.length && braceCount > 0) {
|
|
2293
2504
|
const char = migrationContent[i];
|
|
2294
2505
|
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
2506
|
+
if (!inString && char === "`") {
|
|
2507
|
+
i = skipTemplateLiteral(migrationContent, i);
|
|
2508
|
+
continue;
|
|
2509
|
+
}
|
|
2295
2510
|
if (!inString && (char === '"' || char === "'")) {
|
|
2296
2511
|
inString = true;
|
|
2297
2512
|
stringChar = char;
|
|
@@ -2399,6 +2614,9 @@ function applyMigrationOperations(snapshot, operations) {
|
|
|
2399
2614
|
collection.indexes = collection.indexes.filter((idx) => !update.indexesToRemove.includes(idx));
|
|
2400
2615
|
}
|
|
2401
2616
|
}
|
|
2617
|
+
if (update.viewQuery !== void 0) {
|
|
2618
|
+
collection.viewQuery = update.viewQuery;
|
|
2619
|
+
}
|
|
2402
2620
|
if (Object.keys(update.rulesToUpdate).length > 0) {
|
|
2403
2621
|
if (!collection.rules) collection.rules = {};
|
|
2404
2622
|
if (!collection.permissions) collection.permissions = {};
|
|
@@ -2862,7 +3080,45 @@ function compareCollectionFields(currentCollection, previousCollection, config,
|
|
|
2862
3080
|
fieldsToRemove = fieldsToRemove.filter((_, index) => !processedRemoveIndices.has(index));
|
|
2863
3081
|
return { fieldsToAdd, fieldsToRemove, fieldsToModify };
|
|
2864
3082
|
}
|
|
3083
|
+
function normalizeSql(query) {
|
|
3084
|
+
if (!query) {
|
|
3085
|
+
return "";
|
|
3086
|
+
}
|
|
3087
|
+
return query.split("\n").map((line) => line.trim()).join(" ").replace(/\s+/g, " ").trim();
|
|
3088
|
+
}
|
|
3089
|
+
function compareViewQuery(currentCollection, previousCollection) {
|
|
3090
|
+
const newValue = currentCollection.viewQuery;
|
|
3091
|
+
if (typeof newValue !== "string") {
|
|
3092
|
+
return void 0;
|
|
3093
|
+
}
|
|
3094
|
+
if (normalizeSql(newValue) === normalizeSql(previousCollection.viewQuery)) {
|
|
3095
|
+
return void 0;
|
|
3096
|
+
}
|
|
3097
|
+
return {
|
|
3098
|
+
oldValue: previousCollection.viewQuery ?? null,
|
|
3099
|
+
newValue
|
|
3100
|
+
};
|
|
3101
|
+
}
|
|
2865
3102
|
function buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName) {
|
|
3103
|
+
const isView = currentCollection.type === "view" || previousCollection.type === "view";
|
|
3104
|
+
if (isView) {
|
|
3105
|
+
return {
|
|
3106
|
+
collection: currentCollection.name,
|
|
3107
|
+
fieldsToAdd: [],
|
|
3108
|
+
fieldsToRemove: [],
|
|
3109
|
+
fieldsToModify: [],
|
|
3110
|
+
indexesToAdd: [],
|
|
3111
|
+
indexesToRemove: [],
|
|
3112
|
+
rulesToUpdate: compareRules(
|
|
3113
|
+
currentCollection.rules,
|
|
3114
|
+
previousCollection.rules,
|
|
3115
|
+
currentCollection.permissions,
|
|
3116
|
+
previousCollection.permissions
|
|
3117
|
+
),
|
|
3118
|
+
permissionsToUpdate: comparePermissions(currentCollection.permissions, previousCollection.permissions),
|
|
3119
|
+
viewQueryUpdate: compareViewQuery(currentCollection, previousCollection)
|
|
3120
|
+
};
|
|
3121
|
+
}
|
|
2866
3122
|
const { fieldsToAdd, fieldsToRemove, fieldsToModify } = compareCollectionFields(
|
|
2867
3123
|
currentCollection,
|
|
2868
3124
|
previousCollection,
|
|
@@ -2894,7 +3150,11 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
2894
3150
|
const destructive = [];
|
|
2895
3151
|
const nonDestructive = [];
|
|
2896
3152
|
for (const collection of diff.collectionsToDelete) {
|
|
2897
|
-
|
|
3153
|
+
if (collection.type === "view") {
|
|
3154
|
+
nonDestructive.push(`Delete view collection: ${collection.name}`);
|
|
3155
|
+
} else {
|
|
3156
|
+
destructive.push(`Delete collection: ${collection.name}`);
|
|
3157
|
+
}
|
|
2898
3158
|
}
|
|
2899
3159
|
for (const collection of diff.collectionsToCreate) {
|
|
2900
3160
|
nonDestructive.push(`Create collection: ${collection.name}`);
|
|
@@ -2929,6 +3189,9 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
2929
3189
|
for (const rule of modification.rulesToUpdate) {
|
|
2930
3190
|
nonDestructive.push(`Update rule: ${collectionName}.${rule.ruleType}`);
|
|
2931
3191
|
}
|
|
3192
|
+
if (modification.viewQueryUpdate) {
|
|
3193
|
+
nonDestructive.push(`Update view query: ${collectionName}`);
|
|
3194
|
+
}
|
|
2932
3195
|
}
|
|
2933
3196
|
return { destructive, nonDestructive };
|
|
2934
3197
|
}
|
|
@@ -2957,12 +3220,11 @@ function filterDiff(diff, options) {
|
|
|
2957
3220
|
});
|
|
2958
3221
|
let collectionsToDelete = diff.collectionsToDelete;
|
|
2959
3222
|
if (skipDestructive) {
|
|
2960
|
-
collectionsToDelete =
|
|
2961
|
-
} else {
|
|
2962
|
-
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
2963
|
-
return matchesPattern(col.name, patterns);
|
|
2964
|
-
});
|
|
3223
|
+
collectionsToDelete = collectionsToDelete.filter((col) => col.type === "view");
|
|
2965
3224
|
}
|
|
3225
|
+
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
3226
|
+
return matchesPattern(col.name, patterns);
|
|
3227
|
+
});
|
|
2966
3228
|
const collectionsToModify = diff.collectionsToModify.map((mod) => {
|
|
2967
3229
|
const collectionMatches = matchesPattern(mod.collection, patterns);
|
|
2968
3230
|
const fieldsToAdd = mod.fieldsToAdd.filter((field) => {
|
|
@@ -2987,6 +3249,7 @@ function filterDiff(diff, options) {
|
|
|
2987
3249
|
const indexesToRemove = collectionMatches ? mod.indexesToRemove : [];
|
|
2988
3250
|
const rulesToUpdate = collectionMatches ? mod.rulesToUpdate : [];
|
|
2989
3251
|
const permissionsToUpdate = collectionMatches ? mod.permissionsToUpdate : [];
|
|
3252
|
+
const viewQueryUpdate = collectionMatches ? mod.viewQueryUpdate : void 0;
|
|
2990
3253
|
return {
|
|
2991
3254
|
...mod,
|
|
2992
3255
|
fieldsToAdd,
|
|
@@ -2995,10 +3258,11 @@ function filterDiff(diff, options) {
|
|
|
2995
3258
|
indexesToAdd,
|
|
2996
3259
|
indexesToRemove,
|
|
2997
3260
|
rulesToUpdate,
|
|
2998
|
-
permissionsToUpdate
|
|
3261
|
+
permissionsToUpdate,
|
|
3262
|
+
viewQueryUpdate
|
|
2999
3263
|
};
|
|
3000
3264
|
}).filter((mod) => {
|
|
3001
|
-
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;
|
|
3265
|
+
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;
|
|
3002
3266
|
});
|
|
3003
3267
|
return {
|
|
3004
3268
|
...diff,
|
|
@@ -3010,7 +3274,7 @@ function filterDiff(diff, options) {
|
|
|
3010
3274
|
|
|
3011
3275
|
// src/migration/diff/index.ts
|
|
3012
3276
|
function hasChanges(modification) {
|
|
3013
|
-
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;
|
|
3277
|
+
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;
|
|
3014
3278
|
}
|
|
3015
3279
|
function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
3016
3280
|
const collectionIdToName = /* @__PURE__ */ new Map();
|
|
@@ -3189,6 +3453,13 @@ function formatValue(value) {
|
|
|
3189
3453
|
}
|
|
3190
3454
|
return String(value);
|
|
3191
3455
|
}
|
|
3456
|
+
function formatSqlTemplate(query, indent = " ") {
|
|
3457
|
+
const escaped = query.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
3458
|
+
const body = escaped.split("\n").map((line) => line.trim() === "" ? "" : `${indent}${line}`).join("\n");
|
|
3459
|
+
return `\`
|
|
3460
|
+
${body}
|
|
3461
|
+
${indent.slice(0, -2)}\``;
|
|
3462
|
+
}
|
|
3192
3463
|
function getFieldConstructorName(fieldType) {
|
|
3193
3464
|
const constructorMap = {
|
|
3194
3465
|
text: "TextField",
|
|
@@ -3227,6 +3498,36 @@ function getSystemFields() {
|
|
|
3227
3498
|
}
|
|
3228
3499
|
];
|
|
3229
3500
|
}
|
|
3501
|
+
function getSystemTimestampFields() {
|
|
3502
|
+
return [
|
|
3503
|
+
{
|
|
3504
|
+
name: "created",
|
|
3505
|
+
id: "autodate2990389176",
|
|
3506
|
+
type: "autodate",
|
|
3507
|
+
required: false,
|
|
3508
|
+
options: {
|
|
3509
|
+
hidden: false,
|
|
3510
|
+
onCreate: true,
|
|
3511
|
+
onUpdate: false,
|
|
3512
|
+
presentable: false,
|
|
3513
|
+
system: true
|
|
3514
|
+
}
|
|
3515
|
+
},
|
|
3516
|
+
{
|
|
3517
|
+
name: "updated",
|
|
3518
|
+
id: "autodate3332085495",
|
|
3519
|
+
type: "autodate",
|
|
3520
|
+
required: false,
|
|
3521
|
+
options: {
|
|
3522
|
+
hidden: false,
|
|
3523
|
+
onCreate: true,
|
|
3524
|
+
onUpdate: true,
|
|
3525
|
+
presentable: false,
|
|
3526
|
+
system: true
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3529
|
+
];
|
|
3530
|
+
}
|
|
3230
3531
|
function getAuthSystemFields() {
|
|
3231
3532
|
return [
|
|
3232
3533
|
{
|
|
@@ -3519,6 +3820,15 @@ function generateCollectionRules(rules, collectionType = "base") {
|
|
|
3519
3820
|
if (!rules) {
|
|
3520
3821
|
return "";
|
|
3521
3822
|
}
|
|
3823
|
+
if (collectionType === "view") {
|
|
3824
|
+
return [
|
|
3825
|
+
`"listRule": ${formatValue(rules.listRule ?? null)}`,
|
|
3826
|
+
`"viewRule": ${formatValue(rules.viewRule ?? null)}`,
|
|
3827
|
+
`"createRule": null`,
|
|
3828
|
+
`"updateRule": null`,
|
|
3829
|
+
`"deleteRule": null`
|
|
3830
|
+
].join(",\n ");
|
|
3831
|
+
}
|
|
3522
3832
|
const parts = [];
|
|
3523
3833
|
if (rules.listRule !== void 0) {
|
|
3524
3834
|
parts.push(`"listRule": ${formatValue(rules.listRule)}`);
|
|
@@ -3544,6 +3854,15 @@ function generateCollectionPermissions(permissions, collectionType = "base") {
|
|
|
3544
3854
|
if (!permissions) {
|
|
3545
3855
|
return "";
|
|
3546
3856
|
}
|
|
3857
|
+
if (collectionType === "view") {
|
|
3858
|
+
return [
|
|
3859
|
+
`"listRule": ${formatValue(permissions.listRule ?? null)}`,
|
|
3860
|
+
`"viewRule": ${formatValue(permissions.viewRule ?? null)}`,
|
|
3861
|
+
`"createRule": null`,
|
|
3862
|
+
`"updateRule": null`,
|
|
3863
|
+
`"deleteRule": null`
|
|
3864
|
+
].join(",\n ");
|
|
3865
|
+
}
|
|
3547
3866
|
const parts = [];
|
|
3548
3867
|
if (permissions.listRule !== void 0) {
|
|
3549
3868
|
parts.push(`"listRule": ${formatValue(permissions.listRule)}`);
|
|
@@ -3581,6 +3900,28 @@ function generatePermissionUpdate(collectionName, ruleType, newValue, varName, i
|
|
|
3581
3900
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3582
3901
|
return lines.join("\n");
|
|
3583
3902
|
}
|
|
3903
|
+
function generateViewQueryUpdate(collectionName, viewQuery, varName, isLast = false, collectionIdMap) {
|
|
3904
|
+
const lines = [];
|
|
3905
|
+
const collectionVar = varName || `collection_${collectionName}_viewQuery`;
|
|
3906
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
3907
|
+
lines.push(` unmarshal({`);
|
|
3908
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(viewQuery, " ")},`);
|
|
3909
|
+
lines.push(` }, ${collectionVar})`);
|
|
3910
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3911
|
+
return lines.join("\n");
|
|
3912
|
+
}
|
|
3913
|
+
function generateGroupedRuleUpdates(collectionName, entries, varSuffix, isLast = false, collectionIdMap) {
|
|
3914
|
+
const collectionVar = `collection_${collectionName}_${varSuffix}`;
|
|
3915
|
+
const lines = [];
|
|
3916
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
3917
|
+
lines.push(` unmarshal({`);
|
|
3918
|
+
for (const entry of entries) {
|
|
3919
|
+
lines.push(` "${entry.ruleType}": ${formatValue(entry.value)},`);
|
|
3920
|
+
}
|
|
3921
|
+
lines.push(` }, ${collectionVar})`);
|
|
3922
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3923
|
+
return lines.join("\n");
|
|
3924
|
+
}
|
|
3584
3925
|
|
|
3585
3926
|
// src/migration/generator/collections.ts
|
|
3586
3927
|
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
@@ -3599,16 +3940,24 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
|
|
|
3599
3940
|
} else if (rulesCode) {
|
|
3600
3941
|
lines.push(` ${rulesCode},`);
|
|
3601
3942
|
}
|
|
3943
|
+
if (collection.type === "view") {
|
|
3944
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(collection.viewQuery ?? "")},`);
|
|
3945
|
+
lines.push(` });`);
|
|
3946
|
+
lines.push(``);
|
|
3947
|
+
lines.push(isLast ? ` return app.save(${varName});` : ` app.save(${varName});`);
|
|
3948
|
+
return lines.join("\n");
|
|
3949
|
+
}
|
|
3602
3950
|
const systemFieldNames = ["created", "updated", "id"];
|
|
3603
3951
|
if (collection.type === "auth") {
|
|
3604
3952
|
systemFieldNames.push(...getAuthSystemFields().map((f) => f.name));
|
|
3605
3953
|
}
|
|
3606
3954
|
const userFields = collection.fields.filter((f) => !systemFieldNames.includes(f.name));
|
|
3607
|
-
const allFields = [...getSystemFields()
|
|
3955
|
+
const allFields = [...getSystemFields()];
|
|
3608
3956
|
if (collection.type === "auth") {
|
|
3609
3957
|
allFields.push(...getAuthSystemFields());
|
|
3610
3958
|
}
|
|
3611
3959
|
allFields.push(...userFields);
|
|
3960
|
+
allFields.push(...getSystemTimestampFields());
|
|
3612
3961
|
lines.push(` "fields": ${generateFieldsArray(allFields, collectionIdMap)},`);
|
|
3613
3962
|
let allIndexes = [...collection.indexes || []];
|
|
3614
3963
|
if (collection.type === "auth") {
|
|
@@ -3638,7 +3987,21 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
3638
3987
|
const modification = operation.modifications;
|
|
3639
3988
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
3640
3989
|
let operationCount = 0;
|
|
3641
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
3990
|
+
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);
|
|
3991
|
+
if (modification.viewQueryUpdate) {
|
|
3992
|
+
operationCount++;
|
|
3993
|
+
const isLast = operationCount === totalOperations;
|
|
3994
|
+
lines.push(
|
|
3995
|
+
generateViewQueryUpdate(
|
|
3996
|
+
collectionName,
|
|
3997
|
+
modification.viewQueryUpdate.newValue,
|
|
3998
|
+
void 0,
|
|
3999
|
+
isLast,
|
|
4000
|
+
collectionIdMap
|
|
4001
|
+
)
|
|
4002
|
+
);
|
|
4003
|
+
if (!isLast) lines.push("");
|
|
4004
|
+
}
|
|
3642
4005
|
for (let i = 0; i < modification.fieldsToAdd.length; i++) {
|
|
3643
4006
|
const field = modification.fieldsToAdd[i];
|
|
3644
4007
|
operationCount++;
|
|
@@ -3678,23 +4041,29 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
3678
4041
|
if (!isLast) lines.push("");
|
|
3679
4042
|
}
|
|
3680
4043
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
3681
|
-
|
|
3682
|
-
|
|
4044
|
+
operationCount++;
|
|
4045
|
+
const isLast = operationCount === totalOperations;
|
|
4046
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
4047
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.newValue }));
|
|
4048
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
4049
|
+
} else {
|
|
4050
|
+
const permission = modification.permissionsToUpdate[0];
|
|
3683
4051
|
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
3684
|
-
|
|
3685
|
-
lines.push(
|
|
3686
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap)
|
|
3687
|
-
);
|
|
3688
|
-
if (!isLast) lines.push("");
|
|
4052
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap));
|
|
3689
4053
|
}
|
|
4054
|
+
if (!isLast) lines.push("");
|
|
3690
4055
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
3691
|
-
|
|
3692
|
-
|
|
4056
|
+
operationCount++;
|
|
4057
|
+
const isLast = operationCount === totalOperations;
|
|
4058
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
4059
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.newValue }));
|
|
4060
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
4061
|
+
} else {
|
|
4062
|
+
const rule = modification.rulesToUpdate[0];
|
|
3693
4063
|
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
3694
|
-
const isLast = operationCount === totalOperations;
|
|
3695
4064
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast, collectionIdMap));
|
|
3696
|
-
if (!isLast) lines.push("");
|
|
3697
4065
|
}
|
|
4066
|
+
if (!isLast) lines.push("");
|
|
3698
4067
|
}
|
|
3699
4068
|
} else if (operation.type === "delete") {
|
|
3700
4069
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
|
|
@@ -3733,25 +4102,45 @@ function generateOperationDownMigration(operation, collectionIdMap) {
|
|
|
3733
4102
|
const modification = operation.modifications;
|
|
3734
4103
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
3735
4104
|
let operationCount = 0;
|
|
3736
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
4105
|
+
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);
|
|
4106
|
+
if (modification.viewQueryUpdate) {
|
|
4107
|
+
operationCount++;
|
|
4108
|
+
const isLast = operationCount === totalOperations;
|
|
4109
|
+
lines.push(
|
|
4110
|
+
generateViewQueryUpdate(
|
|
4111
|
+
collectionName,
|
|
4112
|
+
modification.viewQueryUpdate.oldValue ?? "",
|
|
4113
|
+
`collection_${collectionName}_revert_viewQuery`,
|
|
4114
|
+
isLast,
|
|
4115
|
+
collectionIdMap
|
|
4116
|
+
)
|
|
4117
|
+
);
|
|
4118
|
+
if (!isLast) lines.push("");
|
|
4119
|
+
}
|
|
3737
4120
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
3738
|
-
|
|
3739
|
-
|
|
4121
|
+
operationCount++;
|
|
4122
|
+
const isLast = operationCount === totalOperations;
|
|
4123
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
4124
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.oldValue }));
|
|
4125
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
4126
|
+
} else {
|
|
4127
|
+
const permission = modification.permissionsToUpdate[0];
|
|
3740
4128
|
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
3741
|
-
|
|
3742
|
-
lines.push(
|
|
3743
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap)
|
|
3744
|
-
);
|
|
3745
|
-
if (!isLast) lines.push("");
|
|
4129
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap));
|
|
3746
4130
|
}
|
|
4131
|
+
if (!isLast) lines.push("");
|
|
3747
4132
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
3748
|
-
|
|
3749
|
-
|
|
4133
|
+
operationCount++;
|
|
4134
|
+
const isLast = operationCount === totalOperations;
|
|
4135
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
4136
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.oldValue }));
|
|
4137
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
4138
|
+
} else {
|
|
4139
|
+
const rule = modification.rulesToUpdate[0];
|
|
3750
4140
|
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
3751
|
-
const isLast = operationCount === totalOperations;
|
|
3752
4141
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast, collectionIdMap));
|
|
3753
|
-
if (!isLast) lines.push("");
|
|
3754
4142
|
}
|
|
4143
|
+
if (!isLast) lines.push("");
|
|
3755
4144
|
}
|
|
3756
4145
|
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
3757
4146
|
operationCount++;
|
|
@@ -4000,6 +4389,9 @@ function generate(diff, config) {
|
|
|
4000
4389
|
function detectCollectionDeletions(diff) {
|
|
4001
4390
|
const changes = [];
|
|
4002
4391
|
for (const collection of diff.collectionsToDelete) {
|
|
4392
|
+
if (collection.type === "view") {
|
|
4393
|
+
continue;
|
|
4394
|
+
}
|
|
4003
4395
|
changes.push({
|
|
4004
4396
|
type: "collection_deletion" /* COLLECTION_DELETION */,
|
|
4005
4397
|
description: `Delete collection: ${collection.name}`,
|
|
@@ -4413,7 +4805,11 @@ function formatChangeSummary(diff) {
|
|
|
4413
4805
|
lines.push(chalk__default.default.green.bold(`\u2713 ${totalCollectionsToCreate} collection(s) to create:`));
|
|
4414
4806
|
for (const collection of diff.collectionsToCreate) {
|
|
4415
4807
|
lines.push(chalk__default.default.green(` + ${collection.name} (${collection.type})`));
|
|
4416
|
-
|
|
4808
|
+
if (collection.type === "view") {
|
|
4809
|
+
lines.push(chalk__default.default.gray(` fields derived from the view query`));
|
|
4810
|
+
} else {
|
|
4811
|
+
lines.push(chalk__default.default.gray(` ${collection.fields.length} field(s)`));
|
|
4812
|
+
}
|
|
4417
4813
|
}
|
|
4418
4814
|
lines.push("");
|
|
4419
4815
|
}
|
|
@@ -4458,6 +4854,9 @@ function formatChangeSummary(diff) {
|
|
|
4458
4854
|
if (modification.rulesToUpdate.length > 0) {
|
|
4459
4855
|
lines.push(chalk__default.default.yellow(` ~ ${modification.rulesToUpdate.length} rule(s) to update`));
|
|
4460
4856
|
}
|
|
4857
|
+
if (modification.viewQueryUpdate) {
|
|
4858
|
+
lines.push(chalk__default.default.yellow(` ~ view query to update`));
|
|
4859
|
+
}
|
|
4461
4860
|
lines.push("");
|
|
4462
4861
|
}
|
|
4463
4862
|
}
|