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/server.js
CHANGED
|
@@ -454,13 +454,16 @@ function withIndexes(schema, indexes) {
|
|
|
454
454
|
return schema.describe(JSON.stringify(metadata));
|
|
455
455
|
}
|
|
456
456
|
function defineCollection(config) {
|
|
457
|
-
const { collectionName, schema, permissions, indexes, type, ...futureOptions } = config;
|
|
457
|
+
const { collectionName, schema, permissions, indexes, type, viewQuery, ...futureOptions } = config;
|
|
458
458
|
const metadata = {
|
|
459
459
|
collectionName
|
|
460
460
|
};
|
|
461
461
|
if (type) {
|
|
462
462
|
metadata.type = type;
|
|
463
463
|
}
|
|
464
|
+
if (viewQuery !== void 0) {
|
|
465
|
+
metadata.viewQuery = viewQuery;
|
|
466
|
+
}
|
|
464
467
|
if (permissions) {
|
|
465
468
|
metadata.permissions = permissions;
|
|
466
469
|
}
|
|
@@ -726,6 +729,88 @@ function GeoPointField() {
|
|
|
726
729
|
};
|
|
727
730
|
return schema.describe(JSON.stringify(metadata));
|
|
728
731
|
}
|
|
732
|
+
function dedentSql(value) {
|
|
733
|
+
const lines = value.replace(/\r\n/g, "\n").split("\n");
|
|
734
|
+
while (lines.length > 0 && lines[0].trim() === "") {
|
|
735
|
+
lines.shift();
|
|
736
|
+
}
|
|
737
|
+
while (lines.length > 0 && lines[lines.length - 1].trim() === "") {
|
|
738
|
+
lines.pop();
|
|
739
|
+
}
|
|
740
|
+
if (lines.length === 0) {
|
|
741
|
+
return "";
|
|
742
|
+
}
|
|
743
|
+
let minIndent = Infinity;
|
|
744
|
+
for (const line of lines) {
|
|
745
|
+
if (line.trim() === "") continue;
|
|
746
|
+
const indent = line.length - line.trimStart().length;
|
|
747
|
+
if (indent < minIndent) {
|
|
748
|
+
minIndent = indent;
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
if (!Number.isFinite(minIndent) || minIndent === 0) {
|
|
752
|
+
return lines.map((line) => line.trimEnd()).join("\n");
|
|
753
|
+
}
|
|
754
|
+
return lines.map((line) => line.slice(minIndent).trimEnd()).join("\n");
|
|
755
|
+
}
|
|
756
|
+
function sql(strings, ...values) {
|
|
757
|
+
let result = "";
|
|
758
|
+
for (let i = 0; i < strings.length; i++) {
|
|
759
|
+
result += strings[i];
|
|
760
|
+
if (i < values.length) {
|
|
761
|
+
result += String(values[i]);
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
return dedentSql(result);
|
|
765
|
+
}
|
|
766
|
+
function stripLeadingComments(query) {
|
|
767
|
+
let remaining = query.trim();
|
|
768
|
+
while (remaining.length > 0) {
|
|
769
|
+
if (remaining.startsWith("--")) {
|
|
770
|
+
const newline = remaining.indexOf("\n");
|
|
771
|
+
remaining = newline === -1 ? "" : remaining.slice(newline + 1).trim();
|
|
772
|
+
continue;
|
|
773
|
+
}
|
|
774
|
+
if (remaining.startsWith("/*")) {
|
|
775
|
+
const end = remaining.indexOf("*/");
|
|
776
|
+
remaining = end === -1 ? "" : remaining.slice(end + 2).trim();
|
|
777
|
+
continue;
|
|
778
|
+
}
|
|
779
|
+
break;
|
|
780
|
+
}
|
|
781
|
+
return remaining;
|
|
782
|
+
}
|
|
783
|
+
function validateViewQuery(collectionName, viewQuery) {
|
|
784
|
+
if (typeof viewQuery !== "string" || viewQuery.trim() === "") {
|
|
785
|
+
throw new Error(
|
|
786
|
+
`View collection "${collectionName}" requires a non-empty viewQuery. Provide the SQL SELECT statement backing the view.`
|
|
787
|
+
);
|
|
788
|
+
}
|
|
789
|
+
const body = stripLeadingComments(viewQuery);
|
|
790
|
+
if (!/^(select|with)\b/i.test(body)) {
|
|
791
|
+
throw new Error(
|
|
792
|
+
`View collection "${collectionName}" has an invalid viewQuery: it must start with SELECT or WITH. Received: ${body.slice(0, 40)}${body.length > 40 ? "..." : ""}`
|
|
793
|
+
);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
function defineView(config) {
|
|
797
|
+
const { collectionName, schema, viewQuery, permissions } = config;
|
|
798
|
+
validateViewQuery(collectionName, viewQuery);
|
|
799
|
+
return defineCollection({
|
|
800
|
+
collectionName,
|
|
801
|
+
schema,
|
|
802
|
+
type: "view",
|
|
803
|
+
viewQuery,
|
|
804
|
+
// Write rules are always locked for views - PocketBase rejects anything else
|
|
805
|
+
permissions: {
|
|
806
|
+
listRule: permissions?.listRule ?? null,
|
|
807
|
+
viewRule: permissions?.viewRule ?? null,
|
|
808
|
+
createRule: null,
|
|
809
|
+
updateRule: null,
|
|
810
|
+
deleteRule: null
|
|
811
|
+
}
|
|
812
|
+
});
|
|
813
|
+
}
|
|
729
814
|
|
|
730
815
|
// src/utils/permission-templates.ts
|
|
731
816
|
var PermissionTemplates = {
|
|
@@ -2272,13 +2357,26 @@ function extractCollectionTypeFromSchema(zodSchema) {
|
|
|
2272
2357
|
}
|
|
2273
2358
|
try {
|
|
2274
2359
|
const metadata = JSON.parse(zodSchema.description);
|
|
2275
|
-
if (metadata.type === "base" || metadata.type === "auth") {
|
|
2360
|
+
if (metadata.type === "base" || metadata.type === "auth" || metadata.type === "view") {
|
|
2276
2361
|
return metadata.type;
|
|
2277
2362
|
}
|
|
2278
2363
|
} catch {
|
|
2279
2364
|
}
|
|
2280
2365
|
return null;
|
|
2281
2366
|
}
|
|
2367
|
+
function extractViewQueryFromSchema(zodSchema) {
|
|
2368
|
+
if (!zodSchema.description) {
|
|
2369
|
+
return null;
|
|
2370
|
+
}
|
|
2371
|
+
try {
|
|
2372
|
+
const metadata = JSON.parse(zodSchema.description);
|
|
2373
|
+
if (typeof metadata.viewQuery === "string") {
|
|
2374
|
+
return metadata.viewQuery;
|
|
2375
|
+
}
|
|
2376
|
+
} catch {
|
|
2377
|
+
}
|
|
2378
|
+
return null;
|
|
2379
|
+
}
|
|
2282
2380
|
function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema", "Collection"]) {
|
|
2283
2381
|
const result = {};
|
|
2284
2382
|
if (module.default instanceof z.ZodObject) {
|
|
@@ -2437,6 +2535,15 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
2437
2535
|
const rawFields = extractFieldDefinitions(zodSchema);
|
|
2438
2536
|
const explicitType = extractCollectionTypeFromSchema(zodSchema);
|
|
2439
2537
|
const collectionType = explicitType ?? (isAuthCollection(rawFields) ? "auth" : "base");
|
|
2538
|
+
const isView = collectionType === "view";
|
|
2539
|
+
const viewQuery = extractViewQueryFromSchema(zodSchema);
|
|
2540
|
+
if (isView) {
|
|
2541
|
+
validateViewQuery(collectionName, viewQuery);
|
|
2542
|
+
} else if (viewQuery !== null) {
|
|
2543
|
+
console.warn(
|
|
2544
|
+
`[${collectionName}] viewQuery is only used by view collections and will be ignored. Use defineView() or set type: "view" to define a view collection.`
|
|
2545
|
+
);
|
|
2546
|
+
}
|
|
2440
2547
|
const fields = rawFields.filter((f) => !["created", "updated"].includes(f.name)).map(({ name, zodType }) => buildFieldDefinition(name, zodType));
|
|
2441
2548
|
if (collectionType === "auth") {
|
|
2442
2549
|
const authSystemFields = [
|
|
@@ -2496,26 +2603,43 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
2496
2603
|
}
|
|
2497
2604
|
}
|
|
2498
2605
|
const indexes = extractIndexes(zodSchema) || [];
|
|
2606
|
+
if (isView && indexes.length > 0) {
|
|
2607
|
+
throw new Error(
|
|
2608
|
+
`View collection "${collectionName}" cannot declare indexes. PocketBase view collections are backed by a SQL query and do not support indexes.`
|
|
2609
|
+
);
|
|
2610
|
+
}
|
|
2499
2611
|
const permissionAnalyzer = new PermissionAnalyzer();
|
|
2500
2612
|
let permissions = void 0;
|
|
2501
2613
|
const schemaDescription = zodSchema.description;
|
|
2502
2614
|
const extractedPermissions = permissionAnalyzer.extractPermissions(schemaDescription);
|
|
2503
2615
|
if (extractedPermissions) {
|
|
2504
2616
|
const resolvedPermissions = permissionAnalyzer.resolvePermissions(extractedPermissions);
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2511
|
-
|
|
2512
|
-
|
|
2513
|
-
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
2514
|
-
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
2617
|
+
if (isView) {
|
|
2618
|
+
for (const ruleType of ["createRule", "updateRule", "deleteRule", "manageRule"]) {
|
|
2619
|
+
if (resolvedPermissions[ruleType]) {
|
|
2620
|
+
console.warn(
|
|
2621
|
+
`[${collectionName}] ${ruleType} is not supported on view collections and will be set to null.`
|
|
2622
|
+
);
|
|
2623
|
+
}
|
|
2624
|
+
resolvedPermissions[ruleType] = null;
|
|
2515
2625
|
}
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2626
|
+
}
|
|
2627
|
+
if (!isView) {
|
|
2628
|
+
const validationResults = permissionAnalyzer.validatePermissions(
|
|
2629
|
+
collectionName,
|
|
2630
|
+
resolvedPermissions,
|
|
2631
|
+
fields,
|
|
2632
|
+
collectionType === "auth"
|
|
2633
|
+
);
|
|
2634
|
+
for (const [ruleType, result] of validationResults) {
|
|
2635
|
+
if (!result.valid) {
|
|
2636
|
+
console.error(`[${collectionName}] Permission validation failed for ${ruleType}:`);
|
|
2637
|
+
result.errors.forEach((error) => console.error(` - ${error}`));
|
|
2638
|
+
}
|
|
2639
|
+
if (result.warnings.length > 0) {
|
|
2640
|
+
console.warn(`[${collectionName}] Permission warnings for ${ruleType}:`);
|
|
2641
|
+
result.warnings.forEach((warning) => console.warn(` - ${warning}`));
|
|
2642
|
+
}
|
|
2519
2643
|
}
|
|
2520
2644
|
}
|
|
2521
2645
|
permissions = permissionAnalyzer.mergeWithDefaults(resolvedPermissions);
|
|
@@ -2536,6 +2660,9 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
2536
2660
|
},
|
|
2537
2661
|
permissions
|
|
2538
2662
|
};
|
|
2663
|
+
if (isView) {
|
|
2664
|
+
collectionSchema.viewQuery = viewQuery;
|
|
2665
|
+
}
|
|
2539
2666
|
return collectionSchema;
|
|
2540
2667
|
}
|
|
2541
2668
|
var tsxLoaderRegistered = false;
|
|
@@ -2817,8 +2944,9 @@ function convertPocketBaseField(pbField) {
|
|
|
2817
2944
|
}
|
|
2818
2945
|
function convertPocketBaseCollection(pbCollection) {
|
|
2819
2946
|
const fields = [];
|
|
2947
|
+
const isView = pbCollection.type === "view";
|
|
2820
2948
|
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
2821
|
-
if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
2949
|
+
if (!isView && pbCollection.fields && Array.isArray(pbCollection.fields)) {
|
|
2822
2950
|
for (const pbField of pbCollection.fields) {
|
|
2823
2951
|
if (pbField.system || systemFieldNames.includes(pbField.name)) {
|
|
2824
2952
|
const isAuthSystemField = pbCollection.type === "auth" && ["email", "emailVisibility", "verified", "password", "tokenKey"].includes(pbField.name);
|
|
@@ -2838,6 +2966,9 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
2838
2966
|
if (pbCollection.id) {
|
|
2839
2967
|
schema.id = pbCollection.id;
|
|
2840
2968
|
}
|
|
2969
|
+
if (typeof pbCollection.viewQuery === "string") {
|
|
2970
|
+
schema.viewQuery = dedentSql(pbCollection.viewQuery);
|
|
2971
|
+
}
|
|
2841
2972
|
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
2842
2973
|
schema.indexes = pbCollection.indexes;
|
|
2843
2974
|
}
|
|
@@ -2939,6 +3070,24 @@ function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
|
|
|
2939
3070
|
return [];
|
|
2940
3071
|
}
|
|
2941
3072
|
}
|
|
3073
|
+
function skipTemplateLiteral(content, start) {
|
|
3074
|
+
let i = start + 1;
|
|
3075
|
+
while (i < content.length) {
|
|
3076
|
+
const char = content[i];
|
|
3077
|
+
if (char === "\\") {
|
|
3078
|
+
i += 2;
|
|
3079
|
+
continue;
|
|
3080
|
+
}
|
|
3081
|
+
if (char === "`") {
|
|
3082
|
+
return i + 1;
|
|
3083
|
+
}
|
|
3084
|
+
i++;
|
|
3085
|
+
}
|
|
3086
|
+
return i;
|
|
3087
|
+
}
|
|
3088
|
+
function unescapeTemplateLiteral(raw) {
|
|
3089
|
+
return raw.replace(/\\(`|\$\{|\\)/g, "$1");
|
|
3090
|
+
}
|
|
2942
3091
|
function parseMigrationOperationsFromContent(content) {
|
|
2943
3092
|
const collectionsToCreate = [];
|
|
2944
3093
|
const collectionsToDelete = [];
|
|
@@ -3027,6 +3176,10 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
3027
3176
|
while (i < content.length && bCount > 0) {
|
|
3028
3177
|
const char = content[i];
|
|
3029
3178
|
const prev = i > 0 ? content[i - 1] : "";
|
|
3179
|
+
if (!inStr && char === "`") {
|
|
3180
|
+
i = skipTemplateLiteral(content, i);
|
|
3181
|
+
continue;
|
|
3182
|
+
}
|
|
3030
3183
|
if (!inStr && (char === '"' || char === "'")) {
|
|
3031
3184
|
inStr = true;
|
|
3032
3185
|
strChar = char;
|
|
@@ -3216,6 +3369,95 @@ function parseMigrationOperationsFromContent(content) {
|
|
|
3216
3369
|
}
|
|
3217
3370
|
}
|
|
3218
3371
|
}
|
|
3372
|
+
const viewQueryRegex = /(\w+)\.viewQuery\s*=\s*/g;
|
|
3373
|
+
let viewQueryMatch;
|
|
3374
|
+
while ((viewQueryMatch = viewQueryRegex.exec(content)) !== null) {
|
|
3375
|
+
const varInfo = variables.get(viewQueryMatch[1]);
|
|
3376
|
+
if (!varInfo || varInfo.type !== "collection") continue;
|
|
3377
|
+
const valueStart = viewQueryMatch.index + viewQueryMatch[0].length;
|
|
3378
|
+
if (content[valueStart] === "`") {
|
|
3379
|
+
const end = skipTemplateLiteral(content, valueStart);
|
|
3380
|
+
const raw = content.substring(valueStart + 1, end - 1);
|
|
3381
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
3382
|
+
viewQueryRegex.lastIndex = end;
|
|
3383
|
+
} else {
|
|
3384
|
+
const terminator = content.indexOf(";", valueStart);
|
|
3385
|
+
const valueStr = content.substring(valueStart, terminator === -1 ? content.length : terminator);
|
|
3386
|
+
try {
|
|
3387
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(new Function("app", `return ${valueStr}`)(mockApp));
|
|
3388
|
+
} catch {
|
|
3389
|
+
getUpdate(varInfo.name).viewQuery = dedentSql(valueStr.trim());
|
|
3390
|
+
}
|
|
3391
|
+
}
|
|
3392
|
+
}
|
|
3393
|
+
const unmarshalRegex = /unmarshal\s*\(/g;
|
|
3394
|
+
let unmarshalMatch;
|
|
3395
|
+
while ((unmarshalMatch = unmarshalRegex.exec(content)) !== null) {
|
|
3396
|
+
let i = unmarshalMatch.index + unmarshalMatch[0].length;
|
|
3397
|
+
while (i < content.length && /\s/.test(content[i])) i++;
|
|
3398
|
+
if (content[i] !== "{") continue;
|
|
3399
|
+
const objStart = i;
|
|
3400
|
+
let braceCount = 1;
|
|
3401
|
+
let inStr = false;
|
|
3402
|
+
let strChar = null;
|
|
3403
|
+
i++;
|
|
3404
|
+
while (i < content.length && braceCount > 0) {
|
|
3405
|
+
const ch = content[i];
|
|
3406
|
+
const prev = i > 0 ? content[i - 1] : "";
|
|
3407
|
+
if (!inStr && ch === "`") {
|
|
3408
|
+
i = skipTemplateLiteral(content, i);
|
|
3409
|
+
continue;
|
|
3410
|
+
}
|
|
3411
|
+
if (!inStr && (ch === '"' || ch === "'")) {
|
|
3412
|
+
inStr = true;
|
|
3413
|
+
strChar = ch;
|
|
3414
|
+
} else if (inStr && ch === strChar && prev !== "\\") {
|
|
3415
|
+
inStr = false;
|
|
3416
|
+
strChar = null;
|
|
3417
|
+
}
|
|
3418
|
+
if (!inStr) {
|
|
3419
|
+
if (ch === "{") braceCount++;
|
|
3420
|
+
if (ch === "}") braceCount--;
|
|
3421
|
+
}
|
|
3422
|
+
i++;
|
|
3423
|
+
}
|
|
3424
|
+
if (braceCount !== 0) continue;
|
|
3425
|
+
const objStr = content.substring(objStart, i);
|
|
3426
|
+
while (i < content.length && /[\s,]/.test(content[i])) i++;
|
|
3427
|
+
const varStart = i;
|
|
3428
|
+
while (i < content.length && /\w/.test(content[i])) i++;
|
|
3429
|
+
const colVarName = content.substring(varStart, i);
|
|
3430
|
+
const colInfo = variables.get(colVarName);
|
|
3431
|
+
if (!colInfo || colInfo.type !== "collection") continue;
|
|
3432
|
+
const keyValRegex = /"(\w+Rule)"\s*:\s*([^,}\n]+)/g;
|
|
3433
|
+
let kvMatch;
|
|
3434
|
+
while ((kvMatch = keyValRegex.exec(objStr)) !== null) {
|
|
3435
|
+
const ruleKey = kvMatch[1];
|
|
3436
|
+
const valStr = kvMatch[2].trim();
|
|
3437
|
+
try {
|
|
3438
|
+
const value = new Function("app", `return ${valStr}`)(mockApp);
|
|
3439
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = value;
|
|
3440
|
+
} catch {
|
|
3441
|
+
getUpdate(colInfo.name).rulesToUpdate[ruleKey] = valStr;
|
|
3442
|
+
}
|
|
3443
|
+
}
|
|
3444
|
+
const viewQueryKey = objStr.match(/"viewQuery"\s*:\s*/);
|
|
3445
|
+
if (viewQueryKey) {
|
|
3446
|
+
const valueStart = viewQueryKey.index + viewQueryKey[0].length;
|
|
3447
|
+
if (objStr[valueStart] === "`") {
|
|
3448
|
+
const end = skipTemplateLiteral(objStr, valueStart);
|
|
3449
|
+
const raw = objStr.substring(valueStart + 1, end - 1);
|
|
3450
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(unescapeTemplateLiteral(raw));
|
|
3451
|
+
} else {
|
|
3452
|
+
const valStr = objStr.substring(valueStart).replace(/[,}\s]+$/, "");
|
|
3453
|
+
try {
|
|
3454
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(new Function("app", `return ${valStr}`)(mockApp));
|
|
3455
|
+
} catch {
|
|
3456
|
+
getUpdate(colInfo.name).viewQuery = dedentSql(valStr);
|
|
3457
|
+
}
|
|
3458
|
+
}
|
|
3459
|
+
}
|
|
3460
|
+
}
|
|
3219
3461
|
const idxPushRegex = /(\w+)\.indexes\.push\s*\(/g;
|
|
3220
3462
|
let match;
|
|
3221
3463
|
while ((match = idxPushRegex.exec(content)) !== null) {
|
|
@@ -3345,6 +3587,10 @@ function parseMigrationOperations(migrationContent) {
|
|
|
3345
3587
|
while (i < migrationContent.length && braceCount > 0) {
|
|
3346
3588
|
const char = migrationContent[i];
|
|
3347
3589
|
const prevChar = i > 0 ? migrationContent[i - 1] : "";
|
|
3590
|
+
if (!inString && char === "`") {
|
|
3591
|
+
i = skipTemplateLiteral(migrationContent, i);
|
|
3592
|
+
continue;
|
|
3593
|
+
}
|
|
3348
3594
|
if (!inString && (char === '"' || char === "'")) {
|
|
3349
3595
|
inString = true;
|
|
3350
3596
|
stringChar = char;
|
|
@@ -3680,6 +3926,9 @@ function applyMigrationOperations(snapshot, operations) {
|
|
|
3680
3926
|
collection.indexes = collection.indexes.filter((idx) => !update.indexesToRemove.includes(idx));
|
|
3681
3927
|
}
|
|
3682
3928
|
}
|
|
3929
|
+
if (update.viewQuery !== void 0) {
|
|
3930
|
+
collection.viewQuery = update.viewQuery;
|
|
3931
|
+
}
|
|
3683
3932
|
if (Object.keys(update.rulesToUpdate).length > 0) {
|
|
3684
3933
|
if (!collection.rules) collection.rules = {};
|
|
3685
3934
|
if (!collection.permissions) collection.permissions = {};
|
|
@@ -4299,7 +4548,45 @@ function compareCollectionFields(currentCollection, previousCollection, config,
|
|
|
4299
4548
|
fieldsToRemove = fieldsToRemove.filter((_, index) => !processedRemoveIndices.has(index));
|
|
4300
4549
|
return { fieldsToAdd, fieldsToRemove, fieldsToModify };
|
|
4301
4550
|
}
|
|
4551
|
+
function normalizeSql(query) {
|
|
4552
|
+
if (!query) {
|
|
4553
|
+
return "";
|
|
4554
|
+
}
|
|
4555
|
+
return query.split("\n").map((line) => line.trim()).join(" ").replace(/\s+/g, " ").trim();
|
|
4556
|
+
}
|
|
4557
|
+
function compareViewQuery(currentCollection, previousCollection) {
|
|
4558
|
+
const newValue = currentCollection.viewQuery;
|
|
4559
|
+
if (typeof newValue !== "string") {
|
|
4560
|
+
return void 0;
|
|
4561
|
+
}
|
|
4562
|
+
if (normalizeSql(newValue) === normalizeSql(previousCollection.viewQuery)) {
|
|
4563
|
+
return void 0;
|
|
4564
|
+
}
|
|
4565
|
+
return {
|
|
4566
|
+
oldValue: previousCollection.viewQuery ?? null,
|
|
4567
|
+
newValue
|
|
4568
|
+
};
|
|
4569
|
+
}
|
|
4302
4570
|
function buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName) {
|
|
4571
|
+
const isView = currentCollection.type === "view" || previousCollection.type === "view";
|
|
4572
|
+
if (isView) {
|
|
4573
|
+
return {
|
|
4574
|
+
collection: currentCollection.name,
|
|
4575
|
+
fieldsToAdd: [],
|
|
4576
|
+
fieldsToRemove: [],
|
|
4577
|
+
fieldsToModify: [],
|
|
4578
|
+
indexesToAdd: [],
|
|
4579
|
+
indexesToRemove: [],
|
|
4580
|
+
rulesToUpdate: compareRules(
|
|
4581
|
+
currentCollection.rules,
|
|
4582
|
+
previousCollection.rules,
|
|
4583
|
+
currentCollection.permissions,
|
|
4584
|
+
previousCollection.permissions
|
|
4585
|
+
),
|
|
4586
|
+
permissionsToUpdate: comparePermissions(currentCollection.permissions, previousCollection.permissions),
|
|
4587
|
+
viewQueryUpdate: compareViewQuery(currentCollection, previousCollection)
|
|
4588
|
+
};
|
|
4589
|
+
}
|
|
4303
4590
|
const { fieldsToAdd, fieldsToRemove, fieldsToModify } = compareCollectionFields(
|
|
4304
4591
|
currentCollection,
|
|
4305
4592
|
previousCollection,
|
|
@@ -4331,6 +4618,9 @@ function detectDestructiveChanges(diff, config) {
|
|
|
4331
4618
|
const destructiveChanges = [];
|
|
4332
4619
|
const mergedConfig = mergeConfig3(config);
|
|
4333
4620
|
for (const collection of diff.collectionsToDelete) {
|
|
4621
|
+
if (collection.type === "view") {
|
|
4622
|
+
continue;
|
|
4623
|
+
}
|
|
4334
4624
|
destructiveChanges.push({
|
|
4335
4625
|
type: "collection_delete",
|
|
4336
4626
|
severity: "high",
|
|
@@ -4418,7 +4708,11 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
4418
4708
|
const destructive = [];
|
|
4419
4709
|
const nonDestructive = [];
|
|
4420
4710
|
for (const collection of diff.collectionsToDelete) {
|
|
4421
|
-
|
|
4711
|
+
if (collection.type === "view") {
|
|
4712
|
+
nonDestructive.push(`Delete view collection: ${collection.name}`);
|
|
4713
|
+
} else {
|
|
4714
|
+
destructive.push(`Delete collection: ${collection.name}`);
|
|
4715
|
+
}
|
|
4422
4716
|
}
|
|
4423
4717
|
for (const collection of diff.collectionsToCreate) {
|
|
4424
4718
|
nonDestructive.push(`Create collection: ${collection.name}`);
|
|
@@ -4453,6 +4747,9 @@ function categorizeChangesBySeverity(diff, _config) {
|
|
|
4453
4747
|
for (const rule of modification.rulesToUpdate) {
|
|
4454
4748
|
nonDestructive.push(`Update rule: ${collectionName}.${rule.ruleType}`);
|
|
4455
4749
|
}
|
|
4750
|
+
if (modification.viewQueryUpdate) {
|
|
4751
|
+
nonDestructive.push(`Update view query: ${collectionName}`);
|
|
4752
|
+
}
|
|
4456
4753
|
}
|
|
4457
4754
|
return { destructive, nonDestructive };
|
|
4458
4755
|
}
|
|
@@ -4465,6 +4762,7 @@ function generateChangeSummary(diff, config) {
|
|
|
4465
4762
|
let indexChanges = 0;
|
|
4466
4763
|
let ruleChanges = 0;
|
|
4467
4764
|
let permissionChanges = 0;
|
|
4765
|
+
let viewQueryChanges = 0;
|
|
4468
4766
|
for (const modification of diff.collectionsToModify) {
|
|
4469
4767
|
fieldsToAdd += modification.fieldsToAdd.length;
|
|
4470
4768
|
fieldsToRemove += modification.fieldsToRemove.length;
|
|
@@ -4472,6 +4770,9 @@ function generateChangeSummary(diff, config) {
|
|
|
4472
4770
|
indexChanges += modification.indexesToAdd.length + modification.indexesToRemove.length;
|
|
4473
4771
|
ruleChanges += modification.rulesToUpdate.length;
|
|
4474
4772
|
permissionChanges += modification.permissionsToUpdate.length;
|
|
4773
|
+
if (modification.viewQueryUpdate) {
|
|
4774
|
+
viewQueryChanges += 1;
|
|
4775
|
+
}
|
|
4475
4776
|
}
|
|
4476
4777
|
return {
|
|
4477
4778
|
totalChanges: diff.collectionsToCreate.length + diff.collectionsToDelete.length + diff.collectionsToModify.length,
|
|
@@ -4484,6 +4785,7 @@ function generateChangeSummary(diff, config) {
|
|
|
4484
4785
|
indexChanges,
|
|
4485
4786
|
ruleChanges,
|
|
4486
4787
|
permissionChanges,
|
|
4788
|
+
viewQueryChanges,
|
|
4487
4789
|
destructiveChanges,
|
|
4488
4790
|
nonDestructiveChanges: nonDestructive
|
|
4489
4791
|
};
|
|
@@ -4513,12 +4815,11 @@ function filterDiff(diff, options) {
|
|
|
4513
4815
|
});
|
|
4514
4816
|
let collectionsToDelete = diff.collectionsToDelete;
|
|
4515
4817
|
if (skipDestructive) {
|
|
4516
|
-
collectionsToDelete =
|
|
4517
|
-
} else {
|
|
4518
|
-
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
4519
|
-
return matchesPattern(col.name, patterns);
|
|
4520
|
-
});
|
|
4818
|
+
collectionsToDelete = collectionsToDelete.filter((col) => col.type === "view");
|
|
4521
4819
|
}
|
|
4820
|
+
collectionsToDelete = collectionsToDelete.filter((col) => {
|
|
4821
|
+
return matchesPattern(col.name, patterns);
|
|
4822
|
+
});
|
|
4522
4823
|
const collectionsToModify = diff.collectionsToModify.map((mod) => {
|
|
4523
4824
|
const collectionMatches = matchesPattern(mod.collection, patterns);
|
|
4524
4825
|
const fieldsToAdd = mod.fieldsToAdd.filter((field) => {
|
|
@@ -4543,6 +4844,7 @@ function filterDiff(diff, options) {
|
|
|
4543
4844
|
const indexesToRemove = collectionMatches ? mod.indexesToRemove : [];
|
|
4544
4845
|
const rulesToUpdate = collectionMatches ? mod.rulesToUpdate : [];
|
|
4545
4846
|
const permissionsToUpdate = collectionMatches ? mod.permissionsToUpdate : [];
|
|
4847
|
+
const viewQueryUpdate = collectionMatches ? mod.viewQueryUpdate : void 0;
|
|
4546
4848
|
return {
|
|
4547
4849
|
...mod,
|
|
4548
4850
|
fieldsToAdd,
|
|
@@ -4551,10 +4853,11 @@ function filterDiff(diff, options) {
|
|
|
4551
4853
|
indexesToAdd,
|
|
4552
4854
|
indexesToRemove,
|
|
4553
4855
|
rulesToUpdate,
|
|
4554
|
-
permissionsToUpdate
|
|
4856
|
+
permissionsToUpdate,
|
|
4857
|
+
viewQueryUpdate
|
|
4555
4858
|
};
|
|
4556
4859
|
}).filter((mod) => {
|
|
4557
|
-
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;
|
|
4860
|
+
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;
|
|
4558
4861
|
});
|
|
4559
4862
|
return {
|
|
4560
4863
|
...diff,
|
|
@@ -4566,7 +4869,7 @@ function filterDiff(diff, options) {
|
|
|
4566
4869
|
|
|
4567
4870
|
// src/migration/diff/index.ts
|
|
4568
4871
|
function hasChanges(modification) {
|
|
4569
|
-
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;
|
|
4872
|
+
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;
|
|
4570
4873
|
}
|
|
4571
4874
|
function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
4572
4875
|
const collectionIdToName = /* @__PURE__ */ new Map();
|
|
@@ -4781,6 +5084,13 @@ function formatValue(value) {
|
|
|
4781
5084
|
}
|
|
4782
5085
|
return String(value);
|
|
4783
5086
|
}
|
|
5087
|
+
function formatSqlTemplate(query, indent = " ") {
|
|
5088
|
+
const escaped = query.replace(/\\/g, "\\\\").replace(/`/g, "\\`").replace(/\$\{/g, "\\${");
|
|
5089
|
+
const body = escaped.split("\n").map((line) => line.trim() === "" ? "" : `${indent}${line}`).join("\n");
|
|
5090
|
+
return `\`
|
|
5091
|
+
${body}
|
|
5092
|
+
${indent.slice(0, -2)}\``;
|
|
5093
|
+
}
|
|
4784
5094
|
function getFieldConstructorName(fieldType) {
|
|
4785
5095
|
const constructorMap = {
|
|
4786
5096
|
text: "TextField",
|
|
@@ -4819,6 +5129,36 @@ function getSystemFields() {
|
|
|
4819
5129
|
}
|
|
4820
5130
|
];
|
|
4821
5131
|
}
|
|
5132
|
+
function getSystemTimestampFields() {
|
|
5133
|
+
return [
|
|
5134
|
+
{
|
|
5135
|
+
name: "created",
|
|
5136
|
+
id: "autodate2990389176",
|
|
5137
|
+
type: "autodate",
|
|
5138
|
+
required: false,
|
|
5139
|
+
options: {
|
|
5140
|
+
hidden: false,
|
|
5141
|
+
onCreate: true,
|
|
5142
|
+
onUpdate: false,
|
|
5143
|
+
presentable: false,
|
|
5144
|
+
system: true
|
|
5145
|
+
}
|
|
5146
|
+
},
|
|
5147
|
+
{
|
|
5148
|
+
name: "updated",
|
|
5149
|
+
id: "autodate3332085495",
|
|
5150
|
+
type: "autodate",
|
|
5151
|
+
required: false,
|
|
5152
|
+
options: {
|
|
5153
|
+
hidden: false,
|
|
5154
|
+
onCreate: true,
|
|
5155
|
+
onUpdate: true,
|
|
5156
|
+
presentable: false,
|
|
5157
|
+
system: true
|
|
5158
|
+
}
|
|
5159
|
+
}
|
|
5160
|
+
];
|
|
5161
|
+
}
|
|
4822
5162
|
function getAuthSystemFields() {
|
|
4823
5163
|
return [
|
|
4824
5164
|
{
|
|
@@ -5111,6 +5451,15 @@ function generateCollectionRules(rules, collectionType = "base") {
|
|
|
5111
5451
|
if (!rules) {
|
|
5112
5452
|
return "";
|
|
5113
5453
|
}
|
|
5454
|
+
if (collectionType === "view") {
|
|
5455
|
+
return [
|
|
5456
|
+
`"listRule": ${formatValue(rules.listRule ?? null)}`,
|
|
5457
|
+
`"viewRule": ${formatValue(rules.viewRule ?? null)}`,
|
|
5458
|
+
`"createRule": null`,
|
|
5459
|
+
`"updateRule": null`,
|
|
5460
|
+
`"deleteRule": null`
|
|
5461
|
+
].join(",\n ");
|
|
5462
|
+
}
|
|
5114
5463
|
const parts = [];
|
|
5115
5464
|
if (rules.listRule !== void 0) {
|
|
5116
5465
|
parts.push(`"listRule": ${formatValue(rules.listRule)}`);
|
|
@@ -5136,6 +5485,15 @@ function generateCollectionPermissions(permissions, collectionType = "base") {
|
|
|
5136
5485
|
if (!permissions) {
|
|
5137
5486
|
return "";
|
|
5138
5487
|
}
|
|
5488
|
+
if (collectionType === "view") {
|
|
5489
|
+
return [
|
|
5490
|
+
`"listRule": ${formatValue(permissions.listRule ?? null)}`,
|
|
5491
|
+
`"viewRule": ${formatValue(permissions.viewRule ?? null)}`,
|
|
5492
|
+
`"createRule": null`,
|
|
5493
|
+
`"updateRule": null`,
|
|
5494
|
+
`"deleteRule": null`
|
|
5495
|
+
].join(",\n ");
|
|
5496
|
+
}
|
|
5139
5497
|
const parts = [];
|
|
5140
5498
|
if (permissions.listRule !== void 0) {
|
|
5141
5499
|
parts.push(`"listRule": ${formatValue(permissions.listRule)}`);
|
|
@@ -5173,6 +5531,28 @@ function generatePermissionUpdate(collectionName, ruleType, newValue, varName, i
|
|
|
5173
5531
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
5174
5532
|
return lines.join("\n");
|
|
5175
5533
|
}
|
|
5534
|
+
function generateViewQueryUpdate(collectionName, viewQuery, varName, isLast = false, collectionIdMap) {
|
|
5535
|
+
const lines = [];
|
|
5536
|
+
const collectionVar = varName || `collection_${collectionName}_viewQuery`;
|
|
5537
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
5538
|
+
lines.push(` unmarshal({`);
|
|
5539
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(viewQuery, " ")},`);
|
|
5540
|
+
lines.push(` }, ${collectionVar})`);
|
|
5541
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
5542
|
+
return lines.join("\n");
|
|
5543
|
+
}
|
|
5544
|
+
function generateGroupedRuleUpdates(collectionName, entries, varSuffix, isLast = false, collectionIdMap) {
|
|
5545
|
+
const collectionVar = `collection_${collectionName}_${varSuffix}`;
|
|
5546
|
+
const lines = [];
|
|
5547
|
+
lines.push(` const ${collectionVar} = ${generateFindCollectionCode(collectionName, collectionIdMap)};`);
|
|
5548
|
+
lines.push(` unmarshal({`);
|
|
5549
|
+
for (const entry of entries) {
|
|
5550
|
+
lines.push(` "${entry.ruleType}": ${formatValue(entry.value)},`);
|
|
5551
|
+
}
|
|
5552
|
+
lines.push(` }, ${collectionVar})`);
|
|
5553
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
5554
|
+
return lines.join("\n");
|
|
5555
|
+
}
|
|
5176
5556
|
|
|
5177
5557
|
// src/migration/generator/collections.ts
|
|
5178
5558
|
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
@@ -5191,16 +5571,24 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
|
|
|
5191
5571
|
} else if (rulesCode) {
|
|
5192
5572
|
lines.push(` ${rulesCode},`);
|
|
5193
5573
|
}
|
|
5574
|
+
if (collection.type === "view") {
|
|
5575
|
+
lines.push(` "viewQuery": ${formatSqlTemplate(collection.viewQuery ?? "")},`);
|
|
5576
|
+
lines.push(` });`);
|
|
5577
|
+
lines.push(``);
|
|
5578
|
+
lines.push(isLast ? ` return app.save(${varName});` : ` app.save(${varName});`);
|
|
5579
|
+
return lines.join("\n");
|
|
5580
|
+
}
|
|
5194
5581
|
const systemFieldNames = ["created", "updated", "id"];
|
|
5195
5582
|
if (collection.type === "auth") {
|
|
5196
5583
|
systemFieldNames.push(...getAuthSystemFields().map((f) => f.name));
|
|
5197
5584
|
}
|
|
5198
5585
|
const userFields = collection.fields.filter((f) => !systemFieldNames.includes(f.name));
|
|
5199
|
-
const allFields = [...getSystemFields()
|
|
5586
|
+
const allFields = [...getSystemFields()];
|
|
5200
5587
|
if (collection.type === "auth") {
|
|
5201
5588
|
allFields.push(...getAuthSystemFields());
|
|
5202
5589
|
}
|
|
5203
5590
|
allFields.push(...userFields);
|
|
5591
|
+
allFields.push(...getSystemTimestampFields());
|
|
5204
5592
|
lines.push(` "fields": ${generateFieldsArray(allFields, collectionIdMap)},`);
|
|
5205
5593
|
let allIndexes = [...collection.indexes || []];
|
|
5206
5594
|
if (collection.type === "auth") {
|
|
@@ -5230,7 +5618,21 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
5230
5618
|
const modification = operation.modifications;
|
|
5231
5619
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
5232
5620
|
let operationCount = 0;
|
|
5233
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
5621
|
+
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);
|
|
5622
|
+
if (modification.viewQueryUpdate) {
|
|
5623
|
+
operationCount++;
|
|
5624
|
+
const isLast = operationCount === totalOperations;
|
|
5625
|
+
lines.push(
|
|
5626
|
+
generateViewQueryUpdate(
|
|
5627
|
+
collectionName,
|
|
5628
|
+
modification.viewQueryUpdate.newValue,
|
|
5629
|
+
void 0,
|
|
5630
|
+
isLast,
|
|
5631
|
+
collectionIdMap
|
|
5632
|
+
)
|
|
5633
|
+
);
|
|
5634
|
+
if (!isLast) lines.push("");
|
|
5635
|
+
}
|
|
5234
5636
|
for (let i = 0; i < modification.fieldsToAdd.length; i++) {
|
|
5235
5637
|
const field = modification.fieldsToAdd[i];
|
|
5236
5638
|
operationCount++;
|
|
@@ -5270,23 +5672,29 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
5270
5672
|
if (!isLast) lines.push("");
|
|
5271
5673
|
}
|
|
5272
5674
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
5273
|
-
|
|
5274
|
-
|
|
5675
|
+
operationCount++;
|
|
5676
|
+
const isLast = operationCount === totalOperations;
|
|
5677
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
5678
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.newValue }));
|
|
5679
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
5680
|
+
} else {
|
|
5681
|
+
const permission = modification.permissionsToUpdate[0];
|
|
5275
5682
|
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
5276
|
-
|
|
5277
|
-
lines.push(
|
|
5278
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap)
|
|
5279
|
-
);
|
|
5280
|
-
if (!isLast) lines.push("");
|
|
5683
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast, collectionIdMap));
|
|
5281
5684
|
}
|
|
5685
|
+
if (!isLast) lines.push("");
|
|
5282
5686
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
5283
|
-
|
|
5284
|
-
|
|
5687
|
+
operationCount++;
|
|
5688
|
+
const isLast = operationCount === totalOperations;
|
|
5689
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
5690
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.newValue }));
|
|
5691
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", isLast, collectionIdMap));
|
|
5692
|
+
} else {
|
|
5693
|
+
const rule = modification.rulesToUpdate[0];
|
|
5285
5694
|
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
5286
|
-
const isLast = operationCount === totalOperations;
|
|
5287
5695
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast, collectionIdMap));
|
|
5288
|
-
if (!isLast) lines.push("");
|
|
5289
5696
|
}
|
|
5697
|
+
if (!isLast) lines.push("");
|
|
5290
5698
|
}
|
|
5291
5699
|
} else if (operation.type === "delete") {
|
|
5292
5700
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
|
|
@@ -5325,25 +5733,45 @@ function generateOperationDownMigration(operation, collectionIdMap) {
|
|
|
5325
5733
|
const modification = operation.modifications;
|
|
5326
5734
|
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
5327
5735
|
let operationCount = 0;
|
|
5328
|
-
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.
|
|
5736
|
+
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);
|
|
5737
|
+
if (modification.viewQueryUpdate) {
|
|
5738
|
+
operationCount++;
|
|
5739
|
+
const isLast = operationCount === totalOperations;
|
|
5740
|
+
lines.push(
|
|
5741
|
+
generateViewQueryUpdate(
|
|
5742
|
+
collectionName,
|
|
5743
|
+
modification.viewQueryUpdate.oldValue ?? "",
|
|
5744
|
+
`collection_${collectionName}_revert_viewQuery`,
|
|
5745
|
+
isLast,
|
|
5746
|
+
collectionIdMap
|
|
5747
|
+
)
|
|
5748
|
+
);
|
|
5749
|
+
if (!isLast) lines.push("");
|
|
5750
|
+
}
|
|
5329
5751
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
5330
|
-
|
|
5331
|
-
|
|
5752
|
+
operationCount++;
|
|
5753
|
+
const isLast = operationCount === totalOperations;
|
|
5754
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
5755
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.oldValue }));
|
|
5756
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
5757
|
+
} else {
|
|
5758
|
+
const permission = modification.permissionsToUpdate[0];
|
|
5332
5759
|
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
5333
|
-
|
|
5334
|
-
lines.push(
|
|
5335
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap)
|
|
5336
|
-
);
|
|
5337
|
-
if (!isLast) lines.push("");
|
|
5760
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast, collectionIdMap));
|
|
5338
5761
|
}
|
|
5762
|
+
if (!isLast) lines.push("");
|
|
5339
5763
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
5340
|
-
|
|
5341
|
-
|
|
5764
|
+
operationCount++;
|
|
5765
|
+
const isLast = operationCount === totalOperations;
|
|
5766
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
5767
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.oldValue }));
|
|
5768
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", isLast, collectionIdMap));
|
|
5769
|
+
} else {
|
|
5770
|
+
const rule = modification.rulesToUpdate[0];
|
|
5342
5771
|
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
5343
|
-
const isLast = operationCount === totalOperations;
|
|
5344
5772
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast, collectionIdMap));
|
|
5345
|
-
if (!isLast) lines.push("");
|
|
5346
5773
|
}
|
|
5774
|
+
if (!isLast) lines.push("");
|
|
5347
5775
|
}
|
|
5348
5776
|
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
5349
5777
|
operationCount++;
|
|
@@ -5450,6 +5878,19 @@ function generateUpMigration(diff) {
|
|
|
5450
5878
|
lines.push(` // Modify existing collections`);
|
|
5451
5879
|
for (const modification of diff.collectionsToModify) {
|
|
5452
5880
|
const collectionName = modification.collection;
|
|
5881
|
+
if (modification.viewQueryUpdate) {
|
|
5882
|
+
lines.push(` // Update the view query of ${collectionName}`);
|
|
5883
|
+
lines.push(
|
|
5884
|
+
generateViewQueryUpdate(
|
|
5885
|
+
collectionName,
|
|
5886
|
+
modification.viewQueryUpdate.newValue,
|
|
5887
|
+
void 0,
|
|
5888
|
+
false,
|
|
5889
|
+
collectionIdMap
|
|
5890
|
+
)
|
|
5891
|
+
);
|
|
5892
|
+
lines.push(``);
|
|
5893
|
+
}
|
|
5453
5894
|
if (modification.fieldsToAdd.length > 0) {
|
|
5454
5895
|
lines.push(` // Add fields to ${collectionName}`);
|
|
5455
5896
|
for (let i = 0; i < modification.fieldsToAdd.length; i++) {
|
|
@@ -5495,20 +5936,26 @@ function generateUpMigration(diff) {
|
|
|
5495
5936
|
}
|
|
5496
5937
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
5497
5938
|
lines.push(` // Update permissions for ${collectionName}`);
|
|
5498
|
-
|
|
5939
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
5940
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.newValue }));
|
|
5941
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", false, collectionIdMap));
|
|
5942
|
+
} else {
|
|
5943
|
+
const permission = modification.permissionsToUpdate[0];
|
|
5499
5944
|
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
5500
|
-
lines.push(
|
|
5501
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, false, collectionIdMap)
|
|
5502
|
-
);
|
|
5503
|
-
lines.push(``);
|
|
5945
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, false, collectionIdMap));
|
|
5504
5946
|
}
|
|
5947
|
+
lines.push(``);
|
|
5505
5948
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
5506
5949
|
lines.push(` // Update rules for ${collectionName}`);
|
|
5507
|
-
|
|
5950
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
5951
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.newValue }));
|
|
5952
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "rules", false, collectionIdMap));
|
|
5953
|
+
} else {
|
|
5954
|
+
const rule = modification.rulesToUpdate[0];
|
|
5508
5955
|
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
5509
5956
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, false, collectionIdMap));
|
|
5510
|
-
lines.push(``);
|
|
5511
5957
|
}
|
|
5958
|
+
lines.push(``);
|
|
5512
5959
|
}
|
|
5513
5960
|
}
|
|
5514
5961
|
}
|
|
@@ -5580,22 +6027,41 @@ function generateDownMigration(diff) {
|
|
|
5580
6027
|
lines.push(` // Revert modifications`);
|
|
5581
6028
|
for (const modification of diff.collectionsToModify) {
|
|
5582
6029
|
const collectionName = modification.collection;
|
|
6030
|
+
if (modification.viewQueryUpdate) {
|
|
6031
|
+
lines.push(` // Restore the view query of ${collectionName}`);
|
|
6032
|
+
lines.push(
|
|
6033
|
+
generateViewQueryUpdate(
|
|
6034
|
+
collectionName,
|
|
6035
|
+
modification.viewQueryUpdate.oldValue ?? "",
|
|
6036
|
+
`collection_${collectionName}_revert_viewQuery`,
|
|
6037
|
+
false,
|
|
6038
|
+
collectionIdMap
|
|
6039
|
+
)
|
|
6040
|
+
);
|
|
6041
|
+
lines.push(``);
|
|
6042
|
+
}
|
|
5583
6043
|
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
5584
6044
|
lines.push(` // Revert permissions for ${collectionName}`);
|
|
5585
|
-
|
|
6045
|
+
if (modification.permissionsToUpdate.length >= 2) {
|
|
6046
|
+
const entries = modification.permissionsToUpdate.map((p) => ({ ruleType: p.ruleType, value: p.oldValue }));
|
|
6047
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", false, collectionIdMap));
|
|
6048
|
+
} else {
|
|
6049
|
+
const permission = modification.permissionsToUpdate[0];
|
|
5586
6050
|
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
5587
|
-
lines.push(
|
|
5588
|
-
generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, false, collectionIdMap)
|
|
5589
|
-
);
|
|
5590
|
-
lines.push(``);
|
|
6051
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, false, collectionIdMap));
|
|
5591
6052
|
}
|
|
6053
|
+
lines.push(``);
|
|
5592
6054
|
} else if (modification.rulesToUpdate.length > 0) {
|
|
5593
6055
|
lines.push(` // Revert rules for ${collectionName}`);
|
|
5594
|
-
|
|
6056
|
+
if (modification.rulesToUpdate.length >= 2) {
|
|
6057
|
+
const entries = modification.rulesToUpdate.map((r) => ({ ruleType: r.ruleType, value: r.oldValue }));
|
|
6058
|
+
lines.push(generateGroupedRuleUpdates(collectionName, entries, "revert_rules", false, collectionIdMap));
|
|
6059
|
+
} else {
|
|
6060
|
+
const rule = modification.rulesToUpdate[0];
|
|
5595
6061
|
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
5596
6062
|
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, false, collectionIdMap));
|
|
5597
|
-
lines.push(``);
|
|
5598
6063
|
}
|
|
6064
|
+
lines.push(``);
|
|
5599
6065
|
}
|
|
5600
6066
|
if (modification.indexesToRemove.length > 0) {
|
|
5601
6067
|
lines.push(` // Restore indexes to ${collectionName}`);
|
|
@@ -5925,6 +6391,9 @@ var MigrationGenerator = class {
|
|
|
5925
6391
|
function detectCollectionDeletions(diff) {
|
|
5926
6392
|
const changes = [];
|
|
5927
6393
|
for (const collection of diff.collectionsToDelete) {
|
|
6394
|
+
if (collection.type === "view") {
|
|
6395
|
+
continue;
|
|
6396
|
+
}
|
|
5928
6397
|
changes.push({
|
|
5929
6398
|
type: "collection_deletion" /* COLLECTION_DELETION */,
|
|
5930
6399
|
description: `Delete collection: ${collection.name}`,
|
|
@@ -6339,7 +6808,11 @@ function formatChangeSummary(diff) {
|
|
|
6339
6808
|
lines.push(chalk.green.bold(`\u2713 ${totalCollectionsToCreate} collection(s) to create:`));
|
|
6340
6809
|
for (const collection of diff.collectionsToCreate) {
|
|
6341
6810
|
lines.push(chalk.green(` + ${collection.name} (${collection.type})`));
|
|
6342
|
-
|
|
6811
|
+
if (collection.type === "view") {
|
|
6812
|
+
lines.push(chalk.gray(` fields derived from the view query`));
|
|
6813
|
+
} else {
|
|
6814
|
+
lines.push(chalk.gray(` ${collection.fields.length} field(s)`));
|
|
6815
|
+
}
|
|
6343
6816
|
}
|
|
6344
6817
|
lines.push("");
|
|
6345
6818
|
}
|
|
@@ -6384,6 +6857,9 @@ function formatChangeSummary(diff) {
|
|
|
6384
6857
|
if (modification.rulesToUpdate.length > 0) {
|
|
6385
6858
|
lines.push(chalk.yellow(` ~ ${modification.rulesToUpdate.length} rule(s) to update`));
|
|
6386
6859
|
}
|
|
6860
|
+
if (modification.viewQueryUpdate) {
|
|
6861
|
+
lines.push(chalk.yellow(` ~ view query to update`));
|
|
6862
|
+
}
|
|
6387
6863
|
lines.push("");
|
|
6388
6864
|
}
|
|
6389
6865
|
}
|
|
@@ -6806,6 +7282,6 @@ async function executeStatus(options) {
|
|
|
6806
7282
|
}
|
|
6807
7283
|
}
|
|
6808
7284
|
|
|
6809
|
-
export { AutodateField, BaseMutator, BoolField, CLIUsageError, ConfigurationError, DateField, DiffEngine, EditorField, EmailField, FIELD_METADATA_KEY, FIELD_TYPE_INFO, FileField, FileSystemError, FilesField, GeoPointField, JSONField, MigrationError, MigrationGenerationError, MigrationGenerator, MultiSelectField, NumberField, POCKETBASE_FIELD_TYPES, PermissionTemplates, RelationField, RelationsField, SchemaAnalyzer, SchemaParsingError, SelectField, SingleSelectField, SnapshotError, SnapshotManager, StatusEnum, TextField, URLField, aggregateChanges, baseImageFileSchema, baseSchema, baseSchemaWithTimestamps, buildFieldDefinition, buildSchemaDefinition, categorizeChangesBySeverity, compare, compareFieldConstraints, compareFieldOptions, compareFieldTypes, comparePermissions, compareRelationConfigurations, convertPocketBaseMigration, convertZodSchemaToCollectionSchema, createMigrationFileStructure, createPermissions, defineCollection, detectDestructiveChanges, detectDestructiveChanges2 as detectDestructiveChangesValidation, detectFieldChanges, discoverSchemaFiles, extractComprehensiveFieldOptions, extractFieldDefinitions, extractFieldMetadata, extractFieldOptions, extractIndexes, extractRelationMetadata, extractSchemaDefinitions, filterDiff, filterSystemCollections, findLatestSnapshot, findNewCollections, findNewFields, findRemovedCollections, findRemovedFields, formatChangeSummary, formatDestructiveChanges, generate, generateChangeSummary, generateCollectionCreation, generateCollectionPermissions, generateCollectionRules, generateDownMigration, generateFieldAddition, generateFieldDefinitionObject, generateFieldDeletion, generateFieldModification, generateFieldsArray, generateIndexesArray, executeGenerate as generateMigration, generateMigrationDescription, generateMigrationFilename, generatePermissionUpdate, generateTimestamp, generateUpMigration, getArrayElementType, getCollectionNameFromFile, getDefaultValue, getFieldTypeInfo, getMaxSelect, executeStatus as getMigrationStatus, getMinSelect, getSnapshotPath, getSnapshotVersion, getUsersSystemFields, hasDestructiveChanges, importSchemaModule, inputImageFileSchema, isArrayType, isAuthCollection, isFieldRequired, isGeoPointType, isMultipleRelationField, isPermissionSchema, isRelationField, isSingleRelationField, isSystemCollection, isTemplateConfig, loadBaseMigration, loadConfig, loadSnapshot, loadSnapshotIfExists, loadSnapshotWithMigrations, logError, logInfo, logSection, logSuccess, logWarning, mapZodArrayType, mapZodBooleanType, mapZodDateType, mapZodEnumType, mapZodNumberType, mapZodRecordType, mapZodStringType, mapZodTypeToPocketBase, matchCollectionsByName, matchFieldsByName, mergePermissions, mergeSnapshots, omitImageFilesSchema, parseSchemaFiles, pluralize, requiresForceFlag, requiresForceFlag2 as requiresForceFlagValidation, resolveTargetCollection, resolveTemplate, saveSnapshot, selectSchemaForCollection, singularize, snapshotExists, summarizeDestructiveChanges, toCollectionName, unwrapZodType, validatePermissionConfig, validateRuleExpression, validateSnapshot, withIndexes, withPermissions, withProgress, writeMigrationFile };
|
|
7285
|
+
export { AutodateField, BaseMutator, BoolField, CLIUsageError, ConfigurationError, DateField, DiffEngine, EditorField, EmailField, FIELD_METADATA_KEY, FIELD_TYPE_INFO, FileField, FileSystemError, FilesField, GeoPointField, JSONField, MigrationError, MigrationGenerationError, MigrationGenerator, MultiSelectField, NumberField, POCKETBASE_FIELD_TYPES, PermissionTemplates, RelationField, RelationsField, SchemaAnalyzer, SchemaParsingError, SelectField, SingleSelectField, SnapshotError, SnapshotManager, StatusEnum, TextField, URLField, aggregateChanges, baseImageFileSchema, baseSchema, baseSchemaWithTimestamps, buildFieldDefinition, buildSchemaDefinition, categorizeChangesBySeverity, compare, compareFieldConstraints, compareFieldOptions, compareFieldTypes, comparePermissions, compareRelationConfigurations, convertPocketBaseMigration, convertZodSchemaToCollectionSchema, createMigrationFileStructure, createPermissions, dedentSql, defineCollection, defineView, detectDestructiveChanges, detectDestructiveChanges2 as detectDestructiveChangesValidation, detectFieldChanges, discoverSchemaFiles, extractComprehensiveFieldOptions, extractFieldDefinitions, extractFieldMetadata, extractFieldOptions, extractIndexes, extractRelationMetadata, extractSchemaDefinitions, filterDiff, filterSystemCollections, findLatestSnapshot, findNewCollections, findNewFields, findRemovedCollections, findRemovedFields, formatChangeSummary, formatDestructiveChanges, generate, generateChangeSummary, generateCollectionCreation, generateCollectionPermissions, generateCollectionRules, generateDownMigration, generateFieldAddition, generateFieldDefinitionObject, generateFieldDeletion, generateFieldModification, generateFieldsArray, generateIndexesArray, executeGenerate as generateMigration, generateMigrationDescription, generateMigrationFilename, generatePermissionUpdate, generateTimestamp, generateUpMigration, getArrayElementType, getCollectionNameFromFile, getDefaultValue, getFieldTypeInfo, getMaxSelect, executeStatus as getMigrationStatus, getMinSelect, getSnapshotPath, getSnapshotVersion, getUsersSystemFields, hasDestructiveChanges, importSchemaModule, inputImageFileSchema, isArrayType, isAuthCollection, isFieldRequired, isGeoPointType, isMultipleRelationField, isPermissionSchema, isRelationField, isSingleRelationField, isSystemCollection, isTemplateConfig, loadBaseMigration, loadConfig, loadSnapshot, loadSnapshotIfExists, loadSnapshotWithMigrations, logError, logInfo, logSection, logSuccess, logWarning, mapZodArrayType, mapZodBooleanType, mapZodDateType, mapZodEnumType, mapZodNumberType, mapZodRecordType, mapZodStringType, mapZodTypeToPocketBase, matchCollectionsByName, matchFieldsByName, mergePermissions, mergeSnapshots, omitImageFilesSchema, parseSchemaFiles, pluralize, requiresForceFlag, requiresForceFlag2 as requiresForceFlagValidation, resolveTargetCollection, resolveTemplate, saveSnapshot, selectSchemaForCollection, singularize, snapshotExists, sql, summarizeDestructiveChanges, toCollectionName, unwrapZodType, validatePermissionConfig, validateRuleExpression, validateSnapshot, validateViewQuery, withIndexes, withPermissions, withProgress, writeMigrationFile };
|
|
6810
7286
|
//# sourceMappingURL=server.js.map
|
|
6811
7287
|
//# sourceMappingURL=server.js.map
|