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/migrate.cjs
CHANGED
|
@@ -1225,6 +1225,60 @@ function unwrapZodType(zodType) {
|
|
|
1225
1225
|
}
|
|
1226
1226
|
return unwrapped;
|
|
1227
1227
|
}
|
|
1228
|
+
function dedentSql(value) {
|
|
1229
|
+
const lines = value.replace(/\r\n/g, "\n").split("\n");
|
|
1230
|
+
while (lines.length > 0 && lines[0].trim() === "") {
|
|
1231
|
+
lines.shift();
|
|
1232
|
+
}
|
|
1233
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
|
|
1234
|
+
lines.pop();
|
|
1235
|
+
}
|
|
1236
|
+
if (lines.length === 0) {
|
|
1237
|
+
return "";
|
|
1238
|
+
}
|
|
1239
|
+
let minIndent = Infinity;
|
|
1240
|
+
for (const line of lines) {
|
|
1241
|
+
if (line.trim() === "") continue;
|
|
1242
|
+
const indent = line.length - line.trimStart().length;
|
|
1243
|
+
if (indent < minIndent) {
|
|
1244
|
+
minIndent = indent;
|
|
1245
|
+
}
|
|
1246
|
+
}
|
|
1247
|
+
if (!Number.isFinite(minIndent) || minIndent === 0) {
|
|
1248
|
+
return lines.map((line) => line.trimEnd()).join("\n");
|
|
1249
|
+
}
|
|
1250
|
+
return lines.map((line) => line.slice(minIndent).trimEnd()).join("\n");
|
|
1251
|
+
}
|
|
1252
|
+
function stripLeadingComments(query) {
|
|
1253
|
+
let remaining = query.trim();
|
|
1254
|
+
while (remaining.length > 0) {
|
|
1255
|
+
if (remaining.startsWith("--")) {
|
|
1256
|
+
const newline = remaining.indexOf("\n");
|
|
1257
|
+
remaining = newline === -1 ? "" : remaining.slice(newline + 1).trim();
|
|
1258
|
+
continue;
|
|
1259
|
+
}
|
|
1260
|
+
if (remaining.startsWith("/*")) {
|
|
1261
|
+
const end = remaining.indexOf("*/");
|
|
1262
|
+
remaining = end === -1 ? "" : remaining.slice(end + 2).trim();
|
|
1263
|
+
continue;
|
|
1264
|
+
}
|
|
1265
|
+
break;
|
|
1266
|
+
}
|
|
1267
|
+
return remaining;
|
|
1268
|
+
}
|
|
1269
|
+
function validateViewQuery(collectionName, viewQuery) {
|
|
1270
|
+
if (typeof viewQuery !== "string" || viewQuery.trim() === "") {
|
|
1271
|
+
throw new Error(
|
|
1272
|
+
`View collection "${collectionName}" requires a non-empty viewQuery. Provide the SQL SELECT statement backing the view.`
|
|
1273
|
+
);
|
|
1274
|
+
}
|
|
1275
|
+
const body = stripLeadingComments(viewQuery);
|
|
1276
|
+
if (!/^(select|with)\b/i.test(body)) {
|
|
1277
|
+
throw new Error(
|
|
1278
|
+
`View collection "${collectionName}" has an invalid viewQuery: it must start with SELECT or WITH. Received: ${body.slice(0, 40)}${body.length > 40 ? "..." : ""}`
|
|
1279
|
+
);
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1228
1282
|
function getCollectionNameFromFile(filePath) {
|
|
1229
1283
|
const filename = path8__namespace.basename(filePath).replace(/\.(ts|js)$/, "");
|
|
1230
1284
|
return toCollectionName(filename);
|
|
@@ -1248,13 +1302,26 @@ function extractCollectionTypeFromSchema(zodSchema) {
|
|
|
1248
1302
|
}
|
|
1249
1303
|
try {
|
|
1250
1304
|
const metadata = JSON.parse(zodSchema.description);
|
|
1251
|
-
if (metadata.type === "base" || metadata.type === "auth") {
|
|
1305
|
+
if (metadata.type === "base" || metadata.type === "auth" || metadata.type === "view") {
|
|
1252
1306
|
return metadata.type;
|
|
1253
1307
|
}
|
|
1254
1308
|
} catch {
|
|
1255
1309
|
}
|
|
1256
1310
|
return null;
|
|
1257
1311
|
}
|
|
1312
|
+
function extractViewQueryFromSchema(zodSchema) {
|
|
1313
|
+
if (!zodSchema.description) {
|
|
1314
|
+
return null;
|
|
1315
|
+
}
|
|
1316
|
+
try {
|
|
1317
|
+
const metadata = JSON.parse(zodSchema.description);
|
|
1318
|
+
if (typeof metadata.viewQuery === "string") {
|
|
1319
|
+
return metadata.viewQuery;
|
|
1320
|
+
}
|
|
1321
|
+
} catch {
|
|
1322
|
+
}
|
|
1323
|
+
return null;
|
|
1324
|
+
}
|
|
1258
1325
|
function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema", "Collection"]) {
|
|
1259
1326
|
const result = {};
|
|
1260
1327
|
if (module.default instanceof zod.z.ZodObject) {
|
|
@@ -1413,6 +1480,15 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1413
1480
|
const rawFields = extractFieldDefinitions(zodSchema);
|
|
1414
1481
|
const explicitType = extractCollectionTypeFromSchema(zodSchema);
|
|
1415
1482
|
const collectionType = explicitType ?? (isAuthCollection(rawFields) ? "auth" : "base");
|
|
1483
|
+
const isView = collectionType === "view";
|
|
1484
|
+
const viewQuery = extractViewQueryFromSchema(zodSchema);
|
|
1485
|
+
if (isView) {
|
|
1486
|
+
validateViewQuery(collectionName, viewQuery);
|
|
1487
|
+
} else if (viewQuery !== null) {
|
|
1488
|
+
console.warn(
|
|
1489
|
+
`[${collectionName}] viewQuery is only used by view collections and will be ignored. Use defineView() or set type: "view" to define a view collection.`
|
|
1490
|
+
);
|
|
1491
|
+
}
|
|
1416
1492
|
const fields = rawFields.filter((f) => !["created", "updated"].includes(f.name)).map(({ name, zodType }) => buildFieldDefinition(name, zodType));
|
|
1417
1493
|
if (collectionType === "auth") {
|
|
1418
1494
|
const authSystemFields = [
|
|
@@ -1472,26 +1548,43 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1472
1548
|
}
|
|
1473
1549
|
}
|
|
1474
1550
|
const indexes = extractIndexes(zodSchema) || [];
|
|
1551
|
+
if (isView && indexes.length > 0) {
|
|
1552
|
+
throw new Error(
|
|
1553
|
+
`View collection "${collectionName}" cannot declare indexes. PocketBase view collections are backed by a SQL query and do not support indexes.`
|
|
1554
|
+
);
|
|
1555
|
+
}
|
|
1475
1556
|
const permissionAnalyzer = new PermissionAnalyzer();
|
|
1476
1557
|
let permissions = void 0;
|
|
1477
1558
|
const schemaDescription = zodSchema.description;
|
|
1478
1559
|
const extractedPermissions = permissionAnalyzer.extractPermissions(schemaDescription);
|
|
1479
1560
|
if (extractedPermissions) {
|
|
1480
1561
|
const resolvedPermissions = permissionAnalyzer.resolvePermissions(extractedPermissions);
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
1490
|
-
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
1562
|
+
if (isView) {
|
|
1563
|
+
for (const ruleType of ["createRule", "updateRule", "deleteRule", "manageRule"]) {
|
|
1564
|
+
if (resolvedPermissions[ruleType]) {
|
|
1565
|
+
console.warn(
|
|
1566
|
+
`[${collectionName}] ${ruleType} is not supported on view collections and will be set to null.`
|
|
1567
|
+
);
|
|
1568
|
+
}
|
|
1569
|
+
resolvedPermissions[ruleType] = null;
|
|
1491
1570
|
}
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1571
|
+
}
|
|
1572
|
+
if (!isView) {
|
|
1573
|
+
const validationResults = permissionAnalyzer.validatePermissions(
|
|
1574
|
+
collectionName,
|
|
1575
|
+
resolvedPermissions,
|
|
1576
|
+
fields,
|
|
1577
|
+
collectionType === "auth"
|
|
1578
|
+
);
|
|
1579
|
+
for (const [ruleType, result] of validationResults) {
|
|
1580
|
+
if (!result.valid) {
|
|
1581
|
+
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
1582
|
+
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
1583
|
+
}
|
|
1584
|
+
if (result.warnings.length > 0) {
|
|
1585
|
+
console.warn(`[${collectionName}] Permission warnings for ${ruleType}:`);
|
|
1586
|
+
result.warnings.forEach((warning) => console.warn(` - ${warning}`));
|
|
1587
|
+
}
|
|
1495
1588
|
}
|
|
1496
1589
|
}
|
|
1497
1590
|
permissions = permissionAnalyzer.mergeWithDefaults(resolvedPermissions);
|
|
@@ -1512,6 +1605,9 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1512
1605
|
},
|
|
1513
1606
|
permissions
|
|
1514
1607
|
};
|
|
1608
|
+
if (isView) {
|
|
1609
|
+
collectionSchema.viewQuery = viewQuery;
|
|
1610
|
+
}
|
|
1515
1611
|
return collectionSchema;
|
|
1516
1612
|
}
|
|
1517
1613
|
var tsxLoaderRegistered = false;
|
|
@@ -1769,8 +1865,9 @@ function convertPocketBaseField(pbField) {
|
|
|
1769
1865
|
}
|
|
1770
1866
|
function convertPocketBaseCollection(pbCollection) {
|
|
1771
1867
|
const fields = [];
|
|
1868
|
+
const isView = pbCollection.type === "view";
|
|
1772
1869
|
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
1773
|
-
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
1870
|
+
if (!isView && pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
1774
1871
|
for (const pbField of pbCollection.fields) {
|
|
1775
1872
|
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
1776
1873
|
const isAuthSystemField = pbCollection.type === "auth" && ["email", "emailVisibility", "verified", "password", "tokenKey"].includes(pbField.name);
|
|
@@ -1790,6 +1887,9 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
1790
1887
|
if (pbCollection.id) {
|
|
1791
1888
|
schema.id = pbCollection.id;
|
|
1792
1889
|
}
|
|
1890
|
+
if (typeof pbCollection.viewQuery === "string") {
|
|
1891
|
+
schema.viewQuery = dedentSql(pbCollection.viewQuery);
|
|
1892
|
+
}
|
|
1793
1893
|
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
1794
1894
|
schema.indexes = pbCollection.indexes;
|
|
1795
1895
|
}
|
|
@@ -1891,6 +1991,24 @@ function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
|
|
|
1891
1991
|
return [];
|
|
1892
1992
|
}
|
|
1893
1993
|
}
|
|
1994
|
+
function skipTemplateLiteral(content, start) {
|
|
1995
|
+
let i = start + 1;
|
|
1996
|
+
while (i < content.length) {
|
|
1997
|
+
const char = content[i];
|
|
1998
|
+
if (char === "\\") {
|
|
1999
|
+
i += 2;
|
|
2000
|
+
continue;
|
|
2001
|
+
}
|
|
2002
|
+
if (char === "`") {
|
|
2003
|
+
return i + 1;
|
|
2004
|
+
}
|
|
2005
|
+
i++;
|
|
2006
|
+
}
|
|
2007
|
+
return i;
|
|
2008
|
+
}
|
|
2009
|
+
function unescapeTemplateLiteral(raw) {
|
|
2010
|
+
return raw.replace(/\\(`|\$\{|\\)/g, "$1");
|
|
2011
|
+
}
|
|
1894
2012
|
function parseMigrationOperationsFromContent(content) {
|
|
1895
2013
|
const collectionsToCreate = [];
|
|
1896
2014
|
const collectionsToDelete = [];
|
|
@@ -1979,6 +2097,10 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
1979
2097
|
while (i < content.length && bCount > 0) {
|
|
1980
2098
|
const char = content[i];
|
|
1981
2099
|
const prev = i > 0 ? content[i - 1] : "";
|
|
2100
|
+
if (!inStr && char === "`") {
|
|
2101
|
+
i = skipTemplateLiteral(content, i);
|
|
2102
|
+
continue;
|
|
2103
|
+
}
|
|
1982
2104
|
if (!inStr && (char === '"' || char === "'")) {
|
|
1983
2105
|
inStr = true;
|
|
1984
2106
|
strChar = char;
|
|
@@ -2168,6 +2290,95 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
2168
2290
|
}
|
|
2169
2291
|
}
|
|
2170
2292
|
}
|
|
2293
|
+
const viewQueryRegex = /(\w+)\.viewQuery\s*=\s*/g;
|
|
2294
|
+
let viewQueryMatch;
|
|
2295
|
+
while ((viewQueryMatch = viewQueryRegex.exec(content)) !== null) {
|
|
2296
|
+
const varInfo = variables.get(viewQueryMatch[1]);
|
|
2297
|
+
if (!varInfo || varInfo.type !== "collection") continue;
|
|
2298
|
+
const valueStart = viewQueryMatch.index + viewQueryMatch[0].length;
|
|
2299
|
+
if (content[valueStart] === "`") {
|
|
2300
|
+
const end = skipTemplateLiteral(content, valueStart);
|
|
2301
|
+
const raw = content.substring(valueStart + 1, end - 1);
|
|
2302
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
2303
|
+
viewQueryRegex.lastIndex = end;
|
|
2304
|
+
} else {
|
|
2305
|
+
const terminator = content.indexOf(";", valueStart);
|
|
2306
|
+
const valueStr = content.substring(valueStart, terminator === -1 ? content.length : terminator);
|
|
2307
|
+
try {
|
|
2308
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(new Function("app", `return ${valueStr}`)(mockApp));
|
|
2309
|
+
} catch {
|
|
2310
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(valueStr.trim());
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
}
|
|
2314
|
+
const unmarshalRegex = /unmarshal\s*\(/g;
|
|
2315
|
+
let unmarshalMatch;
|
|
2316
|
+
while ((unmarshalMatch = unmarshalRegex.exec(content)) !== null) {
|
|
2317
|
+
let i = unmarshalMatch.index + unmarshalMatch[0].length;
|
|
2318
|
+
while (i < content.length && /\s/.test(content[i])) i++;
|
|
2319
|
+
if (content[i] !== "{") continue;
|
|
2320
|
+
const objStart = i;
|
|
2321
|
+
let braceCount = 1;
|
|
2322
|
+
let inStr = false;
|
|
2323
|
+
let strChar = null;
|
|
2324
|
+
i++;
|
|
2325
|
+
while (i < content.length && braceCount > 0) {
|
|
2326
|
+
const ch = content[i];
|
|
2327
|
+
const prev = i > 0 ? content[i - 1] : "";
|
|
2328
|
+
if (!inStr && ch === "`") {
|
|
2329
|
+
i = skipTemplateLiteral(content, i);
|
|
2330
|
+
continue;
|
|
2331
|
+
}
|
|
2332
|
+
if (!inStr && (ch === '"' || ch === "'")) {
|
|
2333
|
+
inStr = true;
|
|
2334
|
+
strChar = ch;
|
|
2335
|
+
} else if (inStr && ch === strChar && prev !== "\\") {
|
|
2336
|
+
inStr = false;
|
|
2337
|
+
strChar = null;
|
|
2338
|
+
}
|
|
2339
|
+
if (!inStr) {
|
|
2340
|
+
if (ch === "{") braceCount++;
|
|
2341
|
+
if (ch === "}") braceCount--;
|
|
2342
|
+
}
|
|
2343
|
+
i++;
|
|
2344
|
+
}
|
|
2345
|
+
if (braceCount !== 0) continue;
|
|
2346
|
+
const objStr = content.substring(objStart, i);
|
|
2347
|
+
while (i < content.length && /[\s,]/.test(content[i])) i++;
|
|
2348
|
+
const varStart = i;
|
|
2349
|
+
while (i < content.length && /\w/.test(content[i])) i++;
|
|
2350
|
+
const colVarName = content.substring(varStart, i);
|
|
2351
|
+
const colInfo = variables.get(colVarName);
|
|
2352
|
+
if (!colInfo || colInfo.type !== "collection") continue;
|
|
2353
|
+
const keyValRegex = /"(\w+Rule)"\s*:\s*([^,}\n]+)/g;
|
|
2354
|
+
let kvMatch;
|
|
2355
|
+
while ((kvMatch = keyValRegex.exec(objStr)) !== null) {
|
|
2356
|
+
const ruleKey = kvMatch[1];
|
|
2357
|
+
const valStr = kvMatch[2].trim();
|
|
2358
|
+
try {
|
|
2359
|
+
const value = new Function("app", `return ${valStr}`)(mockApp);
|
|
2360
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = value;
|
|
2361
|
+
} catch {
|
|
2362
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = valStr;
|
|
2363
|
+
}
|
|
2364
|
+
}
|
|
2365
|
+
const viewQueryKey = objStr.match(/"viewQuery"\s*:\s*/);
|
|
2366
|
+
if (viewQueryKey) {
|
|
2367
|
+
const valueStart = viewQueryKey.index + viewQueryKey[0].length;
|
|
2368
|
+
if (objStr[valueStart] === "`") {
|
|
2369
|
+
const end = skipTemplateLiteral(objStr, valueStart);
|
|
2370
|
+
const raw = objStr.substring(valueStart + 1, end - 1);
|
|
2371
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
2372
|
+
} else {
|
|
2373
|
+
const valStr = objStr.substring(valueStart).replace(/[,}\s]+$/, "");
|
|
2374
|
+
try {
|
|
2375
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(new Function("app", `return ${valStr}`)(mockApp));
|
|
2376
|
+
} catch {
|
|
2377
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(valStr);
|
|
2378
|
+
}
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
}
|
|
2171
2382
|
const idxPushRegex = /(\w+)\.indexes\.push\s*\(/g;
|
|
2172
2383
|
let match;
|
|
2173
2384
|
while ((match = idxPushRegex.exec(content)) !== null) {
|
|
@@ -2297,6 +2508,10 @@ function parseMigrationOperations(migrationContent) {
|
|
|
2297
2508
|
while (i < migrationContent.length && braceCount > 0) {
|
|
2298
2509
|
const char = migrationContent[i];
|
|
2299
2510
|
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
2511
|
+
if (!inString && char === "`") {
|
|
2512
|
+
i = skipTemplateLiteral(migrationContent, i);
|
|
2513
|
+
continue;
|
|
2514
|
+
}
|
|
2300
2515
|
if (!inString && (char === '"' || char === "'")) {
|
|
2301
2516
|
inString = true;
|
|
2302
2517
|
stringChar = char;
|
|
@@ -2404,6 +2619,9 @@ function applyMigrationOperations(snapshot, operations) {
|
|
|
2404
2619
|
collection.indexes = collection.indexes.filter((idx) => !update.indexesToRemove.includes(idx));
|
|
2405
2620
|
}
|
|
2406
2621
|
}
|
|
2622
|
+
if (update.viewQuery !== void 0) {
|
|
2623
|
+
collection.viewQuery = update.viewQuery;
|
|
2624
|
+
}
|
|
2407
2625
|
if (Object.keys(update.rulesToUpdate).length > 0) {
|
|
2408
2626
|
if (!collection.rules) collection.rules = {};
|
|
2409
2627
|
if (!collection.permissions) collection.permissions = {};
|
|
@@ -2867,7 +3085,45 @@ function compareCollectionFields(currentCollection, previousCollection, config,
|
|
|
2867
3085
|
fieldsToRemove = fieldsToRemove.filter((_, index) => !processedRemoveIndices.has(index));
|
|
2868
3086
|
return { fieldsToAdd, fieldsToRemove, fieldsToModify };
|
|
2869
3087
|
}
|
|
3088
|
+
function normalizeSql(query) {
|
|
3089
|
+
if (!query) {
|
|
3090
|
+
return "";
|
|
3091
|
+
}
|
|
3092
|
+
return query.split("\n").map((line) => line.trim()).join(" ").replace(/\s+/g, " ").trim();
|
|
3093
|
+
}
|
|
3094
|
+
function compareViewQuery(currentCollection, previousCollection) {
|
|
3095
|
+
const newValue = currentCollection.viewQuery;
|
|
3096
|
+
if (typeof newValue !== "string") {
|
|
3097
|
+
return void 0;
|
|
3098
|
+
}
|
|
3099
|
+
if (normalizeSql(newValue) === normalizeSql(previousCollection.viewQuery)) {
|
|
3100
|
+
return void 0;
|
|
3101
|
+
}
|
|
3102
|
+
return {
|
|
3103
|
+
oldValue: previousCollection.viewQuery ?? null,
|
|
3104
|
+
newValue
|
|
3105
|
+
};
|
|
3106
|
+
}
|
|
2870
3107
|
function buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName) {
|
|
3108
|
+
const isView = currentCollection.type === "view" || previousCollection.type === "view";
|
|
3109
|
+
if (isView) {
|
|
3110
|
+
return {
|
|
3111
|
+
collection: currentCollection.name,
|
|
3112
|
+
fieldsToAdd: [],
|
|
3113
|
+
fieldsToRemove: [],
|
|
3114
|
+
fieldsToModify: [],
|
|
3115
|
+
indexesToAdd: [],
|
|
3116
|
+
indexesToRemove: [],
|
|
3117
|
+
rulesToUpdate: compareRules(
|
|
3118
|
+
currentCollection.rules,
|
|
3119
|
+
previousCollection.rules,
|
|
3120
|
+
currentCollection.permissions,
|
|
3121
|
+
previousCollection.permissions
|
|
3122
|
+
),
|
|
3123
|
+
permissionsToUpdate: comparePermissions(currentCollection.permissions, previousCollection.permissions),
|
|
3124
|
+
viewQueryUpdate: compareViewQuery(currentCollection, previousCollection)
|
|
3125
|
+
};
|
|
3126
|
+
}
|
|
2871
3127
|
const { fieldsToAdd, fieldsToRemove, fieldsToModify } = compareCollectionFields(
|
|
2872
3128
|
currentCollection,
|
|
2873
3129
|
previousCollection,
|
|
@@ -2899,7 +3155,11 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
2899
3155
|
const destructive = [];
|
|
2900
3156
|
const nonDestructive = [];
|
|
2901
3157
|
for (const collection of diff.collectionsToDelete) {
|
|
2902
|
-
|
|
3158
|
+
if (collection.type === "view") {
|
|
3159
|
+
nonDestructive.push(`Delete view collection: ${collection.name}`);
|
|
3160
|
+
} else {
|
|
3161
|
+
destructive.push(`Delete collection: ${collection.name}`);
|
|
3162
|
+
}
|
|
2903
3163
|
}
|
|
2904
3164
|
for (const collection of diff.collectionsToCreate) {
|
|
2905
3165
|
nonDestructive.push(`Create collection: ${collection.name}`);
|
|
@@ -2934,6 +3194,9 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
2934
3194
|
for (const rule of modification.rulesToUpdate) {
|
|
2935
3195
|
nonDestructive.push(`Update rule: ${collectionName}.${rule.ruleType}`);
|
|
2936
3196
|
}
|
|
3197
|
+
if (modification.viewQueryUpdate) {
|
|
3198
|
+
nonDestructive.push(`Update view query: ${collectionName}`);
|
|
3199
|
+
}
|
|
2937
3200
|
}
|
|
2938
3201
|
return { destructive, nonDestructive };
|
|
2939
3202
|
}
|
|
@@ -2962,12 +3225,11 @@ function filterDiff(diff, options) {
|
|
|
2962
3225
|
});
|
|
2963
3226
|
let collectionsToDelete = diff.collectionsToDelete;
|
|
2964
3227
|
if (skipDestructive) {
|
|
2965
|
-
collectionsToDelete =
|
|
2966
|
-
} else {
|
|
2967
|
-
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
2968
|
-
return matchesPattern(col.name, patterns);
|
|
2969
|
-
});
|
|
3228
|
+
collectionsToDelete = collectionsToDelete.filter((col) => col.type === "view");
|
|
2970
3229
|
}
|
|
3230
|
+
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
3231
|
+
return matchesPattern(col.name, patterns);
|
|
3232
|
+
});
|
|
2971
3233
|
const collectionsToModify = diff.collectionsToModify.map((mod) => {
|
|
2972
3234
|
const collectionMatches = matchesPattern(mod.collection, patterns);
|
|
2973
3235
|
const fieldsToAdd = mod.fieldsToAdd.filter((field) => {
|
|
@@ -2992,6 +3254,7 @@ function filterDiff(diff, options) {
|
|
|
2992
3254
|
const indexesToRemove = collectionMatches ? mod.indexesToRemove : [];
|
|
2993
3255
|
const rulesToUpdate = collectionMatches ? mod.rulesToUpdate : [];
|
|
2994
3256
|
const permissionsToUpdate = collectionMatches ? mod.permissionsToUpdate : [];
|
|
3257
|
+
const viewQueryUpdate = collectionMatches ? mod.viewQueryUpdate : void 0;
|
|
2995
3258
|
return {
|
|
2996
3259
|
...mod,
|
|
2997
3260
|
fieldsToAdd,
|
|
@@ -3000,10 +3263,11 @@ function filterDiff(diff, options) {
|
|
|
3000
3263
|
indexesToAdd,
|
|
3001
3264
|
indexesToRemove,
|
|
3002
3265
|
rulesToUpdate,
|
|
3003
|
-
permissionsToUpdate
|
|
3266
|
+
permissionsToUpdate,
|
|
3267
|
+
viewQueryUpdate
|
|
3004
3268
|
};
|
|
3005
3269
|
}).filter((mod) => {
|
|
3006
|
-
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;
|
|
3270
|
+
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;
|
|
3007
3271
|
});
|
|
3008
3272
|
return {
|
|
3009
3273
|
...diff,
|
|
@@ -3015,7 +3279,7 @@ function filterDiff(diff, options) {
|
|
|
3015
3279
|
|
|
3016
3280
|
// src/migration/diff/index.ts
|
|
3017
3281
|
function hasChanges(modification) {
|
|
3018
|
-
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;
|
|
3282
|
+
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;
|
|
3019
3283
|
}
|
|
3020
3284
|
function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
3021
3285
|
const collectionIdToName = /* @__PURE__ */ new Map();
|
|
@@ -3194,6 +3458,13 @@ function formatValue(value) {
|
|
|
3194
3458
|
}
|
|
3195
3459
|
return String(value);
|
|
3196
3460
|
}
|
|
3461
|
+
function formatSqlTemplate(query, indent = " ") {
|
|
3462
|
+
const escaped = query.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
3463
|
+
const body = escaped.split("\n").map((line) => line.trim() === "" ? "" : `${indent}${line}`).join("\n");
|
|
3464
|
+
return `\`
|
|
3465
|
+
${body}
|
|
3466
|
+
${indent.slice(0, -2)}\``;
|
|
3467
|
+
}
|
|
3197
3468
|
function getFieldConstructorName(fieldType) {
|
|
3198
3469
|
const constructorMap = {
|
|
3199
3470
|
text: "TextField",
|
|
@@ -3232,6 +3503,36 @@ function getSystemFields() {
|
|
|
3232
3503
|
}
|
|
3233
3504
|
];
|
|
3234
3505
|
}
|
|
3506
|
+
function getSystemTimestampFields() {
|
|
3507
|
+
return [
|
|
3508
|
+
{
|
|
3509
|
+
name: "created",
|
|
3510
|
+
id: "autodate2990389176",
|
|
3511
|
+
type: "autodate",
|
|
3512
|
+
required: false,
|
|
3513
|
+
options: {
|
|
3514
|
+
hidden: false,
|
|
3515
|
+
onCreate: true,
|
|
3516
|
+
onUpdate: false,
|
|
3517
|
+
presentable: false,
|
|
3518
|
+
system: true
|
|
3519
|
+
}
|
|
3520
|
+
},
|
|
3521
|
+
{
|
|
3522
|
+
name: "updated",
|
|
3523
|
+
id: "autodate3332085495",
|
|
3524
|
+
type: "autodate",
|
|
3525
|
+
required: false,
|
|
3526
|
+
options: {
|
|
3527
|
+
hidden: false,
|
|
3528
|
+
onCreate: true,
|
|
3529
|
+
onUpdate: true,
|
|
3530
|
+
presentable: false,
|
|
3531
|
+
system: true
|
|
3532
|
+
}
|
|
3533
|
+
}
|
|
3534
|
+
];
|
|
3535
|
+
}
|
|
3235
3536
|
function getAuthSystemFields() {
|
|
3236
3537
|
return [
|
|
3237
3538
|
{
|
|
@@ -3524,6 +3825,15 @@ function generateCollectionRules(rules, collectionType = "base") {
|
|
|
3524
3825
|
if (!rules) {
|
|
3525
3826
|
return "";
|
|
3526
3827
|
}
|
|
3828
|
+
if (collectionType === "view") {
|
|
3829
|
+
return [
|
|
3830
|
+
`"listRule": ${formatValue(rules.listRule ?? null)}`,
|
|
3831
|
+
`"viewRule": ${formatValue(rules.viewRule ?? null)}`,
|
|
3832
|
+
`"createRule": null`,
|
|
3833
|
+
`"updateRule": null`,
|
|
3834
|
+
`"deleteRule": null`
|
|
3835
|
+
].join(",\n ");
|
|
3836
|
+
}
|
|
3527
3837
|
const parts = [];
|
|
3528
3838
|
if (rules.listRule !== void 0) {
|
|
3529
3839
|
parts.push(`"listRule": ${formatValue(rules.listRule)}`);
|
|
@@ -3549,6 +3859,15 @@ function generateCollectionPermissions(permissions, collectionType = "base") {
|
|
|
3549
3859
|
if (!permissions) {
|
|
3550
3860
|
return "";
|
|
3551
3861
|
}
|
|
3862
|
+
if (collectionType === "view") {
|
|
3863
|
+
return [
|
|
3864
|
+
`"listRule": ${formatValue(permissions.listRule ?? null)}`,
|
|
3865
|
+
`"viewRule": ${formatValue(permissions.viewRule ?? null)}`,
|
|
3866
|
+
`"createRule": null`,
|
|
3867
|
+
`"updateRule": null`,
|
|
3868
|
+
`"deleteRule": null`
|
|
3869
|
+
].join(",\n ");
|
|
3870
|
+
}
|
|
3552
3871
|
const parts = [];
|
|
3553
3872
|
if (permissions.listRule !== void 0) {
|
|
3554
3873
|
parts.push(`"listRule": ${formatValue(permissions.listRule)}`);
|
|
@@ -3586,6 +3905,28 @@ function generatePermissionUpdate(collectionName, ruleType, newValue, varName, i
|
|
|
3586
3905
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3587
3906
|
return lines.join("\n");
|
|
3588
3907
|
}
|
|
3908
|
+
function generateViewQueryUpdate(collectionName, viewQuery, varName, isLast = false, collectionIdMap) {
|
|
3909
|
+
const lines = [];
|
|
3910
|
+
const collectionVar = varName || `collection_${collectionName}_viewQuery`;
|
|
3911
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
3912
|
+
lines.push(` unmarshal({`);
|
|
3913
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(viewQuery, " ")},`);
|
|
3914
|
+
lines.push(` }, ${collectionVar})`);
|
|
3915
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3916
|
+
return lines.join("\n");
|
|
3917
|
+
}
|
|
3918
|
+
function generateGroupedRuleUpdates(collectionName, entries, varSuffix, isLast = false, collectionIdMap) {
|
|
3919
|
+
const collectionVar = `collection_${collectionName}_${varSuffix}`;
|
|
3920
|
+
const lines = [];
|
|
3921
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
3922
|
+
lines.push(` unmarshal({`);
|
|
3923
|
+
for (const entry of entries) {
|
|
3924
|
+
lines.push(` "${entry.ruleType}": ${formatValue(entry.value)},`);
|
|
3925
|
+
}
|
|
3926
|
+
lines.push(` }, ${collectionVar})`);
|
|
3927
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3928
|
+
return lines.join("\n");
|
|
3929
|
+
}
|
|
3589
3930
|
|
|
3590
3931
|
// src/migration/generator/collections.ts
|
|
3591
3932
|
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
@@ -3604,16 +3945,24 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
|
|
|
3604
3945
|
} else if (rulesCode) {
|
|
3605
3946
|
lines.push(` ${rulesCode},`);
|
|
3606
3947
|
}
|
|
3948
|
+
if (collection.type === "view") {
|
|
3949
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(collection.viewQuery ?? "")},`);
|
|
3950
|
+
lines.push(` });`);
|
|
3951
|
+
lines.push(``);
|
|
3952
|
+
lines.push(isLast ? ` return app.save(${varName});` : ` app.save(${varName});`);
|
|
3953
|
+
return lines.join("\n");
|
|
3954
|
+
}
|
|
3607
3955
|
const systemFieldNames = ["created", "updated", "id"];
|
|
3608
3956
|
if (collection.type === "auth") {
|
|
3609
3957
|
systemFieldNames.push(...getAuthSystemFields().map((f) => f.name));
|
|
3610
3958
|
}
|
|
3611
3959
|
const userFields = collection.fields.filter((f) => !systemFieldNames.includes(f.name));
|
|
3612
|
-
const allFields = [...getSystemFields()
|
|
3960
|
+
const allFields = [...getSystemFields()];
|
|
3613
3961
|
if (collection.type === "auth") {
|
|
3614
3962
|
allFields.push(...getAuthSystemFields());
|
|
3615
3963
|
}
|
|
3616
3964
|
allFields.push(...userFields);
|
|
3965
|
+
allFields.push(...getSystemTimestampFields());
|
|
3617
3966
|
lines.push(` "fields": ${generateFieldsArray(allFields, collectionIdMap)},`);
|
|
3618
3967
|
let allIndexes = [...collection.indexes || []];
|
|
3619
3968
|
if (collection.type === "auth") {
|
|
@@ -3643,7 +3992,21 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
3643
3992
|
const modification = operation.modifications;
|
|
3644
3993
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
3645
3994
|
let operationCount = 0;
|
|
3646
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
3995
|
+
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);
|
|
3996
|
+
if (modification.viewQueryUpdate) {
|
|
3997
|
+
operationCount++;
|
|
3998
|
+
const isLast = operationCount === totalOperations;
|
|
3999
|
+
lines.push(
|
|
4000
|
+
generateViewQueryUpdate(
|
|
4001
|
+
collectionName,
|
|
4002
|
+
modification.viewQueryUpdate.newValue,
|
|
4003
|
+
void 0,
|
|
4004
|
+
isLast,
|
|
4005
|
+
collectionIdMap
|
|
4006
|
+
)
|
|
4007
|
+
);
|
|
4008
|
+
if (!isLast) lines.push("");
|
|
4009
|
+
}
|
|
3647
4010
|
for (let i = 0; i < modification.fieldsToAdd.length; i++) {
|
|
3648
4011
|
const field = modification.fieldsToAdd[i];
|
|
3649
4012
|
operationCount++;
|
|
@@ -3683,23 +4046,29 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
3683
4046
|
if (!isLast) lines.push("");
|
|
3684
4047
|
}
|
|
3685
4048
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
3686
|
-
|
|
3687
|
-
|
|
4049
|
+
operationCount++;
|
|
4050
|
+
const isLast = operationCount === totalOperations;
|
|
4051
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
4052
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.newValue }));
|
|
4053
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
4054
|
+
} else {
|
|
4055
|
+
const permission = modification.permissionsToUpdate[0];
|
|
3688
4056
|
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
3689
|
-
|
|
3690
|
-
lines.push(
|
|
3691
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap)
|
|
3692
|
-
);
|
|
3693
|
-
if (!isLast) lines.push("");
|
|
4057
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap));
|
|
3694
4058
|
}
|
|
4059
|
+
if (!isLast) lines.push("");
|
|
3695
4060
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
3696
|
-
|
|
3697
|
-
|
|
4061
|
+
operationCount++;
|
|
4062
|
+
const isLast = operationCount === totalOperations;
|
|
4063
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
4064
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.newValue }));
|
|
4065
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
4066
|
+
} else {
|
|
4067
|
+
const rule = modification.rulesToUpdate[0];
|
|
3698
4068
|
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
3699
|
-
const isLast = operationCount === totalOperations;
|
|
3700
4069
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast, collectionIdMap));
|
|
3701
|
-
if (!isLast) lines.push("");
|
|
3702
4070
|
}
|
|
4071
|
+
if (!isLast) lines.push("");
|
|
3703
4072
|
}
|
|
3704
4073
|
} else if (operation.type === "delete") {
|
|
3705
4074
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
|
|
@@ -3738,25 +4107,45 @@ function generateOperationDownMigration(operation, collectionIdMap) {
|
|
|
3738
4107
|
const modification = operation.modifications;
|
|
3739
4108
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
3740
4109
|
let operationCount = 0;
|
|
3741
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
4110
|
+
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);
|
|
4111
|
+
if (modification.viewQueryUpdate) {
|
|
4112
|
+
operationCount++;
|
|
4113
|
+
const isLast = operationCount === totalOperations;
|
|
4114
|
+
lines.push(
|
|
4115
|
+
generateViewQueryUpdate(
|
|
4116
|
+
collectionName,
|
|
4117
|
+
modification.viewQueryUpdate.oldValue ?? "",
|
|
4118
|
+
`collection_${collectionName}_revert_viewQuery`,
|
|
4119
|
+
isLast,
|
|
4120
|
+
collectionIdMap
|
|
4121
|
+
)
|
|
4122
|
+
);
|
|
4123
|
+
if (!isLast) lines.push("");
|
|
4124
|
+
}
|
|
3742
4125
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
3743
|
-
|
|
3744
|
-
|
|
4126
|
+
operationCount++;
|
|
4127
|
+
const isLast = operationCount === totalOperations;
|
|
4128
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
4129
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.oldValue }));
|
|
4130
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
4131
|
+
} else {
|
|
4132
|
+
const permission = modification.permissionsToUpdate[0];
|
|
3745
4133
|
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
3746
|
-
|
|
3747
|
-
lines.push(
|
|
3748
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap)
|
|
3749
|
-
);
|
|
3750
|
-
if (!isLast) lines.push("");
|
|
4134
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap));
|
|
3751
4135
|
}
|
|
4136
|
+
if (!isLast) lines.push("");
|
|
3752
4137
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
3753
|
-
|
|
3754
|
-
|
|
4138
|
+
operationCount++;
|
|
4139
|
+
const isLast = operationCount === totalOperations;
|
|
4140
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
4141
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.oldValue }));
|
|
4142
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
4143
|
+
} else {
|
|
4144
|
+
const rule = modification.rulesToUpdate[0];
|
|
3755
4145
|
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
3756
|
-
const isLast = operationCount === totalOperations;
|
|
3757
4146
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast, collectionIdMap));
|
|
3758
|
-
if (!isLast) lines.push("");
|
|
3759
4147
|
}
|
|
4148
|
+
if (!isLast) lines.push("");
|
|
3760
4149
|
}
|
|
3761
4150
|
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
3762
4151
|
operationCount++;
|
|
@@ -4005,6 +4394,9 @@ function generate(diff, config) {
|
|
|
4005
4394
|
function detectCollectionDeletions(diff) {
|
|
4006
4395
|
const changes = [];
|
|
4007
4396
|
for (const collection of diff.collectionsToDelete) {
|
|
4397
|
+
if (collection.type === "view") {
|
|
4398
|
+
continue;
|
|
4399
|
+
}
|
|
4008
4400
|
changes.push({
|
|
4009
4401
|
type: "collection_deletion" /* COLLECTION_DELETION */,
|
|
4010
4402
|
description: `Delete collection: ${collection.name}`,
|
|
@@ -4415,7 +4807,11 @@ function formatChangeSummary(diff) {
|
|
|
4415
4807
|
lines.push(chalk__default.default.green.bold(`\u2713 ${totalCollectionsToCreate} collection(s) to create:`));
|
|
4416
4808
|
for (const collection of diff.collectionsToCreate) {
|
|
4417
4809
|
lines.push(chalk__default.default.green(` + ${collection.name} (${collection.type})`));
|
|
4418
|
-
|
|
4810
|
+
if (collection.type === "view") {
|
|
4811
|
+
lines.push(chalk__default.default.gray(` fields derived from the view query`));
|
|
4812
|
+
} else {
|
|
4813
|
+
lines.push(chalk__default.default.gray(` ${collection.fields.length} field(s)`));
|
|
4814
|
+
}
|
|
4419
4815
|
}
|
|
4420
4816
|
lines.push("");
|
|
4421
4817
|
}
|
|
@@ -4460,6 +4856,9 @@ function formatChangeSummary(diff) {
|
|
|
4460
4856
|
if (modification.rulesToUpdate.length > 0) {
|
|
4461
4857
|
lines.push(chalk__default.default.yellow(` ~ ${modification.rulesToUpdate.length} rule(s) to update`));
|
|
4462
4858
|
}
|
|
4859
|
+
if (modification.viewQueryUpdate) {
|
|
4860
|
+
lines.push(chalk__default.default.yellow(` ~ view query to update`));
|
|
4861
|
+
}
|
|
4463
4862
|
lines.push("");
|
|
4464
4863
|
}
|
|
4465
4864
|
}
|
|
@@ -4845,11 +5244,14 @@ var TypeGenerator = class {
|
|
|
4845
5244
|
}
|
|
4846
5245
|
generateCollectionType(collection) {
|
|
4847
5246
|
const typeName = this.toPascalCase(collection.name);
|
|
5247
|
+
const isView = collection.type === "view";
|
|
4848
5248
|
const lines = [];
|
|
4849
5249
|
lines.push(`export interface ${typeName}Record {`);
|
|
4850
5250
|
lines.push(` id: string;`);
|
|
4851
|
-
|
|
4852
|
-
|
|
5251
|
+
if (!isView) {
|
|
5252
|
+
lines.push(` created: string;`);
|
|
5253
|
+
lines.push(` updated: string;`);
|
|
5254
|
+
}
|
|
4853
5255
|
lines.push(` collectionId: string;`);
|
|
4854
5256
|
lines.push(` collectionName: "${collection.name}";`);
|
|
4855
5257
|
for (const field of collection.fields) {
|
|
@@ -4861,7 +5263,7 @@ var TypeGenerator = class {
|
|
|
4861
5263
|
lines.push(`}`);
|
|
4862
5264
|
lines.push(``);
|
|
4863
5265
|
const expandFields = [];
|
|
4864
|
-
for (const field of collection.fields) {
|
|
5266
|
+
for (const field of isView ? [] : collection.fields) {
|
|
4865
5267
|
if (field.type === "relation" && field.relation) {
|
|
4866
5268
|
const targetCollection = field.relation.collection;
|
|
4867
5269
|
let targetType = "RecordModel";
|