pocketbase-zod-schema 0.1.2 → 0.1.3
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 +8 -0
- package/README.md +329 -99
- package/dist/cli/index.cjs +176 -55
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +176 -55
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/migrate.cjs +196 -58
- package/dist/cli/migrate.cjs.map +1 -1
- package/dist/cli/migrate.js +194 -57
- package/dist/cli/migrate.js.map +1 -1
- package/dist/cli/utils/index.cjs +1 -1
- package/dist/cli/utils/index.cjs.map +1 -1
- package/dist/cli/utils/index.js +1 -1
- package/dist/cli/utils/index.js.map +1 -1
- package/dist/index.cjs +197 -96
- 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 +197 -95
- package/dist/index.js.map +1 -1
- package/dist/migration/analyzer.cjs +101 -28
- package/dist/migration/analyzer.cjs.map +1 -1
- package/dist/migration/analyzer.js +101 -28
- package/dist/migration/analyzer.js.map +1 -1
- package/dist/migration/generator.cjs +60 -25
- package/dist/migration/generator.cjs.map +1 -1
- package/dist/migration/generator.d.cts +9 -5
- package/dist/migration/generator.d.ts +9 -5
- package/dist/migration/generator.js +60 -25
- package/dist/migration/generator.js.map +1 -1
- package/dist/migration/index.cjs +162 -53
- package/dist/migration/index.cjs.map +1 -1
- package/dist/migration/index.js +162 -53
- package/dist/migration/index.js.map +1 -1
- package/dist/migration/snapshot.cjs +1 -0
- package/dist/migration/snapshot.cjs.map +1 -1
- package/dist/migration/snapshot.js +1 -0
- package/dist/migration/snapshot.js.map +1 -1
- package/dist/migration/utils/index.cjs +19 -17
- package/dist/migration/utils/index.cjs.map +1 -1
- package/dist/migration/utils/index.d.cts +3 -1
- package/dist/migration/utils/index.d.ts +3 -1
- package/dist/migration/utils/index.js +19 -17
- package/dist/migration/utils/index.js.map +1 -1
- package/dist/mutator.cjs +9 -11
- package/dist/mutator.cjs.map +1 -1
- package/dist/mutator.d.cts +5 -9
- package/dist/mutator.d.ts +5 -9
- package/dist/mutator.js +9 -11
- package/dist/mutator.js.map +1 -1
- package/dist/schema.cjs +50 -53
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +94 -12
- package/dist/schema.d.ts +94 -12
- package/dist/schema.js +50 -52
- package/dist/schema.js.map +1 -1
- package/dist/types.d.cts +2 -5
- package/dist/types.d.ts +2 -5
- package/dist/user-C39DQ40N.d.cts +53 -0
- package/dist/user-C39DQ40N.d.ts +53 -0
- package/package.json +2 -3
- package/dist/user-jS1aYoeD.d.cts +0 -123
- package/dist/user-jS1aYoeD.d.ts +0 -123
package/dist/index.cjs
CHANGED
|
@@ -104,14 +104,48 @@ function filesField(options) {
|
|
|
104
104
|
if (options?.max !== void 0) schema = schema.max(options.max);
|
|
105
105
|
return schema;
|
|
106
106
|
}
|
|
107
|
-
|
|
108
|
-
|
|
107
|
+
var RELATION_METADATA_KEY = "__pocketbase_relation__";
|
|
108
|
+
function relationField(config) {
|
|
109
|
+
const metadata = {
|
|
110
|
+
[RELATION_METADATA_KEY]: {
|
|
111
|
+
type: "single",
|
|
112
|
+
collection: config.collection,
|
|
113
|
+
cascadeDelete: config.cascadeDelete ?? false,
|
|
114
|
+
maxSelect: 1,
|
|
115
|
+
minSelect: 0
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
return zod.z.string().describe(JSON.stringify(metadata));
|
|
109
119
|
}
|
|
110
|
-
function relationsField(
|
|
120
|
+
function relationsField(config) {
|
|
121
|
+
const metadata = {
|
|
122
|
+
[RELATION_METADATA_KEY]: {
|
|
123
|
+
type: "multiple",
|
|
124
|
+
collection: config.collection,
|
|
125
|
+
cascadeDelete: config.cascadeDelete ?? false,
|
|
126
|
+
maxSelect: config.maxSelect ?? 999,
|
|
127
|
+
minSelect: config.minSelect ?? 0
|
|
128
|
+
}
|
|
129
|
+
};
|
|
111
130
|
let schema = zod.z.array(zod.z.string());
|
|
112
|
-
if (
|
|
113
|
-
|
|
114
|
-
|
|
131
|
+
if (config.minSelect !== void 0) {
|
|
132
|
+
schema = schema.min(config.minSelect);
|
|
133
|
+
}
|
|
134
|
+
if (config.maxSelect !== void 0) {
|
|
135
|
+
schema = schema.max(config.maxSelect);
|
|
136
|
+
}
|
|
137
|
+
return schema.describe(JSON.stringify(metadata));
|
|
138
|
+
}
|
|
139
|
+
function extractRelationMetadata(description) {
|
|
140
|
+
if (!description) return null;
|
|
141
|
+
try {
|
|
142
|
+
const parsed = JSON.parse(description);
|
|
143
|
+
if (parsed[RELATION_METADATA_KEY]) {
|
|
144
|
+
return parsed[RELATION_METADATA_KEY];
|
|
145
|
+
}
|
|
146
|
+
} catch {
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
115
149
|
}
|
|
116
150
|
function editorField() {
|
|
117
151
|
return zod.z.string();
|
|
@@ -143,7 +177,7 @@ function withIndexes(schema, indexes) {
|
|
|
143
177
|
return schema.describe(JSON.stringify(metadata));
|
|
144
178
|
}
|
|
145
179
|
|
|
146
|
-
// src/
|
|
180
|
+
// src/utils/permission-templates.ts
|
|
147
181
|
var PermissionTemplates = {
|
|
148
182
|
/**
|
|
149
183
|
* Public access - anyone can perform all operations
|
|
@@ -362,44 +396,22 @@ function mergePermissions(...schemas) {
|
|
|
362
396
|
}
|
|
363
397
|
return merged;
|
|
364
398
|
}
|
|
365
|
-
var ProjectInputSchema = zod.z.object({
|
|
366
|
-
// Required fields
|
|
367
|
-
title: zod.z.string(),
|
|
368
|
-
content: zod.z.string(),
|
|
369
|
-
status: StatusEnum,
|
|
370
|
-
summary: zod.z.string().optional(),
|
|
371
|
-
User: zod.z.string().nonempty("User ID is missing"),
|
|
372
|
-
SubscriberUsers: zod.z.array(zod.z.string())
|
|
373
|
-
}).extend(inputImageFileSchema);
|
|
374
|
-
var ProjectSchema = withPermissions(
|
|
375
|
-
ProjectInputSchema.omit(omitImageFilesSchema).extend(baseImageFileSchema),
|
|
376
|
-
{
|
|
377
|
-
template: "owner-only",
|
|
378
|
-
ownerField: "User",
|
|
379
|
-
customRules: {
|
|
380
|
-
// Override list rule to allow authenticated users to see all projects
|
|
381
|
-
listRule: '@request.auth.id != ""',
|
|
382
|
-
// Allow viewing if user is owner OR a subscriber
|
|
383
|
-
viewRule: '@request.auth.id != "" && (User = @request.auth.id || SubscriberUsers ?= @request.auth.id)'
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
);
|
|
387
399
|
var UserInputSchema = zod.z.object({
|
|
388
|
-
name: zod.z.string().
|
|
400
|
+
name: zod.z.string().optional(),
|
|
389
401
|
email: zod.z.string().email(),
|
|
390
402
|
password: zod.z.string().min(8, "Password must be at least 8 characters"),
|
|
391
403
|
passwordConfirm: zod.z.string(),
|
|
392
404
|
avatar: zod.z.instanceof(File).optional()
|
|
393
405
|
});
|
|
394
406
|
var UserDatabaseSchema = zod.z.object({
|
|
395
|
-
name: zod.z.string().
|
|
407
|
+
name: zod.z.string().optional(),
|
|
396
408
|
email: zod.z.string().email(),
|
|
397
409
|
password: zod.z.string().min(8, "Password must be at least 8 characters"),
|
|
398
410
|
avatar: zod.z.instanceof(File).optional()
|
|
399
411
|
});
|
|
400
412
|
var UserSchema = withIndexes(
|
|
401
413
|
withPermissions(UserDatabaseSchema.extend(baseSchema), {
|
|
402
|
-
// Users can list
|
|
414
|
+
// Users can list their own profile
|
|
403
415
|
listRule: "id = @request.auth.id",
|
|
404
416
|
// Users can view their own profile
|
|
405
417
|
viewRule: "id = @request.auth.id",
|
|
@@ -408,15 +420,13 @@ var UserSchema = withIndexes(
|
|
|
408
420
|
// Users can only update their own profile
|
|
409
421
|
updateRule: "id = @request.auth.id",
|
|
410
422
|
// Users can only delete their own account
|
|
411
|
-
deleteRule: "id = @request.auth.id"
|
|
412
|
-
//
|
|
413
|
-
manageRule: "id = @request.auth.id"
|
|
423
|
+
deleteRule: "id = @request.auth.id"
|
|
424
|
+
// manageRule is null in PocketBase default (not set)
|
|
414
425
|
}),
|
|
415
426
|
[
|
|
416
|
-
//
|
|
417
|
-
"CREATE UNIQUE INDEX
|
|
418
|
-
|
|
419
|
-
"CREATE INDEX idx_users_name ON users (name)"
|
|
427
|
+
// PocketBase's default indexes for auth collections
|
|
428
|
+
"CREATE UNIQUE INDEX `idx_tokenKey__pb_users_auth_` ON `users` (`tokenKey`)",
|
|
429
|
+
"CREATE UNIQUE INDEX `idx_email__pb_users_auth_` ON `users` (`email`) WHERE `email` != ''"
|
|
420
430
|
]
|
|
421
431
|
);
|
|
422
432
|
var BaseMutator = class {
|
|
@@ -757,7 +767,7 @@ var UserMutator = class extends BaseMutator {
|
|
|
757
767
|
};
|
|
758
768
|
}
|
|
759
769
|
getCollection() {
|
|
760
|
-
return this.pb.collection("
|
|
770
|
+
return this.pb.collection("Users");
|
|
761
771
|
}
|
|
762
772
|
async validateInput(input) {
|
|
763
773
|
return UserInputSchema.parse(input);
|
|
@@ -1523,26 +1533,28 @@ function getMaxSelect(fieldName, zodType) {
|
|
|
1523
1533
|
return 1;
|
|
1524
1534
|
}
|
|
1525
1535
|
function getMinSelect(fieldName, zodType) {
|
|
1526
|
-
if (
|
|
1527
|
-
return
|
|
1528
|
-
}
|
|
1529
|
-
let unwrappedType = zodType;
|
|
1530
|
-
if (zodType instanceof zod.z.ZodOptional) {
|
|
1531
|
-
unwrappedType = zodType._def.innerType;
|
|
1532
|
-
}
|
|
1533
|
-
if (unwrappedType instanceof zod.z.ZodNullable) {
|
|
1534
|
-
unwrappedType = unwrappedType._def.innerType;
|
|
1535
|
-
}
|
|
1536
|
-
if (unwrappedType instanceof zod.z.ZodDefault) {
|
|
1537
|
-
unwrappedType = unwrappedType._def.innerType;
|
|
1536
|
+
if (isSingleRelationField(fieldName, zodType)) {
|
|
1537
|
+
return 0;
|
|
1538
1538
|
}
|
|
1539
|
-
if (
|
|
1540
|
-
|
|
1541
|
-
if (
|
|
1542
|
-
|
|
1539
|
+
if (isMultipleRelationField(fieldName, zodType)) {
|
|
1540
|
+
let unwrappedType = zodType;
|
|
1541
|
+
if (zodType instanceof zod.z.ZodOptional) {
|
|
1542
|
+
unwrappedType = zodType._def.innerType;
|
|
1543
|
+
}
|
|
1544
|
+
if (unwrappedType instanceof zod.z.ZodNullable) {
|
|
1545
|
+
unwrappedType = unwrappedType._def.innerType;
|
|
1546
|
+
}
|
|
1547
|
+
if (unwrappedType instanceof zod.z.ZodDefault) {
|
|
1548
|
+
unwrappedType = unwrappedType._def.innerType;
|
|
1549
|
+
}
|
|
1550
|
+
if (unwrappedType instanceof zod.z.ZodArray) {
|
|
1551
|
+
const arrayDef = unwrappedType._def;
|
|
1552
|
+
if (arrayDef.minLength) {
|
|
1553
|
+
return arrayDef.minLength.value;
|
|
1554
|
+
}
|
|
1543
1555
|
}
|
|
1544
1556
|
}
|
|
1545
|
-
return
|
|
1557
|
+
return 0;
|
|
1546
1558
|
}
|
|
1547
1559
|
var POCKETBASE_FIELD_TYPES = [
|
|
1548
1560
|
"text",
|
|
@@ -2025,13 +2037,32 @@ async function importSchemaModule(filePath, config) {
|
|
|
2025
2037
|
if (config?.pathTransformer) {
|
|
2026
2038
|
importPath = config.pathTransformer(filePath);
|
|
2027
2039
|
}
|
|
2028
|
-
|
|
2029
|
-
|
|
2040
|
+
let resolvedPath = null;
|
|
2041
|
+
const jsPath = `${importPath}.js`;
|
|
2042
|
+
const tsPath = `${importPath}.ts`;
|
|
2043
|
+
if (fs2__namespace.existsSync(jsPath)) {
|
|
2044
|
+
resolvedPath = jsPath;
|
|
2045
|
+
} else if (fs2__namespace.existsSync(tsPath)) {
|
|
2046
|
+
resolvedPath = tsPath;
|
|
2047
|
+
} else {
|
|
2048
|
+
resolvedPath = jsPath;
|
|
2030
2049
|
}
|
|
2031
|
-
const fileUrl = new URL(`file://${path4__namespace.resolve(
|
|
2050
|
+
const fileUrl = new URL(`file://${path4__namespace.resolve(resolvedPath)}`);
|
|
2032
2051
|
const module = await import(fileUrl.href);
|
|
2033
2052
|
return module;
|
|
2034
2053
|
} catch (error) {
|
|
2054
|
+
const tsPath = `${filePath}.ts`;
|
|
2055
|
+
const isTypeScriptFile = fs2__namespace.existsSync(tsPath);
|
|
2056
|
+
if (isTypeScriptFile) {
|
|
2057
|
+
throw new SchemaParsingError(
|
|
2058
|
+
`Failed to import TypeScript schema file. Node.js cannot import TypeScript files directly.
|
|
2059
|
+
Please either:
|
|
2060
|
+
1. Compile your schema files to JavaScript first, or
|
|
2061
|
+
2. Use tsx to run the migration tool (e.g., "npx tsx package/dist/cli/migrate.js status" or "tsx package/dist/cli/migrate.js status")`,
|
|
2062
|
+
filePath,
|
|
2063
|
+
error
|
|
2064
|
+
);
|
|
2065
|
+
}
|
|
2035
2066
|
throw new SchemaParsingError(
|
|
2036
2067
|
`Failed to import schema module. Make sure the schema files are compiled to JavaScript.`,
|
|
2037
2068
|
filePath,
|
|
@@ -2094,7 +2125,17 @@ function buildFieldDefinition(fieldName, zodType) {
|
|
|
2094
2125
|
required,
|
|
2095
2126
|
options
|
|
2096
2127
|
};
|
|
2097
|
-
|
|
2128
|
+
const relationMetadata = extractRelationMetadata(zodType.description);
|
|
2129
|
+
if (relationMetadata) {
|
|
2130
|
+
fieldDef.type = "relation";
|
|
2131
|
+
fieldDef.relation = {
|
|
2132
|
+
collection: relationMetadata.collection,
|
|
2133
|
+
maxSelect: relationMetadata.maxSelect,
|
|
2134
|
+
minSelect: relationMetadata.minSelect,
|
|
2135
|
+
cascadeDelete: relationMetadata.cascadeDelete
|
|
2136
|
+
};
|
|
2137
|
+
fieldDef.options = void 0;
|
|
2138
|
+
} else if (isRelationField(fieldName, zodType)) {
|
|
2098
2139
|
fieldDef.type = "relation";
|
|
2099
2140
|
const targetCollection = resolveTargetCollection(fieldName);
|
|
2100
2141
|
const maxSelect = getMaxSelect(fieldName, zodType);
|
|
@@ -2106,6 +2147,13 @@ function buildFieldDefinition(fieldName, zodType) {
|
|
|
2106
2147
|
cascadeDelete: false
|
|
2107
2148
|
// Default to false, can be configured later
|
|
2108
2149
|
};
|
|
2150
|
+
if (fieldDef.options) {
|
|
2151
|
+
const { min, max, pattern, ...relationSafeOptions } = fieldDef.options;
|
|
2152
|
+
console.log("min", min);
|
|
2153
|
+
console.log("max", max);
|
|
2154
|
+
console.log("pattern", pattern);
|
|
2155
|
+
fieldDef.options = Object.keys(relationSafeOptions).length > 0 ? relationSafeOptions : void 0;
|
|
2156
|
+
}
|
|
2109
2157
|
}
|
|
2110
2158
|
return fieldDef;
|
|
2111
2159
|
}
|
|
@@ -2158,11 +2206,12 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
|
|
|
2158
2206
|
fields,
|
|
2159
2207
|
indexes,
|
|
2160
2208
|
rules: {
|
|
2161
|
-
listRule: null,
|
|
2162
|
-
viewRule: null,
|
|
2163
|
-
createRule: null,
|
|
2164
|
-
updateRule: null,
|
|
2165
|
-
deleteRule: null
|
|
2209
|
+
listRule: permissions?.listRule ?? null,
|
|
2210
|
+
viewRule: permissions?.viewRule ?? null,
|
|
2211
|
+
createRule: permissions?.createRule ?? null,
|
|
2212
|
+
updateRule: permissions?.updateRule ?? null,
|
|
2213
|
+
deleteRule: permissions?.deleteRule ?? null,
|
|
2214
|
+
manageRule: permissions?.manageRule ?? null
|
|
2166
2215
|
},
|
|
2167
2216
|
permissions
|
|
2168
2217
|
};
|
|
@@ -2186,7 +2235,12 @@ async function buildSchemaDefinition(config) {
|
|
|
2186
2235
|
if (normalizedConfig.pathTransformer) {
|
|
2187
2236
|
importPath = normalizedConfig.pathTransformer(filePath);
|
|
2188
2237
|
} else if (mergedConfig.useCompiledFiles) {
|
|
2189
|
-
|
|
2238
|
+
const distPath = filePath.replace(/\/src\//, "/dist/");
|
|
2239
|
+
if (fs2__namespace.existsSync(`${distPath}.js`) || fs2__namespace.existsSync(`${distPath}.mjs`)) {
|
|
2240
|
+
importPath = distPath;
|
|
2241
|
+
} else {
|
|
2242
|
+
importPath = filePath;
|
|
2243
|
+
}
|
|
2190
2244
|
}
|
|
2191
2245
|
const module = await importSchemaModule(importPath, normalizedConfig);
|
|
2192
2246
|
const schemas = extractSchemaDefinitions(module, mergedConfig.schemaPatterns);
|
|
@@ -2563,6 +2617,7 @@ function convertPocketBaseCollection(pbCollection) {
|
|
|
2563
2617
|
if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
|
|
2564
2618
|
if (Object.keys(rules).length > 0) {
|
|
2565
2619
|
schema.rules = rules;
|
|
2620
|
+
schema.permissions = { ...rules };
|
|
2566
2621
|
}
|
|
2567
2622
|
return schema;
|
|
2568
2623
|
}
|
|
@@ -3258,10 +3313,8 @@ var DiffEngine = class {
|
|
|
3258
3313
|
var DEFAULT_TEMPLATE = `/// <reference path="{{TYPES_PATH}}" />
|
|
3259
3314
|
migrate((app) => {
|
|
3260
3315
|
{{UP_CODE}}
|
|
3261
|
-
return true;
|
|
3262
3316
|
}, (app) => {
|
|
3263
3317
|
{{DOWN_CODE}}
|
|
3264
|
-
return true;
|
|
3265
3318
|
});
|
|
3266
3319
|
`;
|
|
3267
3320
|
var DEFAULT_CONFIG4 = {
|
|
@@ -3426,7 +3479,8 @@ function generateFieldDefinitionObject(field) {
|
|
|
3426
3479
|
}
|
|
3427
3480
|
}
|
|
3428
3481
|
if (field.relation) {
|
|
3429
|
-
const
|
|
3482
|
+
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
3483
|
+
const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
3430
3484
|
parts.push(` collectionId: ${collectionIdPlaceholder}`);
|
|
3431
3485
|
if (field.relation.maxSelect !== void 0) {
|
|
3432
3486
|
parts.push(` maxSelect: ${field.relation.maxSelect}`);
|
|
@@ -3510,7 +3564,7 @@ function generateIndexesArray(indexes) {
|
|
|
3510
3564
|
${indexStrings.join(",\n ")},
|
|
3511
3565
|
]`;
|
|
3512
3566
|
}
|
|
3513
|
-
function generateCollectionCreation(collection, varName = "collection") {
|
|
3567
|
+
function generateCollectionCreation(collection, varName = "collection", isLast = false) {
|
|
3514
3568
|
const lines = [];
|
|
3515
3569
|
lines.push(` const ${varName} = new Collection({`);
|
|
3516
3570
|
lines.push(` name: "${collection.name}",`);
|
|
@@ -3526,7 +3580,7 @@ function generateCollectionCreation(collection, varName = "collection") {
|
|
|
3526
3580
|
lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
|
|
3527
3581
|
lines.push(` });`);
|
|
3528
3582
|
lines.push(``);
|
|
3529
|
-
lines.push(` app.save(${varName});`);
|
|
3583
|
+
lines.push(isLast ? ` return app.save(${varName});` : ` app.save(${varName});`);
|
|
3530
3584
|
return lines.join("\n");
|
|
3531
3585
|
}
|
|
3532
3586
|
function getFieldConstructorName(fieldType) {
|
|
@@ -3557,7 +3611,8 @@ function generateFieldConstructorOptions(field) {
|
|
|
3557
3611
|
}
|
|
3558
3612
|
}
|
|
3559
3613
|
if (field.relation && field.type === "relation") {
|
|
3560
|
-
const
|
|
3614
|
+
const isUsersCollection = field.relation.collection.toLowerCase() === "users";
|
|
3615
|
+
const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
|
|
3561
3616
|
parts.push(` collectionId: ${collectionIdPlaceholder}`);
|
|
3562
3617
|
if (field.relation.maxSelect !== void 0) {
|
|
3563
3618
|
parts.push(` maxSelect: ${field.relation.maxSelect}`);
|
|
@@ -3571,7 +3626,7 @@ function generateFieldConstructorOptions(field) {
|
|
|
3571
3626
|
}
|
|
3572
3627
|
return parts.join(",\n");
|
|
3573
3628
|
}
|
|
3574
|
-
function generateFieldAddition(collectionName, field, varName) {
|
|
3629
|
+
function generateFieldAddition(collectionName, field, varName, isLast = false) {
|
|
3575
3630
|
const lines = [];
|
|
3576
3631
|
const constructorName = getFieldConstructorName(field.type);
|
|
3577
3632
|
const collectionVar = varName || `collection_${collectionName}_${field.name}`;
|
|
@@ -3581,10 +3636,10 @@ function generateFieldAddition(collectionName, field, varName) {
|
|
|
3581
3636
|
lines.push(generateFieldConstructorOptions(field));
|
|
3582
3637
|
lines.push(` }));`);
|
|
3583
3638
|
lines.push(``);
|
|
3584
|
-
lines.push(` app.save(${collectionVar});`);
|
|
3639
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3585
3640
|
return lines.join("\n");
|
|
3586
3641
|
}
|
|
3587
|
-
function generateFieldModification(collectionName, modification, varName) {
|
|
3642
|
+
function generateFieldModification(collectionName, modification, varName, isLast = false) {
|
|
3588
3643
|
const lines = [];
|
|
3589
3644
|
const collectionVar = varName || `collection_${collectionName}_${modification.fieldName}`;
|
|
3590
3645
|
const fieldVar = `${collectionVar}_field`;
|
|
@@ -3598,7 +3653,8 @@ function generateFieldModification(collectionName, modification, varName) {
|
|
|
3598
3653
|
} else if (change.property.startsWith("relation.")) {
|
|
3599
3654
|
const relationKey = change.property.replace("relation.", "");
|
|
3600
3655
|
if (relationKey === "collection") {
|
|
3601
|
-
const
|
|
3656
|
+
const isUsersCollection = String(change.newValue).toLowerCase() === "users";
|
|
3657
|
+
const collectionIdValue = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${change.newValue}").id`;
|
|
3602
3658
|
lines.push(` ${fieldVar}.collectionId = ${collectionIdValue};`);
|
|
3603
3659
|
} else {
|
|
3604
3660
|
lines.push(` ${fieldVar}.${relationKey} = ${formatValue(change.newValue)};`);
|
|
@@ -3608,10 +3664,10 @@ function generateFieldModification(collectionName, modification, varName) {
|
|
|
3608
3664
|
}
|
|
3609
3665
|
}
|
|
3610
3666
|
lines.push(``);
|
|
3611
|
-
lines.push(` app.save(${collectionVar});`);
|
|
3667
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3612
3668
|
return lines.join("\n");
|
|
3613
3669
|
}
|
|
3614
|
-
function generateFieldDeletion(collectionName, fieldName, varName) {
|
|
3670
|
+
function generateFieldDeletion(collectionName, fieldName, varName, isLast = false) {
|
|
3615
3671
|
const lines = [];
|
|
3616
3672
|
const collectionVar = varName || `collection_${collectionName}_${fieldName}`;
|
|
3617
3673
|
const fieldVar = `${collectionVar}_field`;
|
|
@@ -3620,18 +3676,18 @@ function generateFieldDeletion(collectionName, fieldName, varName) {
|
|
|
3620
3676
|
lines.push(``);
|
|
3621
3677
|
lines.push(` ${collectionVar}.fields.remove(${fieldVar}.id);`);
|
|
3622
3678
|
lines.push(``);
|
|
3623
|
-
lines.push(` app.save(${collectionVar});`);
|
|
3679
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3624
3680
|
return lines.join("\n");
|
|
3625
3681
|
}
|
|
3626
|
-
function generateIndexAddition(collectionName, index, varName) {
|
|
3682
|
+
function generateIndexAddition(collectionName, index, varName, isLast = false) {
|
|
3627
3683
|
const lines = [];
|
|
3628
3684
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
3629
3685
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
3630
3686
|
lines.push(` ${collectionVar}.indexes.push("${index}");`);
|
|
3631
|
-
lines.push(` app.save(${collectionVar});`);
|
|
3687
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3632
3688
|
return lines.join("\n");
|
|
3633
3689
|
}
|
|
3634
|
-
function generateIndexRemoval(collectionName, index, varName) {
|
|
3690
|
+
function generateIndexRemoval(collectionName, index, varName, isLast = false) {
|
|
3635
3691
|
const lines = [];
|
|
3636
3692
|
const collectionVar = varName || `collection_${collectionName}_idx`;
|
|
3637
3693
|
const indexVar = `${collectionVar}_indexToRemove`;
|
|
@@ -3640,29 +3696,29 @@ function generateIndexRemoval(collectionName, index, varName) {
|
|
|
3640
3696
|
lines.push(` if (${indexVar} !== -1) {`);
|
|
3641
3697
|
lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
|
|
3642
3698
|
lines.push(` }`);
|
|
3643
|
-
lines.push(` app.save(${collectionVar});`);
|
|
3699
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3644
3700
|
return lines.join("\n");
|
|
3645
3701
|
}
|
|
3646
|
-
function generateRuleUpdate(collectionName, ruleType, newValue, varName) {
|
|
3702
|
+
function generateRuleUpdate(collectionName, ruleType, newValue, varName, isLast = false) {
|
|
3647
3703
|
const lines = [];
|
|
3648
3704
|
const collectionVar = varName || `collection_${collectionName}_${ruleType}`;
|
|
3649
3705
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
3650
3706
|
lines.push(` ${collectionVar}.${ruleType} = ${formatValue(newValue)};`);
|
|
3651
|
-
lines.push(` app.save(${collectionVar});`);
|
|
3707
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3652
3708
|
return lines.join("\n");
|
|
3653
3709
|
}
|
|
3654
|
-
function generatePermissionUpdate(collectionName, ruleType, newValue, varName) {
|
|
3710
|
+
function generatePermissionUpdate(collectionName, ruleType, newValue, varName, isLast = false) {
|
|
3655
3711
|
const lines = [];
|
|
3656
3712
|
const collectionVar = varName || `collection_${collectionName}_${ruleType}`;
|
|
3657
3713
|
lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
3658
3714
|
lines.push(` ${collectionVar}.${ruleType} = ${formatValue(newValue)};`);
|
|
3659
|
-
lines.push(` app.save(${collectionVar});`);
|
|
3715
|
+
lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
|
|
3660
3716
|
return lines.join("\n");
|
|
3661
3717
|
}
|
|
3662
|
-
function generateCollectionDeletion(collectionName, varName = "collection") {
|
|
3718
|
+
function generateCollectionDeletion(collectionName, varName = "collection", isLast = false) {
|
|
3663
3719
|
const lines = [];
|
|
3664
3720
|
lines.push(` const ${varName} = app.findCollectionByNameOrId("${collectionName}");`);
|
|
3665
|
-
lines.push(` app.delete(${varName});`);
|
|
3721
|
+
lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
|
|
3666
3722
|
return lines.join("\n");
|
|
3667
3723
|
}
|
|
3668
3724
|
function generateUpMigration(diff) {
|
|
@@ -3754,7 +3810,24 @@ function generateUpMigration(diff) {
|
|
|
3754
3810
|
lines.push(` // No changes detected`);
|
|
3755
3811
|
lines.push(``);
|
|
3756
3812
|
}
|
|
3757
|
-
|
|
3813
|
+
let code = lines.join("\n");
|
|
3814
|
+
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
3815
|
+
const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
|
|
3816
|
+
const saveMatches = [...code.matchAll(savePattern)];
|
|
3817
|
+
const deleteMatches = [...code.matchAll(deletePattern)];
|
|
3818
|
+
const allMatches = [
|
|
3819
|
+
...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
|
|
3820
|
+
...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
|
|
3821
|
+
].sort((a, b) => b.index - a.index);
|
|
3822
|
+
if (allMatches.length > 0) {
|
|
3823
|
+
const lastMatch = allMatches[0];
|
|
3824
|
+
if (lastMatch.type === "save") {
|
|
3825
|
+
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);
|
|
3826
|
+
} else {
|
|
3827
|
+
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);
|
|
3828
|
+
}
|
|
3829
|
+
}
|
|
3830
|
+
return code;
|
|
3758
3831
|
}
|
|
3759
3832
|
function generateDownMigration(diff) {
|
|
3760
3833
|
const lines = [];
|
|
@@ -3856,7 +3929,24 @@ function generateDownMigration(diff) {
|
|
|
3856
3929
|
lines.push(` // No changes to revert`);
|
|
3857
3930
|
lines.push(``);
|
|
3858
3931
|
}
|
|
3859
|
-
|
|
3932
|
+
let code = lines.join("\n");
|
|
3933
|
+
const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
|
|
3934
|
+
const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
|
|
3935
|
+
const saveMatches = [...code.matchAll(savePattern)];
|
|
3936
|
+
const deleteMatches = [...code.matchAll(deletePattern)];
|
|
3937
|
+
const allMatches = [
|
|
3938
|
+
...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
|
|
3939
|
+
...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
|
|
3940
|
+
].sort((a, b) => b.index - a.index);
|
|
3941
|
+
if (allMatches.length > 0) {
|
|
3942
|
+
const lastMatch = allMatches[0];
|
|
3943
|
+
if (lastMatch.type === "save") {
|
|
3944
|
+
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);
|
|
3945
|
+
} else {
|
|
3946
|
+
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);
|
|
3947
|
+
}
|
|
3948
|
+
}
|
|
3949
|
+
return code;
|
|
3860
3950
|
}
|
|
3861
3951
|
function generate(diff, config) {
|
|
3862
3952
|
const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
|
|
@@ -4457,7 +4547,13 @@ async function executeGenerate(options) {
|
|
|
4457
4547
|
const schemaDir = getSchemaDirectory(config);
|
|
4458
4548
|
const migrationsDir = getMigrationsDirectory(config);
|
|
4459
4549
|
logSection("\u{1F50D} Analyzing Schema");
|
|
4460
|
-
const
|
|
4550
|
+
const analyzerConfig = {
|
|
4551
|
+
schemaDir,
|
|
4552
|
+
excludePatterns: config.schema.exclude,
|
|
4553
|
+
useCompiledFiles: false
|
|
4554
|
+
// Use source files since we're in development/testing
|
|
4555
|
+
};
|
|
4556
|
+
const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
|
|
4461
4557
|
logSuccess(`Found ${currentSchema.collections.size} collection(s)`);
|
|
4462
4558
|
logInfo("Loading previous snapshot...");
|
|
4463
4559
|
const previousSnapshot = loadSnapshotIfExists({
|
|
@@ -4644,7 +4740,13 @@ async function executeStatus(options) {
|
|
|
4644
4740
|
const schemaDir = getSchemaDirectory(config);
|
|
4645
4741
|
const migrationsDir = getMigrationsDirectory(config);
|
|
4646
4742
|
logSection("\u{1F50D} Checking Migration Status");
|
|
4647
|
-
const
|
|
4743
|
+
const analyzerConfig = {
|
|
4744
|
+
schemaDir,
|
|
4745
|
+
excludePatterns: config.schema.exclude,
|
|
4746
|
+
useCompiledFiles: false
|
|
4747
|
+
// Use source files since we're in development/testing
|
|
4748
|
+
};
|
|
4749
|
+
const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
|
|
4648
4750
|
logSuccess(`Found ${currentSchema.collections.size} collection(s) in schema`);
|
|
4649
4751
|
logInfo("Loading previous snapshot...");
|
|
4650
4752
|
const previousSnapshot = loadSnapshotIfExists({
|
|
@@ -4758,8 +4860,6 @@ exports.MigrationGenerationError = MigrationGenerationError;
|
|
|
4758
4860
|
exports.MigrationGenerator = MigrationGenerator;
|
|
4759
4861
|
exports.POCKETBASE_FIELD_TYPES = POCKETBASE_FIELD_TYPES;
|
|
4760
4862
|
exports.PermissionTemplates = PermissionTemplates;
|
|
4761
|
-
exports.ProjectInputSchema = ProjectInputSchema;
|
|
4762
|
-
exports.ProjectSchema = ProjectSchema;
|
|
4763
4863
|
exports.SchemaAnalyzer = SchemaAnalyzer;
|
|
4764
4864
|
exports.SchemaParsingError = SchemaParsingError;
|
|
4765
4865
|
exports.SnapshotError = SnapshotError;
|
|
@@ -4796,6 +4896,7 @@ exports.extractComprehensiveFieldOptions = extractComprehensiveFieldOptions;
|
|
|
4796
4896
|
exports.extractFieldDefinitions = extractFieldDefinitions;
|
|
4797
4897
|
exports.extractFieldOptions = extractFieldOptions;
|
|
4798
4898
|
exports.extractIndexes = extractIndexes;
|
|
4899
|
+
exports.extractRelationMetadata = extractRelationMetadata;
|
|
4799
4900
|
exports.extractSchemaDefinitions = extractSchemaDefinitions;
|
|
4800
4901
|
exports.fileField = fileField;
|
|
4801
4902
|
exports.filesField = filesField;
|