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.cjs CHANGED
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var zod = require('zod');
4
- var fs2 = require('fs');
5
- var path4 = require('path');
4
+ var fs3 = require('fs');
5
+ var path5 = require('path');
6
6
  var chalk = require('chalk');
7
7
  var ora = require('ora');
8
8
 
@@ -26,8 +26,8 @@ function _interopNamespace(e) {
26
26
  return Object.freeze(n);
27
27
  }
28
28
 
29
- var fs2__namespace = /*#__PURE__*/_interopNamespace(fs2);
30
- var path4__namespace = /*#__PURE__*/_interopNamespace(path4);
29
+ var fs3__namespace = /*#__PURE__*/_interopNamespace(fs3);
30
+ var path5__namespace = /*#__PURE__*/_interopNamespace(path5);
31
31
  var chalk__default = /*#__PURE__*/_interopDefault(chalk);
32
32
  var ora__default = /*#__PURE__*/_interopDefault(ora);
33
33
 
@@ -104,14 +104,48 @@ function filesField(options) {
104
104
  if (options?.max !== void 0) schema = schema.max(options.max);
105
105
  return schema;
106
106
  }
107
- function relationField() {
108
- return zod.z.string();
107
+ var RELATION_METADATA_KEY = "__pocketbase_relation__";
108
+ function relationField(config) {
109
+ const metadata = {
110
+ [RELATION_METADATA_KEY]: {
111
+ type: "single",
112
+ collection: config.collection,
113
+ cascadeDelete: config.cascadeDelete ?? false,
114
+ maxSelect: 1,
115
+ minSelect: 0
116
+ }
117
+ };
118
+ return zod.z.string().describe(JSON.stringify(metadata));
109
119
  }
110
- function relationsField(options) {
120
+ function relationsField(config) {
121
+ const metadata = {
122
+ [RELATION_METADATA_KEY]: {
123
+ type: "multiple",
124
+ collection: config.collection,
125
+ cascadeDelete: config.cascadeDelete ?? false,
126
+ maxSelect: config.maxSelect ?? 999,
127
+ minSelect: config.minSelect ?? 0
128
+ }
129
+ };
111
130
  let schema = zod.z.array(zod.z.string());
112
- if (options?.min !== void 0) schema = schema.min(options.min);
113
- if (options?.max !== void 0) schema = schema.max(options.max);
114
- return schema;
131
+ if (config.minSelect !== void 0) {
132
+ schema = schema.min(config.minSelect);
133
+ }
134
+ if (config.maxSelect !== void 0) {
135
+ schema = schema.max(config.maxSelect);
136
+ }
137
+ return schema.describe(JSON.stringify(metadata));
138
+ }
139
+ function extractRelationMetadata(description) {
140
+ if (!description) return null;
141
+ try {
142
+ const parsed = JSON.parse(description);
143
+ if (parsed[RELATION_METADATA_KEY]) {
144
+ return parsed[RELATION_METADATA_KEY];
145
+ }
146
+ } catch {
147
+ }
148
+ return null;
115
149
  }
116
150
  function editorField() {
117
151
  return zod.z.string();
@@ -143,7 +177,7 @@ function withIndexes(schema, indexes) {
143
177
  return schema.describe(JSON.stringify(metadata));
144
178
  }
145
179
 
146
- // src/schema/permission-templates.ts
180
+ // src/utils/permission-templates.ts
147
181
  var PermissionTemplates = {
148
182
  /**
149
183
  * Public access - anyone can perform all operations
@@ -368,38 +402,36 @@ var ProjectInputSchema = zod.z.object({
368
402
  content: zod.z.string(),
369
403
  status: StatusEnum,
370
404
  summary: zod.z.string().optional(),
371
- User: zod.z.string().nonempty("User ID is missing"),
372
- SubscriberUsers: zod.z.array(zod.z.string())
405
+ OwnerUser: relationField({ collection: "Users" }),
406
+ SubscriberUsers: relationsField({ collection: "Users" })
373
407
  }).extend(inputImageFileSchema);
374
408
  var ProjectSchema = withPermissions(
375
409
  ProjectInputSchema.omit(omitImageFilesSchema).extend(baseImageFileSchema),
376
410
  {
377
411
  template: "owner-only",
378
- ownerField: "User",
412
+ ownerField: "OwnerUser",
379
413
  customRules: {
380
- // Override list rule to allow authenticated users to see all projects
381
414
  listRule: '@request.auth.id != ""',
382
- // Allow viewing if user is owner OR a subscriber
383
- viewRule: '@request.auth.id != "" && (User = @request.auth.id || SubscriberUsers ?= @request.auth.id)'
415
+ viewRule: '@request.auth.id != "" && (OwnerUser = @request.auth.id || SubscriberUsers ?= @request.auth.id)'
384
416
  }
385
417
  }
386
418
  );
387
419
  var UserInputSchema = zod.z.object({
388
- name: zod.z.string().min(2, "Name must be longer").optional(),
420
+ name: zod.z.string().optional(),
389
421
  email: zod.z.string().email(),
390
422
  password: zod.z.string().min(8, "Password must be at least 8 characters"),
391
423
  passwordConfirm: zod.z.string(),
392
424
  avatar: zod.z.instanceof(File).optional()
393
425
  });
394
426
  var UserDatabaseSchema = zod.z.object({
395
- name: zod.z.string().min(2, "Name must be longer").optional(),
427
+ name: zod.z.string().optional(),
396
428
  email: zod.z.string().email(),
397
429
  password: zod.z.string().min(8, "Password must be at least 8 characters"),
398
430
  avatar: zod.z.instanceof(File).optional()
399
431
  });
400
432
  var UserSchema = withIndexes(
401
433
  withPermissions(UserDatabaseSchema.extend(baseSchema), {
402
- // Users can list other users (for mentions, user search, etc.)
434
+ // Users can list their own profile
403
435
  listRule: "id = @request.auth.id",
404
436
  // Users can view their own profile
405
437
  viewRule: "id = @request.auth.id",
@@ -408,15 +440,13 @@ var UserSchema = withIndexes(
408
440
  // Users can only update their own profile
409
441
  updateRule: "id = @request.auth.id",
410
442
  // Users can only delete their own account
411
- deleteRule: "id = @request.auth.id",
412
- // Users can only manage their own account (change email, password, etc.)
413
- manageRule: "id = @request.auth.id"
443
+ deleteRule: "id = @request.auth.id"
444
+ // manageRule is null in PocketBase default (not set)
414
445
  }),
415
446
  [
416
- // Email should be unique for authentication
417
- "CREATE UNIQUE INDEX idx_users_email ON users (email)",
418
- // Index on name for user search and sorting
419
- "CREATE INDEX idx_users_name ON users (name)"
447
+ // PocketBase's default indexes for auth collections
448
+ "CREATE UNIQUE INDEX `idx_tokenKey__pb_users_auth_` ON `users` (`tokenKey`)",
449
+ "CREATE UNIQUE INDEX `idx_email__pb_users_auth_` ON `users` (`email`) WHERE `email` != ''"
420
450
  ]
421
451
  );
422
452
  var BaseMutator = class {
@@ -757,7 +787,7 @@ var UserMutator = class extends BaseMutator {
757
787
  };
758
788
  }
759
789
  getCollection() {
760
- return this.pb.collection("Projects");
790
+ return this.pb.collection("Users");
761
791
  }
762
792
  async validateInput(input) {
763
793
  return UserInputSchema.parse(input);
@@ -861,10 +891,10 @@ var FileSystemError = class _FileSystemError extends MigrationError {
861
891
  operation;
862
892
  code;
863
893
  originalError;
864
- constructor(message, path6, operation, code, originalError) {
894
+ constructor(message, path7, operation, code, originalError) {
865
895
  super(message);
866
896
  this.name = "FileSystemError";
867
- this.path = path6;
897
+ this.path = path7;
868
898
  this.operation = operation;
869
899
  this.code = code;
870
900
  this.originalError = originalError;
@@ -1523,26 +1553,28 @@ function getMaxSelect(fieldName, zodType) {
1523
1553
  return 1;
1524
1554
  }
1525
1555
  function getMinSelect(fieldName, zodType) {
1526
- if (!isMultipleRelationField(fieldName, zodType)) {
1527
- return void 0;
1528
- }
1529
- let unwrappedType = zodType;
1530
- if (zodType instanceof zod.z.ZodOptional) {
1531
- unwrappedType = zodType._def.innerType;
1532
- }
1533
- if (unwrappedType instanceof zod.z.ZodNullable) {
1534
- unwrappedType = unwrappedType._def.innerType;
1535
- }
1536
- if (unwrappedType instanceof zod.z.ZodDefault) {
1537
- unwrappedType = unwrappedType._def.innerType;
1556
+ if (isSingleRelationField(fieldName, zodType)) {
1557
+ return 0;
1538
1558
  }
1539
- if (unwrappedType instanceof zod.z.ZodArray) {
1540
- const arrayDef = unwrappedType._def;
1541
- if (arrayDef.minLength) {
1542
- return arrayDef.minLength.value;
1559
+ if (isMultipleRelationField(fieldName, zodType)) {
1560
+ let unwrappedType = zodType;
1561
+ if (zodType instanceof zod.z.ZodOptional) {
1562
+ unwrappedType = zodType._def.innerType;
1563
+ }
1564
+ if (unwrappedType instanceof zod.z.ZodNullable) {
1565
+ unwrappedType = unwrappedType._def.innerType;
1566
+ }
1567
+ if (unwrappedType instanceof zod.z.ZodDefault) {
1568
+ unwrappedType = unwrappedType._def.innerType;
1569
+ }
1570
+ if (unwrappedType instanceof zod.z.ZodArray) {
1571
+ const arrayDef = unwrappedType._def;
1572
+ if (arrayDef.minLength) {
1573
+ return arrayDef.minLength.value;
1574
+ }
1543
1575
  }
1544
1576
  }
1545
- return void 0;
1577
+ return 0;
1546
1578
  }
1547
1579
  var POCKETBASE_FIELD_TYPES = [
1548
1580
  "text",
@@ -1965,20 +1997,20 @@ function mergeConfig(config) {
1965
1997
  }
1966
1998
  function resolveSchemaDir(config) {
1967
1999
  const workspaceRoot = config.workspaceRoot || process.cwd();
1968
- if (path4__namespace.isAbsolute(config.schemaDir)) {
2000
+ if (path5__namespace.isAbsolute(config.schemaDir)) {
1969
2001
  return config.schemaDir;
1970
2002
  }
1971
- return path4__namespace.join(workspaceRoot, config.schemaDir);
2003
+ return path5__namespace.join(workspaceRoot, config.schemaDir);
1972
2004
  }
1973
2005
  function discoverSchemaFiles(config) {
1974
2006
  const normalizedConfig = typeof config === "string" ? { schemaDir: config } : config;
1975
2007
  const mergedConfig = mergeConfig(normalizedConfig);
1976
2008
  const schemaDir = resolveSchemaDir(normalizedConfig);
1977
2009
  try {
1978
- if (!fs2__namespace.existsSync(schemaDir)) {
2010
+ if (!fs3__namespace.existsSync(schemaDir)) {
1979
2011
  throw new FileSystemError(`Schema directory not found: ${schemaDir}`, schemaDir, "access", "ENOENT");
1980
2012
  }
1981
- const files = fs2__namespace.readdirSync(schemaDir);
2013
+ const files = fs3__namespace.readdirSync(schemaDir);
1982
2014
  const schemaFiles = files.filter((file) => {
1983
2015
  const hasValidExtension = mergedConfig.includeExtensions.some((ext) => file.endsWith(ext));
1984
2016
  if (!hasValidExtension) return false;
@@ -1994,7 +2026,7 @@ function discoverSchemaFiles(config) {
1994
2026
  });
1995
2027
  return schemaFiles.map((file) => {
1996
2028
  const ext = mergedConfig.includeExtensions.find((ext2) => file.endsWith(ext2)) || ".ts";
1997
- return path4__namespace.join(schemaDir, file.replace(new RegExp(`\\${ext}$`), ""));
2029
+ return path5__namespace.join(schemaDir, file.replace(new RegExp(`\\${ext}$`), ""));
1998
2030
  });
1999
2031
  } catch (error) {
2000
2032
  if (error instanceof FileSystemError) {
@@ -2025,13 +2057,32 @@ async function importSchemaModule(filePath, config) {
2025
2057
  if (config?.pathTransformer) {
2026
2058
  importPath = config.pathTransformer(filePath);
2027
2059
  }
2028
- if (!importPath.endsWith(".js")) {
2029
- importPath = `${importPath}.js`;
2060
+ let resolvedPath = null;
2061
+ const jsPath = `${importPath}.js`;
2062
+ const tsPath = `${importPath}.ts`;
2063
+ if (fs3__namespace.existsSync(jsPath)) {
2064
+ resolvedPath = jsPath;
2065
+ } else if (fs3__namespace.existsSync(tsPath)) {
2066
+ resolvedPath = tsPath;
2067
+ } else {
2068
+ resolvedPath = jsPath;
2030
2069
  }
2031
- const fileUrl = new URL(`file://${path4__namespace.resolve(importPath)}`);
2070
+ const fileUrl = new URL(`file://${path5__namespace.resolve(resolvedPath)}`);
2032
2071
  const module = await import(fileUrl.href);
2033
2072
  return module;
2034
2073
  } catch (error) {
2074
+ const tsPath = `${filePath}.ts`;
2075
+ const isTypeScriptFile = fs3__namespace.existsSync(tsPath);
2076
+ if (isTypeScriptFile) {
2077
+ throw new SchemaParsingError(
2078
+ `Failed to import TypeScript schema file. Node.js cannot import TypeScript files directly.
2079
+ Please either:
2080
+ 1. Compile your schema files to JavaScript first, or
2081
+ 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")`,
2082
+ filePath,
2083
+ error
2084
+ );
2085
+ }
2035
2086
  throw new SchemaParsingError(
2036
2087
  `Failed to import schema module. Make sure the schema files are compiled to JavaScript.`,
2037
2088
  filePath,
@@ -2040,7 +2091,7 @@ async function importSchemaModule(filePath, config) {
2040
2091
  }
2041
2092
  }
2042
2093
  function getCollectionNameFromFile(filePath) {
2043
- const filename = path4__namespace.basename(filePath).replace(/\.(ts|js)$/, "");
2094
+ const filename = path5__namespace.basename(filePath).replace(/\.(ts|js)$/, "");
2044
2095
  return toCollectionName(filename);
2045
2096
  }
2046
2097
  function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema"]) {
@@ -2094,7 +2145,17 @@ function buildFieldDefinition(fieldName, zodType) {
2094
2145
  required,
2095
2146
  options
2096
2147
  };
2097
- if (isRelationField(fieldName, zodType)) {
2148
+ const relationMetadata = extractRelationMetadata(zodType.description);
2149
+ if (relationMetadata) {
2150
+ fieldDef.type = "relation";
2151
+ fieldDef.relation = {
2152
+ collection: relationMetadata.collection,
2153
+ maxSelect: relationMetadata.maxSelect,
2154
+ minSelect: relationMetadata.minSelect,
2155
+ cascadeDelete: relationMetadata.cascadeDelete
2156
+ };
2157
+ fieldDef.options = void 0;
2158
+ } else if (isRelationField(fieldName, zodType)) {
2098
2159
  fieldDef.type = "relation";
2099
2160
  const targetCollection = resolveTargetCollection(fieldName);
2100
2161
  const maxSelect = getMaxSelect(fieldName, zodType);
@@ -2106,6 +2167,13 @@ function buildFieldDefinition(fieldName, zodType) {
2106
2167
  cascadeDelete: false
2107
2168
  // Default to false, can be configured later
2108
2169
  };
2170
+ if (fieldDef.options) {
2171
+ const { min, max, pattern, ...relationSafeOptions } = fieldDef.options;
2172
+ console.log("min", min);
2173
+ console.log("max", max);
2174
+ console.log("pattern", pattern);
2175
+ fieldDef.options = Object.keys(relationSafeOptions).length > 0 ? relationSafeOptions : void 0;
2176
+ }
2109
2177
  }
2110
2178
  return fieldDef;
2111
2179
  }
@@ -2158,11 +2226,12 @@ function convertZodSchemaToCollectionSchema(collectionName, zodSchema) {
2158
2226
  fields,
2159
2227
  indexes,
2160
2228
  rules: {
2161
- listRule: null,
2162
- viewRule: null,
2163
- createRule: null,
2164
- updateRule: null,
2165
- deleteRule: null
2229
+ listRule: permissions?.listRule ?? null,
2230
+ viewRule: permissions?.viewRule ?? null,
2231
+ createRule: permissions?.createRule ?? null,
2232
+ updateRule: permissions?.updateRule ?? null,
2233
+ deleteRule: permissions?.deleteRule ?? null,
2234
+ manageRule: permissions?.manageRule ?? null
2166
2235
  },
2167
2236
  permissions
2168
2237
  };
@@ -2186,7 +2255,12 @@ async function buildSchemaDefinition(config) {
2186
2255
  if (normalizedConfig.pathTransformer) {
2187
2256
  importPath = normalizedConfig.pathTransformer(filePath);
2188
2257
  } else if (mergedConfig.useCompiledFiles) {
2189
- importPath = filePath.replace(/\/src\//, "/dist/");
2258
+ const distPath = filePath.replace(/\/src\//, "/dist/");
2259
+ if (fs3__namespace.existsSync(`${distPath}.js`) || fs3__namespace.existsSync(`${distPath}.mjs`)) {
2260
+ importPath = distPath;
2261
+ } else {
2262
+ importPath = filePath;
2263
+ }
2190
2264
  }
2191
2265
  const module = await importSchemaModule(importPath, normalizedConfig);
2192
2266
  const schemas = extractSchemaDefinitions(module, mergedConfig.schemaPatterns);
@@ -2238,7 +2312,359 @@ var SchemaAnalyzer = class {
2238
2312
  return convertZodSchemaToCollectionSchema(name, schema);
2239
2313
  }
2240
2314
  };
2315
+
2316
+ // src/migration/pocketbase-converter.ts
2241
2317
  var SNAPSHOT_VERSION = "1.0.0";
2318
+ function resolveCollectionIdToName(collectionId) {
2319
+ if (collectionId === "_pb_users_auth_") {
2320
+ return "Users";
2321
+ }
2322
+ const nameMatch = collectionId.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
2323
+ if (nameMatch) {
2324
+ return nameMatch[1];
2325
+ }
2326
+ return collectionId;
2327
+ }
2328
+ function convertPocketBaseCollection(pbCollection) {
2329
+ const fields = [];
2330
+ const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
2331
+ const authSystemFieldNames = ["email", "emailVisibility", "verified", "password", "tokenKey"];
2332
+ if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
2333
+ for (const pbField of pbCollection.fields) {
2334
+ if (pbField.system || systemFieldNames.includes(pbField.name)) {
2335
+ continue;
2336
+ }
2337
+ if (pbCollection.type === "auth" && authSystemFieldNames.includes(pbField.name)) {
2338
+ continue;
2339
+ }
2340
+ const field = {
2341
+ name: pbField.name,
2342
+ type: pbField.type,
2343
+ required: pbField.required || false
2344
+ };
2345
+ field.options = pbField.options ? { ...pbField.options } : {};
2346
+ if (pbField.type === "select") {
2347
+ if (pbField.values && Array.isArray(pbField.values)) {
2348
+ field.options.values = pbField.values;
2349
+ } else if (pbField.options?.values && Array.isArray(pbField.options.values)) {
2350
+ field.options.values = pbField.options.values;
2351
+ }
2352
+ }
2353
+ if (pbField.type === "relation") {
2354
+ const collectionId = pbField.collectionId || pbField.options?.collectionId || "";
2355
+ const collectionName = resolveCollectionIdToName(collectionId);
2356
+ field.relation = {
2357
+ collection: collectionName,
2358
+ cascadeDelete: pbField.cascadeDelete ?? pbField.options?.cascadeDelete ?? false,
2359
+ maxSelect: pbField.maxSelect ?? pbField.options?.maxSelect,
2360
+ minSelect: pbField.minSelect ?? pbField.options?.minSelect
2361
+ };
2362
+ }
2363
+ const hasOnlyValues = Object.keys(field.options).length === 1 && field.options.values !== void 0;
2364
+ if (Object.keys(field.options).length === 0) {
2365
+ delete field.options;
2366
+ } else if (pbField.type === "select" && hasOnlyValues) ;
2367
+ fields.push(field);
2368
+ }
2369
+ }
2370
+ const schema = {
2371
+ name: pbCollection.name,
2372
+ type: pbCollection.type || "base",
2373
+ fields
2374
+ };
2375
+ if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
2376
+ schema.indexes = pbCollection.indexes;
2377
+ }
2378
+ const rules = {};
2379
+ if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
2380
+ if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
2381
+ if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
2382
+ if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
2383
+ if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
2384
+ if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
2385
+ if (Object.keys(rules).length > 0) {
2386
+ schema.rules = rules;
2387
+ schema.permissions = { ...rules };
2388
+ }
2389
+ return schema;
2390
+ }
2391
+ function convertPocketBaseMigration(migrationContent) {
2392
+ try {
2393
+ const snapshotMatch = migrationContent.match(/const\s+snapshot\s*=\s*(\[[\s\S]*?\]);/);
2394
+ if (!snapshotMatch) {
2395
+ throw new Error("Could not find snapshot array in migration file");
2396
+ }
2397
+ const snapshotArrayStr = snapshotMatch[1];
2398
+ let snapshotArray;
2399
+ try {
2400
+ snapshotArray = new Function(`return ${snapshotArrayStr}`)();
2401
+ } catch (parseError) {
2402
+ throw new Error(`Failed to parse snapshot array: ${parseError}`);
2403
+ }
2404
+ if (!Array.isArray(snapshotArray)) {
2405
+ throw new Error("Snapshot is not an array");
2406
+ }
2407
+ const collections = /* @__PURE__ */ new Map();
2408
+ for (const pbCollection of snapshotArray) {
2409
+ if (!pbCollection.name) {
2410
+ console.warn("Skipping collection without name");
2411
+ continue;
2412
+ }
2413
+ const schema = convertPocketBaseCollection(pbCollection);
2414
+ collections.set(pbCollection.name, schema);
2415
+ }
2416
+ return {
2417
+ version: SNAPSHOT_VERSION,
2418
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2419
+ collections
2420
+ };
2421
+ } catch (error) {
2422
+ throw new SnapshotError(
2423
+ `Failed to convert PocketBase migration: ${error instanceof Error ? error.message : String(error)}`,
2424
+ void 0,
2425
+ "parse",
2426
+ error instanceof Error ? error : void 0
2427
+ );
2428
+ }
2429
+ }
2430
+
2431
+ // src/migration/migration-parser.ts
2432
+ function extractTimestampFromFilename(filename) {
2433
+ const match = filename.match(/^(\d+)_/);
2434
+ if (match) {
2435
+ return parseInt(match[1], 10);
2436
+ }
2437
+ return null;
2438
+ }
2439
+ function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
2440
+ try {
2441
+ if (!fs3__namespace.existsSync(migrationsPath)) {
2442
+ return [];
2443
+ }
2444
+ const files = fs3__namespace.readdirSync(migrationsPath);
2445
+ const migrationFiles = [];
2446
+ for (const file of files) {
2447
+ if (file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")) {
2448
+ continue;
2449
+ }
2450
+ if (!file.endsWith(".js")) {
2451
+ continue;
2452
+ }
2453
+ const timestamp = extractTimestampFromFilename(file);
2454
+ if (timestamp && timestamp > snapshotTimestamp) {
2455
+ migrationFiles.push({
2456
+ path: path5__namespace.join(migrationsPath, file),
2457
+ timestamp
2458
+ });
2459
+ }
2460
+ }
2461
+ migrationFiles.sort((a, b) => a.timestamp - b.timestamp);
2462
+ return migrationFiles.map((f) => f.path);
2463
+ } catch (error) {
2464
+ console.warn(`Error finding migrations after snapshot: ${error}`);
2465
+ return [];
2466
+ }
2467
+ }
2468
+ function parseMigrationOperationsFromContent(content) {
2469
+ const collectionsToCreate = [];
2470
+ const collectionsToDelete = [];
2471
+ try {
2472
+ let searchIndex = 0;
2473
+ while (true) {
2474
+ const collectionStart = content.indexOf("new Collection(", searchIndex);
2475
+ if (collectionStart === -1) {
2476
+ break;
2477
+ }
2478
+ const openParen = collectionStart + "new Collection(".length;
2479
+ let braceCount = 0;
2480
+ let parenCount = 1;
2481
+ let inString = false;
2482
+ let stringChar = null;
2483
+ let i = openParen;
2484
+ while (i < content.length && /\s/.test(content[i])) {
2485
+ i++;
2486
+ }
2487
+ if (content[i] !== "{") {
2488
+ searchIndex = i + 1;
2489
+ continue;
2490
+ }
2491
+ const objectStart = i;
2492
+ braceCount = 1;
2493
+ i++;
2494
+ while (i < content.length && (braceCount > 0 || parenCount > 0)) {
2495
+ const char = content[i];
2496
+ const prevChar = i > 0 ? content[i - 1] : "";
2497
+ if (!inString && (char === '"' || char === "'")) {
2498
+ inString = true;
2499
+ stringChar = char;
2500
+ } else if (inString && char === stringChar && prevChar !== "\\") {
2501
+ inString = false;
2502
+ stringChar = null;
2503
+ }
2504
+ if (!inString) {
2505
+ if (char === "{") braceCount++;
2506
+ if (char === "}") braceCount--;
2507
+ if (char === "(") parenCount++;
2508
+ if (char === ")") parenCount--;
2509
+ }
2510
+ i++;
2511
+ }
2512
+ if (braceCount === 0 && parenCount === 0) {
2513
+ const objectContent = content.substring(objectStart, i - 1);
2514
+ try {
2515
+ const collectionObj = new Function(`return ${objectContent}`)();
2516
+ if (collectionObj && collectionObj.name) {
2517
+ const schema = convertPocketBaseCollection(collectionObj);
2518
+ collectionsToCreate.push(schema);
2519
+ }
2520
+ } catch (error) {
2521
+ console.warn(`Failed to parse collection definition: ${error}`);
2522
+ }
2523
+ }
2524
+ searchIndex = i;
2525
+ }
2526
+ const deleteMatches = content.matchAll(
2527
+ /app\.delete\s*\(\s*(?:collection_\w+|app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\))\s*\)/g
2528
+ );
2529
+ for (const match of deleteMatches) {
2530
+ if (match[1]) {
2531
+ collectionsToDelete.push(match[1]);
2532
+ } else {
2533
+ const varNameMatch = match[0].match(/collection_(\w+)/);
2534
+ if (varNameMatch) {
2535
+ const varName = `collection_${varNameMatch[1]}`;
2536
+ const deleteIndex = content.indexOf(match[0]);
2537
+ const beforeDelete = content.substring(0, deleteIndex);
2538
+ const varDefMatch = beforeDelete.match(
2539
+ new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`, "g")
2540
+ );
2541
+ if (varDefMatch && varDefMatch.length > 0) {
2542
+ const collectionDefMatch = beforeDelete.match(
2543
+ new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`)
2544
+ );
2545
+ if (collectionDefMatch) {
2546
+ try {
2547
+ const collectionDefStr = collectionDefMatch[1];
2548
+ const collectionObj = new Function(`return ${collectionDefStr}`)();
2549
+ if (collectionObj && collectionObj.name) {
2550
+ collectionsToDelete.push(collectionObj.name);
2551
+ }
2552
+ } catch {
2553
+ }
2554
+ }
2555
+ }
2556
+ }
2557
+ }
2558
+ }
2559
+ const findAndDeleteMatches = content.matchAll(
2560
+ /app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)[\s\S]*?app\.delete/g
2561
+ );
2562
+ for (const match of findAndDeleteMatches) {
2563
+ collectionsToDelete.push(match[1]);
2564
+ }
2565
+ } catch (error) {
2566
+ console.warn(`Failed to parse migration operations from content: ${error}`);
2567
+ }
2568
+ return { collectionsToCreate, collectionsToDelete };
2569
+ }
2570
+ function parseMigrationOperations(migrationContent) {
2571
+ try {
2572
+ const migrateMatch = migrationContent.match(/migrate\s*\(\s*/);
2573
+ if (!migrateMatch) {
2574
+ return parseMigrationOperationsFromContent(migrationContent);
2575
+ }
2576
+ const startIndex = migrateMatch.index + migrateMatch[0].length;
2577
+ let i = startIndex;
2578
+ let parenCount = 0;
2579
+ let foundFirstParen = false;
2580
+ while (i < migrationContent.length) {
2581
+ const char = migrationContent[i];
2582
+ if (char === "(") {
2583
+ parenCount++;
2584
+ foundFirstParen = true;
2585
+ i++;
2586
+ break;
2587
+ }
2588
+ i++;
2589
+ }
2590
+ if (!foundFirstParen) {
2591
+ return parseMigrationOperationsFromContent(migrationContent);
2592
+ }
2593
+ let inString = false;
2594
+ let stringChar = null;
2595
+ let foundBrace = false;
2596
+ let braceStart = -1;
2597
+ while (i < migrationContent.length && !foundBrace) {
2598
+ const char = migrationContent[i];
2599
+ const prevChar = i > 0 ? migrationContent[i - 1] : "";
2600
+ if (!inString && (char === '"' || char === "'")) {
2601
+ inString = true;
2602
+ stringChar = char;
2603
+ } else if (inString && char === stringChar && prevChar !== "\\") {
2604
+ inString = false;
2605
+ stringChar = null;
2606
+ }
2607
+ if (!inString) {
2608
+ if (char === "(") parenCount++;
2609
+ if (char === ")") {
2610
+ parenCount--;
2611
+ if (parenCount === 0) {
2612
+ i++;
2613
+ while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
2614
+ i++;
2615
+ }
2616
+ if (i < migrationContent.length - 1 && migrationContent[i] === "=" && migrationContent[i + 1] === ">") {
2617
+ i += 2;
2618
+ while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
2619
+ i++;
2620
+ }
2621
+ if (i < migrationContent.length && migrationContent[i] === "{") {
2622
+ foundBrace = true;
2623
+ braceStart = i + 1;
2624
+ break;
2625
+ }
2626
+ }
2627
+ }
2628
+ }
2629
+ }
2630
+ i++;
2631
+ }
2632
+ if (!foundBrace || braceStart === -1) {
2633
+ return parseMigrationOperationsFromContent(migrationContent);
2634
+ }
2635
+ let braceCount = 1;
2636
+ i = braceStart;
2637
+ inString = false;
2638
+ stringChar = null;
2639
+ while (i < migrationContent.length && braceCount > 0) {
2640
+ const char = migrationContent[i];
2641
+ const prevChar = i > 0 ? migrationContent[i - 1] : "";
2642
+ if (!inString && (char === '"' || char === "'")) {
2643
+ inString = true;
2644
+ stringChar = char;
2645
+ } else if (inString && char === stringChar && prevChar !== "\\") {
2646
+ inString = false;
2647
+ stringChar = null;
2648
+ }
2649
+ if (!inString) {
2650
+ if (char === "{") braceCount++;
2651
+ if (char === "}") braceCount--;
2652
+ }
2653
+ i++;
2654
+ }
2655
+ if (braceCount === 0) {
2656
+ const upMigrationContent = migrationContent.substring(braceStart, i - 1);
2657
+ return parseMigrationOperationsFromContent(upMigrationContent);
2658
+ }
2659
+ return parseMigrationOperationsFromContent(migrationContent);
2660
+ } catch (error) {
2661
+ console.warn(`Failed to parse migration operations: ${error}`);
2662
+ return { collectionsToCreate: [], collectionsToDelete: [] };
2663
+ }
2664
+ }
2665
+
2666
+ // src/migration/snapshot.ts
2667
+ var SNAPSHOT_VERSION2 = "1.0.0";
2242
2668
  var DEFAULT_SNAPSHOT_FILENAME = ".migration-snapshot.json";
2243
2669
  var SNAPSHOT_MIGRATIONS = [
2244
2670
  // Add migrations here as the format evolves
@@ -2253,7 +2679,7 @@ var DEFAULT_CONFIG2 = {
2253
2679
  snapshotPath: DEFAULT_SNAPSHOT_FILENAME,
2254
2680
  workspaceRoot: process.cwd(),
2255
2681
  autoMigrate: true,
2256
- version: SNAPSHOT_VERSION
2682
+ version: SNAPSHOT_VERSION2
2257
2683
  };
2258
2684
  function mergeConfig2(config = {}) {
2259
2685
  return {
@@ -2265,15 +2691,15 @@ function getSnapshotPath(config = {}) {
2265
2691
  const mergedConfig = mergeConfig2(config);
2266
2692
  const workspaceRoot = mergedConfig.workspaceRoot;
2267
2693
  const snapshotFilename = mergedConfig.snapshotPath;
2268
- if (path4__namespace.isAbsolute(snapshotFilename)) {
2694
+ if (path5__namespace.isAbsolute(snapshotFilename)) {
2269
2695
  return snapshotFilename;
2270
2696
  }
2271
- return path4__namespace.join(workspaceRoot, snapshotFilename);
2697
+ return path5__namespace.join(workspaceRoot, snapshotFilename);
2272
2698
  }
2273
2699
  function snapshotExists(config = {}) {
2274
2700
  try {
2275
2701
  const snapshotPath = getSnapshotPath(config);
2276
- return fs2__namespace.existsSync(snapshotPath);
2702
+ return fs3__namespace.existsSync(snapshotPath);
2277
2703
  } catch {
2278
2704
  return false;
2279
2705
  }
@@ -2332,13 +2758,13 @@ function addSnapshotMetadata(schema, config) {
2332
2758
  function saveSnapshot(schema, config = {}) {
2333
2759
  const snapshotPath = getSnapshotPath(config);
2334
2760
  try {
2335
- const snapshotDir = path4__namespace.dirname(snapshotPath);
2336
- if (!fs2__namespace.existsSync(snapshotDir)) {
2337
- fs2__namespace.mkdirSync(snapshotDir, { recursive: true });
2761
+ const snapshotDir = path5__namespace.dirname(snapshotPath);
2762
+ if (!fs3__namespace.existsSync(snapshotDir)) {
2763
+ fs3__namespace.mkdirSync(snapshotDir, { recursive: true });
2338
2764
  }
2339
2765
  const snapshotData = addSnapshotMetadata(schema, config);
2340
2766
  const jsonContent = JSON.stringify(snapshotData, null, 2);
2341
- fs2__namespace.writeFileSync(snapshotPath, jsonContent, "utf-8");
2767
+ fs3__namespace.writeFileSync(snapshotPath, jsonContent, "utf-8");
2342
2768
  } catch (error) {
2343
2769
  handleFileSystemError(error, "write", snapshotPath);
2344
2770
  }
@@ -2433,7 +2859,7 @@ function deserializeSnapshot(data) {
2433
2859
  function loadSnapshot(config = {}) {
2434
2860
  const snapshotPath = getSnapshotPath(config);
2435
2861
  try {
2436
- const jsonContent = fs2__namespace.readFileSync(snapshotPath, "utf-8");
2862
+ const jsonContent = fs3__namespace.readFileSync(snapshotPath, "utf-8");
2437
2863
  const data = parseAndValidateSnapshot(jsonContent, snapshotPath);
2438
2864
  const migratedData = migrateSnapshotFormat(data, config);
2439
2865
  return deserializeSnapshot(migratedData);
@@ -2468,10 +2894,10 @@ function mergeSnapshots(baseSnapshot, customSnapshot) {
2468
2894
  }
2469
2895
  function findLatestSnapshot(migrationsPath) {
2470
2896
  try {
2471
- if (!fs2__namespace.existsSync(migrationsPath)) {
2897
+ if (!fs3__namespace.existsSync(migrationsPath)) {
2472
2898
  return null;
2473
2899
  }
2474
- const files = fs2__namespace.readdirSync(migrationsPath);
2900
+ const files = fs3__namespace.readdirSync(migrationsPath);
2475
2901
  const snapshotFiles = files.filter(
2476
2902
  (file) => file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")
2477
2903
  );
@@ -2483,20 +2909,74 @@ function findLatestSnapshot(migrationsPath) {
2483
2909
  if (!latestSnapshot) {
2484
2910
  return null;
2485
2911
  }
2486
- return path4__namespace.join(migrationsPath, latestSnapshot);
2912
+ return path5__namespace.join(migrationsPath, latestSnapshot);
2487
2913
  } catch (error) {
2488
2914
  console.warn(`Error finding latest snapshot: ${error}`);
2489
2915
  return null;
2490
2916
  }
2491
2917
  }
2918
+ function applyMigrationOperations(snapshot, operations) {
2919
+ const updatedCollections = new Map(snapshot.collections);
2920
+ for (const collectionName of operations.collectionsToDelete) {
2921
+ updatedCollections.delete(collectionName);
2922
+ }
2923
+ for (const collection of operations.collectionsToCreate) {
2924
+ updatedCollections.set(collection.name, collection);
2925
+ }
2926
+ return {
2927
+ ...snapshot,
2928
+ collections: updatedCollections
2929
+ };
2930
+ }
2931
+ function loadSnapshotWithMigrations(config = {}) {
2932
+ const migrationsPath = config.migrationsPath;
2933
+ if (!migrationsPath) {
2934
+ return null;
2935
+ }
2936
+ if (fs3__namespace.existsSync(migrationsPath) && fs3__namespace.statSync(migrationsPath).isFile()) {
2937
+ try {
2938
+ const migrationContent = fs3__namespace.readFileSync(migrationsPath, "utf-8");
2939
+ return convertPocketBaseMigration(migrationContent);
2940
+ } catch (error) {
2941
+ console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
2942
+ return null;
2943
+ }
2944
+ }
2945
+ const latestSnapshotPath = findLatestSnapshot(migrationsPath);
2946
+ if (!latestSnapshotPath) {
2947
+ return null;
2948
+ }
2949
+ try {
2950
+ const migrationContent = fs3__namespace.readFileSync(latestSnapshotPath, "utf-8");
2951
+ let snapshot = convertPocketBaseMigration(migrationContent);
2952
+ const snapshotFilename = path5__namespace.basename(latestSnapshotPath);
2953
+ const snapshotTimestamp = extractTimestampFromFilename(snapshotFilename);
2954
+ if (snapshotTimestamp) {
2955
+ const migrationFiles = findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp);
2956
+ for (const migrationFile of migrationFiles) {
2957
+ try {
2958
+ const migrationContent2 = fs3__namespace.readFileSync(migrationFile, "utf-8");
2959
+ const operations = parseMigrationOperations(migrationContent2);
2960
+ snapshot = applyMigrationOperations(snapshot, operations);
2961
+ } catch (error) {
2962
+ console.warn(`Failed to apply migration ${migrationFile}: ${error}`);
2963
+ }
2964
+ }
2965
+ }
2966
+ return snapshot;
2967
+ } catch (error) {
2968
+ console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
2969
+ return null;
2970
+ }
2971
+ }
2492
2972
  function loadSnapshotIfExists(config = {}) {
2493
2973
  const migrationsPath = config.migrationsPath;
2494
2974
  if (!migrationsPath) {
2495
2975
  return null;
2496
2976
  }
2497
- if (fs2__namespace.existsSync(migrationsPath) && fs2__namespace.statSync(migrationsPath).isFile()) {
2977
+ if (fs3__namespace.existsSync(migrationsPath) && fs3__namespace.statSync(migrationsPath).isFile()) {
2498
2978
  try {
2499
- const migrationContent = fs2__namespace.readFileSync(migrationsPath, "utf-8");
2979
+ const migrationContent = fs3__namespace.readFileSync(migrationsPath, "utf-8");
2500
2980
  return convertPocketBaseMigration(migrationContent);
2501
2981
  } catch (error) {
2502
2982
  console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
@@ -2506,7 +2986,7 @@ function loadSnapshotIfExists(config = {}) {
2506
2986
  const latestSnapshotPath = findLatestSnapshot(migrationsPath);
2507
2987
  if (latestSnapshotPath) {
2508
2988
  try {
2509
- const migrationContent = fs2__namespace.readFileSync(latestSnapshotPath, "utf-8");
2989
+ const migrationContent = fs3__namespace.readFileSync(latestSnapshotPath, "utf-8");
2510
2990
  return convertPocketBaseMigration(migrationContent);
2511
2991
  } catch (error) {
2512
2992
  console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
@@ -2515,99 +2995,9 @@ function loadSnapshotIfExists(config = {}) {
2515
2995
  }
2516
2996
  return null;
2517
2997
  }
2518
- function convertPocketBaseCollection(pbCollection) {
2519
- const fields = [];
2520
- const systemFieldNames = ["id", "created", "updated", "collectionId", "collectionName", "expand"];
2521
- const authSystemFieldNames = ["email", "emailVisibility", "verified", "password", "tokenKey"];
2522
- if (pbCollection.fields && Array.isArray(pbCollection.fields)) {
2523
- for (const pbField of pbCollection.fields) {
2524
- if (pbField.system || systemFieldNames.includes(pbField.name)) {
2525
- continue;
2526
- }
2527
- if (pbCollection.type === "auth" && authSystemFieldNames.includes(pbField.name)) {
2528
- continue;
2529
- }
2530
- const field = {
2531
- name: pbField.name,
2532
- type: pbField.type,
2533
- required: pbField.required || false
2534
- };
2535
- if (pbField.options) {
2536
- field.options = pbField.options;
2537
- }
2538
- if (pbField.type === "relation") {
2539
- field.relation = {
2540
- collection: pbField.options?.collectionId || "",
2541
- cascadeDelete: pbField.options?.cascadeDelete || false,
2542
- maxSelect: pbField.options?.maxSelect,
2543
- minSelect: pbField.options?.minSelect
2544
- };
2545
- }
2546
- fields.push(field);
2547
- }
2548
- }
2549
- const schema = {
2550
- name: pbCollection.name,
2551
- type: pbCollection.type || "base",
2552
- fields
2553
- };
2554
- if (pbCollection.indexes && Array.isArray(pbCollection.indexes)) {
2555
- schema.indexes = pbCollection.indexes;
2556
- }
2557
- const rules = {};
2558
- if (pbCollection.listRule !== void 0) rules.listRule = pbCollection.listRule;
2559
- if (pbCollection.viewRule !== void 0) rules.viewRule = pbCollection.viewRule;
2560
- if (pbCollection.createRule !== void 0) rules.createRule = pbCollection.createRule;
2561
- if (pbCollection.updateRule !== void 0) rules.updateRule = pbCollection.updateRule;
2562
- if (pbCollection.deleteRule !== void 0) rules.deleteRule = pbCollection.deleteRule;
2563
- if (pbCollection.manageRule !== void 0) rules.manageRule = pbCollection.manageRule;
2564
- if (Object.keys(rules).length > 0) {
2565
- schema.rules = rules;
2566
- }
2567
- return schema;
2568
- }
2569
- function convertPocketBaseMigration(migrationContent) {
2570
- try {
2571
- const snapshotMatch = migrationContent.match(/const\s+snapshot\s*=\s*(\[[\s\S]*?\]);/);
2572
- if (!snapshotMatch) {
2573
- throw new Error("Could not find snapshot array in migration file");
2574
- }
2575
- const snapshotArrayStr = snapshotMatch[1];
2576
- let snapshotArray;
2577
- try {
2578
- snapshotArray = new Function(`return ${snapshotArrayStr}`)();
2579
- } catch (parseError) {
2580
- throw new Error(`Failed to parse snapshot array: ${parseError}`);
2581
- }
2582
- if (!Array.isArray(snapshotArray)) {
2583
- throw new Error("Snapshot is not an array");
2584
- }
2585
- const collections = /* @__PURE__ */ new Map();
2586
- for (const pbCollection of snapshotArray) {
2587
- if (!pbCollection.name) {
2588
- console.warn("Skipping collection without name");
2589
- continue;
2590
- }
2591
- const schema = convertPocketBaseCollection(pbCollection);
2592
- collections.set(pbCollection.name, schema);
2593
- }
2594
- return {
2595
- version: SNAPSHOT_VERSION,
2596
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2597
- collections
2598
- };
2599
- } catch (error) {
2600
- throw new SnapshotError(
2601
- `Failed to convert PocketBase migration: ${error instanceof Error ? error.message : String(error)}`,
2602
- void 0,
2603
- "parse",
2604
- error instanceof Error ? error : void 0
2605
- );
2606
- }
2607
- }
2608
2998
  function loadBaseMigration(migrationPath) {
2609
2999
  try {
2610
- if (!fs2__namespace.existsSync(migrationPath)) {
3000
+ if (!fs3__namespace.existsSync(migrationPath)) {
2611
3001
  throw new SnapshotError(
2612
3002
  `Base migration file not found: ${migrationPath}
2613
3003
 
@@ -2618,7 +3008,7 @@ If the file exists in a different location, update the configuration.`,
2618
3008
  "read"
2619
3009
  );
2620
3010
  }
2621
- const migrationContent = fs2__namespace.readFileSync(migrationPath, "utf-8");
3011
+ const migrationContent = fs3__namespace.readFileSync(migrationPath, "utf-8");
2622
3012
  const snapshot = convertPocketBaseMigration(migrationContent);
2623
3013
  return snapshot;
2624
3014
  } catch (error) {
@@ -2654,14 +3044,14 @@ Please ensure PocketBase is properly set up by running 'yarn setup'.`,
2654
3044
  }
2655
3045
  }
2656
3046
  function getSnapshotVersion() {
2657
- return SNAPSHOT_VERSION;
3047
+ return SNAPSHOT_VERSION2;
2658
3048
  }
2659
3049
  function validateSnapshot(snapshot) {
2660
3050
  const issues = [];
2661
3051
  if (!snapshot.version) {
2662
3052
  issues.push("Missing version field");
2663
- } else if (compareVersions(snapshot.version, SNAPSHOT_VERSION) > 0) {
2664
- issues.push(`Snapshot version ${snapshot.version} is newer than supported version ${SNAPSHOT_VERSION}`);
3053
+ } else if (compareVersions(snapshot.version, SNAPSHOT_VERSION2) > 0) {
3054
+ issues.push(`Snapshot version ${snapshot.version} is newer than supported version ${SNAPSHOT_VERSION2}`);
2665
3055
  }
2666
3056
  if (!snapshot.timestamp) {
2667
3057
  issues.push("Missing timestamp field");
@@ -2880,6 +3270,9 @@ function compareFieldOptions(currentField, previousField) {
2880
3270
  for (const key of allKeys) {
2881
3271
  const currentValue = currentOptions[key];
2882
3272
  const previousValue = previousOptions[key];
3273
+ if (currentValue === void 0 && previousValue === void 0) {
3274
+ continue;
3275
+ }
2883
3276
  if (!areValuesEqual(currentValue, previousValue)) {
2884
3277
  changes.push({
2885
3278
  property: `options.${key}`,
@@ -2900,11 +3293,26 @@ function compareRelationConfigurations(currentField, previousField) {
2900
3293
  if (!currentRelation || !previousRelation) {
2901
3294
  return changes;
2902
3295
  }
2903
- if (currentRelation.collection !== previousRelation.collection) {
3296
+ const normalizeCollection = (collection) => {
3297
+ if (!collection) return collection;
3298
+ if (collection === "_pb_users_auth_") {
3299
+ return "Users";
3300
+ }
3301
+ const nameMatch = collection.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
3302
+ if (nameMatch) {
3303
+ return nameMatch[1];
3304
+ }
3305
+ return collection;
3306
+ };
3307
+ const normalizedCurrent = normalizeCollection(currentRelation.collection);
3308
+ const normalizedPrevious = normalizeCollection(previousRelation.collection);
3309
+ if (normalizedCurrent !== normalizedPrevious) {
2904
3310
  changes.push({
2905
3311
  property: "relation.collection",
2906
- oldValue: previousRelation.collection,
2907
- newValue: currentRelation.collection
3312
+ oldValue: normalizedPrevious,
3313
+ // Use normalized value for clarity
3314
+ newValue: normalizedCurrent
3315
+ // Use normalized value for clarity
2908
3316
  });
2909
3317
  }
2910
3318
  if (currentRelation.cascadeDelete !== previousRelation.cascadeDelete) {
@@ -3258,10 +3666,8 @@ var DiffEngine = class {
3258
3666
  var DEFAULT_TEMPLATE = `/// <reference path="{{TYPES_PATH}}" />
3259
3667
  migrate((app) => {
3260
3668
  {{UP_CODE}}
3261
- return true;
3262
3669
  }, (app) => {
3263
3670
  {{DOWN_CODE}}
3264
- return true;
3265
3671
  });
3266
3672
  `;
3267
3673
  var DEFAULT_CONFIG4 = {
@@ -3279,10 +3685,10 @@ function mergeConfig4(config) {
3279
3685
  }
3280
3686
  function resolveMigrationDir(config) {
3281
3687
  const workspaceRoot = config.workspaceRoot || process.cwd();
3282
- if (path4__namespace.isAbsolute(config.migrationDir)) {
3688
+ if (path5__namespace.isAbsolute(config.migrationDir)) {
3283
3689
  return config.migrationDir;
3284
3690
  }
3285
- return path4__namespace.join(workspaceRoot, config.migrationDir);
3691
+ return path5__namespace.join(workspaceRoot, config.migrationDir);
3286
3692
  }
3287
3693
  function generateTimestamp(config) {
3288
3694
  if (config?.timestampGenerator) {
@@ -3340,9 +3746,9 @@ function createMigrationFileStructure(upCode, downCode, config) {
3340
3746
  }
3341
3747
  function writeMigrationFile(migrationDir, filename, content) {
3342
3748
  try {
3343
- if (!fs2__namespace.existsSync(migrationDir)) {
3749
+ if (!fs3__namespace.existsSync(migrationDir)) {
3344
3750
  try {
3345
- fs2__namespace.mkdirSync(migrationDir, { recursive: true });
3751
+ fs3__namespace.mkdirSync(migrationDir, { recursive: true });
3346
3752
  } catch (error) {
3347
3753
  const fsError = error;
3348
3754
  if (fsError.code === "EACCES" || fsError.code === "EPERM") {
@@ -3363,15 +3769,15 @@ function writeMigrationFile(migrationDir, filename, content) {
3363
3769
  );
3364
3770
  }
3365
3771
  }
3366
- const filePath = path4__namespace.join(migrationDir, filename);
3367
- fs2__namespace.writeFileSync(filePath, content, "utf-8");
3772
+ const filePath = path5__namespace.join(migrationDir, filename);
3773
+ fs3__namespace.writeFileSync(filePath, content, "utf-8");
3368
3774
  return filePath;
3369
3775
  } catch (error) {
3370
3776
  if (error instanceof FileSystemError) {
3371
3777
  throw error;
3372
3778
  }
3373
3779
  const fsError = error;
3374
- const filePath = path4__namespace.join(migrationDir, filename);
3780
+ const filePath = path5__namespace.join(migrationDir, filename);
3375
3781
  if (fsError.code === "EACCES" || fsError.code === "EPERM") {
3376
3782
  throw new FileSystemError(
3377
3783
  `Permission denied writing migration file. Check file and directory permissions.`,
@@ -3426,7 +3832,8 @@ function generateFieldDefinitionObject(field) {
3426
3832
  }
3427
3833
  }
3428
3834
  if (field.relation) {
3429
- const collectionIdPlaceholder = field.relation.collection === "Users" ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3835
+ const isUsersCollection = field.relation.collection.toLowerCase() === "users";
3836
+ const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3430
3837
  parts.push(` collectionId: ${collectionIdPlaceholder}`);
3431
3838
  if (field.relation.maxSelect !== void 0) {
3432
3839
  parts.push(` maxSelect: ${field.relation.maxSelect}`);
@@ -3510,7 +3917,7 @@ function generateIndexesArray(indexes) {
3510
3917
  ${indexStrings.join(",\n ")},
3511
3918
  ]`;
3512
3919
  }
3513
- function generateCollectionCreation(collection, varName = "collection") {
3920
+ function generateCollectionCreation(collection, varName = "collection", isLast = false) {
3514
3921
  const lines = [];
3515
3922
  lines.push(` const ${varName} = new Collection({`);
3516
3923
  lines.push(` name: "${collection.name}",`);
@@ -3526,7 +3933,7 @@ function generateCollectionCreation(collection, varName = "collection") {
3526
3933
  lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
3527
3934
  lines.push(` });`);
3528
3935
  lines.push(``);
3529
- lines.push(` app.save(${varName});`);
3936
+ lines.push(isLast ? ` return app.save(${varName});` : ` app.save(${varName});`);
3530
3937
  return lines.join("\n");
3531
3938
  }
3532
3939
  function getFieldConstructorName(fieldType) {
@@ -3557,7 +3964,8 @@ function generateFieldConstructorOptions(field) {
3557
3964
  }
3558
3965
  }
3559
3966
  if (field.relation && field.type === "relation") {
3560
- const collectionIdPlaceholder = field.relation.collection === "Users" ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3967
+ const isUsersCollection = field.relation.collection.toLowerCase() === "users";
3968
+ const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3561
3969
  parts.push(` collectionId: ${collectionIdPlaceholder}`);
3562
3970
  if (field.relation.maxSelect !== void 0) {
3563
3971
  parts.push(` maxSelect: ${field.relation.maxSelect}`);
@@ -3571,7 +3979,7 @@ function generateFieldConstructorOptions(field) {
3571
3979
  }
3572
3980
  return parts.join(",\n");
3573
3981
  }
3574
- function generateFieldAddition(collectionName, field, varName) {
3982
+ function generateFieldAddition(collectionName, field, varName, isLast = false) {
3575
3983
  const lines = [];
3576
3984
  const constructorName = getFieldConstructorName(field.type);
3577
3985
  const collectionVar = varName || `collection_${collectionName}_${field.name}`;
@@ -3581,10 +3989,10 @@ function generateFieldAddition(collectionName, field, varName) {
3581
3989
  lines.push(generateFieldConstructorOptions(field));
3582
3990
  lines.push(` }));`);
3583
3991
  lines.push(``);
3584
- lines.push(` app.save(${collectionVar});`);
3992
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3585
3993
  return lines.join("\n");
3586
3994
  }
3587
- function generateFieldModification(collectionName, modification, varName) {
3995
+ function generateFieldModification(collectionName, modification, varName, isLast = false) {
3588
3996
  const lines = [];
3589
3997
  const collectionVar = varName || `collection_${collectionName}_${modification.fieldName}`;
3590
3998
  const fieldVar = `${collectionVar}_field`;
@@ -3598,7 +4006,8 @@ function generateFieldModification(collectionName, modification, varName) {
3598
4006
  } else if (change.property.startsWith("relation.")) {
3599
4007
  const relationKey = change.property.replace("relation.", "");
3600
4008
  if (relationKey === "collection") {
3601
- const collectionIdValue = change.newValue === "Users" ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${change.newValue}").id`;
4009
+ const isUsersCollection = String(change.newValue).toLowerCase() === "users";
4010
+ const collectionIdValue = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${change.newValue}").id`;
3602
4011
  lines.push(` ${fieldVar}.collectionId = ${collectionIdValue};`);
3603
4012
  } else {
3604
4013
  lines.push(` ${fieldVar}.${relationKey} = ${formatValue(change.newValue)};`);
@@ -3608,10 +4017,10 @@ function generateFieldModification(collectionName, modification, varName) {
3608
4017
  }
3609
4018
  }
3610
4019
  lines.push(``);
3611
- lines.push(` app.save(${collectionVar});`);
4020
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3612
4021
  return lines.join("\n");
3613
4022
  }
3614
- function generateFieldDeletion(collectionName, fieldName, varName) {
4023
+ function generateFieldDeletion(collectionName, fieldName, varName, isLast = false) {
3615
4024
  const lines = [];
3616
4025
  const collectionVar = varName || `collection_${collectionName}_${fieldName}`;
3617
4026
  const fieldVar = `${collectionVar}_field`;
@@ -3620,18 +4029,18 @@ function generateFieldDeletion(collectionName, fieldName, varName) {
3620
4029
  lines.push(``);
3621
4030
  lines.push(` ${collectionVar}.fields.remove(${fieldVar}.id);`);
3622
4031
  lines.push(``);
3623
- lines.push(` app.save(${collectionVar});`);
4032
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3624
4033
  return lines.join("\n");
3625
4034
  }
3626
- function generateIndexAddition(collectionName, index, varName) {
4035
+ function generateIndexAddition(collectionName, index, varName, isLast = false) {
3627
4036
  const lines = [];
3628
4037
  const collectionVar = varName || `collection_${collectionName}_idx`;
3629
4038
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3630
4039
  lines.push(` ${collectionVar}.indexes.push("${index}");`);
3631
- lines.push(` app.save(${collectionVar});`);
4040
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3632
4041
  return lines.join("\n");
3633
4042
  }
3634
- function generateIndexRemoval(collectionName, index, varName) {
4043
+ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
3635
4044
  const lines = [];
3636
4045
  const collectionVar = varName || `collection_${collectionName}_idx`;
3637
4046
  const indexVar = `${collectionVar}_indexToRemove`;
@@ -3640,29 +4049,29 @@ function generateIndexRemoval(collectionName, index, varName) {
3640
4049
  lines.push(` if (${indexVar} !== -1) {`);
3641
4050
  lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
3642
4051
  lines.push(` }`);
3643
- lines.push(` app.save(${collectionVar});`);
4052
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3644
4053
  return lines.join("\n");
3645
4054
  }
3646
- function generateRuleUpdate(collectionName, ruleType, newValue, varName) {
4055
+ function generateRuleUpdate(collectionName, ruleType, newValue, varName, isLast = false) {
3647
4056
  const lines = [];
3648
4057
  const collectionVar = varName || `collection_${collectionName}_${ruleType}`;
3649
4058
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3650
4059
  lines.push(` ${collectionVar}.${ruleType} = ${formatValue(newValue)};`);
3651
- lines.push(` app.save(${collectionVar});`);
4060
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3652
4061
  return lines.join("\n");
3653
4062
  }
3654
- function generatePermissionUpdate(collectionName, ruleType, newValue, varName) {
4063
+ function generatePermissionUpdate(collectionName, ruleType, newValue, varName, isLast = false) {
3655
4064
  const lines = [];
3656
4065
  const collectionVar = varName || `collection_${collectionName}_${ruleType}`;
3657
4066
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3658
4067
  lines.push(` ${collectionVar}.${ruleType} = ${formatValue(newValue)};`);
3659
- lines.push(` app.save(${collectionVar});`);
4068
+ lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3660
4069
  return lines.join("\n");
3661
4070
  }
3662
- function generateCollectionDeletion(collectionName, varName = "collection") {
4071
+ function generateCollectionDeletion(collectionName, varName = "collection", isLast = false) {
3663
4072
  const lines = [];
3664
4073
  lines.push(` const ${varName} = app.findCollectionByNameOrId("${collectionName}");`);
3665
- lines.push(` app.delete(${varName});`);
4074
+ lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
3666
4075
  return lines.join("\n");
3667
4076
  }
3668
4077
  function generateUpMigration(diff) {
@@ -3754,7 +4163,24 @@ function generateUpMigration(diff) {
3754
4163
  lines.push(` // No changes detected`);
3755
4164
  lines.push(``);
3756
4165
  }
3757
- return lines.join("\n");
4166
+ let code = lines.join("\n");
4167
+ const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
4168
+ const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
4169
+ const saveMatches = [...code.matchAll(savePattern)];
4170
+ const deleteMatches = [...code.matchAll(deletePattern)];
4171
+ const allMatches = [
4172
+ ...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
4173
+ ...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
4174
+ ].sort((a, b) => b.index - a.index);
4175
+ if (allMatches.length > 0) {
4176
+ const lastMatch = allMatches[0];
4177
+ if (lastMatch.type === "save") {
4178
+ 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);
4179
+ } else {
4180
+ 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);
4181
+ }
4182
+ }
4183
+ return code;
3758
4184
  }
3759
4185
  function generateDownMigration(diff) {
3760
4186
  const lines = [];
@@ -3856,7 +4282,24 @@ function generateDownMigration(diff) {
3856
4282
  lines.push(` // No changes to revert`);
3857
4283
  lines.push(``);
3858
4284
  }
3859
- return lines.join("\n");
4285
+ let code = lines.join("\n");
4286
+ const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
4287
+ const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
4288
+ const saveMatches = [...code.matchAll(savePattern)];
4289
+ const deleteMatches = [...code.matchAll(deletePattern)];
4290
+ const allMatches = [
4291
+ ...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
4292
+ ...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
4293
+ ].sort((a, b) => b.index - a.index);
4294
+ if (allMatches.length > 0) {
4295
+ const lastMatch = allMatches[0];
4296
+ if (lastMatch.type === "save") {
4297
+ 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);
4298
+ } else {
4299
+ 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);
4300
+ }
4301
+ }
4302
+ return code;
3860
4303
  }
3861
4304
  function generate(diff, config) {
3862
4305
  const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
@@ -4078,8 +4521,8 @@ var DEFAULT_CONFIG5 = {
4078
4521
  };
4079
4522
  function findConfigFile(directory) {
4080
4523
  for (const fileName of CONFIG_FILE_NAMES) {
4081
- const filePath = path4__namespace.join(directory, fileName);
4082
- if (fs2__namespace.existsSync(filePath)) {
4524
+ const filePath = path5__namespace.join(directory, fileName);
4525
+ if (fs3__namespace.existsSync(filePath)) {
4083
4526
  return filePath;
4084
4527
  }
4085
4528
  }
@@ -4087,7 +4530,7 @@ function findConfigFile(directory) {
4087
4530
  }
4088
4531
  function loadJsonConfig(configPath) {
4089
4532
  try {
4090
- const content = fs2__namespace.readFileSync(configPath, "utf-8");
4533
+ const content = fs3__namespace.readFileSync(configPath, "utf-8");
4091
4534
  return JSON.parse(content);
4092
4535
  } catch (error) {
4093
4536
  if (error instanceof SyntaxError) {
@@ -4116,10 +4559,10 @@ async function loadJsConfig(configPath) {
4116
4559
  }
4117
4560
  }
4118
4561
  async function loadConfigFile(configPath) {
4119
- if (!fs2__namespace.existsSync(configPath)) {
4562
+ if (!fs3__namespace.existsSync(configPath)) {
4120
4563
  return null;
4121
4564
  }
4122
- const ext = path4__namespace.extname(configPath).toLowerCase();
4565
+ const ext = path5__namespace.extname(configPath).toLowerCase();
4123
4566
  if (ext === ".json") {
4124
4567
  return loadJsonConfig(configPath);
4125
4568
  } else if (ext === ".js" || ext === ".mjs") {
@@ -4186,10 +4629,10 @@ function validateConfig(config, configPath) {
4186
4629
  }
4187
4630
  const cwd = process.cwd();
4188
4631
  const possiblePaths = [
4189
- path4__namespace.resolve(cwd, config.schema.directory),
4190
- path4__namespace.resolve(cwd, "shared", config.schema.directory)
4632
+ path5__namespace.resolve(cwd, config.schema.directory),
4633
+ path5__namespace.resolve(cwd, "shared", config.schema.directory)
4191
4634
  ];
4192
- const schemaDir = possiblePaths.find((p) => fs2__namespace.existsSync(p));
4635
+ const schemaDir = possiblePaths.find((p) => fs3__namespace.existsSync(p));
4193
4636
  if (!schemaDir) {
4194
4637
  throw new ConfigurationError(`Schema directory not found. Tried: ${possiblePaths.join(", ")}`, configPath, [
4195
4638
  "schema.directory"
@@ -4201,15 +4644,15 @@ async function loadConfig(options = {}) {
4201
4644
  let configFilePath;
4202
4645
  const cwd = process.cwd();
4203
4646
  if (options.config) {
4204
- const explicitPath = path4__namespace.resolve(cwd, options.config);
4205
- if (!fs2__namespace.existsSync(explicitPath)) {
4647
+ const explicitPath = path5__namespace.resolve(cwd, options.config);
4648
+ if (!fs3__namespace.existsSync(explicitPath)) {
4206
4649
  throw new ConfigurationError(`Configuration file not found: ${explicitPath}`, explicitPath);
4207
4650
  }
4208
4651
  configFilePath = explicitPath;
4209
4652
  } else {
4210
- const searchDirs = [cwd, path4__namespace.join(cwd, "shared")];
4653
+ const searchDirs = [cwd, path5__namespace.join(cwd, "shared")];
4211
4654
  for (const dir of searchDirs) {
4212
- if (fs2__namespace.existsSync(dir)) {
4655
+ if (fs3__namespace.existsSync(dir)) {
4213
4656
  const found = findConfigFile(dir);
4214
4657
  if (found) {
4215
4658
  configFilePath = found;
@@ -4238,18 +4681,18 @@ async function loadConfig(options = {}) {
4238
4681
  function getSchemaDirectory(config) {
4239
4682
  const cwd = process.cwd();
4240
4683
  const possiblePaths = [
4241
- path4__namespace.resolve(cwd, config.schema.directory),
4242
- path4__namespace.resolve(cwd, "shared", config.schema.directory)
4684
+ path5__namespace.resolve(cwd, config.schema.directory),
4685
+ path5__namespace.resolve(cwd, "shared", config.schema.directory)
4243
4686
  ];
4244
- return possiblePaths.find((p) => fs2__namespace.existsSync(p)) || possiblePaths[0];
4687
+ return possiblePaths.find((p) => fs3__namespace.existsSync(p)) || possiblePaths[0];
4245
4688
  }
4246
4689
  function getMigrationsDirectory(config) {
4247
4690
  const cwd = process.cwd();
4248
4691
  const possiblePaths = [
4249
- path4__namespace.resolve(cwd, config.migrations.directory),
4250
- path4__namespace.resolve(cwd, "shared", config.migrations.directory)
4692
+ path5__namespace.resolve(cwd, config.migrations.directory),
4693
+ path5__namespace.resolve(cwd, "shared", config.migrations.directory)
4251
4694
  ];
4252
- return possiblePaths.find((p) => fs2__namespace.existsSync(p)) || possiblePaths[0];
4695
+ return possiblePaths.find((p) => fs3__namespace.existsSync(p)) || possiblePaths[0];
4253
4696
  }
4254
4697
  var currentVerbosity = "normal";
4255
4698
  function setVerbosity(level) {
@@ -4457,10 +4900,16 @@ async function executeGenerate(options) {
4457
4900
  const schemaDir = getSchemaDirectory(config);
4458
4901
  const migrationsDir = getMigrationsDirectory(config);
4459
4902
  logSection("\u{1F50D} Analyzing Schema");
4460
- const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(schemaDir));
4903
+ const analyzerConfig = {
4904
+ schemaDir,
4905
+ excludePatterns: config.schema.exclude,
4906
+ useCompiledFiles: false
4907
+ // Use source files since we're in development/testing
4908
+ };
4909
+ const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
4461
4910
  logSuccess(`Found ${currentSchema.collections.size} collection(s)`);
4462
4911
  logInfo("Loading previous snapshot...");
4463
- const previousSnapshot = loadSnapshotIfExists({
4912
+ const previousSnapshot = loadSnapshotWithMigrations({
4464
4913
  migrationsPath: migrationsDir,
4465
4914
  workspaceRoot: process.cwd()
4466
4915
  });
@@ -4487,7 +4936,7 @@ async function executeGenerate(options) {
4487
4936
  "Creating migration file...",
4488
4937
  () => Promise.resolve(generate(diff, migrationsDir))
4489
4938
  );
4490
- logSuccess(`Migration file created: ${path4__namespace.basename(migrationPath)}`);
4939
+ logSuccess(`Migration file created: ${path5__namespace.basename(migrationPath)}`);
4491
4940
  logSection("\u2705 Next Steps");
4492
4941
  console.log();
4493
4942
  console.log(" 1. Review the generated migration file:");
@@ -4644,10 +5093,16 @@ async function executeStatus(options) {
4644
5093
  const schemaDir = getSchemaDirectory(config);
4645
5094
  const migrationsDir = getMigrationsDirectory(config);
4646
5095
  logSection("\u{1F50D} Checking Migration Status");
4647
- const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(schemaDir));
5096
+ const analyzerConfig = {
5097
+ schemaDir,
5098
+ excludePatterns: config.schema.exclude,
5099
+ useCompiledFiles: false
5100
+ // Use source files since we're in development/testing
5101
+ };
5102
+ const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
4648
5103
  logSuccess(`Found ${currentSchema.collections.size} collection(s) in schema`);
4649
5104
  logInfo("Loading previous snapshot...");
4650
- const previousSnapshot = loadSnapshotIfExists({
5105
+ const previousSnapshot = loadSnapshotWithMigrations({
4651
5106
  migrationsPath: migrationsDir,
4652
5107
  workspaceRoot: process.cwd()
4653
5108
  });
@@ -4796,6 +5251,7 @@ exports.extractComprehensiveFieldOptions = extractComprehensiveFieldOptions;
4796
5251
  exports.extractFieldDefinitions = extractFieldDefinitions;
4797
5252
  exports.extractFieldOptions = extractFieldOptions;
4798
5253
  exports.extractIndexes = extractIndexes;
5254
+ exports.extractRelationMetadata = extractRelationMetadata;
4799
5255
  exports.extractSchemaDefinitions = extractSchemaDefinitions;
4800
5256
  exports.fileField = fileField;
4801
5257
  exports.filesField = filesField;
@@ -4854,6 +5310,7 @@ exports.loadBaseMigration = loadBaseMigration;
4854
5310
  exports.loadConfig = loadConfig;
4855
5311
  exports.loadSnapshot = loadSnapshot;
4856
5312
  exports.loadSnapshotIfExists = loadSnapshotIfExists;
5313
+ exports.loadSnapshotWithMigrations = loadSnapshotWithMigrations;
4857
5314
  exports.logError = logError;
4858
5315
  exports.logInfo = logInfo;
4859
5316
  exports.logSection = logSection;