pocketbase-zod-schema 0.3.0 → 0.3.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 +15 -0
- package/dist/cli/index.cjs +175 -50
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +2 -2
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.js +175 -50
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/migrate.cjs +175 -50
- package/dist/cli/migrate.cjs.map +1 -1
- package/dist/cli/migrate.js +175 -50
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/utils/index.d.cts +2 -2
- package/dist/cli/utils/index.d.ts +2 -2
- package/dist/{fields-UcOPu1OQ.d.cts → fields-DBBm06VU.d.cts} +35 -7
- package/dist/{fields-UcOPu1OQ.d.ts → fields-DBBm06VU.d.ts} +35 -7
- package/dist/index.cjs +264 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +264 -84
- package/dist/index.js.map +1 -1
- package/dist/migration/analyzer.cjs.map +1 -1
- package/dist/migration/analyzer.d.cts +2 -2
- package/dist/migration/analyzer.d.ts +2 -2
- package/dist/migration/analyzer.js.map +1 -1
- package/dist/migration/diff.cjs +77 -26
- package/dist/migration/diff.cjs.map +1 -1
- package/dist/migration/diff.d.cts +4 -4
- package/dist/migration/diff.d.ts +4 -4
- package/dist/migration/diff.js +77 -26
- package/dist/migration/diff.js.map +1 -1
- package/dist/migration/generator.cjs +81 -34
- package/dist/migration/generator.cjs.map +1 -1
- package/dist/migration/generator.d.cts +2 -2
- package/dist/migration/generator.d.ts +2 -2
- package/dist/migration/generator.js +81 -34
- package/dist/migration/generator.js.map +1 -1
- package/dist/migration/index.cjs +209 -78
- package/dist/migration/index.cjs.map +1 -1
- package/dist/migration/index.d.cts +3 -3
- package/dist/migration/index.d.ts +3 -3
- package/dist/migration/index.js +209 -78
- package/dist/migration/index.js.map +1 -1
- package/dist/migration/snapshot.cjs +51 -18
- package/dist/migration/snapshot.cjs.map +1 -1
- package/dist/migration/snapshot.d.cts +2 -2
- package/dist/migration/snapshot.d.ts +2 -2
- package/dist/migration/snapshot.js +51 -18
- package/dist/migration/snapshot.js.map +1 -1
- package/dist/migration/utils/index.cjs +5 -3
- package/dist/migration/utils/index.cjs.map +1 -1
- package/dist/migration/utils/index.d.cts +4 -4
- package/dist/migration/utils/index.d.ts +4 -4
- package/dist/migration/utils/index.js +5 -3
- package/dist/migration/utils/index.js.map +1 -1
- package/dist/schema.cjs +55 -6
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +55 -6
- package/dist/schema.js.map +1 -1
- package/dist/{type-mapper-DrQmtznD.d.cts → type-mapper-DsGgZwUo.d.cts} +1 -1
- package/dist/{type-mapper-n231Fspm.d.ts → type-mapper-Dvh4QTM-.d.ts} +1 -1
- package/dist/{types-YoBjsa-A.d.cts → types-CVxPCgWX.d.cts} +1 -1
- package/dist/{types-Ds3NQvny.d.ts → types-Dfp-NP2D.d.ts} +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -488,6 +488,45 @@ function extractFieldMetadata(description) {
|
|
|
488
488
|
}
|
|
489
489
|
return null;
|
|
490
490
|
}
|
|
491
|
+
var MAX_FILE_SIZE_BYTES = 8 * 1024 * 1024 * 1024;
|
|
492
|
+
function parseByteSizeToBytes(value, context) {
|
|
493
|
+
let bytes;
|
|
494
|
+
if (typeof value === "number") {
|
|
495
|
+
if (!Number.isFinite(value)) {
|
|
496
|
+
throw new Error(`${context}: maxSize must be a finite number of bytes`);
|
|
497
|
+
}
|
|
498
|
+
bytes = Math.round(value);
|
|
499
|
+
} else {
|
|
500
|
+
const trimmed = value.trim();
|
|
501
|
+
const match = /^(\d+(?:\.\d+)?)\s*([KMG])$/i.exec(trimmed);
|
|
502
|
+
if (!match) {
|
|
503
|
+
throw new Error(`${context}: maxSize string must be like "10K", "5M", or "1G" (case-insensitive)`);
|
|
504
|
+
}
|
|
505
|
+
const amount = Number(match[1]);
|
|
506
|
+
const unit = match[2].toUpperCase();
|
|
507
|
+
if (!Number.isFinite(amount)) {
|
|
508
|
+
throw new Error(`${context}: maxSize must be a valid number`);
|
|
509
|
+
}
|
|
510
|
+
const multiplier = unit === "K" ? 1024 : unit === "M" ? 1024 * 1024 : 1024 * 1024 * 1024;
|
|
511
|
+
bytes = Math.round(amount * multiplier);
|
|
512
|
+
}
|
|
513
|
+
if (bytes < 0) {
|
|
514
|
+
throw new Error(`${context}: maxSize must be >= 0`);
|
|
515
|
+
}
|
|
516
|
+
if (bytes > MAX_FILE_SIZE_BYTES) {
|
|
517
|
+
throw new Error(`${context}: maxSize cannot exceed 8G (${MAX_FILE_SIZE_BYTES} bytes)`);
|
|
518
|
+
}
|
|
519
|
+
return bytes;
|
|
520
|
+
}
|
|
521
|
+
function normalizeFileFieldOptions(options, context) {
|
|
522
|
+
if (!options) return options;
|
|
523
|
+
if (options.maxSize === void 0) return options;
|
|
524
|
+
return {
|
|
525
|
+
...options,
|
|
526
|
+
// PocketBase expects bytes; normalize any human-friendly inputs to bytes here.
|
|
527
|
+
maxSize: parseByteSizeToBytes(options.maxSize, context)
|
|
528
|
+
};
|
|
529
|
+
}
|
|
491
530
|
function BoolField() {
|
|
492
531
|
const metadata = {
|
|
493
532
|
[FIELD_METADATA_KEY]: {
|
|
@@ -610,11 +649,14 @@ function SelectField(values, options) {
|
|
|
610
649
|
return enumSchema.describe(JSON.stringify(metadata));
|
|
611
650
|
}
|
|
612
651
|
function FileField(options) {
|
|
613
|
-
const schema = zod.z.
|
|
652
|
+
const schema = zod.z.preprocess((val) => {
|
|
653
|
+
return val instanceof File ? val.name || "" : val;
|
|
654
|
+
}, zod.z.string());
|
|
655
|
+
const normalizedOptions = normalizeFileFieldOptions(options, "FileField");
|
|
614
656
|
const metadata = {
|
|
615
657
|
[FIELD_METADATA_KEY]: {
|
|
616
658
|
type: "file",
|
|
617
|
-
options:
|
|
659
|
+
options: normalizedOptions || {}
|
|
618
660
|
}
|
|
619
661
|
};
|
|
620
662
|
return schema.describe(JSON.stringify(metadata));
|
|
@@ -625,17 +667,24 @@ function FilesField(options) {
|
|
|
625
667
|
throw new Error("FilesField: minSelect cannot be greater than maxSelect");
|
|
626
668
|
}
|
|
627
669
|
}
|
|
628
|
-
let
|
|
670
|
+
let baseArraySchema = zod.z.array(zod.z.string());
|
|
629
671
|
if (options?.minSelect !== void 0) {
|
|
630
|
-
|
|
672
|
+
baseArraySchema = baseArraySchema.min(options.minSelect);
|
|
631
673
|
}
|
|
632
674
|
if (options?.maxSelect !== void 0) {
|
|
633
|
-
|
|
675
|
+
baseArraySchema = baseArraySchema.max(options.maxSelect);
|
|
634
676
|
}
|
|
677
|
+
const schema = zod.z.preprocess((val) => {
|
|
678
|
+
if (Array.isArray(val)) {
|
|
679
|
+
return val.map((item) => item instanceof File ? item.name || "" : item);
|
|
680
|
+
}
|
|
681
|
+
return val;
|
|
682
|
+
}, baseArraySchema);
|
|
683
|
+
const normalizedOptions = normalizeFileFieldOptions(options, "FilesField");
|
|
635
684
|
const metadata = {
|
|
636
685
|
[FIELD_METADATA_KEY]: {
|
|
637
686
|
type: "file",
|
|
638
|
-
options:
|
|
687
|
+
options: normalizedOptions || {}
|
|
639
688
|
}
|
|
640
689
|
};
|
|
641
690
|
return schema.describe(JSON.stringify(metadata));
|
|
@@ -2497,7 +2546,7 @@ var SchemaAnalyzer = class {
|
|
|
2497
2546
|
var SNAPSHOT_VERSION = "1.0.0";
|
|
2498
2547
|
function resolveCollectionIdToName(collectionId) {
|
|
2499
2548
|
if (collectionId === "_pb_users_auth_") {
|
|
2500
|
-
return "
|
|
2549
|
+
return "users";
|
|
2501
2550
|
}
|
|
2502
2551
|
const nameMatch = collectionId.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
2503
2552
|
if (nameMatch) {
|
|
@@ -2505,6 +2554,39 @@ function resolveCollectionIdToName(collectionId) {
|
|
|
2505
2554
|
}
|
|
2506
2555
|
return collectionId;
|
|
2507
2556
|
}
|
|
2557
|
+
function extractFieldOptions2(pbField) {
|
|
2558
|
+
const options = {};
|
|
2559
|
+
if (pbField.options && typeof pbField.options === "object") {
|
|
2560
|
+
Object.assign(options, pbField.options);
|
|
2561
|
+
}
|
|
2562
|
+
const directOptionKeys = [
|
|
2563
|
+
"min",
|
|
2564
|
+
"max",
|
|
2565
|
+
"pattern",
|
|
2566
|
+
"noDecimal",
|
|
2567
|
+
// text/number fields
|
|
2568
|
+
"values",
|
|
2569
|
+
"maxSelect",
|
|
2570
|
+
// select fields
|
|
2571
|
+
"mimeTypes",
|
|
2572
|
+
"maxSize",
|
|
2573
|
+
"thumbs",
|
|
2574
|
+
"protected",
|
|
2575
|
+
// file fields
|
|
2576
|
+
"onCreate",
|
|
2577
|
+
"onUpdate",
|
|
2578
|
+
// autodate fields
|
|
2579
|
+
"exceptDomains",
|
|
2580
|
+
"onlyDomains"
|
|
2581
|
+
// email/url fields
|
|
2582
|
+
];
|
|
2583
|
+
for (const key of directOptionKeys) {
|
|
2584
|
+
if (pbField[key] !== void 0) {
|
|
2585
|
+
options[key] = pbField[key];
|
|
2586
|
+
}
|
|
2587
|
+
}
|
|
2588
|
+
return options;
|
|
2589
|
+
}
|
|
2508
2590
|
function convertPocketBaseCollection(pbCollection) {
|
|
2509
2591
|
const fields = [];
|
|
2510
2592
|
const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
|
|
@@ -2522,23 +2604,19 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
2522
2604
|
type: pbField.type,
|
|
2523
2605
|
required: pbField.required || false
|
|
2524
2606
|
};
|
|
2525
|
-
field.options = pbField
|
|
2526
|
-
if (pbField.type === "select") {
|
|
2527
|
-
if (pbField.values && Array.isArray(pbField.values)) {
|
|
2528
|
-
field.options.values = pbField.values;
|
|
2529
|
-
} else if (pbField.options?.values && Array.isArray(pbField.options.values)) {
|
|
2530
|
-
field.options.values = pbField.options.values;
|
|
2531
|
-
}
|
|
2532
|
-
}
|
|
2607
|
+
field.options = extractFieldOptions2(pbField);
|
|
2533
2608
|
if (pbField.type === "relation") {
|
|
2534
2609
|
const collectionId = pbField.collectionId || pbField.options?.collectionId || "";
|
|
2535
|
-
const collectionName = resolveCollectionIdToName(collectionId);
|
|
2610
|
+
const collectionName = resolveCollectionIdToName(collectionId || "");
|
|
2536
2611
|
field.relation = {
|
|
2537
2612
|
collection: collectionName,
|
|
2538
2613
|
cascadeDelete: pbField.cascadeDelete ?? pbField.options?.cascadeDelete ?? false,
|
|
2539
2614
|
maxSelect: pbField.maxSelect ?? pbField.options?.maxSelect,
|
|
2540
2615
|
minSelect: pbField.minSelect ?? pbField.options?.minSelect
|
|
2541
2616
|
};
|
|
2617
|
+
delete field.options.maxSelect;
|
|
2618
|
+
delete field.options.minSelect;
|
|
2619
|
+
delete field.options.cascadeDelete;
|
|
2542
2620
|
}
|
|
2543
2621
|
const hasOnlyValues = Object.keys(field.options).length === 1 && field.options.values !== void 0;
|
|
2544
2622
|
if (Object.keys(field.options).length === 0) {
|
|
@@ -2552,17 +2630,21 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
2552
2630
|
type: pbCollection.type || "base",
|
|
2553
2631
|
fields
|
|
2554
2632
|
};
|
|
2633
|
+
if (pbCollection.id) {
|
|
2634
|
+
schema.id = pbCollection.id;
|
|
2635
|
+
}
|
|
2555
2636
|
if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
|
|
2556
2637
|
schema.indexes = pbCollection.indexes;
|
|
2557
2638
|
}
|
|
2558
|
-
const
|
|
2559
|
-
if (
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2639
|
+
const hasAnyRule = pbCollection.listRule !== void 0 || pbCollection.viewRule !== void 0 || pbCollection.createRule !== void 0 || pbCollection.updateRule !== void 0 || pbCollection.deleteRule !== void 0 || pbCollection.manageRule !== void 0;
|
|
2640
|
+
if (hasAnyRule) {
|
|
2641
|
+
const rules = {};
|
|
2642
|
+
if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
|
|
2643
|
+
if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
|
|
2644
|
+
if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
|
|
2645
|
+
if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
|
|
2646
|
+
if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
|
|
2647
|
+
if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
|
|
2566
2648
|
schema.rules = rules;
|
|
2567
2649
|
schema.permissions = { ...rules };
|
|
2568
2650
|
}
|
|
@@ -3312,17 +3394,19 @@ var CollectionIdRegistry = class {
|
|
|
3312
3394
|
}
|
|
3313
3395
|
/**
|
|
3314
3396
|
* Generates a unique collection ID for a given collection name
|
|
3315
|
-
* Special case: Returns constant "_pb_users_auth_" for users collection
|
|
3316
3397
|
* Retries up to 10 times if collision occurs (extremely rare)
|
|
3398
|
+
* Special case: returns "_pb_users_auth_" for users collection
|
|
3317
3399
|
*
|
|
3318
|
-
* @param collectionName - The name of the collection
|
|
3400
|
+
* @param collectionName - The name of the collection (optional)
|
|
3319
3401
|
* @returns A unique collection ID
|
|
3320
3402
|
* @throws Error if unable to generate unique ID after max attempts
|
|
3321
3403
|
*/
|
|
3322
3404
|
generate(collectionName) {
|
|
3323
3405
|
if (collectionName && collectionName.toLowerCase() === "users") {
|
|
3324
3406
|
const usersId = "_pb_users_auth_";
|
|
3325
|
-
this.
|
|
3407
|
+
if (!this.has(usersId)) {
|
|
3408
|
+
this.register(usersId);
|
|
3409
|
+
}
|
|
3326
3410
|
return usersId;
|
|
3327
3411
|
}
|
|
3328
3412
|
const maxAttempts = 10;
|
|
@@ -3506,18 +3590,49 @@ function compareFieldConstraints(currentField, previousField) {
|
|
|
3506
3590
|
}
|
|
3507
3591
|
return changes;
|
|
3508
3592
|
}
|
|
3593
|
+
function normalizeOptionValue(key, value, fieldType) {
|
|
3594
|
+
if (key === "maxSelect" && value === 1 && (fieldType === "select" || fieldType === "file")) {
|
|
3595
|
+
return void 0;
|
|
3596
|
+
}
|
|
3597
|
+
if (key === "maxSize" && value === 0 && fieldType === "file") {
|
|
3598
|
+
return void 0;
|
|
3599
|
+
}
|
|
3600
|
+
if (fieldType === "file") {
|
|
3601
|
+
if (key === "mimeTypes" && Array.isArray(value) && value.length === 0) {
|
|
3602
|
+
return void 0;
|
|
3603
|
+
}
|
|
3604
|
+
if (key === "thumbs" && Array.isArray(value) && value.length === 0) {
|
|
3605
|
+
return void 0;
|
|
3606
|
+
}
|
|
3607
|
+
if (key === "protected" && value === false) {
|
|
3608
|
+
return void 0;
|
|
3609
|
+
}
|
|
3610
|
+
}
|
|
3611
|
+
if (fieldType === "autodate") {
|
|
3612
|
+
if (key === "onCreate" && value === true) {
|
|
3613
|
+
return void 0;
|
|
3614
|
+
}
|
|
3615
|
+
if (key === "onUpdate" && value === false) {
|
|
3616
|
+
return void 0;
|
|
3617
|
+
}
|
|
3618
|
+
}
|
|
3619
|
+
return value;
|
|
3620
|
+
}
|
|
3509
3621
|
function compareFieldOptions(currentField, previousField) {
|
|
3510
3622
|
const changes = [];
|
|
3511
3623
|
const currentOptions = currentField.options || {};
|
|
3512
3624
|
const previousOptions = previousField.options || {};
|
|
3513
3625
|
const allKeys = /* @__PURE__ */ new Set([...Object.keys(currentOptions), ...Object.keys(previousOptions)]);
|
|
3626
|
+
const fieldType = currentField.type;
|
|
3514
3627
|
for (const key of allKeys) {
|
|
3515
3628
|
const currentValue = currentOptions[key];
|
|
3516
3629
|
const previousValue = previousOptions[key];
|
|
3517
|
-
|
|
3630
|
+
const normalizedCurrent = normalizeOptionValue(key, currentValue, fieldType);
|
|
3631
|
+
const normalizedPrevious = normalizeOptionValue(key, previousValue, fieldType);
|
|
3632
|
+
if (normalizedCurrent === void 0 && normalizedPrevious === void 0) {
|
|
3518
3633
|
continue;
|
|
3519
3634
|
}
|
|
3520
|
-
if (!areValuesEqual(
|
|
3635
|
+
if (!areValuesEqual(normalizedCurrent, normalizedPrevious)) {
|
|
3521
3636
|
changes.push({
|
|
3522
3637
|
property: `options.${key}`,
|
|
3523
3638
|
oldValue: previousValue,
|
|
@@ -3527,7 +3642,7 @@ function compareFieldOptions(currentField, previousField) {
|
|
|
3527
3642
|
}
|
|
3528
3643
|
return changes;
|
|
3529
3644
|
}
|
|
3530
|
-
function compareRelationConfigurations(currentField, previousField) {
|
|
3645
|
+
function compareRelationConfigurations(currentField, previousField, collectionIdToName) {
|
|
3531
3646
|
const changes = [];
|
|
3532
3647
|
const currentRelation = currentField.relation;
|
|
3533
3648
|
const previousRelation = previousField.relation;
|
|
@@ -3539,8 +3654,8 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
3539
3654
|
}
|
|
3540
3655
|
const normalizeCollection = (collection) => {
|
|
3541
3656
|
if (!collection) return collection;
|
|
3542
|
-
if (
|
|
3543
|
-
return
|
|
3657
|
+
if (collectionIdToName && collectionIdToName.has(collection)) {
|
|
3658
|
+
return collectionIdToName.get(collection);
|
|
3544
3659
|
}
|
|
3545
3660
|
const nameMatch = collection.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
|
|
3546
3661
|
if (nameMatch) {
|
|
@@ -3550,13 +3665,11 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
3550
3665
|
};
|
|
3551
3666
|
const normalizedCurrent = normalizeCollection(currentRelation.collection);
|
|
3552
3667
|
const normalizedPrevious = normalizeCollection(previousRelation.collection);
|
|
3553
|
-
if (normalizedCurrent !== normalizedPrevious) {
|
|
3668
|
+
if (normalizedCurrent.toLowerCase() !== normalizedPrevious.toLowerCase()) {
|
|
3554
3669
|
changes.push({
|
|
3555
3670
|
property: "relation.collection",
|
|
3556
|
-
oldValue:
|
|
3557
|
-
|
|
3558
|
-
newValue: normalizedCurrent
|
|
3559
|
-
// Use normalized value for clarity
|
|
3671
|
+
oldValue: previousRelation.collection,
|
|
3672
|
+
newValue: currentRelation.collection
|
|
3560
3673
|
});
|
|
3561
3674
|
}
|
|
3562
3675
|
if (currentRelation.cascadeDelete !== previousRelation.cascadeDelete) {
|
|
@@ -3566,14 +3679,20 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
3566
3679
|
newValue: currentRelation.cascadeDelete
|
|
3567
3680
|
});
|
|
3568
3681
|
}
|
|
3569
|
-
|
|
3682
|
+
const normalizeMax = (val) => val === 1 ? null : val;
|
|
3683
|
+
const currentMax = normalizeMax(currentRelation.maxSelect);
|
|
3684
|
+
const previousMax = normalizeMax(previousRelation.maxSelect);
|
|
3685
|
+
if (currentMax != previousMax) {
|
|
3570
3686
|
changes.push({
|
|
3571
3687
|
property: "relation.maxSelect",
|
|
3572
3688
|
oldValue: previousRelation.maxSelect,
|
|
3573
3689
|
newValue: currentRelation.maxSelect
|
|
3574
3690
|
});
|
|
3575
3691
|
}
|
|
3576
|
-
|
|
3692
|
+
const normalizeMin = (val) => val === 0 ? null : val;
|
|
3693
|
+
const currentMin = normalizeMin(currentRelation.minSelect);
|
|
3694
|
+
const previousMin = normalizeMin(previousRelation.minSelect);
|
|
3695
|
+
if (currentMin != previousMin) {
|
|
3577
3696
|
changes.push({
|
|
3578
3697
|
property: "relation.minSelect",
|
|
3579
3698
|
oldValue: previousRelation.minSelect,
|
|
@@ -3582,7 +3701,7 @@ function compareRelationConfigurations(currentField, previousField) {
|
|
|
3582
3701
|
}
|
|
3583
3702
|
return changes;
|
|
3584
3703
|
}
|
|
3585
|
-
function detectFieldChanges(currentField, previousField) {
|
|
3704
|
+
function detectFieldChanges(currentField, previousField, collectionIdToName) {
|
|
3586
3705
|
const changes = [];
|
|
3587
3706
|
const typeChange = compareFieldTypes(currentField, previousField);
|
|
3588
3707
|
if (typeChange) {
|
|
@@ -3591,7 +3710,7 @@ function detectFieldChanges(currentField, previousField) {
|
|
|
3591
3710
|
changes.push(...compareFieldConstraints(currentField, previousField));
|
|
3592
3711
|
changes.push(...compareFieldOptions(currentField, previousField));
|
|
3593
3712
|
if (currentField.type === "relation" && previousField.type === "relation") {
|
|
3594
|
-
changes.push(...compareRelationConfigurations(currentField, previousField));
|
|
3713
|
+
changes.push(...compareRelationConfigurations(currentField, previousField, collectionIdToName));
|
|
3595
3714
|
}
|
|
3596
3715
|
return changes;
|
|
3597
3716
|
}
|
|
@@ -3602,7 +3721,7 @@ function compareIndexes(currentIndexes = [], previousIndexes = []) {
|
|
|
3602
3721
|
const indexesToRemove = previousIndexes.filter((idx) => !currentSet.has(idx));
|
|
3603
3722
|
return { indexesToAdd, indexesToRemove };
|
|
3604
3723
|
}
|
|
3605
|
-
function compareRules(currentRules, previousRules) {
|
|
3724
|
+
function compareRules(currentRules, previousRules, currentPermissions, previousPermissions) {
|
|
3606
3725
|
const updates = [];
|
|
3607
3726
|
const ruleTypes = [
|
|
3608
3727
|
"listRule",
|
|
@@ -3613,8 +3732,8 @@ function compareRules(currentRules, previousRules) {
|
|
|
3613
3732
|
"manageRule"
|
|
3614
3733
|
];
|
|
3615
3734
|
for (const ruleType of ruleTypes) {
|
|
3616
|
-
const currentValue = currentRules?.[ruleType] ?? null;
|
|
3617
|
-
const previousValue = previousRules?.[ruleType] ?? null;
|
|
3735
|
+
const currentValue = currentRules?.[ruleType] ?? currentPermissions?.[ruleType] ?? null;
|
|
3736
|
+
const previousValue = previousRules?.[ruleType] ?? previousPermissions?.[ruleType] ?? null;
|
|
3618
3737
|
if (currentValue !== previousValue) {
|
|
3619
3738
|
updates.push({
|
|
3620
3739
|
ruleType,
|
|
@@ -3641,7 +3760,7 @@ function comparePermissions(currentPermissions, previousPermissions) {
|
|
|
3641
3760
|
}
|
|
3642
3761
|
return changes;
|
|
3643
3762
|
}
|
|
3644
|
-
function compareCollectionFields(currentCollection, previousCollection, config) {
|
|
3763
|
+
function compareCollectionFields(currentCollection, previousCollection, config, collectionIdToName) {
|
|
3645
3764
|
let fieldsToAdd = findNewFields(currentCollection.fields, previousCollection.fields);
|
|
3646
3765
|
const fieldsToRemove = findRemovedFields(currentCollection.fields, previousCollection.fields);
|
|
3647
3766
|
const fieldsToModify = [];
|
|
@@ -3651,7 +3770,7 @@ function compareCollectionFields(currentCollection, previousCollection, config)
|
|
|
3651
3770
|
}
|
|
3652
3771
|
const matchedFields = matchFieldsByName(currentCollection.fields, previousCollection.fields);
|
|
3653
3772
|
for (const [currentField, previousField] of matchedFields) {
|
|
3654
|
-
const changes = detectFieldChanges(currentField, previousField);
|
|
3773
|
+
const changes = detectFieldChanges(currentField, previousField, collectionIdToName);
|
|
3655
3774
|
if (changes.length > 0) {
|
|
3656
3775
|
fieldsToModify.push({
|
|
3657
3776
|
fieldName: currentField.name,
|
|
@@ -3663,14 +3782,20 @@ function compareCollectionFields(currentCollection, previousCollection, config)
|
|
|
3663
3782
|
}
|
|
3664
3783
|
return { fieldsToAdd, fieldsToRemove, fieldsToModify };
|
|
3665
3784
|
}
|
|
3666
|
-
function buildCollectionModification(currentCollection, previousCollection, config) {
|
|
3785
|
+
function buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName) {
|
|
3667
3786
|
const { fieldsToAdd, fieldsToRemove, fieldsToModify } = compareCollectionFields(
|
|
3668
3787
|
currentCollection,
|
|
3669
3788
|
previousCollection,
|
|
3670
|
-
config
|
|
3789
|
+
config,
|
|
3790
|
+
collectionIdToName
|
|
3671
3791
|
);
|
|
3672
3792
|
const { indexesToAdd, indexesToRemove } = compareIndexes(currentCollection.indexes, previousCollection.indexes);
|
|
3673
|
-
const rulesToUpdate = compareRules(
|
|
3793
|
+
const rulesToUpdate = compareRules(
|
|
3794
|
+
currentCollection.rules,
|
|
3795
|
+
previousCollection.rules,
|
|
3796
|
+
currentCollection.permissions,
|
|
3797
|
+
previousCollection.permissions
|
|
3798
|
+
);
|
|
3674
3799
|
const permissionsToUpdate = comparePermissions(currentCollection.permissions, previousCollection.permissions);
|
|
3675
3800
|
return {
|
|
3676
3801
|
collection: currentCollection.name,
|
|
@@ -3687,6 +3812,14 @@ function hasChanges(modification) {
|
|
|
3687
3812
|
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;
|
|
3688
3813
|
}
|
|
3689
3814
|
function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
3815
|
+
const collectionIdToName = /* @__PURE__ */ new Map();
|
|
3816
|
+
if (previousSnapshot) {
|
|
3817
|
+
for (const [name, collection] of previousSnapshot.collections) {
|
|
3818
|
+
if (collection.id) {
|
|
3819
|
+
collectionIdToName.set(collection.id, name);
|
|
3820
|
+
}
|
|
3821
|
+
}
|
|
3822
|
+
}
|
|
3690
3823
|
const collectionsToCreate = findNewCollections(currentSchema, previousSnapshot);
|
|
3691
3824
|
const collectionsToDelete = findRemovedCollections(currentSchema, previousSnapshot);
|
|
3692
3825
|
const filteredCollectionsToCreate = collectionsToCreate.filter(
|
|
@@ -3710,7 +3843,7 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
|
3710
3843
|
const collectionsToModify = [];
|
|
3711
3844
|
const matchedCollections = matchCollectionsByName(currentSchema, previousSnapshot);
|
|
3712
3845
|
for (const [currentCollection, previousCollection] of matchedCollections) {
|
|
3713
|
-
const modification = buildCollectionModification(currentCollection, previousCollection, config);
|
|
3846
|
+
const modification = buildCollectionModification(currentCollection, previousCollection, config, collectionIdToName);
|
|
3714
3847
|
if (hasChanges(modification)) {
|
|
3715
3848
|
collectionsToModify.push(modification);
|
|
3716
3849
|
}
|
|
@@ -4111,7 +4244,7 @@ function formatValue(value) {
|
|
|
4111
4244
|
return JSON.stringify(value).replace(/","/g, '", "');
|
|
4112
4245
|
}
|
|
4113
4246
|
if (typeof value === "object") {
|
|
4114
|
-
const entries = Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
|
|
4247
|
+
const entries = Object.entries(value).filter(([_k, v]) => v !== void 0).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
|
|
4115
4248
|
return `{ ${entries} }`;
|
|
4116
4249
|
}
|
|
4117
4250
|
return String(value);
|
|
@@ -4280,6 +4413,9 @@ function getSystemFields() {
|
|
|
4280
4413
|
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
4281
4414
|
const lines = [];
|
|
4282
4415
|
lines.push(` const ${varName} = new Collection({`);
|
|
4416
|
+
if (collection.id) {
|
|
4417
|
+
lines.push(` id: ${formatValue(collection.id)},`);
|
|
4418
|
+
}
|
|
4283
4419
|
lines.push(` name: "${collection.name}",`);
|
|
4284
4420
|
lines.push(` type: "${collection.type}",`);
|
|
4285
4421
|
const permissionsCode = generateCollectionPermissions(collection.permissions);
|
|
@@ -4402,11 +4538,9 @@ function generateFieldModification(collectionName, modification, varName, isLast
|
|
|
4402
4538
|
function generateFieldDeletion(collectionName, fieldName, varName, isLast = false) {
|
|
4403
4539
|
const lines = [];
|
|
4404
4540
|
const collectionVar = varName || `collection_${collectionName}_${fieldName}`;
|
|
4405
|
-
const fieldVar = `${collectionVar}_field`;
|
|
4406
4541
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
4407
|
-
lines.push(` const ${fieldVar} = ${collectionVar}.fields.getByName("${fieldName}");`);
|
|
4408
4542
|
lines.push(``);
|
|
4409
|
-
lines.push(` ${collectionVar}.fields.
|
|
4543
|
+
lines.push(` ${collectionVar}.fields.removeByName("${fieldName}");`);
|
|
4410
4544
|
lines.push(``);
|
|
4411
4545
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
4412
4546
|
return lines.join("\n");
|
|
@@ -4523,7 +4657,27 @@ function generateOperationUpMigration(operation, collectionIdMap) {
|
|
|
4523
4657
|
const varName = `collection_${collectionName}`;
|
|
4524
4658
|
lines.push(generateCollectionDeletion(collectionName, varName, true));
|
|
4525
4659
|
}
|
|
4526
|
-
|
|
4660
|
+
let code = lines.join("\n");
|
|
4661
|
+
const hasReturnStatement = /return\s+app\.(save|delete)\(/m.test(code);
|
|
4662
|
+
if (!hasReturnStatement) {
|
|
4663
|
+
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
4664
|
+
const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
|
|
4665
|
+
const saveMatches = [...code.matchAll(savePattern)];
|
|
4666
|
+
const deleteMatches = [...code.matchAll(deletePattern)];
|
|
4667
|
+
const allMatches = [
|
|
4668
|
+
...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
|
|
4669
|
+
...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
|
|
4670
|
+
].sort((a, b) => b.index - a.index);
|
|
4671
|
+
if (allMatches.length > 0) {
|
|
4672
|
+
const lastMatch = allMatches[0];
|
|
4673
|
+
if (lastMatch.type === "save") {
|
|
4674
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.save(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4675
|
+
} else {
|
|
4676
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.delete(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4677
|
+
}
|
|
4678
|
+
}
|
|
4679
|
+
}
|
|
4680
|
+
return code;
|
|
4527
4681
|
}
|
|
4528
4682
|
function generateOperationDownMigration(operation, collectionIdMap) {
|
|
4529
4683
|
const lines = [];
|
|
@@ -4608,7 +4762,27 @@ function generateOperationDownMigration(operation, collectionIdMap) {
|
|
|
4608
4762
|
lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
|
|
4609
4763
|
}
|
|
4610
4764
|
}
|
|
4611
|
-
|
|
4765
|
+
let code = lines.join("\n");
|
|
4766
|
+
const hasReturnStatement = /return\s+app\.(save|delete)\(/m.test(code);
|
|
4767
|
+
if (!hasReturnStatement) {
|
|
4768
|
+
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
4769
|
+
const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
|
|
4770
|
+
const saveMatches = [...code.matchAll(savePattern)];
|
|
4771
|
+
const deleteMatches = [...code.matchAll(deletePattern)];
|
|
4772
|
+
const allMatches = [
|
|
4773
|
+
...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
|
|
4774
|
+
...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
|
|
4775
|
+
].sort((a, b) => b.index - a.index);
|
|
4776
|
+
if (allMatches.length > 0) {
|
|
4777
|
+
const lastMatch = allMatches[0];
|
|
4778
|
+
if (lastMatch.type === "save") {
|
|
4779
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.save(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4780
|
+
} else {
|
|
4781
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.delete(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4782
|
+
}
|
|
4783
|
+
}
|
|
4784
|
+
}
|
|
4785
|
+
return code;
|
|
4612
4786
|
}
|
|
4613
4787
|
function generateUpMigration(diff) {
|
|
4614
4788
|
const lines = [];
|
|
@@ -4706,20 +4880,23 @@ function generateUpMigration(diff) {
|
|
|
4706
4880
|
lines.push(``);
|
|
4707
4881
|
}
|
|
4708
4882
|
let code = lines.join("\n");
|
|
4709
|
-
const
|
|
4710
|
-
|
|
4711
|
-
|
|
4712
|
-
|
|
4713
|
-
|
|
4714
|
-
|
|
4715
|
-
|
|
4716
|
-
|
|
4717
|
-
|
|
4718
|
-
|
|
4719
|
-
if (
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4883
|
+
const hasReturnStatement = /return\s+app\.(save|delete)\(/m.test(code);
|
|
4884
|
+
if (!hasReturnStatement) {
|
|
4885
|
+
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
4886
|
+
const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
|
|
4887
|
+
const saveMatches = [...code.matchAll(savePattern)];
|
|
4888
|
+
const deleteMatches = [...code.matchAll(deletePattern)];
|
|
4889
|
+
const allMatches = [
|
|
4890
|
+
...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
|
|
4891
|
+
...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
|
|
4892
|
+
].sort((a, b) => b.index - a.index);
|
|
4893
|
+
if (allMatches.length > 0) {
|
|
4894
|
+
const lastMatch = allMatches[0];
|
|
4895
|
+
if (lastMatch.type === "save") {
|
|
4896
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.save(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4897
|
+
} else {
|
|
4898
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.delete(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
4899
|
+
}
|
|
4723
4900
|
}
|
|
4724
4901
|
}
|
|
4725
4902
|
return code;
|
|
@@ -4836,20 +5013,23 @@ function generateDownMigration(diff) {
|
|
|
4836
5013
|
lines.push(``);
|
|
4837
5014
|
}
|
|
4838
5015
|
let code = lines.join("\n");
|
|
4839
|
-
const
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
|
|
4848
|
-
|
|
4849
|
-
if (
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
|
|
5016
|
+
const hasReturnStatement = /return\s+app\.(save|delete)\(/m.test(code);
|
|
5017
|
+
if (!hasReturnStatement) {
|
|
5018
|
+
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
5019
|
+
const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
|
|
5020
|
+
const saveMatches = [...code.matchAll(savePattern)];
|
|
5021
|
+
const deleteMatches = [...code.matchAll(deletePattern)];
|
|
5022
|
+
const allMatches = [
|
|
5023
|
+
...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
|
|
5024
|
+
...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
|
|
5025
|
+
].sort((a, b) => b.index - a.index);
|
|
5026
|
+
if (allMatches.length > 0) {
|
|
5027
|
+
const lastMatch = allMatches[0];
|
|
5028
|
+
if (lastMatch.type === "save") {
|
|
5029
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.save(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
5030
|
+
} else {
|
|
5031
|
+
code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.delete(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
|
|
5032
|
+
}
|
|
4853
5033
|
}
|
|
4854
5034
|
}
|
|
4855
5035
|
return code;
|