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.
Files changed (63) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +329 -99
  3. package/dist/cli/index.cjs +176 -55
  4. package/dist/cli/index.cjs.map +1 -1
  5. package/dist/cli/index.js +176 -55
  6. package/dist/cli/index.js.map +1 -1
  7. package/dist/cli/migrate.cjs +196 -58
  8. package/dist/cli/migrate.cjs.map +1 -1
  9. package/dist/cli/migrate.js +194 -57
  10. package/dist/cli/migrate.js.map +1 -1
  11. package/dist/cli/utils/index.cjs +1 -1
  12. package/dist/cli/utils/index.cjs.map +1 -1
  13. package/dist/cli/utils/index.js +1 -1
  14. package/dist/cli/utils/index.js.map +1 -1
  15. package/dist/index.cjs +197 -96
  16. package/dist/index.cjs.map +1 -1
  17. package/dist/index.d.cts +3 -3
  18. package/dist/index.d.ts +3 -3
  19. package/dist/index.js +197 -95
  20. package/dist/index.js.map +1 -1
  21. package/dist/migration/analyzer.cjs +101 -28
  22. package/dist/migration/analyzer.cjs.map +1 -1
  23. package/dist/migration/analyzer.js +101 -28
  24. package/dist/migration/analyzer.js.map +1 -1
  25. package/dist/migration/generator.cjs +60 -25
  26. package/dist/migration/generator.cjs.map +1 -1
  27. package/dist/migration/generator.d.cts +9 -5
  28. package/dist/migration/generator.d.ts +9 -5
  29. package/dist/migration/generator.js +60 -25
  30. package/dist/migration/generator.js.map +1 -1
  31. package/dist/migration/index.cjs +162 -53
  32. package/dist/migration/index.cjs.map +1 -1
  33. package/dist/migration/index.js +162 -53
  34. package/dist/migration/index.js.map +1 -1
  35. package/dist/migration/snapshot.cjs +1 -0
  36. package/dist/migration/snapshot.cjs.map +1 -1
  37. package/dist/migration/snapshot.js +1 -0
  38. package/dist/migration/snapshot.js.map +1 -1
  39. package/dist/migration/utils/index.cjs +19 -17
  40. package/dist/migration/utils/index.cjs.map +1 -1
  41. package/dist/migration/utils/index.d.cts +3 -1
  42. package/dist/migration/utils/index.d.ts +3 -1
  43. package/dist/migration/utils/index.js +19 -17
  44. package/dist/migration/utils/index.js.map +1 -1
  45. package/dist/mutator.cjs +9 -11
  46. package/dist/mutator.cjs.map +1 -1
  47. package/dist/mutator.d.cts +5 -9
  48. package/dist/mutator.d.ts +5 -9
  49. package/dist/mutator.js +9 -11
  50. package/dist/mutator.js.map +1 -1
  51. package/dist/schema.cjs +50 -53
  52. package/dist/schema.cjs.map +1 -1
  53. package/dist/schema.d.cts +94 -12
  54. package/dist/schema.d.ts +94 -12
  55. package/dist/schema.js +50 -52
  56. package/dist/schema.js.map +1 -1
  57. package/dist/types.d.cts +2 -5
  58. package/dist/types.d.ts +2 -5
  59. package/dist/user-C39DQ40N.d.cts +53 -0
  60. package/dist/user-C39DQ40N.d.ts +53 -0
  61. package/package.json +2 -3
  62. package/dist/user-jS1aYoeD.d.cts +0 -123
  63. package/dist/user-jS1aYoeD.d.ts +0 -123
package/dist/index.d.cts CHANGED
@@ -1,9 +1,9 @@
1
1
  export { StatusEnum, StatusEnumType } from './enums.cjs';
2
2
  export { UserMutator } from './mutator.cjs';
3
- export { ProjectInputType, ProjectType, TypedPocketBase, UserInputType, UserType } from './types.cjs';
4
- export { PermissionTemplates, PermissionValidationResult, baseImageFileSchema, baseSchema, baseSchemaWithTimestamps, boolField, createPermissions, dateField, editorField, emailField, fileField, filesField, geoPointField, inputImageFileSchema, isPermissionSchema, isTemplateConfig, jsonField, mergePermissions, numberField, omitImageFilesSchema, relationField, relationsField, resolveTemplate, selectField, textField, urlField, validatePermissionConfig, validateRuleExpression, withIndexes, withPermissions } from './schema.cjs';
3
+ export { TypedPocketBase, UserInputType, UserType } from './types.cjs';
4
+ export { PermissionTemplates, PermissionValidationResult, RelationConfig, RelationsConfig, baseImageFileSchema, baseSchema, baseSchemaWithTimestamps, boolField, createPermissions, dateField, editorField, emailField, extractRelationMetadata, fileField, filesField, geoPointField, inputImageFileSchema, isPermissionSchema, isTemplateConfig, jsonField, mergePermissions, numberField, omitImageFilesSchema, relationField, relationsField, resolveTemplate, selectField, textField, urlField, validatePermissionConfig, validateRuleExpression, withIndexes, withPermissions } from './schema.cjs';
5
5
  export { A as APIRuleType, P as PermissionSchema, a as PermissionTemplate, b as PermissionTemplateConfig, R as RuleExpression } from './permissions-ZHafVSIx.cjs';
6
- export { P as ProjectInputSchema, a as ProjectSchema, U as UserInputSchema, b as UserSchema } from './user-jS1aYoeD.cjs';
6
+ export { U as UserInputSchema, a as UserSchema } from './user-C39DQ40N.cjs';
7
7
  export { SchemaAnalyzer, SchemaAnalyzerConfig, buildFieldDefinition, buildSchemaDefinition, convertZodSchemaToCollectionSchema, discoverSchemaFiles, extractFieldDefinitions, extractIndexes, extractSchemaDefinitions, getCollectionNameFromFile, importSchemaModule, isAuthCollection, parseSchemaFiles, selectSchemaForCollection } from './migration/analyzer.cjs';
8
8
  export { SnapshotConfig, SnapshotManager, convertPocketBaseMigration, findLatestSnapshot, getSnapshotPath, getSnapshotVersion, loadBaseMigration, loadSnapshot, loadSnapshotIfExists, mergeSnapshots, saveSnapshot, snapshotExists, validateSnapshot } from './migration/snapshot.cjs';
9
9
  export { ChangeSummary, DestructiveChange, DiffEngine, DiffEngineConfig, aggregateChanges, categorizeChangesBySeverity, compare, compareFieldConstraints, compareFieldOptions, compareFieldTypes, comparePermissions, compareRelationConfigurations, detectDestructiveChanges, detectFieldChanges, filterSystemCollections, findNewCollections, findNewFields, findRemovedCollections, findRemovedFields, generateChangeSummary, getUsersSystemFields, isSystemCollection, matchCollectionsByName, matchFieldsByName, requiresForceFlag } from './migration/diff.cjs';
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  export { StatusEnum, StatusEnumType } from './enums.js';
2
2
  export { UserMutator } from './mutator.js';
3
- export { ProjectInputType, ProjectType, TypedPocketBase, UserInputType, UserType } from './types.js';
4
- export { PermissionTemplates, PermissionValidationResult, baseImageFileSchema, baseSchema, baseSchemaWithTimestamps, boolField, createPermissions, dateField, editorField, emailField, fileField, filesField, geoPointField, inputImageFileSchema, isPermissionSchema, isTemplateConfig, jsonField, mergePermissions, numberField, omitImageFilesSchema, relationField, relationsField, resolveTemplate, selectField, textField, urlField, validatePermissionConfig, validateRuleExpression, withIndexes, withPermissions } from './schema.js';
3
+ export { TypedPocketBase, UserInputType, UserType } from './types.js';
4
+ export { PermissionTemplates, PermissionValidationResult, RelationConfig, RelationsConfig, baseImageFileSchema, baseSchema, baseSchemaWithTimestamps, boolField, createPermissions, dateField, editorField, emailField, extractRelationMetadata, fileField, filesField, geoPointField, inputImageFileSchema, isPermissionSchema, isTemplateConfig, jsonField, mergePermissions, numberField, omitImageFilesSchema, relationField, relationsField, resolveTemplate, selectField, textField, urlField, validatePermissionConfig, validateRuleExpression, withIndexes, withPermissions } from './schema.js';
5
5
  export { A as APIRuleType, P as PermissionSchema, a as PermissionTemplate, b as PermissionTemplateConfig, R as RuleExpression } from './permissions-ZHafVSIx.js';
6
- export { P as ProjectInputSchema, a as ProjectSchema, U as UserInputSchema, b as UserSchema } from './user-jS1aYoeD.js';
6
+ export { U as UserInputSchema, a as UserSchema } from './user-C39DQ40N.js';
7
7
  export { SchemaAnalyzer, SchemaAnalyzerConfig, buildFieldDefinition, buildSchemaDefinition, convertZodSchemaToCollectionSchema, discoverSchemaFiles, extractFieldDefinitions, extractIndexes, extractSchemaDefinitions, getCollectionNameFromFile, importSchemaModule, isAuthCollection, parseSchemaFiles, selectSchemaForCollection } from './migration/analyzer.js';
8
8
  export { SnapshotConfig, SnapshotManager, convertPocketBaseMigration, findLatestSnapshot, getSnapshotPath, getSnapshotVersion, loadBaseMigration, loadSnapshot, loadSnapshotIfExists, mergeSnapshots, saveSnapshot, snapshotExists, validateSnapshot } from './migration/snapshot.js';
9
9
  export { ChangeSummary, DestructiveChange, DiffEngine, DiffEngineConfig, aggregateChanges, categorizeChangesBySeverity, compare, compareFieldConstraints, compareFieldOptions, compareFieldTypes, comparePermissions, compareRelationConfigurations, detectDestructiveChanges, detectFieldChanges, filterSystemCollections, findNewCollections, findNewFields, findRemovedCollections, findRemovedFields, generateChangeSummary, getUsersSystemFields, isSystemCollection, matchCollectionsByName, matchFieldsByName, requiresForceFlag } from './migration/diff.js';
package/dist/index.js CHANGED
@@ -77,14 +77,48 @@ function filesField(options) {
77
77
  if (options?.max !== void 0) schema = schema.max(options.max);
78
78
  return schema;
79
79
  }
80
- function relationField() {
81
- return z.string();
80
+ var RELATION_METADATA_KEY = "__pocketbase_relation__";
81
+ function relationField(config) {
82
+ const metadata = {
83
+ [RELATION_METADATA_KEY]: {
84
+ type: "single",
85
+ collection: config.collection,
86
+ cascadeDelete: config.cascadeDelete ?? false,
87
+ maxSelect: 1,
88
+ minSelect: 0
89
+ }
90
+ };
91
+ return z.string().describe(JSON.stringify(metadata));
82
92
  }
83
- function relationsField(options) {
93
+ function relationsField(config) {
94
+ const metadata = {
95
+ [RELATION_METADATA_KEY]: {
96
+ type: "multiple",
97
+ collection: config.collection,
98
+ cascadeDelete: config.cascadeDelete ?? false,
99
+ maxSelect: config.maxSelect ?? 999,
100
+ minSelect: config.minSelect ?? 0
101
+ }
102
+ };
84
103
  let schema = z.array(z.string());
85
- if (options?.min !== void 0) schema = schema.min(options.min);
86
- if (options?.max !== void 0) schema = schema.max(options.max);
87
- return schema;
104
+ if (config.minSelect !== void 0) {
105
+ schema = schema.min(config.minSelect);
106
+ }
107
+ if (config.maxSelect !== void 0) {
108
+ schema = schema.max(config.maxSelect);
109
+ }
110
+ return schema.describe(JSON.stringify(metadata));
111
+ }
112
+ function extractRelationMetadata(description) {
113
+ if (!description) return null;
114
+ try {
115
+ const parsed = JSON.parse(description);
116
+ if (parsed[RELATION_METADATA_KEY]) {
117
+ return parsed[RELATION_METADATA_KEY];
118
+ }
119
+ } catch {
120
+ }
121
+ return null;
88
122
  }
89
123
  function editorField() {
90
124
  return z.string();
@@ -116,7 +150,7 @@ function withIndexes(schema, indexes) {
116
150
  return schema.describe(JSON.stringify(metadata));
117
151
  }
118
152
 
119
- // src/schema/permission-templates.ts
153
+ // src/utils/permission-templates.ts
120
154
  var PermissionTemplates = {
121
155
  /**
122
156
  * Public access - anyone can perform all operations
@@ -335,44 +369,22 @@ function mergePermissions(...schemas) {
335
369
  }
336
370
  return merged;
337
371
  }
338
- var ProjectInputSchema = z.object({
339
- // Required fields
340
- title: z.string(),
341
- content: z.string(),
342
- status: StatusEnum,
343
- summary: z.string().optional(),
344
- User: z.string().nonempty("User ID is missing"),
345
- SubscriberUsers: z.array(z.string())
346
- }).extend(inputImageFileSchema);
347
- var ProjectSchema = withPermissions(
348
- ProjectInputSchema.omit(omitImageFilesSchema).extend(baseImageFileSchema),
349
- {
350
- template: "owner-only",
351
- ownerField: "User",
352
- customRules: {
353
- // Override list rule to allow authenticated users to see all projects
354
- listRule: '@request.auth.id != ""',
355
- // Allow viewing if user is owner OR a subscriber
356
- viewRule: '@request.auth.id != "" && (User = @request.auth.id || SubscriberUsers ?= @request.auth.id)'
357
- }
358
- }
359
- );
360
372
  var UserInputSchema = z.object({
361
- name: z.string().min(2, "Name must be longer").optional(),
373
+ name: z.string().optional(),
362
374
  email: z.string().email(),
363
375
  password: z.string().min(8, "Password must be at least 8 characters"),
364
376
  passwordConfirm: z.string(),
365
377
  avatar: z.instanceof(File).optional()
366
378
  });
367
379
  var UserDatabaseSchema = z.object({
368
- name: z.string().min(2, "Name must be longer").optional(),
380
+ name: z.string().optional(),
369
381
  email: z.string().email(),
370
382
  password: z.string().min(8, "Password must be at least 8 characters"),
371
383
  avatar: z.instanceof(File).optional()
372
384
  });
373
385
  var UserSchema = withIndexes(
374
386
  withPermissions(UserDatabaseSchema.extend(baseSchema), {
375
- // Users can list other users (for mentions, user search, etc.)
387
+ // Users can list their own profile
376
388
  listRule: "id = @request.auth.id",
377
389
  // Users can view their own profile
378
390
  viewRule: "id = @request.auth.id",
@@ -381,15 +393,13 @@ var UserSchema = withIndexes(
381
393
  // Users can only update their own profile
382
394
  updateRule: "id = @request.auth.id",
383
395
  // Users can only delete their own account
384
- deleteRule: "id = @request.auth.id",
385
- // Users can only manage their own account (change email, password, etc.)
386
- manageRule: "id = @request.auth.id"
396
+ deleteRule: "id = @request.auth.id"
397
+ // manageRule is null in PocketBase default (not set)
387
398
  }),
388
399
  [
389
- // Email should be unique for authentication
390
- "CREATE UNIQUE INDEX idx_users_email ON users (email)",
391
- // Index on name for user search and sorting
392
- "CREATE INDEX idx_users_name ON users (name)"
400
+ // PocketBase's default indexes for auth collections
401
+ "CREATE UNIQUE INDEX `idx_tokenKey__pb_users_auth_` ON `users` (`tokenKey`)",
402
+ "CREATE UNIQUE INDEX `idx_email__pb_users_auth_` ON `users` (`email`) WHERE `email` != ''"
393
403
  ]
394
404
  );
395
405
  var BaseMutator = class {
@@ -730,7 +740,7 @@ var UserMutator = class extends BaseMutator {
730
740
  };
731
741
  }
732
742
  getCollection() {
733
- return this.pb.collection("Projects");
743
+ return this.pb.collection("Users");
734
744
  }
735
745
  async validateInput(input) {
736
746
  return UserInputSchema.parse(input);
@@ -1496,26 +1506,28 @@ function getMaxSelect(fieldName, zodType) {
1496
1506
  return 1;
1497
1507
  }
1498
1508
  function getMinSelect(fieldName, zodType) {
1499
- if (!isMultipleRelationField(fieldName, zodType)) {
1500
- return void 0;
1501
- }
1502
- let unwrappedType = zodType;
1503
- if (zodType instanceof z.ZodOptional) {
1504
- unwrappedType = zodType._def.innerType;
1505
- }
1506
- if (unwrappedType instanceof z.ZodNullable) {
1507
- unwrappedType = unwrappedType._def.innerType;
1508
- }
1509
- if (unwrappedType instanceof z.ZodDefault) {
1510
- unwrappedType = unwrappedType._def.innerType;
1509
+ if (isSingleRelationField(fieldName, zodType)) {
1510
+ return 0;
1511
1511
  }
1512
- if (unwrappedType instanceof z.ZodArray) {
1513
- const arrayDef = unwrappedType._def;
1514
- if (arrayDef.minLength) {
1515
- return arrayDef.minLength.value;
1512
+ if (isMultipleRelationField(fieldName, zodType)) {
1513
+ let unwrappedType = zodType;
1514
+ if (zodType instanceof z.ZodOptional) {
1515
+ unwrappedType = zodType._def.innerType;
1516
+ }
1517
+ if (unwrappedType instanceof z.ZodNullable) {
1518
+ unwrappedType = unwrappedType._def.innerType;
1519
+ }
1520
+ if (unwrappedType instanceof z.ZodDefault) {
1521
+ unwrappedType = unwrappedType._def.innerType;
1522
+ }
1523
+ if (unwrappedType instanceof z.ZodArray) {
1524
+ const arrayDef = unwrappedType._def;
1525
+ if (arrayDef.minLength) {
1526
+ return arrayDef.minLength.value;
1527
+ }
1516
1528
  }
1517
1529
  }
1518
- return void 0;
1530
+ return 0;
1519
1531
  }
1520
1532
  var POCKETBASE_FIELD_TYPES = [
1521
1533
  "text",
@@ -1998,13 +2010,32 @@ async function importSchemaModule(filePath, config) {
1998
2010
  if (config?.pathTransformer) {
1999
2011
  importPath = config.pathTransformer(filePath);
2000
2012
  }
2001
- if (!importPath.endsWith(".js")) {
2002
- importPath = `${importPath}.js`;
2013
+ let resolvedPath = null;
2014
+ const jsPath = `${importPath}.js`;
2015
+ const tsPath = `${importPath}.ts`;
2016
+ if (fs2.existsSync(jsPath)) {
2017
+ resolvedPath = jsPath;
2018
+ } else if (fs2.existsSync(tsPath)) {
2019
+ resolvedPath = tsPath;
2020
+ } else {
2021
+ resolvedPath = jsPath;
2003
2022
  }
2004
- const fileUrl = new URL(`file://${path4.resolve(importPath)}`);
2023
+ const fileUrl = new URL(`file://${path4.resolve(resolvedPath)}`);
2005
2024
  const module = await import(fileUrl.href);
2006
2025
  return module;
2007
2026
  } catch (error) {
2027
+ const tsPath = `${filePath}.ts`;
2028
+ const isTypeScriptFile = fs2.existsSync(tsPath);
2029
+ if (isTypeScriptFile) {
2030
+ throw new SchemaParsingError(
2031
+ `Failed to import TypeScript schema file. Node.js cannot import TypeScript files directly.
2032
+ Please either:
2033
+ 1. Compile your schema files to JavaScript first, or
2034
+ 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")`,
2035
+ filePath,
2036
+ error
2037
+ );
2038
+ }
2008
2039
  throw new SchemaParsingError(
2009
2040
  `Failed to import schema module. Make sure the schema files are compiled to JavaScript.`,
2010
2041
  filePath,
@@ -2067,7 +2098,17 @@ function buildFieldDefinition(fieldName, zodType) {
2067
2098
  required,
2068
2099
  options
2069
2100
  };
2070
- if (isRelationField(fieldName, zodType)) {
2101
+ const relationMetadata = extractRelationMetadata(zodType.description);
2102
+ if (relationMetadata) {
2103
+ fieldDef.type = "relation";
2104
+ fieldDef.relation = {
2105
+ collection: relationMetadata.collection,
2106
+ maxSelect: relationMetadata.maxSelect,
2107
+ minSelect: relationMetadata.minSelect,
2108
+ cascadeDelete: relationMetadata.cascadeDelete
2109
+ };
2110
+ fieldDef.options = void 0;
2111
+ } else if (isRelationField(fieldName, zodType)) {
2071
2112
  fieldDef.type = "relation";
2072
2113
  const targetCollection = resolveTargetCollection(fieldName);
2073
2114
  const maxSelect = getMaxSelect(fieldName, zodType);
@@ -2079,6 +2120,13 @@ function buildFieldDefinition(fieldName, zodType) {
2079
2120
  cascadeDelete: false
2080
2121
  // Default to false, can be configured later
2081
2122
  };
2123
+ if (fieldDef.options) {
2124
+ const { min, max, pattern, ...relationSafeOptions } = fieldDef.options;
2125
+ console.log("min", min);
2126
+ console.log("max", max);
2127
+ console.log("pattern", pattern);
2128
+ fieldDef.options = Object.keys(relationSafeOptions).length > 0 ? relationSafeOptions : void 0;
2129
+ }
2082
2130
  }
2083
2131
  return fieldDef;
2084
2132
  }
@@ -2131,11 +2179,12 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
2131
2179
  fields,
2132
2180
  indexes,
2133
2181
  rules: {
2134
- listRule: null,
2135
- viewRule: null,
2136
- createRule: null,
2137
- updateRule: null,
2138
- deleteRule: null
2182
+ listRule: permissions?.listRule ?? null,
2183
+ viewRule: permissions?.viewRule ?? null,
2184
+ createRule: permissions?.createRule ?? null,
2185
+ updateRule: permissions?.updateRule ?? null,
2186
+ deleteRule: permissions?.deleteRule ?? null,
2187
+ manageRule: permissions?.manageRule ?? null
2139
2188
  },
2140
2189
  permissions
2141
2190
  };
@@ -2159,7 +2208,12 @@ async function buildSchemaDefinition(config) {
2159
2208
  if (normalizedConfig.pathTransformer) {
2160
2209
  importPath = normalizedConfig.pathTransformer(filePath);
2161
2210
  } else if (mergedConfig.useCompiledFiles) {
2162
- importPath = filePath.replace(/\/src\//, "/dist/");
2211
+ const distPath = filePath.replace(/\/src\//, "/dist/");
2212
+ if (fs2.existsSync(`${distPath}.js`) || fs2.existsSync(`${distPath}.mjs`)) {
2213
+ importPath = distPath;
2214
+ } else {
2215
+ importPath = filePath;
2216
+ }
2163
2217
  }
2164
2218
  const module = await importSchemaModule(importPath, normalizedConfig);
2165
2219
  const schemas = extractSchemaDefinitions(module, mergedConfig.schemaPatterns);
@@ -2536,6 +2590,7 @@ function convertPocketBaseCollection(pbCollection) {
2536
2590
  if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
2537
2591
  if (Object.keys(rules).length > 0) {
2538
2592
  schema.rules = rules;
2593
+ schema.permissions = { ...rules };
2539
2594
  }
2540
2595
  return schema;
2541
2596
  }
@@ -3231,10 +3286,8 @@ var DiffEngine = class {
3231
3286
  var DEFAULT_TEMPLATE = `/// <reference path="{{TYPES_PATH}}" />
3232
3287
  migrate((app) => {
3233
3288
  {{UP_CODE}}
3234
- return true;
3235
3289
  }, (app) => {
3236
3290
  {{DOWN_CODE}}
3237
- return true;
3238
3291
  });
3239
3292
  `;
3240
3293
  var DEFAULT_CONFIG4 = {
@@ -3399,7 +3452,8 @@ function generateFieldDefinitionObject(field) {
3399
3452
  }
3400
3453
  }
3401
3454
  if (field.relation) {
3402
- const collectionIdPlaceholder = field.relation.collection === "Users" ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3455
+ const isUsersCollection = field.relation.collection.toLowerCase() === "users";
3456
+ const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3403
3457
  parts.push(` collectionId: ${collectionIdPlaceholder}`);
3404
3458
  if (field.relation.maxSelect !== void 0) {
3405
3459
  parts.push(` maxSelect: ${field.relation.maxSelect}`);
@@ -3483,7 +3537,7 @@ function generateIndexesArray(indexes) {
3483
3537
  ${indexStrings.join(",\n ")},
3484
3538
  ]`;
3485
3539
  }
3486
- function generateCollectionCreation(collection, varName = "collection") {
3540
+ function generateCollectionCreation(collection, varName = "collection", isLast = false) {
3487
3541
  const lines = [];
3488
3542
  lines.push(` const ${varName} = new Collection({`);
3489
3543
  lines.push(` name: "${collection.name}",`);
@@ -3499,7 +3553,7 @@ function generateCollectionCreation(collection, varName = "collection") {
3499
3553
  lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
3500
3554
  lines.push(` });`);
3501
3555
  lines.push(``);
3502
- lines.push(` app.save(${varName});`);
3556
+ lines.push(isLast ? ` return app.save(${varName});` : ` app.save(${varName});`);
3503
3557
  return lines.join("\n");
3504
3558
  }
3505
3559
  function getFieldConstructorName(fieldType) {
@@ -3530,7 +3584,8 @@ function generateFieldConstructorOptions(field) {
3530
3584
  }
3531
3585
  }
3532
3586
  if (field.relation && field.type === "relation") {
3533
- const collectionIdPlaceholder = field.relation.collection === "Users" ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3587
+ const isUsersCollection = field.relation.collection.toLowerCase() === "users";
3588
+ const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3534
3589
  parts.push(` collectionId: ${collectionIdPlaceholder}`);
3535
3590
  if (field.relation.maxSelect !== void 0) {
3536
3591
  parts.push(` maxSelect: ${field.relation.maxSelect}`);
@@ -3544,7 +3599,7 @@ function generateFieldConstructorOptions(field) {
3544
3599
  }
3545
3600
  return parts.join(",\n");
3546
3601
  }
3547
- function generateFieldAddition(collectionName, field, varName) {
3602
+ function generateFieldAddition(collectionName, field, varName, isLast = false) {
3548
3603
  const lines = [];
3549
3604
  const constructorName = getFieldConstructorName(field.type);
3550
3605
  const collectionVar = varName || `collection_${collectionName}_${field.name}`;
@@ -3554,10 +3609,10 @@ function generateFieldAddition(collectionName, field, varName) {
3554
3609
  lines.push(generateFieldConstructorOptions(field));
3555
3610
  lines.push(` }));`);
3556
3611
  lines.push(``);
3557
- lines.push(` app.save(${collectionVar});`);
3612
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3558
3613
  return lines.join("\n");
3559
3614
  }
3560
- function generateFieldModification(collectionName, modification, varName) {
3615
+ function generateFieldModification(collectionName, modification, varName, isLast = false) {
3561
3616
  const lines = [];
3562
3617
  const collectionVar = varName || `collection_${collectionName}_${modification.fieldName}`;
3563
3618
  const fieldVar = `${collectionVar}_field`;
@@ -3571,7 +3626,8 @@ function generateFieldModification(collectionName, modification, varName) {
3571
3626
  } else if (change.property.startsWith("relation.")) {
3572
3627
  const relationKey = change.property.replace("relation.", "");
3573
3628
  if (relationKey === "collection") {
3574
- const collectionIdValue = change.newValue === "Users" ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${change.newValue}").id`;
3629
+ const isUsersCollection = String(change.newValue).toLowerCase() === "users";
3630
+ const collectionIdValue = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${change.newValue}").id`;
3575
3631
  lines.push(` ${fieldVar}.collectionId = ${collectionIdValue};`);
3576
3632
  } else {
3577
3633
  lines.push(` ${fieldVar}.${relationKey} = ${formatValue(change.newValue)};`);
@@ -3581,10 +3637,10 @@ function generateFieldModification(collectionName, modification, varName) {
3581
3637
  }
3582
3638
  }
3583
3639
  lines.push(``);
3584
- lines.push(` app.save(${collectionVar});`);
3640
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3585
3641
  return lines.join("\n");
3586
3642
  }
3587
- function generateFieldDeletion(collectionName, fieldName, varName) {
3643
+ function generateFieldDeletion(collectionName, fieldName, varName, isLast = false) {
3588
3644
  const lines = [];
3589
3645
  const collectionVar = varName || `collection_${collectionName}_${fieldName}`;
3590
3646
  const fieldVar = `${collectionVar}_field`;
@@ -3593,18 +3649,18 @@ function generateFieldDeletion(collectionName, fieldName, varName) {
3593
3649
  lines.push(``);
3594
3650
  lines.push(` ${collectionVar}.fields.remove(${fieldVar}.id);`);
3595
3651
  lines.push(``);
3596
- lines.push(` app.save(${collectionVar});`);
3652
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3597
3653
  return lines.join("\n");
3598
3654
  }
3599
- function generateIndexAddition(collectionName, index, varName) {
3655
+ function generateIndexAddition(collectionName, index, varName, isLast = false) {
3600
3656
  const lines = [];
3601
3657
  const collectionVar = varName || `collection_${collectionName}_idx`;
3602
3658
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3603
3659
  lines.push(` ${collectionVar}.indexes.push("${index}");`);
3604
- lines.push(` app.save(${collectionVar});`);
3660
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3605
3661
  return lines.join("\n");
3606
3662
  }
3607
- function generateIndexRemoval(collectionName, index, varName) {
3663
+ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
3608
3664
  const lines = [];
3609
3665
  const collectionVar = varName || `collection_${collectionName}_idx`;
3610
3666
  const indexVar = `${collectionVar}_indexToRemove`;
@@ -3613,29 +3669,29 @@ function generateIndexRemoval(collectionName, index, varName) {
3613
3669
  lines.push(` if (${indexVar} !== -1) {`);
3614
3670
  lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
3615
3671
  lines.push(` }`);
3616
- lines.push(` app.save(${collectionVar});`);
3672
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3617
3673
  return lines.join("\n");
3618
3674
  }
3619
- function generateRuleUpdate(collectionName, ruleType, newValue, varName) {
3675
+ function generateRuleUpdate(collectionName, ruleType, newValue, varName, isLast = false) {
3620
3676
  const lines = [];
3621
3677
  const collectionVar = varName || `collection_${collectionName}_${ruleType}`;
3622
3678
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3623
3679
  lines.push(` ${collectionVar}.${ruleType} = ${formatValue(newValue)};`);
3624
- lines.push(` app.save(${collectionVar});`);
3680
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3625
3681
  return lines.join("\n");
3626
3682
  }
3627
- function generatePermissionUpdate(collectionName, ruleType, newValue, varName) {
3683
+ function generatePermissionUpdate(collectionName, ruleType, newValue, varName, isLast = false) {
3628
3684
  const lines = [];
3629
3685
  const collectionVar = varName || `collection_${collectionName}_${ruleType}`;
3630
3686
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3631
3687
  lines.push(` ${collectionVar}.${ruleType} = ${formatValue(newValue)};`);
3632
- lines.push(` app.save(${collectionVar});`);
3688
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3633
3689
  return lines.join("\n");
3634
3690
  }
3635
- function generateCollectionDeletion(collectionName, varName = "collection") {
3691
+ function generateCollectionDeletion(collectionName, varName = "collection", isLast = false) {
3636
3692
  const lines = [];
3637
3693
  lines.push(` const ${varName} = app.findCollectionByNameOrId("${collectionName}");`);
3638
- lines.push(` app.delete(${varName});`);
3694
+ lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
3639
3695
  return lines.join("\n");
3640
3696
  }
3641
3697
  function generateUpMigration(diff) {
@@ -3727,7 +3783,24 @@ function generateUpMigration(diff) {
3727
3783
  lines.push(` // No changes detected`);
3728
3784
  lines.push(``);
3729
3785
  }
3730
- return lines.join("\n");
3786
+ let code = lines.join("\n");
3787
+ const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
3788
+ const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
3789
+ const saveMatches = [...code.matchAll(savePattern)];
3790
+ const deleteMatches = [...code.matchAll(deletePattern)];
3791
+ const allMatches = [
3792
+ ...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
3793
+ ...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
3794
+ ].sort((a, b) => b.index - a.index);
3795
+ if (allMatches.length > 0) {
3796
+ const lastMatch = allMatches[0];
3797
+ if (lastMatch.type === "save") {
3798
+ 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);
3799
+ } else {
3800
+ 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);
3801
+ }
3802
+ }
3803
+ return code;
3731
3804
  }
3732
3805
  function generateDownMigration(diff) {
3733
3806
  const lines = [];
@@ -3829,7 +3902,24 @@ function generateDownMigration(diff) {
3829
3902
  lines.push(` // No changes to revert`);
3830
3903
  lines.push(``);
3831
3904
  }
3832
- return lines.join("\n");
3905
+ let code = lines.join("\n");
3906
+ const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
3907
+ const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
3908
+ const saveMatches = [...code.matchAll(savePattern)];
3909
+ const deleteMatches = [...code.matchAll(deletePattern)];
3910
+ const allMatches = [
3911
+ ...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
3912
+ ...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
3913
+ ].sort((a, b) => b.index - a.index);
3914
+ if (allMatches.length > 0) {
3915
+ const lastMatch = allMatches[0];
3916
+ if (lastMatch.type === "save") {
3917
+ 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);
3918
+ } else {
3919
+ 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);
3920
+ }
3921
+ }
3922
+ return code;
3833
3923
  }
3834
3924
  function generate(diff, config) {
3835
3925
  const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
@@ -4430,7 +4520,13 @@ async function executeGenerate(options) {
4430
4520
  const schemaDir = getSchemaDirectory(config);
4431
4521
  const migrationsDir = getMigrationsDirectory(config);
4432
4522
  logSection("\u{1F50D} Analyzing Schema");
4433
- const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(schemaDir));
4523
+ const analyzerConfig = {
4524
+ schemaDir,
4525
+ excludePatterns: config.schema.exclude,
4526
+ useCompiledFiles: false
4527
+ // Use source files since we're in development/testing
4528
+ };
4529
+ const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
4434
4530
  logSuccess(`Found ${currentSchema.collections.size} collection(s)`);
4435
4531
  logInfo("Loading previous snapshot...");
4436
4532
  const previousSnapshot = loadSnapshotIfExists({
@@ -4617,7 +4713,13 @@ async function executeStatus(options) {
4617
4713
  const schemaDir = getSchemaDirectory(config);
4618
4714
  const migrationsDir = getMigrationsDirectory(config);
4619
4715
  logSection("\u{1F50D} Checking Migration Status");
4620
- const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(schemaDir));
4716
+ const analyzerConfig = {
4717
+ schemaDir,
4718
+ excludePatterns: config.schema.exclude,
4719
+ useCompiledFiles: false
4720
+ // Use source files since we're in development/testing
4721
+ };
4722
+ const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
4621
4723
  logSuccess(`Found ${currentSchema.collections.size} collection(s) in schema`);
4622
4724
  logInfo("Loading previous snapshot...");
4623
4725
  const previousSnapshot = loadSnapshotIfExists({
@@ -4721,6 +4823,6 @@ async function executeStatus(options) {
4721
4823
  }
4722
4824
  }
4723
4825
 
4724
- export { CLIUsageError, ConfigurationError, DiffEngine, FIELD_TYPE_INFO, FileSystemError, MigrationError, MigrationGenerationError, MigrationGenerator, POCKETBASE_FIELD_TYPES, PermissionTemplates, ProjectInputSchema, ProjectSchema, SchemaAnalyzer, SchemaParsingError, SnapshotError, SnapshotManager, StatusEnum, UserInputSchema, UserMutator, UserSchema, aggregateChanges, baseImageFileSchema, baseSchema, baseSchemaWithTimestamps, boolField, buildFieldDefinition, buildSchemaDefinition, categorizeChangesBySeverity, compare, compareFieldConstraints, compareFieldOptions, compareFieldTypes, comparePermissions, compareRelationConfigurations, convertPocketBaseMigration, convertZodSchemaToCollectionSchema, createMigrationFileStructure, createPermissions, dateField, detectDestructiveChanges, detectFieldChanges, discoverSchemaFiles, editorField, emailField, extractComprehensiveFieldOptions, extractFieldDefinitions, extractFieldOptions, extractIndexes, extractSchemaDefinitions, fileField, filesField, filterSystemCollections, findLatestSnapshot, findNewCollections, findNewFields, findRemovedCollections, findRemovedFields, formatChangeSummary, generate, generateChangeSummary, generateCollectionCreation, generateCollectionPermissions, generateCollectionRules, generateDownMigration, generateFieldAddition, generateFieldDefinitionObject, generateFieldDeletion, generateFieldModification, generateFieldsArray, generateIndexesArray, executeGenerate as generateMigration, generateMigrationDescription, generateMigrationFilename, generatePermissionUpdate, generateTimestamp, generateUpMigration, geoPointField, getArrayElementType, getCollectionNameFromFile, getDefaultValue, getFieldTypeInfo, getMaxSelect, executeStatus as getMigrationStatus, getMinSelect, getSnapshotPath, getSnapshotVersion, getUsersSystemFields, importSchemaModule, inputImageFileSchema, isArrayType, isAuthCollection, isEditorField, isFieldRequired, isFileFieldByName, isGeoPointType, isMultipleRelationField, isPermissionSchema, isRelationField, isSingleRelationField, isSystemCollection, isTemplateConfig, jsonField, loadBaseMigration, loadConfig, loadSnapshot, loadSnapshotIfExists, logError, logInfo, logSection, logSuccess, logWarning, mapZodArrayType, mapZodBooleanType, mapZodDateType, mapZodEnumType, mapZodNumberType, mapZodRecordType, mapZodStringType, mapZodTypeToPocketBase, matchCollectionsByName, matchFieldsByName, mergePermissions, mergeSnapshots, numberField, omitImageFilesSchema, parseSchemaFiles, pluralize, relationField, relationsField, requiresForceFlag, resolveTargetCollection, resolveTemplate, saveSnapshot, selectField, selectSchemaForCollection, singularize, snapshotExists, textField, toCollectionName, unwrapZodType, urlField, validatePermissionConfig, validateRuleExpression, validateSnapshot, withIndexes, withPermissions, withProgress, writeMigrationFile };
4826
+ export { CLIUsageError, ConfigurationError, DiffEngine, FIELD_TYPE_INFO, FileSystemError, MigrationError, MigrationGenerationError, MigrationGenerator, POCKETBASE_FIELD_TYPES, PermissionTemplates, SchemaAnalyzer, SchemaParsingError, SnapshotError, SnapshotManager, StatusEnum, UserInputSchema, UserMutator, UserSchema, aggregateChanges, baseImageFileSchema, baseSchema, baseSchemaWithTimestamps, boolField, buildFieldDefinition, buildSchemaDefinition, categorizeChangesBySeverity, compare, compareFieldConstraints, compareFieldOptions, compareFieldTypes, comparePermissions, compareRelationConfigurations, convertPocketBaseMigration, convertZodSchemaToCollectionSchema, createMigrationFileStructure, createPermissions, dateField, detectDestructiveChanges, detectFieldChanges, discoverSchemaFiles, editorField, emailField, extractComprehensiveFieldOptions, extractFieldDefinitions, extractFieldOptions, extractIndexes, extractRelationMetadata, extractSchemaDefinitions, fileField, filesField, filterSystemCollections, findLatestSnapshot, findNewCollections, findNewFields, findRemovedCollections, findRemovedFields, formatChangeSummary, generate, generateChangeSummary, generateCollectionCreation, generateCollectionPermissions, generateCollectionRules, generateDownMigration, generateFieldAddition, generateFieldDefinitionObject, generateFieldDeletion, generateFieldModification, generateFieldsArray, generateIndexesArray, executeGenerate as generateMigration, generateMigrationDescription, generateMigrationFilename, generatePermissionUpdate, generateTimestamp, generateUpMigration, geoPointField, getArrayElementType, getCollectionNameFromFile, getDefaultValue, getFieldTypeInfo, getMaxSelect, executeStatus as getMigrationStatus, getMinSelect, getSnapshotPath, getSnapshotVersion, getUsersSystemFields, importSchemaModule, inputImageFileSchema, isArrayType, isAuthCollection, isEditorField, isFieldRequired, isFileFieldByName, isGeoPointType, isMultipleRelationField, isPermissionSchema, isRelationField, isSingleRelationField, isSystemCollection, isTemplateConfig, jsonField, loadBaseMigration, loadConfig, loadSnapshot, loadSnapshotIfExists, logError, logInfo, logSection, logSuccess, logWarning, mapZodArrayType, mapZodBooleanType, mapZodDateType, mapZodEnumType, mapZodNumberType, mapZodRecordType, mapZodStringType, mapZodTypeToPocketBase, matchCollectionsByName, matchFieldsByName, mergePermissions, mergeSnapshots, numberField, omitImageFilesSchema, parseSchemaFiles, pluralize, relationField, relationsField, requiresForceFlag, resolveTargetCollection, resolveTemplate, saveSnapshot, selectField, selectSchemaForCollection, singularize, snapshotExists, textField, toCollectionName, unwrapZodType, urlField, validatePermissionConfig, validateRuleExpression, validateSnapshot, withIndexes, withPermissions, withProgress, writeMigrationFile };
4725
4827
  //# sourceMappingURL=index.js.map
4726
4828
  //# sourceMappingURL=index.js.map