pocketbase-zod-schema 0.1.2 → 0.1.4

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 (69) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +329 -99
  3. package/dist/cli/index.cjs +577 -152
  4. package/dist/cli/index.cjs.map +1 -1
  5. package/dist/cli/index.js +575 -150
  6. package/dist/cli/index.js.map +1 -1
  7. package/dist/cli/migrate.cjs +595 -153
  8. package/dist/cli/migrate.cjs.map +1 -1
  9. package/dist/cli/migrate.js +592 -151
  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 +688 -231
  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 +685 -230
  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/diff.cjs +21 -3
  26. package/dist/migration/diff.cjs.map +1 -1
  27. package/dist/migration/diff.js +21 -3
  28. package/dist/migration/diff.js.map +1 -1
  29. package/dist/migration/generator.cjs +60 -25
  30. package/dist/migration/generator.cjs.map +1 -1
  31. package/dist/migration/generator.d.cts +9 -5
  32. package/dist/migration/generator.d.ts +9 -5
  33. package/dist/migration/generator.js +60 -25
  34. package/dist/migration/generator.js.map +1 -1
  35. package/dist/migration/index.cjs +614 -171
  36. package/dist/migration/index.cjs.map +1 -1
  37. package/dist/migration/index.d.cts +1 -1
  38. package/dist/migration/index.d.ts +1 -1
  39. package/dist/migration/index.js +613 -171
  40. package/dist/migration/index.js.map +1 -1
  41. package/dist/migration/snapshot.cjs +432 -117
  42. package/dist/migration/snapshot.cjs.map +1 -1
  43. package/dist/migration/snapshot.d.cts +34 -12
  44. package/dist/migration/snapshot.d.ts +34 -12
  45. package/dist/migration/snapshot.js +430 -116
  46. package/dist/migration/snapshot.js.map +1 -1
  47. package/dist/migration/utils/index.cjs +19 -17
  48. package/dist/migration/utils/index.cjs.map +1 -1
  49. package/dist/migration/utils/index.d.cts +3 -1
  50. package/dist/migration/utils/index.d.ts +3 -1
  51. package/dist/migration/utils/index.js +19 -17
  52. package/dist/migration/utils/index.js.map +1 -1
  53. package/dist/mutator.cjs +9 -11
  54. package/dist/mutator.cjs.map +1 -1
  55. package/dist/mutator.d.cts +5 -9
  56. package/dist/mutator.d.ts +5 -9
  57. package/dist/mutator.js +9 -11
  58. package/dist/mutator.js.map +1 -1
  59. package/dist/schema.cjs +54 -23
  60. package/dist/schema.cjs.map +1 -1
  61. package/dist/schema.d.cts +94 -12
  62. package/dist/schema.d.ts +94 -12
  63. package/dist/schema.js +54 -24
  64. package/dist/schema.js.map +1 -1
  65. package/dist/types.d.cts +1 -1
  66. package/dist/types.d.ts +1 -1
  67. package/dist/{user-jS1aYoeD.d.cts → user-_AM523hb.d.cts} +6 -6
  68. package/dist/{user-jS1aYoeD.d.ts → user-_AM523hb.d.ts} +6 -6
  69. package/package.json +2 -4
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import * as fs2 from 'fs';
3
- import * as path4 from 'path';
2
+ import * as fs3 from 'fs';
3
+ import * as path5 from 'path';
4
4
  import chalk from 'chalk';
5
5
  import ora from 'ora';
6
6
 
@@ -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
@@ -341,38 +375,36 @@ var ProjectInputSchema = z.object({
341
375
  content: z.string(),
342
376
  status: StatusEnum,
343
377
  summary: z.string().optional(),
344
- User: z.string().nonempty("User ID is missing"),
345
- SubscriberUsers: z.array(z.string())
378
+ OwnerUser: relationField({ collection: "Users" }),
379
+ SubscriberUsers: relationsField({ collection: "Users" })
346
380
  }).extend(inputImageFileSchema);
347
381
  var ProjectSchema = withPermissions(
348
382
  ProjectInputSchema.omit(omitImageFilesSchema).extend(baseImageFileSchema),
349
383
  {
350
384
  template: "owner-only",
351
- ownerField: "User",
385
+ ownerField: "OwnerUser",
352
386
  customRules: {
353
- // Override list rule to allow authenticated users to see all projects
354
387
  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)'
388
+ viewRule: '@request.auth.id != "" && (OwnerUser = @request.auth.id || SubscriberUsers ?= @request.auth.id)'
357
389
  }
358
390
  }
359
391
  );
360
392
  var UserInputSchema = z.object({
361
- name: z.string().min(2, "Name must be longer").optional(),
393
+ name: z.string().optional(),
362
394
  email: z.string().email(),
363
395
  password: z.string().min(8, "Password must be at least 8 characters"),
364
396
  passwordConfirm: z.string(),
365
397
  avatar: z.instanceof(File).optional()
366
398
  });
367
399
  var UserDatabaseSchema = z.object({
368
- name: z.string().min(2, "Name must be longer").optional(),
400
+ name: z.string().optional(),
369
401
  email: z.string().email(),
370
402
  password: z.string().min(8, "Password must be at least 8 characters"),
371
403
  avatar: z.instanceof(File).optional()
372
404
  });
373
405
  var UserSchema = withIndexes(
374
406
  withPermissions(UserDatabaseSchema.extend(baseSchema), {
375
- // Users can list other users (for mentions, user search, etc.)
407
+ // Users can list their own profile
376
408
  listRule: "id = @request.auth.id",
377
409
  // Users can view their own profile
378
410
  viewRule: "id = @request.auth.id",
@@ -381,15 +413,13 @@ var UserSchema = withIndexes(
381
413
  // Users can only update their own profile
382
414
  updateRule: "id = @request.auth.id",
383
415
  // 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"
416
+ deleteRule: "id = @request.auth.id"
417
+ // manageRule is null in PocketBase default (not set)
387
418
  }),
388
419
  [
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)"
420
+ // PocketBase's default indexes for auth collections
421
+ "CREATE UNIQUE INDEX `idx_tokenKey__pb_users_auth_` ON `users` (`tokenKey`)",
422
+ "CREATE UNIQUE INDEX `idx_email__pb_users_auth_` ON `users` (`email`) WHERE `email` != ''"
393
423
  ]
394
424
  );
395
425
  var BaseMutator = class {
@@ -730,7 +760,7 @@ var UserMutator = class extends BaseMutator {
730
760
  };
731
761
  }
732
762
  getCollection() {
733
- return this.pb.collection("Projects");
763
+ return this.pb.collection("Users");
734
764
  }
735
765
  async validateInput(input) {
736
766
  return UserInputSchema.parse(input);
@@ -834,10 +864,10 @@ var FileSystemError = class _FileSystemError extends MigrationError {
834
864
  operation;
835
865
  code;
836
866
  originalError;
837
- constructor(message, path6, operation, code, originalError) {
867
+ constructor(message, path7, operation, code, originalError) {
838
868
  super(message);
839
869
  this.name = "FileSystemError";
840
- this.path = path6;
870
+ this.path = path7;
841
871
  this.operation = operation;
842
872
  this.code = code;
843
873
  this.originalError = originalError;
@@ -1496,26 +1526,28 @@ function getMaxSelect(fieldName, zodType) {
1496
1526
  return 1;
1497
1527
  }
1498
1528
  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;
1529
+ if (isSingleRelationField(fieldName, zodType)) {
1530
+ return 0;
1511
1531
  }
1512
- if (unwrappedType instanceof z.ZodArray) {
1513
- const arrayDef = unwrappedType._def;
1514
- if (arrayDef.minLength) {
1515
- return arrayDef.minLength.value;
1532
+ if (isMultipleRelationField(fieldName, zodType)) {
1533
+ let unwrappedType = zodType;
1534
+ if (zodType instanceof z.ZodOptional) {
1535
+ unwrappedType = zodType._def.innerType;
1536
+ }
1537
+ if (unwrappedType instanceof z.ZodNullable) {
1538
+ unwrappedType = unwrappedType._def.innerType;
1539
+ }
1540
+ if (unwrappedType instanceof z.ZodDefault) {
1541
+ unwrappedType = unwrappedType._def.innerType;
1542
+ }
1543
+ if (unwrappedType instanceof z.ZodArray) {
1544
+ const arrayDef = unwrappedType._def;
1545
+ if (arrayDef.minLength) {
1546
+ return arrayDef.minLength.value;
1547
+ }
1516
1548
  }
1517
1549
  }
1518
- return void 0;
1550
+ return 0;
1519
1551
  }
1520
1552
  var POCKETBASE_FIELD_TYPES = [
1521
1553
  "text",
@@ -1938,20 +1970,20 @@ function mergeConfig(config) {
1938
1970
  }
1939
1971
  function resolveSchemaDir(config) {
1940
1972
  const workspaceRoot = config.workspaceRoot || process.cwd();
1941
- if (path4.isAbsolute(config.schemaDir)) {
1973
+ if (path5.isAbsolute(config.schemaDir)) {
1942
1974
  return config.schemaDir;
1943
1975
  }
1944
- return path4.join(workspaceRoot, config.schemaDir);
1976
+ return path5.join(workspaceRoot, config.schemaDir);
1945
1977
  }
1946
1978
  function discoverSchemaFiles(config) {
1947
1979
  const normalizedConfig = typeof config === "string" ? { schemaDir: config } : config;
1948
1980
  const mergedConfig = mergeConfig(normalizedConfig);
1949
1981
  const schemaDir = resolveSchemaDir(normalizedConfig);
1950
1982
  try {
1951
- if (!fs2.existsSync(schemaDir)) {
1983
+ if (!fs3.existsSync(schemaDir)) {
1952
1984
  throw new FileSystemError(`Schema directory not found: ${schemaDir}`, schemaDir, "access", "ENOENT");
1953
1985
  }
1954
- const files = fs2.readdirSync(schemaDir);
1986
+ const files = fs3.readdirSync(schemaDir);
1955
1987
  const schemaFiles = files.filter((file) => {
1956
1988
  const hasValidExtension = mergedConfig.includeExtensions.some((ext) => file.endsWith(ext));
1957
1989
  if (!hasValidExtension) return false;
@@ -1967,7 +1999,7 @@ function discoverSchemaFiles(config) {
1967
1999
  });
1968
2000
  return schemaFiles.map((file) => {
1969
2001
  const ext = mergedConfig.includeExtensions.find((ext2) => file.endsWith(ext2)) || ".ts";
1970
- return path4.join(schemaDir, file.replace(new RegExp(`\\${ext}$`), ""));
2002
+ return path5.join(schemaDir, file.replace(new RegExp(`\\${ext}$`), ""));
1971
2003
  });
1972
2004
  } catch (error) {
1973
2005
  if (error instanceof FileSystemError) {
@@ -1998,13 +2030,32 @@ async function importSchemaModule(filePath, config) {
1998
2030
  if (config?.pathTransformer) {
1999
2031
  importPath = config.pathTransformer(filePath);
2000
2032
  }
2001
- if (!importPath.endsWith(".js")) {
2002
- importPath = `${importPath}.js`;
2033
+ let resolvedPath = null;
2034
+ const jsPath = `${importPath}.js`;
2035
+ const tsPath = `${importPath}.ts`;
2036
+ if (fs3.existsSync(jsPath)) {
2037
+ resolvedPath = jsPath;
2038
+ } else if (fs3.existsSync(tsPath)) {
2039
+ resolvedPath = tsPath;
2040
+ } else {
2041
+ resolvedPath = jsPath;
2003
2042
  }
2004
- const fileUrl = new URL(`file://${path4.resolve(importPath)}`);
2043
+ const fileUrl = new URL(`file://${path5.resolve(resolvedPath)}`);
2005
2044
  const module = await import(fileUrl.href);
2006
2045
  return module;
2007
2046
  } catch (error) {
2047
+ const tsPath = `${filePath}.ts`;
2048
+ const isTypeScriptFile = fs3.existsSync(tsPath);
2049
+ if (isTypeScriptFile) {
2050
+ throw new SchemaParsingError(
2051
+ `Failed to import TypeScript schema file. Node.js cannot import TypeScript files directly.
2052
+ Please either:
2053
+ 1. Compile your schema files to JavaScript first, or
2054
+ 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")`,
2055
+ filePath,
2056
+ error
2057
+ );
2058
+ }
2008
2059
  throw new SchemaParsingError(
2009
2060
  `Failed to import schema module. Make sure the schema files are compiled to JavaScript.`,
2010
2061
  filePath,
@@ -2013,7 +2064,7 @@ async function importSchemaModule(filePath, config) {
2013
2064
  }
2014
2065
  }
2015
2066
  function getCollectionNameFromFile(filePath) {
2016
- const filename = path4.basename(filePath).replace(/\.(ts|js)$/, "");
2067
+ const filename = path5.basename(filePath).replace(/\.(ts|js)$/, "");
2017
2068
  return toCollectionName(filename);
2018
2069
  }
2019
2070
  function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema"]) {
@@ -2067,7 +2118,17 @@ function buildFieldDefinition(fieldName, zodType) {
2067
2118
  required,
2068
2119
  options
2069
2120
  };
2070
- if (isRelationField(fieldName, zodType)) {
2121
+ const relationMetadata = extractRelationMetadata(zodType.description);
2122
+ if (relationMetadata) {
2123
+ fieldDef.type = "relation";
2124
+ fieldDef.relation = {
2125
+ collection: relationMetadata.collection,
2126
+ maxSelect: relationMetadata.maxSelect,
2127
+ minSelect: relationMetadata.minSelect,
2128
+ cascadeDelete: relationMetadata.cascadeDelete
2129
+ };
2130
+ fieldDef.options = void 0;
2131
+ } else if (isRelationField(fieldName, zodType)) {
2071
2132
  fieldDef.type = "relation";
2072
2133
  const targetCollection = resolveTargetCollection(fieldName);
2073
2134
  const maxSelect = getMaxSelect(fieldName, zodType);
@@ -2079,6 +2140,13 @@ function buildFieldDefinition(fieldName, zodType) {
2079
2140
  cascadeDelete: false
2080
2141
  // Default to false, can be configured later
2081
2142
  };
2143
+ if (fieldDef.options) {
2144
+ const { min, max, pattern, ...relationSafeOptions } = fieldDef.options;
2145
+ console.log("min", min);
2146
+ console.log("max", max);
2147
+ console.log("pattern", pattern);
2148
+ fieldDef.options = Object.keys(relationSafeOptions).length > 0 ? relationSafeOptions : void 0;
2149
+ }
2082
2150
  }
2083
2151
  return fieldDef;
2084
2152
  }
@@ -2131,11 +2199,12 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
2131
2199
  fields,
2132
2200
  indexes,
2133
2201
  rules: {
2134
- listRule: null,
2135
- viewRule: null,
2136
- createRule: null,
2137
- updateRule: null,
2138
- deleteRule: null
2202
+ listRule: permissions?.listRule ?? null,
2203
+ viewRule: permissions?.viewRule ?? null,
2204
+ createRule: permissions?.createRule ?? null,
2205
+ updateRule: permissions?.updateRule ?? null,
2206
+ deleteRule: permissions?.deleteRule ?? null,
2207
+ manageRule: permissions?.manageRule ?? null
2139
2208
  },
2140
2209
  permissions
2141
2210
  };
@@ -2159,7 +2228,12 @@ async function buildSchemaDefinition(config) {
2159
2228
  if (normalizedConfig.pathTransformer) {
2160
2229
  importPath = normalizedConfig.pathTransformer(filePath);
2161
2230
  } else if (mergedConfig.useCompiledFiles) {
2162
- importPath = filePath.replace(/\/src\//, "/dist/");
2231
+ const distPath = filePath.replace(/\/src\//, "/dist/");
2232
+ if (fs3.existsSync(`${distPath}.js`) || fs3.existsSync(`${distPath}.mjs`)) {
2233
+ importPath = distPath;
2234
+ } else {
2235
+ importPath = filePath;
2236
+ }
2163
2237
  }
2164
2238
  const module = await importSchemaModule(importPath, normalizedConfig);
2165
2239
  const schemas = extractSchemaDefinitions(module, mergedConfig.schemaPatterns);
@@ -2211,7 +2285,359 @@ var SchemaAnalyzer = class {
2211
2285
  return convertZodSchemaToCollectionSchema(name, schema);
2212
2286
  }
2213
2287
  };
2288
+
2289
+ // src/migration/pocketbase-converter.ts
2214
2290
  var SNAPSHOT_VERSION = "1.0.0";
2291
+ function resolveCollectionIdToName(collectionId) {
2292
+ if (collectionId === "_pb_users_auth_") {
2293
+ return "Users";
2294
+ }
2295
+ const nameMatch = collectionId.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
2296
+ if (nameMatch) {
2297
+ return nameMatch[1];
2298
+ }
2299
+ return collectionId;
2300
+ }
2301
+ function convertPocketBaseCollection(pbCollection) {
2302
+ const fields = [];
2303
+ const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
2304
+ const authSystemFieldNames = ["email", "emailVisibility", "verified", "password", "tokenKey"];
2305
+ if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
2306
+ for (const pbField of pbCollection.fields) {
2307
+ if (pbField.system || systemFieldNames.includes(pbField.name)) {
2308
+ continue;
2309
+ }
2310
+ if (pbCollection.type === "auth" && authSystemFieldNames.includes(pbField.name)) {
2311
+ continue;
2312
+ }
2313
+ const field = {
2314
+ name: pbField.name,
2315
+ type: pbField.type,
2316
+ required: pbField.required || false
2317
+ };
2318
+ field.options = pbField.options ? { ...pbField.options } : {};
2319
+ if (pbField.type === "select") {
2320
+ if (pbField.values && Array.isArray(pbField.values)) {
2321
+ field.options.values = pbField.values;
2322
+ } else if (pbField.options?.values && Array.isArray(pbField.options.values)) {
2323
+ field.options.values = pbField.options.values;
2324
+ }
2325
+ }
2326
+ if (pbField.type === "relation") {
2327
+ const collectionId = pbField.collectionId || pbField.options?.collectionId || "";
2328
+ const collectionName = resolveCollectionIdToName(collectionId);
2329
+ field.relation = {
2330
+ collection: collectionName,
2331
+ cascadeDelete: pbField.cascadeDelete ?? pbField.options?.cascadeDelete ?? false,
2332
+ maxSelect: pbField.maxSelect ?? pbField.options?.maxSelect,
2333
+ minSelect: pbField.minSelect ?? pbField.options?.minSelect
2334
+ };
2335
+ }
2336
+ const hasOnlyValues = Object.keys(field.options).length === 1 && field.options.values !== void 0;
2337
+ if (Object.keys(field.options).length === 0) {
2338
+ delete field.options;
2339
+ } else if (pbField.type === "select" && hasOnlyValues) ;
2340
+ fields.push(field);
2341
+ }
2342
+ }
2343
+ const schema = {
2344
+ name: pbCollection.name,
2345
+ type: pbCollection.type || "base",
2346
+ fields
2347
+ };
2348
+ if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
2349
+ schema.indexes = pbCollection.indexes;
2350
+ }
2351
+ const rules = {};
2352
+ if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
2353
+ if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
2354
+ if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
2355
+ if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
2356
+ if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
2357
+ if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
2358
+ if (Object.keys(rules).length > 0) {
2359
+ schema.rules = rules;
2360
+ schema.permissions = { ...rules };
2361
+ }
2362
+ return schema;
2363
+ }
2364
+ function convertPocketBaseMigration(migrationContent) {
2365
+ try {
2366
+ const snapshotMatch = migrationContent.match(/const\s+snapshot\s*=\s*(\[[\s\S]*?\]);/);
2367
+ if (!snapshotMatch) {
2368
+ throw new Error("Could not find snapshot array in migration file");
2369
+ }
2370
+ const snapshotArrayStr = snapshotMatch[1];
2371
+ let snapshotArray;
2372
+ try {
2373
+ snapshotArray = new Function(`return ${snapshotArrayStr}`)();
2374
+ } catch (parseError) {
2375
+ throw new Error(`Failed to parse snapshot array: ${parseError}`);
2376
+ }
2377
+ if (!Array.isArray(snapshotArray)) {
2378
+ throw new Error("Snapshot is not an array");
2379
+ }
2380
+ const collections = /* @__PURE__ */ new Map();
2381
+ for (const pbCollection of snapshotArray) {
2382
+ if (!pbCollection.name) {
2383
+ console.warn("Skipping collection without name");
2384
+ continue;
2385
+ }
2386
+ const schema = convertPocketBaseCollection(pbCollection);
2387
+ collections.set(pbCollection.name, schema);
2388
+ }
2389
+ return {
2390
+ version: SNAPSHOT_VERSION,
2391
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2392
+ collections
2393
+ };
2394
+ } catch (error) {
2395
+ throw new SnapshotError(
2396
+ `Failed to convert PocketBase migration: ${error instanceof Error ? error.message : String(error)}`,
2397
+ void 0,
2398
+ "parse",
2399
+ error instanceof Error ? error : void 0
2400
+ );
2401
+ }
2402
+ }
2403
+
2404
+ // src/migration/migration-parser.ts
2405
+ function extractTimestampFromFilename(filename) {
2406
+ const match = filename.match(/^(\d+)_/);
2407
+ if (match) {
2408
+ return parseInt(match[1], 10);
2409
+ }
2410
+ return null;
2411
+ }
2412
+ function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
2413
+ try {
2414
+ if (!fs3.existsSync(migrationsPath)) {
2415
+ return [];
2416
+ }
2417
+ const files = fs3.readdirSync(migrationsPath);
2418
+ const migrationFiles = [];
2419
+ for (const file of files) {
2420
+ if (file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")) {
2421
+ continue;
2422
+ }
2423
+ if (!file.endsWith(".js")) {
2424
+ continue;
2425
+ }
2426
+ const timestamp = extractTimestampFromFilename(file);
2427
+ if (timestamp && timestamp > snapshotTimestamp) {
2428
+ migrationFiles.push({
2429
+ path: path5.join(migrationsPath, file),
2430
+ timestamp
2431
+ });
2432
+ }
2433
+ }
2434
+ migrationFiles.sort((a, b) => a.timestamp - b.timestamp);
2435
+ return migrationFiles.map((f) => f.path);
2436
+ } catch (error) {
2437
+ console.warn(`Error finding migrations after snapshot: ${error}`);
2438
+ return [];
2439
+ }
2440
+ }
2441
+ function parseMigrationOperationsFromContent(content) {
2442
+ const collectionsToCreate = [];
2443
+ const collectionsToDelete = [];
2444
+ try {
2445
+ let searchIndex = 0;
2446
+ while (true) {
2447
+ const collectionStart = content.indexOf("new Collection(", searchIndex);
2448
+ if (collectionStart === -1) {
2449
+ break;
2450
+ }
2451
+ const openParen = collectionStart + "new Collection(".length;
2452
+ let braceCount = 0;
2453
+ let parenCount = 1;
2454
+ let inString = false;
2455
+ let stringChar = null;
2456
+ let i = openParen;
2457
+ while (i < content.length && /\s/.test(content[i])) {
2458
+ i++;
2459
+ }
2460
+ if (content[i] !== "{") {
2461
+ searchIndex = i + 1;
2462
+ continue;
2463
+ }
2464
+ const objectStart = i;
2465
+ braceCount = 1;
2466
+ i++;
2467
+ while (i < content.length && (braceCount > 0 || parenCount > 0)) {
2468
+ const char = content[i];
2469
+ const prevChar = i > 0 ? content[i - 1] : "";
2470
+ if (!inString && (char === '"' || char === "'")) {
2471
+ inString = true;
2472
+ stringChar = char;
2473
+ } else if (inString && char === stringChar && prevChar !== "\\") {
2474
+ inString = false;
2475
+ stringChar = null;
2476
+ }
2477
+ if (!inString) {
2478
+ if (char === "{") braceCount++;
2479
+ if (char === "}") braceCount--;
2480
+ if (char === "(") parenCount++;
2481
+ if (char === ")") parenCount--;
2482
+ }
2483
+ i++;
2484
+ }
2485
+ if (braceCount === 0 && parenCount === 0) {
2486
+ const objectContent = content.substring(objectStart, i - 1);
2487
+ try {
2488
+ const collectionObj = new Function(`return ${objectContent}`)();
2489
+ if (collectionObj && collectionObj.name) {
2490
+ const schema = convertPocketBaseCollection(collectionObj);
2491
+ collectionsToCreate.push(schema);
2492
+ }
2493
+ } catch (error) {
2494
+ console.warn(`Failed to parse collection definition: ${error}`);
2495
+ }
2496
+ }
2497
+ searchIndex = i;
2498
+ }
2499
+ const deleteMatches = content.matchAll(
2500
+ /app\.delete\s*\(\s*(?:collection_\w+|app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\))\s*\)/g
2501
+ );
2502
+ for (const match of deleteMatches) {
2503
+ if (match[1]) {
2504
+ collectionsToDelete.push(match[1]);
2505
+ } else {
2506
+ const varNameMatch = match[0].match(/collection_(\w+)/);
2507
+ if (varNameMatch) {
2508
+ const varName = `collection_${varNameMatch[1]}`;
2509
+ const deleteIndex = content.indexOf(match[0]);
2510
+ const beforeDelete = content.substring(0, deleteIndex);
2511
+ const varDefMatch = beforeDelete.match(
2512
+ new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`, "g")
2513
+ );
2514
+ if (varDefMatch && varDefMatch.length > 0) {
2515
+ const collectionDefMatch = beforeDelete.match(
2516
+ new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`)
2517
+ );
2518
+ if (collectionDefMatch) {
2519
+ try {
2520
+ const collectionDefStr = collectionDefMatch[1];
2521
+ const collectionObj = new Function(`return ${collectionDefStr}`)();
2522
+ if (collectionObj && collectionObj.name) {
2523
+ collectionsToDelete.push(collectionObj.name);
2524
+ }
2525
+ } catch {
2526
+ }
2527
+ }
2528
+ }
2529
+ }
2530
+ }
2531
+ }
2532
+ const findAndDeleteMatches = content.matchAll(
2533
+ /app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)[\s\S]*?app\.delete/g
2534
+ );
2535
+ for (const match of findAndDeleteMatches) {
2536
+ collectionsToDelete.push(match[1]);
2537
+ }
2538
+ } catch (error) {
2539
+ console.warn(`Failed to parse migration operations from content: ${error}`);
2540
+ }
2541
+ return { collectionsToCreate, collectionsToDelete };
2542
+ }
2543
+ function parseMigrationOperations(migrationContent) {
2544
+ try {
2545
+ const migrateMatch = migrationContent.match(/migrate\s*\(\s*/);
2546
+ if (!migrateMatch) {
2547
+ return parseMigrationOperationsFromContent(migrationContent);
2548
+ }
2549
+ const startIndex = migrateMatch.index + migrateMatch[0].length;
2550
+ let i = startIndex;
2551
+ let parenCount = 0;
2552
+ let foundFirstParen = false;
2553
+ while (i < migrationContent.length) {
2554
+ const char = migrationContent[i];
2555
+ if (char === "(") {
2556
+ parenCount++;
2557
+ foundFirstParen = true;
2558
+ i++;
2559
+ break;
2560
+ }
2561
+ i++;
2562
+ }
2563
+ if (!foundFirstParen) {
2564
+ return parseMigrationOperationsFromContent(migrationContent);
2565
+ }
2566
+ let inString = false;
2567
+ let stringChar = null;
2568
+ let foundBrace = false;
2569
+ let braceStart = -1;
2570
+ while (i < migrationContent.length && !foundBrace) {
2571
+ const char = migrationContent[i];
2572
+ const prevChar = i > 0 ? migrationContent[i - 1] : "";
2573
+ if (!inString && (char === '"' || char === "'")) {
2574
+ inString = true;
2575
+ stringChar = char;
2576
+ } else if (inString && char === stringChar && prevChar !== "\\") {
2577
+ inString = false;
2578
+ stringChar = null;
2579
+ }
2580
+ if (!inString) {
2581
+ if (char === "(") parenCount++;
2582
+ if (char === ")") {
2583
+ parenCount--;
2584
+ if (parenCount === 0) {
2585
+ i++;
2586
+ while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
2587
+ i++;
2588
+ }
2589
+ if (i < migrationContent.length - 1 && migrationContent[i] === "=" && migrationContent[i + 1] === ">") {
2590
+ i += 2;
2591
+ while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
2592
+ i++;
2593
+ }
2594
+ if (i < migrationContent.length && migrationContent[i] === "{") {
2595
+ foundBrace = true;
2596
+ braceStart = i + 1;
2597
+ break;
2598
+ }
2599
+ }
2600
+ }
2601
+ }
2602
+ }
2603
+ i++;
2604
+ }
2605
+ if (!foundBrace || braceStart === -1) {
2606
+ return parseMigrationOperationsFromContent(migrationContent);
2607
+ }
2608
+ let braceCount = 1;
2609
+ i = braceStart;
2610
+ inString = false;
2611
+ stringChar = null;
2612
+ while (i < migrationContent.length && braceCount > 0) {
2613
+ const char = migrationContent[i];
2614
+ const prevChar = i > 0 ? migrationContent[i - 1] : "";
2615
+ if (!inString && (char === '"' || char === "'")) {
2616
+ inString = true;
2617
+ stringChar = char;
2618
+ } else if (inString && char === stringChar && prevChar !== "\\") {
2619
+ inString = false;
2620
+ stringChar = null;
2621
+ }
2622
+ if (!inString) {
2623
+ if (char === "{") braceCount++;
2624
+ if (char === "}") braceCount--;
2625
+ }
2626
+ i++;
2627
+ }
2628
+ if (braceCount === 0) {
2629
+ const upMigrationContent = migrationContent.substring(braceStart, i - 1);
2630
+ return parseMigrationOperationsFromContent(upMigrationContent);
2631
+ }
2632
+ return parseMigrationOperationsFromContent(migrationContent);
2633
+ } catch (error) {
2634
+ console.warn(`Failed to parse migration operations: ${error}`);
2635
+ return { collectionsToCreate: [], collectionsToDelete: [] };
2636
+ }
2637
+ }
2638
+
2639
+ // src/migration/snapshot.ts
2640
+ var SNAPSHOT_VERSION2 = "1.0.0";
2215
2641
  var DEFAULT_SNAPSHOT_FILENAME = ".migration-snapshot.json";
2216
2642
  var SNAPSHOT_MIGRATIONS = [
2217
2643
  // Add migrations here as the format evolves
@@ -2226,7 +2652,7 @@ var DEFAULT_CONFIG2 = {
2226
2652
  snapshotPath: DEFAULT_SNAPSHOT_FILENAME,
2227
2653
  workspaceRoot: process.cwd(),
2228
2654
  autoMigrate: true,
2229
- version: SNAPSHOT_VERSION
2655
+ version: SNAPSHOT_VERSION2
2230
2656
  };
2231
2657
  function mergeConfig2(config = {}) {
2232
2658
  return {
@@ -2238,15 +2664,15 @@ function getSnapshotPath(config = {}) {
2238
2664
  const mergedConfig = mergeConfig2(config);
2239
2665
  const workspaceRoot = mergedConfig.workspaceRoot;
2240
2666
  const snapshotFilename = mergedConfig.snapshotPath;
2241
- if (path4.isAbsolute(snapshotFilename)) {
2667
+ if (path5.isAbsolute(snapshotFilename)) {
2242
2668
  return snapshotFilename;
2243
2669
  }
2244
- return path4.join(workspaceRoot, snapshotFilename);
2670
+ return path5.join(workspaceRoot, snapshotFilename);
2245
2671
  }
2246
2672
  function snapshotExists(config = {}) {
2247
2673
  try {
2248
2674
  const snapshotPath = getSnapshotPath(config);
2249
- return fs2.existsSync(snapshotPath);
2675
+ return fs3.existsSync(snapshotPath);
2250
2676
  } catch {
2251
2677
  return false;
2252
2678
  }
@@ -2305,13 +2731,13 @@ function addSnapshotMetadata(schema, config) {
2305
2731
  function saveSnapshot(schema, config = {}) {
2306
2732
  const snapshotPath = getSnapshotPath(config);
2307
2733
  try {
2308
- const snapshotDir = path4.dirname(snapshotPath);
2309
- if (!fs2.existsSync(snapshotDir)) {
2310
- fs2.mkdirSync(snapshotDir, { recursive: true });
2734
+ const snapshotDir = path5.dirname(snapshotPath);
2735
+ if (!fs3.existsSync(snapshotDir)) {
2736
+ fs3.mkdirSync(snapshotDir, { recursive: true });
2311
2737
  }
2312
2738
  const snapshotData = addSnapshotMetadata(schema, config);
2313
2739
  const jsonContent = JSON.stringify(snapshotData, null, 2);
2314
- fs2.writeFileSync(snapshotPath, jsonContent, "utf-8");
2740
+ fs3.writeFileSync(snapshotPath, jsonContent, "utf-8");
2315
2741
  } catch (error) {
2316
2742
  handleFileSystemError(error, "write", snapshotPath);
2317
2743
  }
@@ -2406,7 +2832,7 @@ function deserializeSnapshot(data) {
2406
2832
  function loadSnapshot(config = {}) {
2407
2833
  const snapshotPath = getSnapshotPath(config);
2408
2834
  try {
2409
- const jsonContent = fs2.readFileSync(snapshotPath, "utf-8");
2835
+ const jsonContent = fs3.readFileSync(snapshotPath, "utf-8");
2410
2836
  const data = parseAndValidateSnapshot(jsonContent, snapshotPath);
2411
2837
  const migratedData = migrateSnapshotFormat(data, config);
2412
2838
  return deserializeSnapshot(migratedData);
@@ -2441,10 +2867,10 @@ function mergeSnapshots(baseSnapshot, customSnapshot) {
2441
2867
  }
2442
2868
  function findLatestSnapshot(migrationsPath) {
2443
2869
  try {
2444
- if (!fs2.existsSync(migrationsPath)) {
2870
+ if (!fs3.existsSync(migrationsPath)) {
2445
2871
  return null;
2446
2872
  }
2447
- const files = fs2.readdirSync(migrationsPath);
2873
+ const files = fs3.readdirSync(migrationsPath);
2448
2874
  const snapshotFiles = files.filter(
2449
2875
  (file) => file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")
2450
2876
  );
@@ -2456,20 +2882,74 @@ function findLatestSnapshot(migrationsPath) {
2456
2882
  if (!latestSnapshot) {
2457
2883
  return null;
2458
2884
  }
2459
- return path4.join(migrationsPath, latestSnapshot);
2885
+ return path5.join(migrationsPath, latestSnapshot);
2460
2886
  } catch (error) {
2461
2887
  console.warn(`Error finding latest snapshot: ${error}`);
2462
2888
  return null;
2463
2889
  }
2464
2890
  }
2891
+ function applyMigrationOperations(snapshot, operations) {
2892
+ const updatedCollections = new Map(snapshot.collections);
2893
+ for (const collectionName of operations.collectionsToDelete) {
2894
+ updatedCollections.delete(collectionName);
2895
+ }
2896
+ for (const collection of operations.collectionsToCreate) {
2897
+ updatedCollections.set(collection.name, collection);
2898
+ }
2899
+ return {
2900
+ ...snapshot,
2901
+ collections: updatedCollections
2902
+ };
2903
+ }
2904
+ function loadSnapshotWithMigrations(config = {}) {
2905
+ const migrationsPath = config.migrationsPath;
2906
+ if (!migrationsPath) {
2907
+ return null;
2908
+ }
2909
+ if (fs3.existsSync(migrationsPath) && fs3.statSync(migrationsPath).isFile()) {
2910
+ try {
2911
+ const migrationContent = fs3.readFileSync(migrationsPath, "utf-8");
2912
+ return convertPocketBaseMigration(migrationContent);
2913
+ } catch (error) {
2914
+ console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
2915
+ return null;
2916
+ }
2917
+ }
2918
+ const latestSnapshotPath = findLatestSnapshot(migrationsPath);
2919
+ if (!latestSnapshotPath) {
2920
+ return null;
2921
+ }
2922
+ try {
2923
+ const migrationContent = fs3.readFileSync(latestSnapshotPath, "utf-8");
2924
+ let snapshot = convertPocketBaseMigration(migrationContent);
2925
+ const snapshotFilename = path5.basename(latestSnapshotPath);
2926
+ const snapshotTimestamp = extractTimestampFromFilename(snapshotFilename);
2927
+ if (snapshotTimestamp) {
2928
+ const migrationFiles = findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp);
2929
+ for (const migrationFile of migrationFiles) {
2930
+ try {
2931
+ const migrationContent2 = fs3.readFileSync(migrationFile, "utf-8");
2932
+ const operations = parseMigrationOperations(migrationContent2);
2933
+ snapshot = applyMigrationOperations(snapshot, operations);
2934
+ } catch (error) {
2935
+ console.warn(`Failed to apply migration ${migrationFile}: ${error}`);
2936
+ }
2937
+ }
2938
+ }
2939
+ return snapshot;
2940
+ } catch (error) {
2941
+ console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
2942
+ return null;
2943
+ }
2944
+ }
2465
2945
  function loadSnapshotIfExists(config = {}) {
2466
2946
  const migrationsPath = config.migrationsPath;
2467
2947
  if (!migrationsPath) {
2468
2948
  return null;
2469
2949
  }
2470
- if (fs2.existsSync(migrationsPath) && fs2.statSync(migrationsPath).isFile()) {
2950
+ if (fs3.existsSync(migrationsPath) && fs3.statSync(migrationsPath).isFile()) {
2471
2951
  try {
2472
- const migrationContent = fs2.readFileSync(migrationsPath, "utf-8");
2952
+ const migrationContent = fs3.readFileSync(migrationsPath, "utf-8");
2473
2953
  return convertPocketBaseMigration(migrationContent);
2474
2954
  } catch (error) {
2475
2955
  console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
@@ -2479,7 +2959,7 @@ function loadSnapshotIfExists(config = {}) {
2479
2959
  const latestSnapshotPath = findLatestSnapshot(migrationsPath);
2480
2960
  if (latestSnapshotPath) {
2481
2961
  try {
2482
- const migrationContent = fs2.readFileSync(latestSnapshotPath, "utf-8");
2962
+ const migrationContent = fs3.readFileSync(latestSnapshotPath, "utf-8");
2483
2963
  return convertPocketBaseMigration(migrationContent);
2484
2964
  } catch (error) {
2485
2965
  console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
@@ -2488,99 +2968,9 @@ function loadSnapshotIfExists(config = {}) {
2488
2968
  }
2489
2969
  return null;
2490
2970
  }
2491
- function convertPocketBaseCollection(pbCollection) {
2492
- const fields = [];
2493
- const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
2494
- const authSystemFieldNames = ["email", "emailVisibility", "verified", "password", "tokenKey"];
2495
- if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
2496
- for (const pbField of pbCollection.fields) {
2497
- if (pbField.system || systemFieldNames.includes(pbField.name)) {
2498
- continue;
2499
- }
2500
- if (pbCollection.type === "auth" && authSystemFieldNames.includes(pbField.name)) {
2501
- continue;
2502
- }
2503
- const field = {
2504
- name: pbField.name,
2505
- type: pbField.type,
2506
- required: pbField.required || false
2507
- };
2508
- if (pbField.options) {
2509
- field.options = pbField.options;
2510
- }
2511
- if (pbField.type === "relation") {
2512
- field.relation = {
2513
- collection: pbField.options?.collectionId || "",
2514
- cascadeDelete: pbField.options?.cascadeDelete || false,
2515
- maxSelect: pbField.options?.maxSelect,
2516
- minSelect: pbField.options?.minSelect
2517
- };
2518
- }
2519
- fields.push(field);
2520
- }
2521
- }
2522
- const schema = {
2523
- name: pbCollection.name,
2524
- type: pbCollection.type || "base",
2525
- fields
2526
- };
2527
- if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
2528
- schema.indexes = pbCollection.indexes;
2529
- }
2530
- const rules = {};
2531
- if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
2532
- if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
2533
- if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
2534
- if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
2535
- if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
2536
- if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
2537
- if (Object.keys(rules).length > 0) {
2538
- schema.rules = rules;
2539
- }
2540
- return schema;
2541
- }
2542
- function convertPocketBaseMigration(migrationContent) {
2543
- try {
2544
- const snapshotMatch = migrationContent.match(/const\s+snapshot\s*=\s*(\[[\s\S]*?\]);/);
2545
- if (!snapshotMatch) {
2546
- throw new Error("Could not find snapshot array in migration file");
2547
- }
2548
- const snapshotArrayStr = snapshotMatch[1];
2549
- let snapshotArray;
2550
- try {
2551
- snapshotArray = new Function(`return ${snapshotArrayStr}`)();
2552
- } catch (parseError) {
2553
- throw new Error(`Failed to parse snapshot array: ${parseError}`);
2554
- }
2555
- if (!Array.isArray(snapshotArray)) {
2556
- throw new Error("Snapshot is not an array");
2557
- }
2558
- const collections = /* @__PURE__ */ new Map();
2559
- for (const pbCollection of snapshotArray) {
2560
- if (!pbCollection.name) {
2561
- console.warn("Skipping collection without name");
2562
- continue;
2563
- }
2564
- const schema = convertPocketBaseCollection(pbCollection);
2565
- collections.set(pbCollection.name, schema);
2566
- }
2567
- return {
2568
- version: SNAPSHOT_VERSION,
2569
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2570
- collections
2571
- };
2572
- } catch (error) {
2573
- throw new SnapshotError(
2574
- `Failed to convert PocketBase migration: ${error instanceof Error ? error.message : String(error)}`,
2575
- void 0,
2576
- "parse",
2577
- error instanceof Error ? error : void 0
2578
- );
2579
- }
2580
- }
2581
2971
  function loadBaseMigration(migrationPath) {
2582
2972
  try {
2583
- if (!fs2.existsSync(migrationPath)) {
2973
+ if (!fs3.existsSync(migrationPath)) {
2584
2974
  throw new SnapshotError(
2585
2975
  `Base migration file not found: ${migrationPath}
2586
2976
 
@@ -2591,7 +2981,7 @@ If the file exists in a different location, update the configuration.`,
2591
2981
  "read"
2592
2982
  );
2593
2983
  }
2594
- const migrationContent = fs2.readFileSync(migrationPath, "utf-8");
2984
+ const migrationContent = fs3.readFileSync(migrationPath, "utf-8");
2595
2985
  const snapshot = convertPocketBaseMigration(migrationContent);
2596
2986
  return snapshot;
2597
2987
  } catch (error) {
@@ -2627,14 +3017,14 @@ Please ensure PocketBase is properly set up by running 'yarn setup'.`,
2627
3017
  }
2628
3018
  }
2629
3019
  function getSnapshotVersion() {
2630
- return SNAPSHOT_VERSION;
3020
+ return SNAPSHOT_VERSION2;
2631
3021
  }
2632
3022
  function validateSnapshot(snapshot) {
2633
3023
  const issues = [];
2634
3024
  if (!snapshot.version) {
2635
3025
  issues.push("Missing version field");
2636
- } else if (compareVersions(snapshot.version, SNAPSHOT_VERSION) > 0) {
2637
- issues.push(`Snapshot version ${snapshot.version} is newer than supported version ${SNAPSHOT_VERSION}`);
3026
+ } else if (compareVersions(snapshot.version, SNAPSHOT_VERSION2) > 0) {
3027
+ issues.push(`Snapshot version ${snapshot.version} is newer than supported version ${SNAPSHOT_VERSION2}`);
2638
3028
  }
2639
3029
  if (!snapshot.timestamp) {
2640
3030
  issues.push("Missing timestamp field");
@@ -2853,6 +3243,9 @@ function compareFieldOptions(currentField, previousField) {
2853
3243
  for (const key of allKeys) {
2854
3244
  const currentValue = currentOptions[key];
2855
3245
  const previousValue = previousOptions[key];
3246
+ if (currentValue === void 0 && previousValue === void 0) {
3247
+ continue;
3248
+ }
2856
3249
  if (!areValuesEqual(currentValue, previousValue)) {
2857
3250
  changes.push({
2858
3251
  property: `options.${key}`,
@@ -2873,11 +3266,26 @@ function compareRelationConfigurations(currentField, previousField) {
2873
3266
  if (!currentRelation || !previousRelation) {
2874
3267
  return changes;
2875
3268
  }
2876
- if (currentRelation.collection !== previousRelation.collection) {
3269
+ const normalizeCollection = (collection) => {
3270
+ if (!collection) return collection;
3271
+ if (collection === "_pb_users_auth_") {
3272
+ return "Users";
3273
+ }
3274
+ const nameMatch = collection.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
3275
+ if (nameMatch) {
3276
+ return nameMatch[1];
3277
+ }
3278
+ return collection;
3279
+ };
3280
+ const normalizedCurrent = normalizeCollection(currentRelation.collection);
3281
+ const normalizedPrevious = normalizeCollection(previousRelation.collection);
3282
+ if (normalizedCurrent !== normalizedPrevious) {
2877
3283
  changes.push({
2878
3284
  property: "relation.collection",
2879
- oldValue: previousRelation.collection,
2880
- newValue: currentRelation.collection
3285
+ oldValue: normalizedPrevious,
3286
+ // Use normalized value for clarity
3287
+ newValue: normalizedCurrent
3288
+ // Use normalized value for clarity
2881
3289
  });
2882
3290
  }
2883
3291
  if (currentRelation.cascadeDelete !== previousRelation.cascadeDelete) {
@@ -3231,10 +3639,8 @@ var DiffEngine = class {
3231
3639
  var DEFAULT_TEMPLATE = `/// <reference path="{{TYPES_PATH}}" />
3232
3640
  migrate((app) => {
3233
3641
  {{UP_CODE}}
3234
- return true;
3235
3642
  }, (app) => {
3236
3643
  {{DOWN_CODE}}
3237
- return true;
3238
3644
  });
3239
3645
  `;
3240
3646
  var DEFAULT_CONFIG4 = {
@@ -3252,10 +3658,10 @@ function mergeConfig4(config) {
3252
3658
  }
3253
3659
  function resolveMigrationDir(config) {
3254
3660
  const workspaceRoot = config.workspaceRoot || process.cwd();
3255
- if (path4.isAbsolute(config.migrationDir)) {
3661
+ if (path5.isAbsolute(config.migrationDir)) {
3256
3662
  return config.migrationDir;
3257
3663
  }
3258
- return path4.join(workspaceRoot, config.migrationDir);
3664
+ return path5.join(workspaceRoot, config.migrationDir);
3259
3665
  }
3260
3666
  function generateTimestamp(config) {
3261
3667
  if (config?.timestampGenerator) {
@@ -3313,9 +3719,9 @@ function createMigrationFileStructure(upCode, downCode, config) {
3313
3719
  }
3314
3720
  function writeMigrationFile(migrationDir, filename, content) {
3315
3721
  try {
3316
- if (!fs2.existsSync(migrationDir)) {
3722
+ if (!fs3.existsSync(migrationDir)) {
3317
3723
  try {
3318
- fs2.mkdirSync(migrationDir, { recursive: true });
3724
+ fs3.mkdirSync(migrationDir, { recursive: true });
3319
3725
  } catch (error) {
3320
3726
  const fsError = error;
3321
3727
  if (fsError.code === "EACCES" || fsError.code === "EPERM") {
@@ -3336,15 +3742,15 @@ function writeMigrationFile(migrationDir, filename, content) {
3336
3742
  );
3337
3743
  }
3338
3744
  }
3339
- const filePath = path4.join(migrationDir, filename);
3340
- fs2.writeFileSync(filePath, content, "utf-8");
3745
+ const filePath = path5.join(migrationDir, filename);
3746
+ fs3.writeFileSync(filePath, content, "utf-8");
3341
3747
  return filePath;
3342
3748
  } catch (error) {
3343
3749
  if (error instanceof FileSystemError) {
3344
3750
  throw error;
3345
3751
  }
3346
3752
  const fsError = error;
3347
- const filePath = path4.join(migrationDir, filename);
3753
+ const filePath = path5.join(migrationDir, filename);
3348
3754
  if (fsError.code === "EACCES" || fsError.code === "EPERM") {
3349
3755
  throw new FileSystemError(
3350
3756
  `Permission denied writing migration file. Check file and directory permissions.`,
@@ -3399,7 +3805,8 @@ function generateFieldDefinitionObject(field) {
3399
3805
  }
3400
3806
  }
3401
3807
  if (field.relation) {
3402
- const collectionIdPlaceholder = field.relation.collection === "Users" ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3808
+ const isUsersCollection = field.relation.collection.toLowerCase() === "users";
3809
+ const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3403
3810
  parts.push(` collectionId: ${collectionIdPlaceholder}`);
3404
3811
  if (field.relation.maxSelect !== void 0) {
3405
3812
  parts.push(` maxSelect: ${field.relation.maxSelect}`);
@@ -3483,7 +3890,7 @@ function generateIndexesArray(indexes) {
3483
3890
  ${indexStrings.join(",\n ")},
3484
3891
  ]`;
3485
3892
  }
3486
- function generateCollectionCreation(collection, varName = "collection") {
3893
+ function generateCollectionCreation(collection, varName = "collection", isLast = false) {
3487
3894
  const lines = [];
3488
3895
  lines.push(` const ${varName} = new Collection({`);
3489
3896
  lines.push(` name: "${collection.name}",`);
@@ -3499,7 +3906,7 @@ function generateCollectionCreation(collection, varName = "collection") {
3499
3906
  lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
3500
3907
  lines.push(` });`);
3501
3908
  lines.push(``);
3502
- lines.push(` app.save(${varName});`);
3909
+ lines.push(isLast ? ` return app.save(${varName});` : ` app.save(${varName});`);
3503
3910
  return lines.join("\n");
3504
3911
  }
3505
3912
  function getFieldConstructorName(fieldType) {
@@ -3530,7 +3937,8 @@ function generateFieldConstructorOptions(field) {
3530
3937
  }
3531
3938
  }
3532
3939
  if (field.relation && field.type === "relation") {
3533
- const collectionIdPlaceholder = field.relation.collection === "Users" ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3940
+ const isUsersCollection = field.relation.collection.toLowerCase() === "users";
3941
+ const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3534
3942
  parts.push(` collectionId: ${collectionIdPlaceholder}`);
3535
3943
  if (field.relation.maxSelect !== void 0) {
3536
3944
  parts.push(` maxSelect: ${field.relation.maxSelect}`);
@@ -3544,7 +3952,7 @@ function generateFieldConstructorOptions(field) {
3544
3952
  }
3545
3953
  return parts.join(",\n");
3546
3954
  }
3547
- function generateFieldAddition(collectionName, field, varName) {
3955
+ function generateFieldAddition(collectionName, field, varName, isLast = false) {
3548
3956
  const lines = [];
3549
3957
  const constructorName = getFieldConstructorName(field.type);
3550
3958
  const collectionVar = varName || `collection_${collectionName}_${field.name}`;
@@ -3554,10 +3962,10 @@ function generateFieldAddition(collectionName, field, varName) {
3554
3962
  lines.push(generateFieldConstructorOptions(field));
3555
3963
  lines.push(` }));`);
3556
3964
  lines.push(``);
3557
- lines.push(` app.save(${collectionVar});`);
3965
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3558
3966
  return lines.join("\n");
3559
3967
  }
3560
- function generateFieldModification(collectionName, modification, varName) {
3968
+ function generateFieldModification(collectionName, modification, varName, isLast = false) {
3561
3969
  const lines = [];
3562
3970
  const collectionVar = varName || `collection_${collectionName}_${modification.fieldName}`;
3563
3971
  const fieldVar = `${collectionVar}_field`;
@@ -3571,7 +3979,8 @@ function generateFieldModification(collectionName, modification, varName) {
3571
3979
  } else if (change.property.startsWith("relation.")) {
3572
3980
  const relationKey = change.property.replace("relation.", "");
3573
3981
  if (relationKey === "collection") {
3574
- const collectionIdValue = change.newValue === "Users" ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${change.newValue}").id`;
3982
+ const isUsersCollection = String(change.newValue).toLowerCase() === "users";
3983
+ const collectionIdValue = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${change.newValue}").id`;
3575
3984
  lines.push(` ${fieldVar}.collectionId = ${collectionIdValue};`);
3576
3985
  } else {
3577
3986
  lines.push(` ${fieldVar}.${relationKey} = ${formatValue(change.newValue)};`);
@@ -3581,10 +3990,10 @@ function generateFieldModification(collectionName, modification, varName) {
3581
3990
  }
3582
3991
  }
3583
3992
  lines.push(``);
3584
- lines.push(` app.save(${collectionVar});`);
3993
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3585
3994
  return lines.join("\n");
3586
3995
  }
3587
- function generateFieldDeletion(collectionName, fieldName, varName) {
3996
+ function generateFieldDeletion(collectionName, fieldName, varName, isLast = false) {
3588
3997
  const lines = [];
3589
3998
  const collectionVar = varName || `collection_${collectionName}_${fieldName}`;
3590
3999
  const fieldVar = `${collectionVar}_field`;
@@ -3593,18 +4002,18 @@ function generateFieldDeletion(collectionName, fieldName, varName) {
3593
4002
  lines.push(``);
3594
4003
  lines.push(` ${collectionVar}.fields.remove(${fieldVar}.id);`);
3595
4004
  lines.push(``);
3596
- lines.push(` app.save(${collectionVar});`);
4005
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3597
4006
  return lines.join("\n");
3598
4007
  }
3599
- function generateIndexAddition(collectionName, index, varName) {
4008
+ function generateIndexAddition(collectionName, index, varName, isLast = false) {
3600
4009
  const lines = [];
3601
4010
  const collectionVar = varName || `collection_${collectionName}_idx`;
3602
4011
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3603
4012
  lines.push(` ${collectionVar}.indexes.push("${index}");`);
3604
- lines.push(` app.save(${collectionVar});`);
4013
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3605
4014
  return lines.join("\n");
3606
4015
  }
3607
- function generateIndexRemoval(collectionName, index, varName) {
4016
+ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
3608
4017
  const lines = [];
3609
4018
  const collectionVar = varName || `collection_${collectionName}_idx`;
3610
4019
  const indexVar = `${collectionVar}_indexToRemove`;
@@ -3613,29 +4022,29 @@ function generateIndexRemoval(collectionName, index, varName) {
3613
4022
  lines.push(` if (${indexVar} !== -1) {`);
3614
4023
  lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
3615
4024
  lines.push(` }`);
3616
- lines.push(` app.save(${collectionVar});`);
4025
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3617
4026
  return lines.join("\n");
3618
4027
  }
3619
- function generateRuleUpdate(collectionName, ruleType, newValue, varName) {
4028
+ function generateRuleUpdate(collectionName, ruleType, newValue, varName, isLast = false) {
3620
4029
  const lines = [];
3621
4030
  const collectionVar = varName || `collection_${collectionName}_${ruleType}`;
3622
4031
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3623
4032
  lines.push(` ${collectionVar}.${ruleType} = ${formatValue(newValue)};`);
3624
- lines.push(` app.save(${collectionVar});`);
4033
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3625
4034
  return lines.join("\n");
3626
4035
  }
3627
- function generatePermissionUpdate(collectionName, ruleType, newValue, varName) {
4036
+ function generatePermissionUpdate(collectionName, ruleType, newValue, varName, isLast = false) {
3628
4037
  const lines = [];
3629
4038
  const collectionVar = varName || `collection_${collectionName}_${ruleType}`;
3630
4039
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3631
4040
  lines.push(` ${collectionVar}.${ruleType} = ${formatValue(newValue)};`);
3632
- lines.push(` app.save(${collectionVar});`);
4041
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3633
4042
  return lines.join("\n");
3634
4043
  }
3635
- function generateCollectionDeletion(collectionName, varName = "collection") {
4044
+ function generateCollectionDeletion(collectionName, varName = "collection", isLast = false) {
3636
4045
  const lines = [];
3637
4046
  lines.push(` const ${varName} = app.findCollectionByNameOrId("${collectionName}");`);
3638
- lines.push(` app.delete(${varName});`);
4047
+ lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
3639
4048
  return lines.join("\n");
3640
4049
  }
3641
4050
  function generateUpMigration(diff) {
@@ -3727,7 +4136,24 @@ function generateUpMigration(diff) {
3727
4136
  lines.push(` // No changes detected`);
3728
4137
  lines.push(``);
3729
4138
  }
3730
- return lines.join("\n");
4139
+ let code = lines.join("\n");
4140
+ const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
4141
+ const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
4142
+ const saveMatches = [...code.matchAll(savePattern)];
4143
+ const deleteMatches = [...code.matchAll(deletePattern)];
4144
+ const allMatches = [
4145
+ ...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
4146
+ ...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
4147
+ ].sort((a, b) => b.index - a.index);
4148
+ if (allMatches.length > 0) {
4149
+ const lastMatch = allMatches[0];
4150
+ if (lastMatch.type === "save") {
4151
+ 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);
4152
+ } else {
4153
+ 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);
4154
+ }
4155
+ }
4156
+ return code;
3731
4157
  }
3732
4158
  function generateDownMigration(diff) {
3733
4159
  const lines = [];
@@ -3829,7 +4255,24 @@ function generateDownMigration(diff) {
3829
4255
  lines.push(` // No changes to revert`);
3830
4256
  lines.push(``);
3831
4257
  }
3832
- return lines.join("\n");
4258
+ let code = lines.join("\n");
4259
+ const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
4260
+ const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
4261
+ const saveMatches = [...code.matchAll(savePattern)];
4262
+ const deleteMatches = [...code.matchAll(deletePattern)];
4263
+ const allMatches = [
4264
+ ...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
4265
+ ...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
4266
+ ].sort((a, b) => b.index - a.index);
4267
+ if (allMatches.length > 0) {
4268
+ const lastMatch = allMatches[0];
4269
+ if (lastMatch.type === "save") {
4270
+ 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);
4271
+ } else {
4272
+ 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);
4273
+ }
4274
+ }
4275
+ return code;
3833
4276
  }
3834
4277
  function generate(diff, config) {
3835
4278
  const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
@@ -4051,8 +4494,8 @@ var DEFAULT_CONFIG5 = {
4051
4494
  };
4052
4495
  function findConfigFile(directory) {
4053
4496
  for (const fileName of CONFIG_FILE_NAMES) {
4054
- const filePath = path4.join(directory, fileName);
4055
- if (fs2.existsSync(filePath)) {
4497
+ const filePath = path5.join(directory, fileName);
4498
+ if (fs3.existsSync(filePath)) {
4056
4499
  return filePath;
4057
4500
  }
4058
4501
  }
@@ -4060,7 +4503,7 @@ function findConfigFile(directory) {
4060
4503
  }
4061
4504
  function loadJsonConfig(configPath) {
4062
4505
  try {
4063
- const content = fs2.readFileSync(configPath, "utf-8");
4506
+ const content = fs3.readFileSync(configPath, "utf-8");
4064
4507
  return JSON.parse(content);
4065
4508
  } catch (error) {
4066
4509
  if (error instanceof SyntaxError) {
@@ -4089,10 +4532,10 @@ async function loadJsConfig(configPath) {
4089
4532
  }
4090
4533
  }
4091
4534
  async function loadConfigFile(configPath) {
4092
- if (!fs2.existsSync(configPath)) {
4535
+ if (!fs3.existsSync(configPath)) {
4093
4536
  return null;
4094
4537
  }
4095
- const ext = path4.extname(configPath).toLowerCase();
4538
+ const ext = path5.extname(configPath).toLowerCase();
4096
4539
  if (ext === ".json") {
4097
4540
  return loadJsonConfig(configPath);
4098
4541
  } else if (ext === ".js" || ext === ".mjs") {
@@ -4159,10 +4602,10 @@ function validateConfig(config, configPath) {
4159
4602
  }
4160
4603
  const cwd = process.cwd();
4161
4604
  const possiblePaths = [
4162
- path4.resolve(cwd, config.schema.directory),
4163
- path4.resolve(cwd, "shared", config.schema.directory)
4605
+ path5.resolve(cwd, config.schema.directory),
4606
+ path5.resolve(cwd, "shared", config.schema.directory)
4164
4607
  ];
4165
- const schemaDir = possiblePaths.find((p) => fs2.existsSync(p));
4608
+ const schemaDir = possiblePaths.find((p) => fs3.existsSync(p));
4166
4609
  if (!schemaDir) {
4167
4610
  throw new ConfigurationError(`Schema directory not found. Tried: ${possiblePaths.join(", ")}`, configPath, [
4168
4611
  "schema.directory"
@@ -4174,15 +4617,15 @@ async function loadConfig(options = {}) {
4174
4617
  let configFilePath;
4175
4618
  const cwd = process.cwd();
4176
4619
  if (options.config) {
4177
- const explicitPath = path4.resolve(cwd, options.config);
4178
- if (!fs2.existsSync(explicitPath)) {
4620
+ const explicitPath = path5.resolve(cwd, options.config);
4621
+ if (!fs3.existsSync(explicitPath)) {
4179
4622
  throw new ConfigurationError(`Configuration file not found: ${explicitPath}`, explicitPath);
4180
4623
  }
4181
4624
  configFilePath = explicitPath;
4182
4625
  } else {
4183
- const searchDirs = [cwd, path4.join(cwd, "shared")];
4626
+ const searchDirs = [cwd, path5.join(cwd, "shared")];
4184
4627
  for (const dir of searchDirs) {
4185
- if (fs2.existsSync(dir)) {
4628
+ if (fs3.existsSync(dir)) {
4186
4629
  const found = findConfigFile(dir);
4187
4630
  if (found) {
4188
4631
  configFilePath = found;
@@ -4211,18 +4654,18 @@ async function loadConfig(options = {}) {
4211
4654
  function getSchemaDirectory(config) {
4212
4655
  const cwd = process.cwd();
4213
4656
  const possiblePaths = [
4214
- path4.resolve(cwd, config.schema.directory),
4215
- path4.resolve(cwd, "shared", config.schema.directory)
4657
+ path5.resolve(cwd, config.schema.directory),
4658
+ path5.resolve(cwd, "shared", config.schema.directory)
4216
4659
  ];
4217
- return possiblePaths.find((p) => fs2.existsSync(p)) || possiblePaths[0];
4660
+ return possiblePaths.find((p) => fs3.existsSync(p)) || possiblePaths[0];
4218
4661
  }
4219
4662
  function getMigrationsDirectory(config) {
4220
4663
  const cwd = process.cwd();
4221
4664
  const possiblePaths = [
4222
- path4.resolve(cwd, config.migrations.directory),
4223
- path4.resolve(cwd, "shared", config.migrations.directory)
4665
+ path5.resolve(cwd, config.migrations.directory),
4666
+ path5.resolve(cwd, "shared", config.migrations.directory)
4224
4667
  ];
4225
- return possiblePaths.find((p) => fs2.existsSync(p)) || possiblePaths[0];
4668
+ return possiblePaths.find((p) => fs3.existsSync(p)) || possiblePaths[0];
4226
4669
  }
4227
4670
  var currentVerbosity = "normal";
4228
4671
  function setVerbosity(level) {
@@ -4430,10 +4873,16 @@ async function executeGenerate(options) {
4430
4873
  const schemaDir = getSchemaDirectory(config);
4431
4874
  const migrationsDir = getMigrationsDirectory(config);
4432
4875
  logSection("\u{1F50D} Analyzing Schema");
4433
- const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(schemaDir));
4876
+ const analyzerConfig = {
4877
+ schemaDir,
4878
+ excludePatterns: config.schema.exclude,
4879
+ useCompiledFiles: false
4880
+ // Use source files since we're in development/testing
4881
+ };
4882
+ const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
4434
4883
  logSuccess(`Found ${currentSchema.collections.size} collection(s)`);
4435
4884
  logInfo("Loading previous snapshot...");
4436
- const previousSnapshot = loadSnapshotIfExists({
4885
+ const previousSnapshot = loadSnapshotWithMigrations({
4437
4886
  migrationsPath: migrationsDir,
4438
4887
  workspaceRoot: process.cwd()
4439
4888
  });
@@ -4460,7 +4909,7 @@ async function executeGenerate(options) {
4460
4909
  "Creating migration file...",
4461
4910
  () => Promise.resolve(generate(diff, migrationsDir))
4462
4911
  );
4463
- logSuccess(`Migration file created: ${path4.basename(migrationPath)}`);
4912
+ logSuccess(`Migration file created: ${path5.basename(migrationPath)}`);
4464
4913
  logSection("\u2705 Next Steps");
4465
4914
  console.log();
4466
4915
  console.log(" 1. Review the generated migration file:");
@@ -4617,10 +5066,16 @@ async function executeStatus(options) {
4617
5066
  const schemaDir = getSchemaDirectory(config);
4618
5067
  const migrationsDir = getMigrationsDirectory(config);
4619
5068
  logSection("\u{1F50D} Checking Migration Status");
4620
- const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(schemaDir));
5069
+ const analyzerConfig = {
5070
+ schemaDir,
5071
+ excludePatterns: config.schema.exclude,
5072
+ useCompiledFiles: false
5073
+ // Use source files since we're in development/testing
5074
+ };
5075
+ const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
4621
5076
  logSuccess(`Found ${currentSchema.collections.size} collection(s) in schema`);
4622
5077
  logInfo("Loading previous snapshot...");
4623
- const previousSnapshot = loadSnapshotIfExists({
5078
+ const previousSnapshot = loadSnapshotWithMigrations({
4624
5079
  migrationsPath: migrationsDir,
4625
5080
  workspaceRoot: process.cwd()
4626
5081
  });
@@ -4721,6 +5176,6 @@ async function executeStatus(options) {
4721
5176
  }
4722
5177
  }
4723
5178
 
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 };
5179
+ 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, 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, loadSnapshotWithMigrations, 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
5180
  //# sourceMappingURL=index.js.map
4726
5181
  //# sourceMappingURL=index.js.map