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.js
CHANGED
|
@@ -1196,6 +1196,60 @@ function unwrapZodType(zodType) {
|
|
|
1196
1196
|
}
|
|
1197
1197
|
return unwrapped;
|
|
1198
1198
|
}
|
|
1199
|
+
function dedentSql(value) {
|
|
1200
|
+
const lines = value.replace(/\r\n/g, "\n").split("\n");
|
|
1201
|
+
while (lines.length > 0 && lines[0].trim() === "") {
|
|
1202
|
+
lines.shift();
|
|
1203
|
+
}
|
|
1204
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
|
|
1205
|
+
lines.pop();
|
|
1206
|
+
}
|
|
1207
|
+
if (lines.length === 0) {
|
|
1208
|
+
return "";
|
|
1209
|
+
}
|
|
1210
|
+
let minIndent = Infinity;
|
|
1211
|
+
for (const line of lines) {
|
|
1212
|
+
if (line.trim() === "") continue;
|
|
1213
|
+
const indent = line.length - line.trimStart().length;
|
|
1214
|
+
if (indent < minIndent) {
|
|
1215
|
+
minIndent = indent;
|
|
1216
|
+
}
|
|
1217
|
+
}
|
|
1218
|
+
if (!Number.isFinite(minIndent) || minIndent === 0) {
|
|
1219
|
+
return lines.map((line) => line.trimEnd()).join("\n");
|
|
1220
|
+
}
|
|
1221
|
+
return lines.map((line) => line.slice(minIndent).trimEnd()).join("\n");
|
|
1222
|
+
}
|
|
1223
|
+
function stripLeadingComments(query) {
|
|
1224
|
+
let remaining = query.trim();
|
|
1225
|
+
while (remaining.length > 0) {
|
|
1226
|
+
if (remaining.startsWith("--")) {
|
|
1227
|
+
const newline = remaining.indexOf("\n");
|
|
1228
|
+
remaining = newline === -1 ? "" : remaining.slice(newline + 1).trim();
|
|
1229
|
+
continue;
|
|
1230
|
+
}
|
|
1231
|
+
if (remaining.startsWith("/*")) {
|
|
1232
|
+
const end = remaining.indexOf("*/");
|
|
1233
|
+
remaining = end === -1 ? "" : remaining.slice(end + 2).trim();
|
|
1234
|
+
continue;
|
|
1235
|
+
}
|
|
1236
|
+
break;
|
|
1237
|
+
}
|
|
1238
|
+
return remaining;
|
|
1239
|
+
}
|
|
1240
|
+
function validateViewQuery(collectionName, viewQuery) {
|
|
1241
|
+
if (typeof viewQuery !== "string" || viewQuery.trim() === "") {
|
|
1242
|
+
throw new Error(
|
|
1243
|
+
`View collection "${collectionName}" requires a non-empty viewQuery. Provide the SQL SELECT statement backing the view.`
|
|
1244
|
+
);
|
|
1245
|
+
}
|
|
1246
|
+
const body = stripLeadingComments(viewQuery);
|
|
1247
|
+
if (!/^(select|with)\b/i.test(body)) {
|
|
1248
|
+
throw new Error(
|
|
1249
|
+
`View collection "${collectionName}" has an invalid viewQuery: it must start with SELECT or WITH. Received: ${body.slice(0, 40)}${body.length > 40 ? "..." : ""}`
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1199
1253
|
function getCollectionNameFromFile(filePath) {
|
|
1200
1254
|
const filename = path8.basename(filePath).replace(/\.(ts|js)$/, "");
|
|
1201
1255
|
return toCollectionName(filename);
|
|
@@ -1219,13 +1273,26 @@ function extractCollectionTypeFromSchema(zodSchema) {
|
|
|
1219
1273
|
}
|
|
1220
1274
|
try {
|
|
1221
1275
|
const metadata = JSON.parse(zodSchema.description);
|
|
1222
|
-
if (metadata.type === "base" || metadata.type === "auth") {
|
|
1276
|
+
if (metadata.type === "base" || metadata.type === "auth" || metadata.type === "view") {
|
|
1223
1277
|
return metadata.type;
|
|
1224
1278
|
}
|
|
1225
1279
|
} catch {
|
|
1226
1280
|
}
|
|
1227
1281
|
return null;
|
|
1228
1282
|
}
|
|
1283
|
+
function extractViewQueryFromSchema(zodSchema) {
|
|
1284
|
+
if (!zodSchema.description) {
|
|
1285
|
+
return null;
|
|
1286
|
+
}
|
|
1287
|
+
try {
|
|
1288
|
+
const metadata = JSON.parse(zodSchema.description);
|
|
1289
|
+
if (typeof metadata.viewQuery === "string") {
|
|
1290
|
+
return metadata.viewQuery;
|
|
1291
|
+
}
|
|
1292
|
+
} catch {
|
|
1293
|
+
}
|
|
1294
|
+
return null;
|
|
1295
|
+
}
|
|
1229
1296
|
function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema", "Collection"]) {
|
|
1230
1297
|
const result = {};
|
|
1231
1298
|
if (module.default instanceof z.ZodObject) {
|
|
@@ -1384,6 +1451,15 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1384
1451
|
const rawFields = extractFieldDefinitions(zodSchema);
|
|
1385
1452
|
const explicitType = extractCollectionTypeFromSchema(zodSchema);
|
|
1386
1453
|
const collectionType = explicitType ?? (isAuthCollection(rawFields) ? "auth" : "base");
|
|
1454
|
+
const isView = collectionType === "view";
|
|
1455
|
+
const viewQuery = extractViewQueryFromSchema(zodSchema);
|
|
1456
|
+
if (isView) {
|
|
1457
|
+
validateViewQuery(collectionName, viewQuery);
|
|
1458
|
+
} else if (viewQuery !== null) {
|
|
1459
|
+
console.warn(
|
|
1460
|
+
`[${collectionName}] viewQuery is only used by view collections and will be ignored. Use defineView() or set type: "view" to define a view collection.`
|
|
1461
|
+
);
|
|
1462
|
+
}
|
|
1387
1463
|
const fields = rawFields.filter((f) => !["created", "updated"].includes(f.name)).map(({ name, zodType }) => buildFieldDefinition(name, zodType));
|
|
1388
1464
|
if (collectionType === "auth") {
|
|
1389
1465
|
const authSystemFields = [
|
|
@@ -1443,26 +1519,43 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1443
1519
|
}
|
|
1444
1520
|
}
|
|
1445
1521
|
const indexes = extractIndexes(zodSchema) || [];
|
|
1522
|
+
if (isView && indexes.length > 0) {
|
|
1523
|
+
throw new Error(
|
|
1524
|
+
`View collection "${collectionName}" cannot declare indexes. PocketBase view collections are backed by a SQL query and do not support indexes.`
|
|
1525
|
+
);
|
|
1526
|
+
}
|
|
1446
1527
|
const permissionAnalyzer = new PermissionAnalyzer();
|
|
1447
1528
|
let permissions = void 0;
|
|
1448
1529
|
const schemaDescription = zodSchema.description;
|
|
1449
1530
|
const extractedPermissions = permissionAnalyzer.extractPermissions(schemaDescription);
|
|
1450
1531
|
if (extractedPermissions) {
|
|
1451
1532
|
const resolvedPermissions = permissionAnalyzer.resolvePermissions(extractedPermissions);
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
1461
|
-
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
1533
|
+
if (isView) {
|
|
1534
|
+
for (const ruleType of ["createRule", "updateRule", "deleteRule", "manageRule"]) {
|
|
1535
|
+
if (resolvedPermissions[ruleType]) {
|
|
1536
|
+
console.warn(
|
|
1537
|
+
`[${collectionName}] ${ruleType} is not supported on view collections and will be set to null.`
|
|
1538
|
+
);
|
|
1539
|
+
}
|
|
1540
|
+
resolvedPermissions[ruleType] = null;
|
|
1462
1541
|
}
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1542
|
+
}
|
|
1543
|
+
if (!isView) {
|
|
1544
|
+
const validationResults = permissionAnalyzer.validatePermissions(
|
|
1545
|
+
collectionName,
|
|
1546
|
+
resolvedPermissions,
|
|
1547
|
+
fields,
|
|
1548
|
+
collectionType === "auth"
|
|
1549
|
+
);
|
|
1550
|
+
for (const [ruleType, result] of validationResults) {
|
|
1551
|
+
if (!result.valid) {
|
|
1552
|
+
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
1553
|
+
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
1554
|
+
}
|
|
1555
|
+
if (result.warnings.length > 0) {
|
|
1556
|
+
console.warn(`[${collectionName}] Permission warnings for ${ruleType}:`);
|
|
1557
|
+
result.warnings.forEach((warning) => console.warn(` - ${warning}`));
|
|
1558
|
+
}
|
|
1466
1559
|
}
|
|
1467
1560
|
}
|
|
1468
1561
|
permissions = permissionAnalyzer.mergeWithDefaults(resolvedPermissions);
|
|
@@ -1483,6 +1576,9 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
1483
1576
|
},
|
|
1484
1577
|
permissions
|
|
1485
1578
|
};
|
|
1579
|
+
if (isView) {
|
|
1580
|
+
collectionSchema.viewQuery = viewQuery;
|
|
1581
|
+
}
|
|
1486
1582
|
return collectionSchema;
|
|
1487
1583
|
}
|
|
1488
1584
|
var tsxLoaderRegistered = false;
|
|
@@ -1740,8 +1836,9 @@ function convertPocketBaseField(pbField) {
|
|
|
1740
1836
|
}
|
|
1741
1837
|
function convertPocketBaseCollection(pbCollection) {
|
|
1742
1838
|
const fields = [];
|
|
1839
|
+
const isView = pbCollection.type === "view";
|
|
1743
1840
|
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
1744
|
-
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
1841
|
+
if (!isView && pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
1745
1842
|
for (const pbField of pbCollection.fields) {
|
|
1746
1843
|
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
1747
1844
|
const isAuthSystemField = pbCollection.type === "auth" && ["email", "emailVisibility", "verified", "password", "tokenKey"].includes(pbField.name);
|
|
@@ -1761,6 +1858,9 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
1761
1858
|
if (pbCollection.id) {
|
|
1762
1859
|
schema.id = pbCollection.id;
|
|
1763
1860
|
}
|
|
1861
|
+
if (typeof pbCollection.viewQuery === "string") {
|
|
1862
|
+
schema.viewQuery = dedentSql(pbCollection.viewQuery);
|
|
1863
|
+
}
|
|
1764
1864
|
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
1765
1865
|
schema.indexes = pbCollection.indexes;
|
|
1766
1866
|
}
|
|
@@ -1862,6 +1962,24 @@ function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
|
|
|
1862
1962
|
return [];
|
|
1863
1963
|
}
|
|
1864
1964
|
}
|
|
1965
|
+
function skipTemplateLiteral(content, start) {
|
|
1966
|
+
let i = start + 1;
|
|
1967
|
+
while (i < content.length) {
|
|
1968
|
+
const char = content[i];
|
|
1969
|
+
if (char === "\\") {
|
|
1970
|
+
i += 2;
|
|
1971
|
+
continue;
|
|
1972
|
+
}
|
|
1973
|
+
if (char === "`") {
|
|
1974
|
+
return i + 1;
|
|
1975
|
+
}
|
|
1976
|
+
i++;
|
|
1977
|
+
}
|
|
1978
|
+
return i;
|
|
1979
|
+
}
|
|
1980
|
+
function unescapeTemplateLiteral(raw) {
|
|
1981
|
+
return raw.replace(/\\(`|\$\{|\\)/g, "$1");
|
|
1982
|
+
}
|
|
1865
1983
|
function parseMigrationOperationsFromContent(content) {
|
|
1866
1984
|
const collectionsToCreate = [];
|
|
1867
1985
|
const collectionsToDelete = [];
|
|
@@ -1950,6 +2068,10 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
1950
2068
|
while (i < content.length && bCount > 0) {
|
|
1951
2069
|
const char = content[i];
|
|
1952
2070
|
const prev = i > 0 ? content[i - 1] : "";
|
|
2071
|
+
if (!inStr && char === "`") {
|
|
2072
|
+
i = skipTemplateLiteral(content, i);
|
|
2073
|
+
continue;
|
|
2074
|
+
}
|
|
1953
2075
|
if (!inStr && (char === '"' || char === "'")) {
|
|
1954
2076
|
inStr = true;
|
|
1955
2077
|
strChar = char;
|
|
@@ -2139,6 +2261,95 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
2139
2261
|
}
|
|
2140
2262
|
}
|
|
2141
2263
|
}
|
|
2264
|
+
const viewQueryRegex = /(\w+)\.viewQuery\s*=\s*/g;
|
|
2265
|
+
let viewQueryMatch;
|
|
2266
|
+
while ((viewQueryMatch = viewQueryRegex.exec(content)) !== null) {
|
|
2267
|
+
const varInfo = variables.get(viewQueryMatch[1]);
|
|
2268
|
+
if (!varInfo || varInfo.type !== "collection") continue;
|
|
2269
|
+
const valueStart = viewQueryMatch.index + viewQueryMatch[0].length;
|
|
2270
|
+
if (content[valueStart] === "`") {
|
|
2271
|
+
const end = skipTemplateLiteral(content, valueStart);
|
|
2272
|
+
const raw = content.substring(valueStart + 1, end - 1);
|
|
2273
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
2274
|
+
viewQueryRegex.lastIndex = end;
|
|
2275
|
+
} else {
|
|
2276
|
+
const terminator = content.indexOf(";", valueStart);
|
|
2277
|
+
const valueStr = content.substring(valueStart, terminator === -1 ? content.length : terminator);
|
|
2278
|
+
try {
|
|
2279
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(new Function("app", `return ${valueStr}`)(mockApp));
|
|
2280
|
+
} catch {
|
|
2281
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(valueStr.trim());
|
|
2282
|
+
}
|
|
2283
|
+
}
|
|
2284
|
+
}
|
|
2285
|
+
const unmarshalRegex = /unmarshal\s*\(/g;
|
|
2286
|
+
let unmarshalMatch;
|
|
2287
|
+
while ((unmarshalMatch = unmarshalRegex.exec(content)) !== null) {
|
|
2288
|
+
let i = unmarshalMatch.index + unmarshalMatch[0].length;
|
|
2289
|
+
while (i < content.length && /\s/.test(content[i])) i++;
|
|
2290
|
+
if (content[i] !== "{") continue;
|
|
2291
|
+
const objStart = i;
|
|
2292
|
+
let braceCount = 1;
|
|
2293
|
+
let inStr = false;
|
|
2294
|
+
let strChar = null;
|
|
2295
|
+
i++;
|
|
2296
|
+
while (i < content.length && braceCount > 0) {
|
|
2297
|
+
const ch = content[i];
|
|
2298
|
+
const prev = i > 0 ? content[i - 1] : "";
|
|
2299
|
+
if (!inStr && ch === "`") {
|
|
2300
|
+
i = skipTemplateLiteral(content, i);
|
|
2301
|
+
continue;
|
|
2302
|
+
}
|
|
2303
|
+
if (!inStr && (ch === '"' || ch === "'")) {
|
|
2304
|
+
inStr = true;
|
|
2305
|
+
strChar = ch;
|
|
2306
|
+
} else if (inStr && ch === strChar && prev !== "\\") {
|
|
2307
|
+
inStr = false;
|
|
2308
|
+
strChar = null;
|
|
2309
|
+
}
|
|
2310
|
+
if (!inStr) {
|
|
2311
|
+
if (ch === "{") braceCount++;
|
|
2312
|
+
if (ch === "}") braceCount--;
|
|
2313
|
+
}
|
|
2314
|
+
i++;
|
|
2315
|
+
}
|
|
2316
|
+
if (braceCount !== 0) continue;
|
|
2317
|
+
const objStr = content.substring(objStart, i);
|
|
2318
|
+
while (i < content.length && /[\s,]/.test(content[i])) i++;
|
|
2319
|
+
const varStart = i;
|
|
2320
|
+
while (i < content.length && /\w/.test(content[i])) i++;
|
|
2321
|
+
const colVarName = content.substring(varStart, i);
|
|
2322
|
+
const colInfo = variables.get(colVarName);
|
|
2323
|
+
if (!colInfo || colInfo.type !== "collection") continue;
|
|
2324
|
+
const keyValRegex = /"(\w+Rule)"\s*:\s*([^,}\n]+)/g;
|
|
2325
|
+
let kvMatch;
|
|
2326
|
+
while ((kvMatch = keyValRegex.exec(objStr)) !== null) {
|
|
2327
|
+
const ruleKey = kvMatch[1];
|
|
2328
|
+
const valStr = kvMatch[2].trim();
|
|
2329
|
+
try {
|
|
2330
|
+
const value = new Function("app", `return ${valStr}`)(mockApp);
|
|
2331
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = value;
|
|
2332
|
+
} catch {
|
|
2333
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = valStr;
|
|
2334
|
+
}
|
|
2335
|
+
}
|
|
2336
|
+
const viewQueryKey = objStr.match(/"viewQuery"\s*:\s*/);
|
|
2337
|
+
if (viewQueryKey) {
|
|
2338
|
+
const valueStart = viewQueryKey.index + viewQueryKey[0].length;
|
|
2339
|
+
if (objStr[valueStart] === "`") {
|
|
2340
|
+
const end = skipTemplateLiteral(objStr, valueStart);
|
|
2341
|
+
const raw = objStr.substring(valueStart + 1, end - 1);
|
|
2342
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
2343
|
+
} else {
|
|
2344
|
+
const valStr = objStr.substring(valueStart).replace(/[,}\s]+$/, "");
|
|
2345
|
+
try {
|
|
2346
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(new Function("app", `return ${valStr}`)(mockApp));
|
|
2347
|
+
} catch {
|
|
2348
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(valStr);
|
|
2349
|
+
}
|
|
2350
|
+
}
|
|
2351
|
+
}
|
|
2352
|
+
}
|
|
2142
2353
|
const idxPushRegex = /(\w+)\.indexes\.push\s*\(/g;
|
|
2143
2354
|
let match;
|
|
2144
2355
|
while ((match = idxPushRegex.exec(content)) !== null) {
|
|
@@ -2268,6 +2479,10 @@ function parseMigrationOperations(migrationContent) {
|
|
|
2268
2479
|
while (i < migrationContent.length && braceCount > 0) {
|
|
2269
2480
|
const char = migrationContent[i];
|
|
2270
2481
|
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
2482
|
+
if (!inString && char === "`") {
|
|
2483
|
+
i = skipTemplateLiteral(migrationContent, i);
|
|
2484
|
+
continue;
|
|
2485
|
+
}
|
|
2271
2486
|
if (!inString && (char === '"' || char === "'")) {
|
|
2272
2487
|
inString = true;
|
|
2273
2488
|
stringChar = char;
|
|
@@ -2375,6 +2590,9 @@ function applyMigrationOperations(snapshot, operations) {
|
|
|
2375
2590
|
collection.indexes = collection.indexes.filter((idx) => !update.indexesToRemove.includes(idx));
|
|
2376
2591
|
}
|
|
2377
2592
|
}
|
|
2593
|
+
if (update.viewQuery !== void 0) {
|
|
2594
|
+
collection.viewQuery = update.viewQuery;
|
|
2595
|
+
}
|
|
2378
2596
|
if (Object.keys(update.rulesToUpdate).length > 0) {
|
|
2379
2597
|
if (!collection.rules) collection.rules = {};
|
|
2380
2598
|
if (!collection.permissions) collection.permissions = {};
|
|
@@ -2838,7 +3056,45 @@ function compareCollectionFields(currentCollection, previousCollection, config,
|
|
|
2838
3056
|
fieldsToRemove = fieldsToRemove.filter((_, index) => !processedRemoveIndices.has(index));
|
|
2839
3057
|
return { fieldsToAdd, fieldsToRemove, fieldsToModify };
|
|
2840
3058
|
}
|
|
3059
|
+
function normalizeSql(query) {
|
|
3060
|
+
if (!query) {
|
|
3061
|
+
return "";
|
|
3062
|
+
}
|
|
3063
|
+
return query.split("\n").map((line) => line.trim()).join(" ").replace(/\s+/g, " ").trim();
|
|
3064
|
+
}
|
|
3065
|
+
function compareViewQuery(currentCollection, previousCollection) {
|
|
3066
|
+
const newValue = currentCollection.viewQuery;
|
|
3067
|
+
if (typeof newValue !== "string") {
|
|
3068
|
+
return void 0;
|
|
3069
|
+
}
|
|
3070
|
+
if (normalizeSql(newValue) === normalizeSql(previousCollection.viewQuery)) {
|
|
3071
|
+
return void 0;
|
|
3072
|
+
}
|
|
3073
|
+
return {
|
|
3074
|
+
oldValue: previousCollection.viewQuery ?? null,
|
|
3075
|
+
newValue
|
|
3076
|
+
};
|
|
3077
|
+
}
|
|
2841
3078
|
function buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName) {
|
|
3079
|
+
const isView = currentCollection.type === "view" || previousCollection.type === "view";
|
|
3080
|
+
if (isView) {
|
|
3081
|
+
return {
|
|
3082
|
+
collection: currentCollection.name,
|
|
3083
|
+
fieldsToAdd: [],
|
|
3084
|
+
fieldsToRemove: [],
|
|
3085
|
+
fieldsToModify: [],
|
|
3086
|
+
indexesToAdd: [],
|
|
3087
|
+
indexesToRemove: [],
|
|
3088
|
+
rulesToUpdate: compareRules(
|
|
3089
|
+
currentCollection.rules,
|
|
3090
|
+
previousCollection.rules,
|
|
3091
|
+
currentCollection.permissions,
|
|
3092
|
+
previousCollection.permissions
|
|
3093
|
+
),
|
|
3094
|
+
permissionsToUpdate: comparePermissions(currentCollection.permissions, previousCollection.permissions),
|
|
3095
|
+
viewQueryUpdate: compareViewQuery(currentCollection, previousCollection)
|
|
3096
|
+
};
|
|
3097
|
+
}
|
|
2842
3098
|
const { fieldsToAdd, fieldsToRemove, fieldsToModify } = compareCollectionFields(
|
|
2843
3099
|
currentCollection,
|
|
2844
3100
|
previousCollection,
|
|
@@ -2870,7 +3126,11 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
2870
3126
|
const destructive = [];
|
|
2871
3127
|
const nonDestructive = [];
|
|
2872
3128
|
for (const collection of diff.collectionsToDelete) {
|
|
2873
|
-
|
|
3129
|
+
if (collection.type === "view") {
|
|
3130
|
+
nonDestructive.push(`Delete view collection: ${collection.name}`);
|
|
3131
|
+
} else {
|
|
3132
|
+
destructive.push(`Delete collection: ${collection.name}`);
|
|
3133
|
+
}
|
|
2874
3134
|
}
|
|
2875
3135
|
for (const collection of diff.collectionsToCreate) {
|
|
2876
3136
|
nonDestructive.push(`Create collection: ${collection.name}`);
|
|
@@ -2905,6 +3165,9 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
2905
3165
|
for (const rule of modification.rulesToUpdate) {
|
|
2906
3166
|
nonDestructive.push(`Update rule: ${collectionName}.${rule.ruleType}`);
|
|
2907
3167
|
}
|
|
3168
|
+
if (modification.viewQueryUpdate) {
|
|
3169
|
+
nonDestructive.push(`Update view query: ${collectionName}`);
|
|
3170
|
+
}
|
|
2908
3171
|
}
|
|
2909
3172
|
return { destructive, nonDestructive };
|
|
2910
3173
|
}
|
|
@@ -2933,12 +3196,11 @@ function filterDiff(diff, options) {
|
|
|
2933
3196
|
});
|
|
2934
3197
|
let collectionsToDelete = diff.collectionsToDelete;
|
|
2935
3198
|
if (skipDestructive) {
|
|
2936
|
-
collectionsToDelete =
|
|
2937
|
-
} else {
|
|
2938
|
-
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
2939
|
-
return matchesPattern(col.name, patterns);
|
|
2940
|
-
});
|
|
3199
|
+
collectionsToDelete = collectionsToDelete.filter((col) => col.type === "view");
|
|
2941
3200
|
}
|
|
3201
|
+
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
3202
|
+
return matchesPattern(col.name, patterns);
|
|
3203
|
+
});
|
|
2942
3204
|
const collectionsToModify = diff.collectionsToModify.map((mod) => {
|
|
2943
3205
|
const collectionMatches = matchesPattern(mod.collection, patterns);
|
|
2944
3206
|
const fieldsToAdd = mod.fieldsToAdd.filter((field) => {
|
|
@@ -2963,6 +3225,7 @@ function filterDiff(diff, options) {
|
|
|
2963
3225
|
const indexesToRemove = collectionMatches ? mod.indexesToRemove : [];
|
|
2964
3226
|
const rulesToUpdate = collectionMatches ? mod.rulesToUpdate : [];
|
|
2965
3227
|
const permissionsToUpdate = collectionMatches ? mod.permissionsToUpdate : [];
|
|
3228
|
+
const viewQueryUpdate = collectionMatches ? mod.viewQueryUpdate : void 0;
|
|
2966
3229
|
return {
|
|
2967
3230
|
...mod,
|
|
2968
3231
|
fieldsToAdd,
|
|
@@ -2971,10 +3234,11 @@ function filterDiff(diff, options) {
|
|
|
2971
3234
|
indexesToAdd,
|
|
2972
3235
|
indexesToRemove,
|
|
2973
3236
|
rulesToUpdate,
|
|
2974
|
-
permissionsToUpdate
|
|
3237
|
+
permissionsToUpdate,
|
|
3238
|
+
viewQueryUpdate
|
|
2975
3239
|
};
|
|
2976
3240
|
}).filter((mod) => {
|
|
2977
|
-
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;
|
|
3241
|
+
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;
|
|
2978
3242
|
});
|
|
2979
3243
|
return {
|
|
2980
3244
|
...diff,
|
|
@@ -2986,7 +3250,7 @@ function filterDiff(diff, options) {
|
|
|
2986
3250
|
|
|
2987
3251
|
// src/migration/diff/index.ts
|
|
2988
3252
|
function hasChanges(modification) {
|
|
2989
|
-
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;
|
|
3253
|
+
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;
|
|
2990
3254
|
}
|
|
2991
3255
|
function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
2992
3256
|
const collectionIdToName = /* @__PURE__ */ new Map();
|
|
@@ -3165,6 +3429,13 @@ function formatValue(value) {
|
|
|
3165
3429
|
}
|
|
3166
3430
|
return String(value);
|
|
3167
3431
|
}
|
|
3432
|
+
function formatSqlTemplate(query, indent = " ") {
|
|
3433
|
+
const escaped = query.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
3434
|
+
const body = escaped.split("\n").map((line) => line.trim() === "" ? "" : `${indent}${line}`).join("\n");
|
|
3435
|
+
return `\`
|
|
3436
|
+
${body}
|
|
3437
|
+
${indent.slice(0, -2)}\``;
|
|
3438
|
+
}
|
|
3168
3439
|
function getFieldConstructorName(fieldType) {
|
|
3169
3440
|
const constructorMap = {
|
|
3170
3441
|
text: "TextField",
|
|
@@ -3203,6 +3474,36 @@ function getSystemFields() {
|
|
|
3203
3474
|
}
|
|
3204
3475
|
];
|
|
3205
3476
|
}
|
|
3477
|
+
function getSystemTimestampFields() {
|
|
3478
|
+
return [
|
|
3479
|
+
{
|
|
3480
|
+
name: "created",
|
|
3481
|
+
id: "autodate2990389176",
|
|
3482
|
+
type: "autodate",
|
|
3483
|
+
required: false,
|
|
3484
|
+
options: {
|
|
3485
|
+
hidden: false,
|
|
3486
|
+
onCreate: true,
|
|
3487
|
+
onUpdate: false,
|
|
3488
|
+
presentable: false,
|
|
3489
|
+
system: true
|
|
3490
|
+
}
|
|
3491
|
+
},
|
|
3492
|
+
{
|
|
3493
|
+
name: "updated",
|
|
3494
|
+
id: "autodate3332085495",
|
|
3495
|
+
type: "autodate",
|
|
3496
|
+
required: false,
|
|
3497
|
+
options: {
|
|
3498
|
+
hidden: false,
|
|
3499
|
+
onCreate: true,
|
|
3500
|
+
onUpdate: true,
|
|
3501
|
+
presentable: false,
|
|
3502
|
+
system: true
|
|
3503
|
+
}
|
|
3504
|
+
}
|
|
3505
|
+
];
|
|
3506
|
+
}
|
|
3206
3507
|
function getAuthSystemFields() {
|
|
3207
3508
|
return [
|
|
3208
3509
|
{
|
|
@@ -3495,6 +3796,15 @@ function generateCollectionRules(rules, collectionType = "base") {
|
|
|
3495
3796
|
if (!rules) {
|
|
3496
3797
|
return "";
|
|
3497
3798
|
}
|
|
3799
|
+
if (collectionType === "view") {
|
|
3800
|
+
return [
|
|
3801
|
+
`"listRule": ${formatValue(rules.listRule ?? null)}`,
|
|
3802
|
+
`"viewRule": ${formatValue(rules.viewRule ?? null)}`,
|
|
3803
|
+
`"createRule": null`,
|
|
3804
|
+
`"updateRule": null`,
|
|
3805
|
+
`"deleteRule": null`
|
|
3806
|
+
].join(",\n ");
|
|
3807
|
+
}
|
|
3498
3808
|
const parts = [];
|
|
3499
3809
|
if (rules.listRule !== void 0) {
|
|
3500
3810
|
parts.push(`"listRule": ${formatValue(rules.listRule)}`);
|
|
@@ -3520,6 +3830,15 @@ function generateCollectionPermissions(permissions, collectionType = "base") {
|
|
|
3520
3830
|
if (!permissions) {
|
|
3521
3831
|
return "";
|
|
3522
3832
|
}
|
|
3833
|
+
if (collectionType === "view") {
|
|
3834
|
+
return [
|
|
3835
|
+
`"listRule": ${formatValue(permissions.listRule ?? null)}`,
|
|
3836
|
+
`"viewRule": ${formatValue(permissions.viewRule ?? null)}`,
|
|
3837
|
+
`"createRule": null`,
|
|
3838
|
+
`"updateRule": null`,
|
|
3839
|
+
`"deleteRule": null`
|
|
3840
|
+
].join(",\n ");
|
|
3841
|
+
}
|
|
3523
3842
|
const parts = [];
|
|
3524
3843
|
if (permissions.listRule !== void 0) {
|
|
3525
3844
|
parts.push(`"listRule": ${formatValue(permissions.listRule)}`);
|
|
@@ -3557,6 +3876,28 @@ function generatePermissionUpdate(collectionName, ruleType, newValue, varName, i
|
|
|
3557
3876
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3558
3877
|
return lines.join("\n");
|
|
3559
3878
|
}
|
|
3879
|
+
function generateViewQueryUpdate(collectionName, viewQuery, varName, isLast = false, collectionIdMap) {
|
|
3880
|
+
const lines = [];
|
|
3881
|
+
const collectionVar = varName || `collection_${collectionName}_viewQuery`;
|
|
3882
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
3883
|
+
lines.push(` unmarshal({`);
|
|
3884
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(viewQuery, " ")},`);
|
|
3885
|
+
lines.push(` }, ${collectionVar})`);
|
|
3886
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3887
|
+
return lines.join("\n");
|
|
3888
|
+
}
|
|
3889
|
+
function generateGroupedRuleUpdates(collectionName, entries, varSuffix, isLast = false, collectionIdMap) {
|
|
3890
|
+
const collectionVar = `collection_${collectionName}_${varSuffix}`;
|
|
3891
|
+
const lines = [];
|
|
3892
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
3893
|
+
lines.push(` unmarshal({`);
|
|
3894
|
+
for (const entry of entries) {
|
|
3895
|
+
lines.push(` "${entry.ruleType}": ${formatValue(entry.value)},`);
|
|
3896
|
+
}
|
|
3897
|
+
lines.push(` }, ${collectionVar})`);
|
|
3898
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3899
|
+
return lines.join("\n");
|
|
3900
|
+
}
|
|
3560
3901
|
|
|
3561
3902
|
// src/migration/generator/collections.ts
|
|
3562
3903
|
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
@@ -3575,16 +3916,24 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
|
|
|
3575
3916
|
} else if (rulesCode) {
|
|
3576
3917
|
lines.push(` ${rulesCode},`);
|
|
3577
3918
|
}
|
|
3919
|
+
if (collection.type === "view") {
|
|
3920
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(collection.viewQuery ?? "")},`);
|
|
3921
|
+
lines.push(` });`);
|
|
3922
|
+
lines.push(``);
|
|
3923
|
+
lines.push(isLast ? ` return app.save(${varName});` : ` app.save(${varName});`);
|
|
3924
|
+
return lines.join("\n");
|
|
3925
|
+
}
|
|
3578
3926
|
const systemFieldNames = ["created", "updated", "id"];
|
|
3579
3927
|
if (collection.type === "auth") {
|
|
3580
3928
|
systemFieldNames.push(...getAuthSystemFields().map((f) => f.name));
|
|
3581
3929
|
}
|
|
3582
3930
|
const userFields = collection.fields.filter((f) => !systemFieldNames.includes(f.name));
|
|
3583
|
-
const allFields = [...getSystemFields()
|
|
3931
|
+
const allFields = [...getSystemFields()];
|
|
3584
3932
|
if (collection.type === "auth") {
|
|
3585
3933
|
allFields.push(...getAuthSystemFields());
|
|
3586
3934
|
}
|
|
3587
3935
|
allFields.push(...userFields);
|
|
3936
|
+
allFields.push(...getSystemTimestampFields());
|
|
3588
3937
|
lines.push(` "fields": ${generateFieldsArray(allFields, collectionIdMap)},`);
|
|
3589
3938
|
let allIndexes = [...collection.indexes || []];
|
|
3590
3939
|
if (collection.type === "auth") {
|
|
@@ -3614,7 +3963,21 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
3614
3963
|
const modification = operation.modifications;
|
|
3615
3964
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
3616
3965
|
let operationCount = 0;
|
|
3617
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
3966
|
+
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);
|
|
3967
|
+
if (modification.viewQueryUpdate) {
|
|
3968
|
+
operationCount++;
|
|
3969
|
+
const isLast = operationCount === totalOperations;
|
|
3970
|
+
lines.push(
|
|
3971
|
+
generateViewQueryUpdate(
|
|
3972
|
+
collectionName,
|
|
3973
|
+
modification.viewQueryUpdate.newValue,
|
|
3974
|
+
void 0,
|
|
3975
|
+
isLast,
|
|
3976
|
+
collectionIdMap
|
|
3977
|
+
)
|
|
3978
|
+
);
|
|
3979
|
+
if (!isLast) lines.push("");
|
|
3980
|
+
}
|
|
3618
3981
|
for (let i = 0; i < modification.fieldsToAdd.length; i++) {
|
|
3619
3982
|
const field = modification.fieldsToAdd[i];
|
|
3620
3983
|
operationCount++;
|
|
@@ -3654,23 +4017,29 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
3654
4017
|
if (!isLast) lines.push("");
|
|
3655
4018
|
}
|
|
3656
4019
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
3657
|
-
|
|
3658
|
-
|
|
4020
|
+
operationCount++;
|
|
4021
|
+
const isLast = operationCount === totalOperations;
|
|
4022
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
4023
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.newValue }));
|
|
4024
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
4025
|
+
} else {
|
|
4026
|
+
const permission = modification.permissionsToUpdate[0];
|
|
3659
4027
|
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
3660
|
-
|
|
3661
|
-
lines.push(
|
|
3662
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap)
|
|
3663
|
-
);
|
|
3664
|
-
if (!isLast) lines.push("");
|
|
4028
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap));
|
|
3665
4029
|
}
|
|
4030
|
+
if (!isLast) lines.push("");
|
|
3666
4031
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
3667
|
-
|
|
3668
|
-
|
|
4032
|
+
operationCount++;
|
|
4033
|
+
const isLast = operationCount === totalOperations;
|
|
4034
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
4035
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.newValue }));
|
|
4036
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
4037
|
+
} else {
|
|
4038
|
+
const rule = modification.rulesToUpdate[0];
|
|
3669
4039
|
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
3670
|
-
const isLast = operationCount === totalOperations;
|
|
3671
4040
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast, collectionIdMap));
|
|
3672
|
-
if (!isLast) lines.push("");
|
|
3673
4041
|
}
|
|
4042
|
+
if (!isLast) lines.push("");
|
|
3674
4043
|
}
|
|
3675
4044
|
} else if (operation.type === "delete") {
|
|
3676
4045
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
|
|
@@ -3709,25 +4078,45 @@ function generateOperationDownMigration(operation, collectionIdMap) {
|
|
|
3709
4078
|
const modification = operation.modifications;
|
|
3710
4079
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
3711
4080
|
let operationCount = 0;
|
|
3712
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
4081
|
+
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);
|
|
4082
|
+
if (modification.viewQueryUpdate) {
|
|
4083
|
+
operationCount++;
|
|
4084
|
+
const isLast = operationCount === totalOperations;
|
|
4085
|
+
lines.push(
|
|
4086
|
+
generateViewQueryUpdate(
|
|
4087
|
+
collectionName,
|
|
4088
|
+
modification.viewQueryUpdate.oldValue ?? "",
|
|
4089
|
+
`collection_${collectionName}_revert_viewQuery`,
|
|
4090
|
+
isLast,
|
|
4091
|
+
collectionIdMap
|
|
4092
|
+
)
|
|
4093
|
+
);
|
|
4094
|
+
if (!isLast) lines.push("");
|
|
4095
|
+
}
|
|
3713
4096
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
3714
|
-
|
|
3715
|
-
|
|
4097
|
+
operationCount++;
|
|
4098
|
+
const isLast = operationCount === totalOperations;
|
|
4099
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
4100
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.oldValue }));
|
|
4101
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
4102
|
+
} else {
|
|
4103
|
+
const permission = modification.permissionsToUpdate[0];
|
|
3716
4104
|
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
3717
|
-
|
|
3718
|
-
lines.push(
|
|
3719
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap)
|
|
3720
|
-
);
|
|
3721
|
-
if (!isLast) lines.push("");
|
|
4105
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap));
|
|
3722
4106
|
}
|
|
4107
|
+
if (!isLast) lines.push("");
|
|
3723
4108
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
3724
|
-
|
|
3725
|
-
|
|
4109
|
+
operationCount++;
|
|
4110
|
+
const isLast = operationCount === totalOperations;
|
|
4111
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
4112
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.oldValue }));
|
|
4113
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
4114
|
+
} else {
|
|
4115
|
+
const rule = modification.rulesToUpdate[0];
|
|
3726
4116
|
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
3727
|
-
const isLast = operationCount === totalOperations;
|
|
3728
4117
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast, collectionIdMap));
|
|
3729
|
-
if (!isLast) lines.push("");
|
|
3730
4118
|
}
|
|
4119
|
+
if (!isLast) lines.push("");
|
|
3731
4120
|
}
|
|
3732
4121
|
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
3733
4122
|
operationCount++;
|
|
@@ -3976,6 +4365,9 @@ function generate(diff, config) {
|
|
|
3976
4365
|
function detectCollectionDeletions(diff) {
|
|
3977
4366
|
const changes = [];
|
|
3978
4367
|
for (const collection of diff.collectionsToDelete) {
|
|
4368
|
+
if (collection.type === "view") {
|
|
4369
|
+
continue;
|
|
4370
|
+
}
|
|
3979
4371
|
changes.push({
|
|
3980
4372
|
type: "collection_deletion" /* COLLECTION_DELETION */,
|
|
3981
4373
|
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
|
}
|
|
@@ -4816,11 +5215,14 @@ var TypeGenerator = class {
|
|
|
4816
5215
|
}
|
|
4817
5216
|
generateCollectionType(collection) {
|
|
4818
5217
|
const typeName = this.toPascalCase(collection.name);
|
|
5218
|
+
const isView = collection.type === "view";
|
|
4819
5219
|
const lines = [];
|
|
4820
5220
|
lines.push(`export interface ${typeName}Record {`);
|
|
4821
5221
|
lines.push(` id: string;`);
|
|
4822
|
-
|
|
4823
|
-
|
|
5222
|
+
if (!isView) {
|
|
5223
|
+
lines.push(` created: string;`);
|
|
5224
|
+
lines.push(` updated: string;`);
|
|
5225
|
+
}
|
|
4824
5226
|
lines.push(` collectionId: string;`);
|
|
4825
5227
|
lines.push(` collectionName: "${collection.name}";`);
|
|
4826
5228
|
for (const field of collection.fields) {
|
|
@@ -4832,7 +5234,7 @@ var TypeGenerator = class {
|
|
|
4832
5234
|
lines.push(`}`);
|
|
4833
5235
|
lines.push(``);
|
|
4834
5236
|
const expandFields = [];
|
|
4835
|
-
for (const field of collection.fields) {
|
|
5237
|
+
for (const field of isView ? [] : collection.fields) {
|
|
4836
5238
|
if (field.type === "relation" && field.relation) {
|
|
4837
5239
|
const targetCollection = field.relation.collection;
|
|
4838
5240
|
let targetType = "RecordModel";
|