pocketbase-zod-schema 0.2.4 → 0.3.0
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/README.md +209 -24
- package/dist/cli/index.cjs +406 -294
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.d.cts +3 -1
- package/dist/cli/index.d.ts +3 -1
- package/dist/cli/index.js +406 -294
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/migrate.cjs +406 -294
- package/dist/cli/migrate.cjs.map +1 -1
- package/dist/cli/migrate.js +406 -294
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/utils/index.d.cts +3 -1
- package/dist/cli/utils/index.d.ts +3 -1
- package/dist/fields-UcOPu1OQ.d.cts +364 -0
- package/dist/fields-UcOPu1OQ.d.ts +364 -0
- package/dist/index.cjs +633 -112
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +619 -101
- package/dist/index.js.map +1 -1
- package/dist/migration/analyzer.cjs +44 -0
- package/dist/migration/analyzer.cjs.map +1 -1
- package/dist/migration/analyzer.d.cts +2 -1
- package/dist/migration/analyzer.d.ts +2 -1
- package/dist/migration/analyzer.js +44 -0
- package/dist/migration/analyzer.js.map +1 -1
- package/dist/migration/diff.cjs +76 -1
- package/dist/migration/diff.cjs.map +1 -1
- package/dist/migration/diff.d.cts +3 -1
- package/dist/migration/diff.d.ts +3 -1
- package/dist/migration/diff.js +76 -1
- package/dist/migration/diff.js.map +1 -1
- package/dist/migration/generator.cjs +323 -46
- package/dist/migration/generator.cjs.map +1 -1
- package/dist/migration/generator.d.cts +60 -11
- package/dist/migration/generator.d.ts +60 -11
- package/dist/migration/generator.js +319 -47
- package/dist/migration/generator.js.map +1 -1
- package/dist/migration/index.cjs +433 -47
- package/dist/migration/index.cjs.map +1 -1
- package/dist/migration/index.d.cts +3 -2
- package/dist/migration/index.d.ts +3 -2
- package/dist/migration/index.js +432 -48
- package/dist/migration/index.js.map +1 -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.map +1 -1
- package/dist/migration/utils/index.cjs +80 -0
- package/dist/migration/utils/index.cjs.map +1 -1
- package/dist/migration/utils/index.d.cts +39 -202
- package/dist/migration/utils/index.d.ts +39 -202
- package/dist/migration/utils/index.js +77 -1
- package/dist/migration/utils/index.js.map +1 -1
- package/dist/schema.cjs +200 -61
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +2 -85
- package/dist/schema.d.ts +2 -85
- package/dist/schema.js +186 -50
- package/dist/schema.js.map +1 -1
- package/dist/type-mapper-DrQmtznD.d.cts +208 -0
- package/dist/type-mapper-n231Fspm.d.ts +208 -0
- package/dist/{types-z1Dkjg8m.d.ts → types-Ds3NQvny.d.ts} +33 -2
- package/dist/{types-BbTgmg6H.d.cts → types-YoBjsa-A.d.cts} +33 -2
- package/package.json +1 -1
package/dist/migration/index.cjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
var fs3 = require('fs');
|
|
4
4
|
var path = require('path');
|
|
5
5
|
var zod = require('zod');
|
|
6
|
+
var crypto = require('crypto');
|
|
6
7
|
|
|
7
8
|
function _interopNamespace(e) {
|
|
8
9
|
if (e && e.__esModule) return e;
|
|
@@ -57,6 +58,18 @@ function extractRelationMetadata(description) {
|
|
|
57
58
|
}
|
|
58
59
|
return null;
|
|
59
60
|
}
|
|
61
|
+
var FIELD_METADATA_KEY = "__pocketbase_field__";
|
|
62
|
+
function extractFieldMetadata(description) {
|
|
63
|
+
if (!description) return null;
|
|
64
|
+
try {
|
|
65
|
+
const parsed = JSON.parse(description);
|
|
66
|
+
if (parsed[FIELD_METADATA_KEY]) {
|
|
67
|
+
return parsed[FIELD_METADATA_KEY];
|
|
68
|
+
}
|
|
69
|
+
} catch {
|
|
70
|
+
}
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
60
73
|
|
|
61
74
|
// src/migration/errors.ts
|
|
62
75
|
var MigrationError = class _MigrationError extends Error {
|
|
@@ -1567,6 +1580,38 @@ function isAuthCollection(fields) {
|
|
|
1567
1580
|
return hasEmail && hasPassword;
|
|
1568
1581
|
}
|
|
1569
1582
|
function buildFieldDefinition(fieldName, zodType) {
|
|
1583
|
+
const fieldMetadata = extractFieldMetadata(zodType.description);
|
|
1584
|
+
if (fieldMetadata) {
|
|
1585
|
+
let required2;
|
|
1586
|
+
if (fieldMetadata.type === "number") {
|
|
1587
|
+
if (fieldMetadata.options?.required !== void 0) {
|
|
1588
|
+
required2 = fieldMetadata.options.required;
|
|
1589
|
+
} else {
|
|
1590
|
+
required2 = false;
|
|
1591
|
+
}
|
|
1592
|
+
} else {
|
|
1593
|
+
required2 = isFieldRequired(zodType);
|
|
1594
|
+
}
|
|
1595
|
+
const { required: _required, ...options2 } = fieldMetadata.options || {};
|
|
1596
|
+
const fieldDef2 = {
|
|
1597
|
+
name: fieldName,
|
|
1598
|
+
type: fieldMetadata.type,
|
|
1599
|
+
required: required2,
|
|
1600
|
+
options: Object.keys(options2).length > 0 ? options2 : void 0
|
|
1601
|
+
};
|
|
1602
|
+
if (fieldMetadata.type === "relation") {
|
|
1603
|
+
const relationMetadata2 = extractRelationMetadata(zodType.description);
|
|
1604
|
+
if (relationMetadata2) {
|
|
1605
|
+
fieldDef2.relation = {
|
|
1606
|
+
collection: relationMetadata2.collection,
|
|
1607
|
+
maxSelect: relationMetadata2.maxSelect,
|
|
1608
|
+
minSelect: relationMetadata2.minSelect,
|
|
1609
|
+
cascadeDelete: relationMetadata2.cascadeDelete
|
|
1610
|
+
};
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
return fieldDef2;
|
|
1614
|
+
}
|
|
1570
1615
|
const fieldType = mapZodTypeToPocketBase(zodType, fieldName);
|
|
1571
1616
|
const required = isFieldRequired(zodType);
|
|
1572
1617
|
const options = extractFieldOptions(zodType);
|
|
@@ -2548,6 +2593,65 @@ var SnapshotManager = class {
|
|
|
2548
2593
|
return validateSnapshot(snapshot);
|
|
2549
2594
|
}
|
|
2550
2595
|
};
|
|
2596
|
+
function generateCollectionId() {
|
|
2597
|
+
const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
|
|
2598
|
+
const idLength = 15;
|
|
2599
|
+
const bytes = crypto.randomBytes(idLength);
|
|
2600
|
+
let id = "pb_";
|
|
2601
|
+
for (let i = 0; i < idLength; i++) {
|
|
2602
|
+
const index = bytes[i] % chars.length;
|
|
2603
|
+
id += chars[index];
|
|
2604
|
+
}
|
|
2605
|
+
return id;
|
|
2606
|
+
}
|
|
2607
|
+
var CollectionIdRegistry = class {
|
|
2608
|
+
ids;
|
|
2609
|
+
constructor() {
|
|
2610
|
+
this.ids = /* @__PURE__ */ new Set();
|
|
2611
|
+
}
|
|
2612
|
+
/**
|
|
2613
|
+
* Generates a unique collection ID for a given collection name
|
|
2614
|
+
* Special case: Returns constant "_pb_users_auth_" for users collection
|
|
2615
|
+
* Retries up to 10 times if collision occurs (extremely rare)
|
|
2616
|
+
*
|
|
2617
|
+
* @param collectionName - The name of the collection
|
|
2618
|
+
* @returns A unique collection ID
|
|
2619
|
+
* @throws Error if unable to generate unique ID after max attempts
|
|
2620
|
+
*/
|
|
2621
|
+
generate(collectionName) {
|
|
2622
|
+
if (collectionName && collectionName.toLowerCase() === "users") {
|
|
2623
|
+
const usersId = "_pb_users_auth_";
|
|
2624
|
+
this.register(usersId);
|
|
2625
|
+
return usersId;
|
|
2626
|
+
}
|
|
2627
|
+
const maxAttempts = 10;
|
|
2628
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
2629
|
+
const id = generateCollectionId();
|
|
2630
|
+
if (!this.has(id)) {
|
|
2631
|
+
this.register(id);
|
|
2632
|
+
return id;
|
|
2633
|
+
}
|
|
2634
|
+
}
|
|
2635
|
+
throw new Error("Failed to generate unique collection ID after maximum attempts");
|
|
2636
|
+
}
|
|
2637
|
+
/**
|
|
2638
|
+
* Checks if an ID has already been registered
|
|
2639
|
+
*
|
|
2640
|
+
* @param id - The collection ID to check
|
|
2641
|
+
* @returns True if the ID exists in the registry
|
|
2642
|
+
*/
|
|
2643
|
+
has(id) {
|
|
2644
|
+
return this.ids.has(id);
|
|
2645
|
+
}
|
|
2646
|
+
/**
|
|
2647
|
+
* Registers a collection ID in the registry
|
|
2648
|
+
*
|
|
2649
|
+
* @param id - The collection ID to register
|
|
2650
|
+
*/
|
|
2651
|
+
register(id) {
|
|
2652
|
+
this.ids.add(id);
|
|
2653
|
+
}
|
|
2654
|
+
};
|
|
2551
2655
|
|
|
2552
2656
|
// src/migration/diff.ts
|
|
2553
2657
|
var DEFAULT_CONFIG3 = {
|
|
@@ -2890,6 +2994,18 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
|
2890
2994
|
const filteredCollectionsToDelete = collectionsToDelete.filter(
|
|
2891
2995
|
(collection) => !isSystemCollection(collection.name, config)
|
|
2892
2996
|
);
|
|
2997
|
+
const registry = new CollectionIdRegistry();
|
|
2998
|
+
const collectionsWithIds = filteredCollectionsToCreate.map((collection) => {
|
|
2999
|
+
if (collection.id) {
|
|
3000
|
+
registry.register(collection.id);
|
|
3001
|
+
return collection;
|
|
3002
|
+
}
|
|
3003
|
+
const id = registry.generate(collection.name);
|
|
3004
|
+
return {
|
|
3005
|
+
...collection,
|
|
3006
|
+
id
|
|
3007
|
+
};
|
|
3008
|
+
});
|
|
2893
3009
|
const collectionsToModify = [];
|
|
2894
3010
|
const matchedCollections = matchCollectionsByName(currentSchema, previousSnapshot);
|
|
2895
3011
|
for (const [currentCollection, previousCollection] of matchedCollections) {
|
|
@@ -2899,7 +3015,7 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
|
|
|
2899
3015
|
}
|
|
2900
3016
|
}
|
|
2901
3017
|
return {
|
|
2902
|
-
collectionsToCreate:
|
|
3018
|
+
collectionsToCreate: collectionsWithIds,
|
|
2903
3019
|
collectionsToDelete: filteredCollectionsToDelete,
|
|
2904
3020
|
collectionsToModify
|
|
2905
3021
|
};
|
|
@@ -3135,6 +3251,49 @@ function generateTimestamp(config) {
|
|
|
3135
3251
|
}
|
|
3136
3252
|
return Math.floor(Date.now() / 1e3).toString();
|
|
3137
3253
|
}
|
|
3254
|
+
function splitDiffByCollection(diff, baseTimestamp) {
|
|
3255
|
+
const operations = [];
|
|
3256
|
+
let currentTimestamp = parseInt(baseTimestamp, 10);
|
|
3257
|
+
for (const collection of diff.collectionsToCreate) {
|
|
3258
|
+
operations.push({
|
|
3259
|
+
type: "create",
|
|
3260
|
+
collection,
|
|
3261
|
+
timestamp: currentTimestamp.toString()
|
|
3262
|
+
});
|
|
3263
|
+
currentTimestamp += 1;
|
|
3264
|
+
}
|
|
3265
|
+
for (const modification of diff.collectionsToModify) {
|
|
3266
|
+
operations.push({
|
|
3267
|
+
type: "modify",
|
|
3268
|
+
collection: modification.collection,
|
|
3269
|
+
modifications: modification,
|
|
3270
|
+
timestamp: currentTimestamp.toString()
|
|
3271
|
+
});
|
|
3272
|
+
currentTimestamp += 1;
|
|
3273
|
+
}
|
|
3274
|
+
for (const collection of diff.collectionsToDelete) {
|
|
3275
|
+
operations.push({
|
|
3276
|
+
type: "delete",
|
|
3277
|
+
collection: collection.name || collection,
|
|
3278
|
+
// Handle both object and string
|
|
3279
|
+
timestamp: currentTimestamp.toString()
|
|
3280
|
+
});
|
|
3281
|
+
currentTimestamp += 1;
|
|
3282
|
+
}
|
|
3283
|
+
return operations;
|
|
3284
|
+
}
|
|
3285
|
+
function generateCollectionMigrationFilename(operation) {
|
|
3286
|
+
const timestamp = operation.timestamp;
|
|
3287
|
+
const operationType = operation.type === "modify" ? "updated" : operation.type === "create" ? "created" : "deleted";
|
|
3288
|
+
let collectionName;
|
|
3289
|
+
if (typeof operation.collection === "string") {
|
|
3290
|
+
collectionName = operation.collection;
|
|
3291
|
+
} else {
|
|
3292
|
+
collectionName = operation.collection.name;
|
|
3293
|
+
}
|
|
3294
|
+
const sanitizedName = collectionName.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase();
|
|
3295
|
+
return `${timestamp}_${operationType}_${sanitizedName}.js`;
|
|
3296
|
+
}
|
|
3138
3297
|
function generateMigrationDescription(diff) {
|
|
3139
3298
|
const parts = [];
|
|
3140
3299
|
if (diff.collectionsToCreate.length > 0) {
|
|
@@ -3242,14 +3401,13 @@ function formatValue(value) {
|
|
|
3242
3401
|
return "null";
|
|
3243
3402
|
}
|
|
3244
3403
|
if (typeof value === "string") {
|
|
3245
|
-
return
|
|
3404
|
+
return JSON.stringify(value);
|
|
3246
3405
|
}
|
|
3247
3406
|
if (typeof value === "number" || typeof value === "boolean") {
|
|
3248
3407
|
return String(value);
|
|
3249
3408
|
}
|
|
3250
3409
|
if (Array.isArray(value)) {
|
|
3251
|
-
|
|
3252
|
-
return `[${items}]`;
|
|
3410
|
+
return JSON.stringify(value).replace(/","/g, '", "');
|
|
3253
3411
|
}
|
|
3254
3412
|
if (typeof value === "object") {
|
|
3255
3413
|
const entries = Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
|
|
@@ -3257,7 +3415,7 @@ function formatValue(value) {
|
|
|
3257
3415
|
}
|
|
3258
3416
|
return String(value);
|
|
3259
3417
|
}
|
|
3260
|
-
function generateFieldDefinitionObject(field) {
|
|
3418
|
+
function generateFieldDefinitionObject(field, collectionIdMap) {
|
|
3261
3419
|
const parts = [];
|
|
3262
3420
|
parts.push(` name: "${field.name}"`);
|
|
3263
3421
|
parts.push(` type: "${field.type}"`);
|
|
@@ -3265,34 +3423,47 @@ function generateFieldDefinitionObject(field) {
|
|
|
3265
3423
|
if (field.unique !== void 0) {
|
|
3266
3424
|
parts.push(` unique: ${field.unique}`);
|
|
3267
3425
|
}
|
|
3426
|
+
if (field.type === "select") {
|
|
3427
|
+
const maxSelect = field.options?.maxSelect ?? 1;
|
|
3428
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
3429
|
+
const values = field.options?.values ?? [];
|
|
3430
|
+
parts.push(` values: ${formatValue(values)}`);
|
|
3431
|
+
}
|
|
3268
3432
|
if (field.options && Object.keys(field.options).length > 0) {
|
|
3269
3433
|
for (const [key, value] of Object.entries(field.options)) {
|
|
3434
|
+
if (field.type === "select" && (key === "maxSelect" || key === "values")) {
|
|
3435
|
+
continue;
|
|
3436
|
+
}
|
|
3270
3437
|
parts.push(` ${key}: ${formatValue(value)}`);
|
|
3271
3438
|
}
|
|
3272
3439
|
}
|
|
3273
3440
|
if (field.relation) {
|
|
3274
3441
|
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
}
|
|
3283
|
-
if (field.relation.cascadeDelete !== void 0) {
|
|
3284
|
-
parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
|
|
3442
|
+
let collectionIdValue;
|
|
3443
|
+
if (isUsersCollection) {
|
|
3444
|
+
collectionIdValue = '"_pb_users_auth_"';
|
|
3445
|
+
} else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
|
|
3446
|
+
collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
|
|
3447
|
+
} else {
|
|
3448
|
+
collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
3285
3449
|
}
|
|
3450
|
+
parts.push(` collectionId: ${collectionIdValue}`);
|
|
3451
|
+
const maxSelect = field.relation.maxSelect ?? 1;
|
|
3452
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
3453
|
+
const minSelect = field.relation.minSelect ?? null;
|
|
3454
|
+
parts.push(` minSelect: ${minSelect}`);
|
|
3455
|
+
const cascadeDelete = field.relation.cascadeDelete ?? false;
|
|
3456
|
+
parts.push(` cascadeDelete: ${cascadeDelete}`);
|
|
3286
3457
|
}
|
|
3287
3458
|
return ` {
|
|
3288
3459
|
${parts.join(",\n")},
|
|
3289
3460
|
}`;
|
|
3290
3461
|
}
|
|
3291
|
-
function generateFieldsArray(fields) {
|
|
3462
|
+
function generateFieldsArray(fields, collectionIdMap) {
|
|
3292
3463
|
if (fields.length === 0) {
|
|
3293
3464
|
return "[]";
|
|
3294
3465
|
}
|
|
3295
|
-
const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field));
|
|
3466
|
+
const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field, collectionIdMap));
|
|
3296
3467
|
return `[
|
|
3297
3468
|
${fieldObjects.join(",\n")},
|
|
3298
3469
|
]`;
|
|
@@ -3351,7 +3522,7 @@ function generateIndexesArray(indexes) {
|
|
|
3351
3522
|
if (!indexes || indexes.length === 0) {
|
|
3352
3523
|
return "[]";
|
|
3353
3524
|
}
|
|
3354
|
-
const indexStrings = indexes.map((idx) =>
|
|
3525
|
+
const indexStrings = indexes.map((idx) => JSON.stringify(idx));
|
|
3355
3526
|
return `[
|
|
3356
3527
|
${indexStrings.join(",\n ")},
|
|
3357
3528
|
]`;
|
|
@@ -3405,7 +3576,7 @@ function getSystemFields() {
|
|
|
3405
3576
|
}
|
|
3406
3577
|
];
|
|
3407
3578
|
}
|
|
3408
|
-
function generateCollectionCreation(collection, varName = "collection", isLast = false) {
|
|
3579
|
+
function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
|
|
3409
3580
|
const lines = [];
|
|
3410
3581
|
lines.push(` const ${varName} = new Collection({`);
|
|
3411
3582
|
lines.push(` name: "${collection.name}",`);
|
|
@@ -3419,7 +3590,7 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
|
|
|
3419
3590
|
}
|
|
3420
3591
|
const systemFields = getSystemFields();
|
|
3421
3592
|
const allFields = [...systemFields, ...collection.fields];
|
|
3422
|
-
lines.push(` fields: ${generateFieldsArray(allFields)},`);
|
|
3593
|
+
lines.push(` fields: ${generateFieldsArray(allFields, collectionIdMap)},`);
|
|
3423
3594
|
lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
|
|
3424
3595
|
lines.push(` });`);
|
|
3425
3596
|
lines.push(``);
|
|
@@ -3441,42 +3612,59 @@ function getFieldConstructorName(fieldType) {
|
|
|
3441
3612
|
};
|
|
3442
3613
|
return constructorMap[fieldType] || "TextField";
|
|
3443
3614
|
}
|
|
3444
|
-
function generateFieldConstructorOptions(field) {
|
|
3615
|
+
function generateFieldConstructorOptions(field, collectionIdMap) {
|
|
3445
3616
|
const parts = [];
|
|
3446
3617
|
parts.push(` name: "${field.name}"`);
|
|
3447
3618
|
parts.push(` required: ${field.required}`);
|
|
3448
3619
|
if (field.unique !== void 0) {
|
|
3449
3620
|
parts.push(` unique: ${field.unique}`);
|
|
3450
3621
|
}
|
|
3622
|
+
if (field.type === "select") {
|
|
3623
|
+
const maxSelect = field.options?.maxSelect ?? 1;
|
|
3624
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
3625
|
+
const values = field.options?.values ?? [];
|
|
3626
|
+
parts.push(` values: ${formatValue(values)}`);
|
|
3627
|
+
}
|
|
3451
3628
|
if (field.options && Object.keys(field.options).length > 0) {
|
|
3452
3629
|
for (const [key, value] of Object.entries(field.options)) {
|
|
3453
|
-
|
|
3630
|
+
if (field.type === "select" && (key === "maxSelect" || key === "values")) {
|
|
3631
|
+
continue;
|
|
3632
|
+
}
|
|
3633
|
+
if (field.type === "number" && key === "noDecimal") {
|
|
3634
|
+
parts.push(` onlyInt: ${formatValue(value)}`);
|
|
3635
|
+
} else {
|
|
3636
|
+
parts.push(` ${key}: ${formatValue(value)}`);
|
|
3637
|
+
}
|
|
3454
3638
|
}
|
|
3455
3639
|
}
|
|
3456
3640
|
if (field.relation && field.type === "relation") {
|
|
3457
3641
|
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
}
|
|
3466
|
-
if (field.relation.cascadeDelete !== void 0) {
|
|
3467
|
-
parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
|
|
3642
|
+
let collectionIdValue;
|
|
3643
|
+
if (isUsersCollection) {
|
|
3644
|
+
collectionIdValue = '"_pb_users_auth_"';
|
|
3645
|
+
} else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
|
|
3646
|
+
collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
|
|
3647
|
+
} else {
|
|
3648
|
+
collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
3468
3649
|
}
|
|
3650
|
+
parts.push(` collectionId: ${collectionIdValue}`);
|
|
3651
|
+
const maxSelect = field.relation.maxSelect ?? 1;
|
|
3652
|
+
parts.push(` maxSelect: ${maxSelect}`);
|
|
3653
|
+
const minSelect = field.relation.minSelect ?? null;
|
|
3654
|
+
parts.push(` minSelect: ${minSelect}`);
|
|
3655
|
+
const cascadeDelete = field.relation.cascadeDelete ?? false;
|
|
3656
|
+
parts.push(` cascadeDelete: ${cascadeDelete}`);
|
|
3469
3657
|
}
|
|
3470
3658
|
return parts.join(",\n");
|
|
3471
3659
|
}
|
|
3472
|
-
function generateFieldAddition(collectionName, field, varName, isLast = false) {
|
|
3660
|
+
function generateFieldAddition(collectionName, field, varName, isLast = false, collectionIdMap) {
|
|
3473
3661
|
const lines = [];
|
|
3474
3662
|
const constructorName = getFieldConstructorName(field.type);
|
|
3475
3663
|
const collectionVar = varName || `collection_${collectionName}_${field.name}`;
|
|
3476
3664
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
3477
3665
|
lines.push(``);
|
|
3478
3666
|
lines.push(` ${collectionVar}.fields.add(new ${constructorName}({`);
|
|
3479
|
-
lines.push(generateFieldConstructorOptions(field));
|
|
3667
|
+
lines.push(generateFieldConstructorOptions(field, collectionIdMap));
|
|
3480
3668
|
lines.push(` }));`);
|
|
3481
3669
|
lines.push(``);
|
|
3482
3670
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
@@ -3526,7 +3714,7 @@ function generateIndexAddition(collectionName, index, varName, isLast = false) {
|
|
|
3526
3714
|
const lines = [];
|
|
3527
3715
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
3528
3716
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
3529
|
-
lines.push(` ${collectionVar}.indexes.push(
|
|
3717
|
+
lines.push(` ${collectionVar}.indexes.push(${JSON.stringify(index)});`);
|
|
3530
3718
|
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3531
3719
|
return lines.join("\n");
|
|
3532
3720
|
}
|
|
@@ -3535,7 +3723,7 @@ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
|
|
|
3535
3723
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
3536
3724
|
const indexVar = `${collectionVar}_indexToRemove`;
|
|
3537
3725
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
3538
|
-
lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx ===
|
|
3726
|
+
lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === ${JSON.stringify(index)});`);
|
|
3539
3727
|
lines.push(` if (${indexVar} !== -1) {`);
|
|
3540
3728
|
lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
|
|
3541
3729
|
lines.push(` }`);
|
|
@@ -3564,16 +3752,179 @@ function generateCollectionDeletion(collectionName, varName = "collection", isLa
|
|
|
3564
3752
|
lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
|
|
3565
3753
|
return lines.join("\n");
|
|
3566
3754
|
}
|
|
3755
|
+
function generateOperationUpMigration(operation, collectionIdMap) {
|
|
3756
|
+
const lines = [];
|
|
3757
|
+
if (operation.type === "create") {
|
|
3758
|
+
const collection = operation.collection;
|
|
3759
|
+
const varName = `collection_${collection.name}`;
|
|
3760
|
+
lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
|
|
3761
|
+
} else if (operation.type === "modify") {
|
|
3762
|
+
const modification = operation.modifications;
|
|
3763
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
3764
|
+
let operationCount = 0;
|
|
3765
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
|
|
3766
|
+
for (const field of modification.fieldsToAdd) {
|
|
3767
|
+
operationCount++;
|
|
3768
|
+
const varName = `collection_${collectionName}_add_${field.name}`;
|
|
3769
|
+
const isLast = operationCount === totalOperations;
|
|
3770
|
+
lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
|
|
3771
|
+
if (!isLast) lines.push("");
|
|
3772
|
+
}
|
|
3773
|
+
for (const fieldMod of modification.fieldsToModify) {
|
|
3774
|
+
operationCount++;
|
|
3775
|
+
const varName = `collection_${collectionName}_modify_${fieldMod.fieldName}`;
|
|
3776
|
+
const isLast = operationCount === totalOperations;
|
|
3777
|
+
lines.push(generateFieldModification(collectionName, fieldMod, varName, isLast));
|
|
3778
|
+
if (!isLast) lines.push("");
|
|
3779
|
+
}
|
|
3780
|
+
for (const field of modification.fieldsToRemove) {
|
|
3781
|
+
operationCount++;
|
|
3782
|
+
const varName = `collection_${collectionName}_remove_${field.name}`;
|
|
3783
|
+
const isLast = operationCount === totalOperations;
|
|
3784
|
+
lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
|
|
3785
|
+
if (!isLast) lines.push("");
|
|
3786
|
+
}
|
|
3787
|
+
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
3788
|
+
operationCount++;
|
|
3789
|
+
const index = modification.indexesToAdd[i];
|
|
3790
|
+
const varName = `collection_${collectionName}_addidx_${i}`;
|
|
3791
|
+
const isLast = operationCount === totalOperations;
|
|
3792
|
+
lines.push(generateIndexAddition(collectionName, index, varName, isLast));
|
|
3793
|
+
if (!isLast) lines.push("");
|
|
3794
|
+
}
|
|
3795
|
+
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
3796
|
+
operationCount++;
|
|
3797
|
+
const index = modification.indexesToRemove[i];
|
|
3798
|
+
const varName = `collection_${collectionName}_rmidx_${i}`;
|
|
3799
|
+
const isLast = operationCount === totalOperations;
|
|
3800
|
+
lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
|
|
3801
|
+
if (!isLast) lines.push("");
|
|
3802
|
+
}
|
|
3803
|
+
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
3804
|
+
for (const permission of modification.permissionsToUpdate) {
|
|
3805
|
+
operationCount++;
|
|
3806
|
+
const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
|
|
3807
|
+
const isLast = operationCount === totalOperations;
|
|
3808
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast));
|
|
3809
|
+
if (!isLast) lines.push("");
|
|
3810
|
+
}
|
|
3811
|
+
} else if (modification.rulesToUpdate.length > 0) {
|
|
3812
|
+
for (const rule of modification.rulesToUpdate) {
|
|
3813
|
+
operationCount++;
|
|
3814
|
+
const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
|
|
3815
|
+
const isLast = operationCount === totalOperations;
|
|
3816
|
+
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast));
|
|
3817
|
+
if (!isLast) lines.push("");
|
|
3818
|
+
}
|
|
3819
|
+
}
|
|
3820
|
+
} else if (operation.type === "delete") {
|
|
3821
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
|
|
3822
|
+
const varName = `collection_${collectionName}`;
|
|
3823
|
+
lines.push(generateCollectionDeletion(collectionName, varName, true));
|
|
3824
|
+
}
|
|
3825
|
+
return lines.join("\n");
|
|
3826
|
+
}
|
|
3827
|
+
function generateOperationDownMigration(operation, collectionIdMap) {
|
|
3828
|
+
const lines = [];
|
|
3829
|
+
if (operation.type === "create") {
|
|
3830
|
+
const collection = operation.collection;
|
|
3831
|
+
const varName = `collection_${collection.name}`;
|
|
3832
|
+
lines.push(generateCollectionDeletion(collection.name, varName, true));
|
|
3833
|
+
} else if (operation.type === "modify") {
|
|
3834
|
+
const modification = operation.modifications;
|
|
3835
|
+
const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
|
|
3836
|
+
let operationCount = 0;
|
|
3837
|
+
const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
|
|
3838
|
+
if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
|
|
3839
|
+
for (const permission of modification.permissionsToUpdate) {
|
|
3840
|
+
operationCount++;
|
|
3841
|
+
const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
|
|
3842
|
+
const isLast = operationCount === totalOperations;
|
|
3843
|
+
lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast));
|
|
3844
|
+
if (!isLast) lines.push("");
|
|
3845
|
+
}
|
|
3846
|
+
} else if (modification.rulesToUpdate.length > 0) {
|
|
3847
|
+
for (const rule of modification.rulesToUpdate) {
|
|
3848
|
+
operationCount++;
|
|
3849
|
+
const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
|
|
3850
|
+
const isLast = operationCount === totalOperations;
|
|
3851
|
+
lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast));
|
|
3852
|
+
if (!isLast) lines.push("");
|
|
3853
|
+
}
|
|
3854
|
+
}
|
|
3855
|
+
for (let i = 0; i < modification.indexesToRemove.length; i++) {
|
|
3856
|
+
operationCount++;
|
|
3857
|
+
const index = modification.indexesToRemove[i];
|
|
3858
|
+
const varName = `collection_${collectionName}_restore_idx_${i}`;
|
|
3859
|
+
const isLast = operationCount === totalOperations;
|
|
3860
|
+
lines.push(generateIndexAddition(collectionName, index, varName, isLast));
|
|
3861
|
+
if (!isLast) lines.push("");
|
|
3862
|
+
}
|
|
3863
|
+
for (let i = 0; i < modification.indexesToAdd.length; i++) {
|
|
3864
|
+
operationCount++;
|
|
3865
|
+
const index = modification.indexesToAdd[i];
|
|
3866
|
+
const varName = `collection_${collectionName}_revert_idx_${i}`;
|
|
3867
|
+
const isLast = operationCount === totalOperations;
|
|
3868
|
+
lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
|
|
3869
|
+
if (!isLast) lines.push("");
|
|
3870
|
+
}
|
|
3871
|
+
for (const field of modification.fieldsToRemove) {
|
|
3872
|
+
operationCount++;
|
|
3873
|
+
const varName = `collection_${collectionName}_restore_${field.name}`;
|
|
3874
|
+
const isLast = operationCount === totalOperations;
|
|
3875
|
+
lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
|
|
3876
|
+
if (!isLast) lines.push("");
|
|
3877
|
+
}
|
|
3878
|
+
for (const fieldMod of modification.fieldsToModify) {
|
|
3879
|
+
operationCount++;
|
|
3880
|
+
const reverseChanges = fieldMod.changes.map((change) => ({
|
|
3881
|
+
property: change.property,
|
|
3882
|
+
oldValue: change.newValue,
|
|
3883
|
+
newValue: change.oldValue
|
|
3884
|
+
}));
|
|
3885
|
+
const reverseMod = {
|
|
3886
|
+
fieldName: fieldMod.fieldName,
|
|
3887
|
+
currentDefinition: fieldMod.newDefinition,
|
|
3888
|
+
newDefinition: fieldMod.currentDefinition,
|
|
3889
|
+
changes: reverseChanges
|
|
3890
|
+
};
|
|
3891
|
+
const varName = `collection_${collectionName}_revert_${fieldMod.fieldName}`;
|
|
3892
|
+
const isLast = operationCount === totalOperations;
|
|
3893
|
+
lines.push(generateFieldModification(collectionName, reverseMod, varName, isLast));
|
|
3894
|
+
if (!isLast) lines.push("");
|
|
3895
|
+
}
|
|
3896
|
+
for (const field of modification.fieldsToAdd) {
|
|
3897
|
+
operationCount++;
|
|
3898
|
+
const varName = `collection_${collectionName}_revert_add_${field.name}`;
|
|
3899
|
+
const isLast = operationCount === totalOperations;
|
|
3900
|
+
lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
|
|
3901
|
+
if (!isLast) lines.push("");
|
|
3902
|
+
}
|
|
3903
|
+
} else if (operation.type === "delete") {
|
|
3904
|
+
const collection = operation.collection;
|
|
3905
|
+
if (typeof collection !== "string") {
|
|
3906
|
+
const varName = `collection_${collection.name}`;
|
|
3907
|
+
lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
|
|
3908
|
+
}
|
|
3909
|
+
}
|
|
3910
|
+
return lines.join("\n");
|
|
3911
|
+
}
|
|
3567
3912
|
function generateUpMigration(diff) {
|
|
3568
3913
|
const lines = [];
|
|
3569
3914
|
lines.push(` // UP MIGRATION`);
|
|
3570
3915
|
lines.push(``);
|
|
3916
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
3917
|
+
for (const collection of diff.collectionsToCreate) {
|
|
3918
|
+
if (collection.id) {
|
|
3919
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
3920
|
+
}
|
|
3921
|
+
}
|
|
3571
3922
|
if (diff.collectionsToCreate.length > 0) {
|
|
3572
3923
|
lines.push(` // Create new collections`);
|
|
3573
3924
|
for (let i = 0; i < diff.collectionsToCreate.length; i++) {
|
|
3574
3925
|
const collection = diff.collectionsToCreate[i];
|
|
3575
3926
|
const varName = `collection_${collection.name}_create`;
|
|
3576
|
-
lines.push(generateCollectionCreation(collection, varName));
|
|
3927
|
+
lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
|
|
3577
3928
|
lines.push(``);
|
|
3578
3929
|
}
|
|
3579
3930
|
}
|
|
@@ -3585,7 +3936,7 @@ function generateUpMigration(diff) {
|
|
|
3585
3936
|
lines.push(` // Add fields to ${collectionName}`);
|
|
3586
3937
|
for (const field of modification.fieldsToAdd) {
|
|
3587
3938
|
const varName = `collection_${collectionName}_add_${field.name}`;
|
|
3588
|
-
lines.push(generateFieldAddition(collectionName, field, varName));
|
|
3939
|
+
lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
|
|
3589
3940
|
lines.push(``);
|
|
3590
3941
|
}
|
|
3591
3942
|
}
|
|
@@ -3676,12 +4027,23 @@ function generateDownMigration(diff) {
|
|
|
3676
4027
|
const lines = [];
|
|
3677
4028
|
lines.push(` // DOWN MIGRATION (ROLLBACK)`);
|
|
3678
4029
|
lines.push(``);
|
|
4030
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
4031
|
+
for (const collection of diff.collectionsToCreate) {
|
|
4032
|
+
if (collection.id) {
|
|
4033
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4034
|
+
}
|
|
4035
|
+
}
|
|
4036
|
+
for (const collection of diff.collectionsToDelete) {
|
|
4037
|
+
if (collection.id) {
|
|
4038
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4039
|
+
}
|
|
4040
|
+
}
|
|
3679
4041
|
if (diff.collectionsToDelete.length > 0) {
|
|
3680
4042
|
lines.push(` // Recreate deleted collections`);
|
|
3681
4043
|
for (let i = 0; i < diff.collectionsToDelete.length; i++) {
|
|
3682
4044
|
const collection = diff.collectionsToDelete[i];
|
|
3683
4045
|
const varName = `collection_${collection.name}_recreate`;
|
|
3684
|
-
lines.push(generateCollectionCreation(collection, varName));
|
|
4046
|
+
lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
|
|
3685
4047
|
lines.push(``);
|
|
3686
4048
|
}
|
|
3687
4049
|
}
|
|
@@ -3726,7 +4088,7 @@ function generateDownMigration(diff) {
|
|
|
3726
4088
|
lines.push(` // Restore fields to ${collectionName}`);
|
|
3727
4089
|
for (const field of modification.fieldsToRemove) {
|
|
3728
4090
|
const varName = `collection_${collectionName}_restore_${field.name}`;
|
|
3729
|
-
lines.push(generateFieldAddition(collectionName, field, varName));
|
|
4091
|
+
lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
|
|
3730
4092
|
lines.push(``);
|
|
3731
4093
|
}
|
|
3732
4094
|
}
|
|
@@ -3795,12 +4157,33 @@ function generate(diff, config) {
|
|
|
3795
4157
|
const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
|
|
3796
4158
|
try {
|
|
3797
4159
|
const migrationDir = resolveMigrationDir(normalizedConfig);
|
|
3798
|
-
const
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
const
|
|
3803
|
-
|
|
4160
|
+
const hasChanges2 = diff.collectionsToCreate.length > 0 || diff.collectionsToModify.length > 0 || diff.collectionsToDelete.length > 0;
|
|
4161
|
+
if (!hasChanges2) {
|
|
4162
|
+
return [];
|
|
4163
|
+
}
|
|
4164
|
+
const collectionIdMap = /* @__PURE__ */ new Map();
|
|
4165
|
+
for (const collection of diff.collectionsToCreate) {
|
|
4166
|
+
if (collection.id) {
|
|
4167
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4168
|
+
}
|
|
4169
|
+
}
|
|
4170
|
+
for (const collection of diff.collectionsToDelete) {
|
|
4171
|
+
if (collection.id) {
|
|
4172
|
+
collectionIdMap.set(collection.name, collection.id);
|
|
4173
|
+
}
|
|
4174
|
+
}
|
|
4175
|
+
const baseTimestamp = generateTimestamp(normalizedConfig);
|
|
4176
|
+
const operations = splitDiffByCollection(diff, baseTimestamp);
|
|
4177
|
+
const filePaths = [];
|
|
4178
|
+
for (const operation of operations) {
|
|
4179
|
+
const upCode = generateOperationUpMigration(operation, collectionIdMap);
|
|
4180
|
+
const downCode = generateOperationDownMigration(operation, collectionIdMap);
|
|
4181
|
+
const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
|
|
4182
|
+
const filename = generateCollectionMigrationFilename(operation);
|
|
4183
|
+
const filePath = writeMigrationFile(migrationDir, filename, content);
|
|
4184
|
+
filePaths.push(filePath);
|
|
4185
|
+
}
|
|
4186
|
+
return filePaths;
|
|
3804
4187
|
} catch (error) {
|
|
3805
4188
|
if (error instanceof MigrationGenerationError || error instanceof FileSystemError) {
|
|
3806
4189
|
throw error;
|
|
@@ -3818,7 +4201,8 @@ var MigrationGenerator = class {
|
|
|
3818
4201
|
this.config = mergeConfig4(config);
|
|
3819
4202
|
}
|
|
3820
4203
|
/**
|
|
3821
|
-
* Generates
|
|
4204
|
+
* Generates migration files from a schema diff
|
|
4205
|
+
* Returns array of file paths (one per collection operation)
|
|
3822
4206
|
*/
|
|
3823
4207
|
generate(diff) {
|
|
3824
4208
|
return generate(diff, this.config);
|
|
@@ -3846,6 +4230,7 @@ var MigrationGenerator = class {
|
|
|
3846
4230
|
exports.CLIUsageError = CLIUsageError;
|
|
3847
4231
|
exports.ConfigurationError = ConfigurationError;
|
|
3848
4232
|
exports.DiffEngine = DiffEngine;
|
|
4233
|
+
exports.FIELD_METADATA_KEY = FIELD_METADATA_KEY;
|
|
3849
4234
|
exports.FIELD_TYPE_INFO = FIELD_TYPE_INFO;
|
|
3850
4235
|
exports.FileSystemError = FileSystemError;
|
|
3851
4236
|
exports.MigrationError = MigrationError;
|
|
@@ -3874,6 +4259,7 @@ exports.detectFieldChanges = detectFieldChanges;
|
|
|
3874
4259
|
exports.discoverSchemaFiles = discoverSchemaFiles;
|
|
3875
4260
|
exports.extractComprehensiveFieldOptions = extractComprehensiveFieldOptions;
|
|
3876
4261
|
exports.extractFieldDefinitions = extractFieldDefinitions;
|
|
4262
|
+
exports.extractFieldMetadata = extractFieldMetadata;
|
|
3877
4263
|
exports.extractFieldOptions = extractFieldOptions;
|
|
3878
4264
|
exports.extractIndexes = extractIndexes;
|
|
3879
4265
|
exports.extractSchemaDefinitions = extractSchemaDefinitions;
|