pocketbase-zod-schema 0.1.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +233 -98
  3. package/dist/cli/index.cjs +449 -108
  4. package/dist/cli/index.cjs.map +1 -1
  5. package/dist/cli/index.js +447 -106
  6. package/dist/cli/index.js.map +1 -1
  7. package/dist/cli/migrate.cjs +452 -111
  8. package/dist/cli/migrate.cjs.map +1 -1
  9. package/dist/cli/migrate.js +447 -106
  10. package/dist/cli/migrate.js.map +1 -1
  11. package/dist/index.cjs +593 -175
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.d.cts +4 -4
  14. package/dist/index.d.ts +4 -4
  15. package/dist/index.js +583 -172
  16. package/dist/index.js.map +1 -1
  17. package/dist/migration/analyzer.cjs +44 -6
  18. package/dist/migration/analyzer.cjs.map +1 -1
  19. package/dist/migration/analyzer.d.cts +11 -1
  20. package/dist/migration/analyzer.d.ts +11 -1
  21. package/dist/migration/analyzer.js +44 -7
  22. package/dist/migration/analyzer.js.map +1 -1
  23. package/dist/migration/diff.cjs +21 -3
  24. package/dist/migration/diff.cjs.map +1 -1
  25. package/dist/migration/diff.js +21 -3
  26. package/dist/migration/diff.js.map +1 -1
  27. package/dist/migration/index.cjs +500 -129
  28. package/dist/migration/index.cjs.map +1 -1
  29. package/dist/migration/index.d.cts +1 -1
  30. package/dist/migration/index.d.ts +1 -1
  31. package/dist/migration/index.js +499 -129
  32. package/dist/migration/index.js.map +1 -1
  33. package/dist/migration/snapshot.cjs +432 -118
  34. package/dist/migration/snapshot.cjs.map +1 -1
  35. package/dist/migration/snapshot.d.cts +34 -12
  36. package/dist/migration/snapshot.d.ts +34 -12
  37. package/dist/migration/snapshot.js +430 -117
  38. package/dist/migration/snapshot.js.map +1 -1
  39. package/dist/mutator.cjs +20 -21
  40. package/dist/mutator.cjs.map +1 -1
  41. package/dist/mutator.d.cts +4 -4
  42. package/dist/mutator.d.ts +4 -4
  43. package/dist/mutator.js +20 -21
  44. package/dist/mutator.js.map +1 -1
  45. package/dist/schema.cjs +69 -10
  46. package/dist/schema.cjs.map +1 -1
  47. package/dist/schema.d.cts +98 -8
  48. package/dist/schema.d.ts +98 -8
  49. package/dist/schema.js +62 -9
  50. package/dist/schema.js.map +1 -1
  51. package/dist/types.d.cts +5 -2
  52. package/dist/types.d.ts +5 -2
  53. package/dist/user-DTJQIj4K.d.cts +149 -0
  54. package/dist/user-DTJQIj4K.d.ts +149 -0
  55. package/package.json +3 -3
  56. package/dist/user-C39DQ40N.d.cts +0 -53
  57. package/dist/user-C39DQ40N.d.ts +0 -53
@@ -3,8 +3,8 @@
3
3
 
4
4
  var chalk = require('chalk');
5
5
  var commander = require('commander');
6
- var fs4 = require('fs');
7
- var path4 = require('path');
6
+ var fs5 = require('fs');
7
+ var path5 = require('path');
8
8
  var url = require('url');
9
9
  var zod = require('zod');
10
10
  var ora = require('ora');
@@ -30,8 +30,8 @@ function _interopNamespace(e) {
30
30
  }
31
31
 
32
32
  var chalk__default = /*#__PURE__*/_interopDefault(chalk);
33
- var fs4__namespace = /*#__PURE__*/_interopNamespace(fs4);
34
- var path4__namespace = /*#__PURE__*/_interopNamespace(path4);
33
+ var fs5__namespace = /*#__PURE__*/_interopNamespace(fs5);
34
+ var path5__namespace = /*#__PURE__*/_interopNamespace(path5);
35
35
  var ora__default = /*#__PURE__*/_interopDefault(ora);
36
36
 
37
37
  // ../node_modules/tsup/assets/cjs_shims.js
@@ -164,10 +164,10 @@ var FileSystemError = class _FileSystemError extends MigrationError {
164
164
  operation;
165
165
  code;
166
166
  originalError;
167
- constructor(message, path6, operation, code, originalError) {
167
+ constructor(message, path7, operation, code, originalError) {
168
168
  super(message);
169
169
  this.name = "FileSystemError";
170
- this.path = path6;
170
+ this.path = path7;
171
171
  this.operation = operation;
172
172
  this.code = code;
173
173
  this.originalError = originalError;
@@ -1081,6 +1081,16 @@ function isFieldRequired(zodType) {
1081
1081
  }
1082
1082
 
1083
1083
  // src/migration/analyzer.ts
1084
+ var tsxLoaderRegistered = false;
1085
+ async function ensureTsxLoader() {
1086
+ if (tsxLoaderRegistered) return;
1087
+ try {
1088
+ await import('tsx/esm');
1089
+ tsxLoaderRegistered = true;
1090
+ } catch {
1091
+ tsxLoaderRegistered = false;
1092
+ }
1093
+ }
1084
1094
  var DEFAULT_CONFIG = {
1085
1095
  workspaceRoot: process.cwd(),
1086
1096
  excludePatterns: [
@@ -1108,20 +1118,20 @@ function mergeConfig(config) {
1108
1118
  }
1109
1119
  function resolveSchemaDir(config) {
1110
1120
  const workspaceRoot = config.workspaceRoot || process.cwd();
1111
- if (path4__namespace.isAbsolute(config.schemaDir)) {
1121
+ if (path5__namespace.isAbsolute(config.schemaDir)) {
1112
1122
  return config.schemaDir;
1113
1123
  }
1114
- return path4__namespace.join(workspaceRoot, config.schemaDir);
1124
+ return path5__namespace.join(workspaceRoot, config.schemaDir);
1115
1125
  }
1116
1126
  function discoverSchemaFiles(config) {
1117
1127
  const normalizedConfig = typeof config === "string" ? { schemaDir: config } : config;
1118
1128
  const mergedConfig = mergeConfig(normalizedConfig);
1119
1129
  const schemaDir = resolveSchemaDir(normalizedConfig);
1120
1130
  try {
1121
- if (!fs4__namespace.existsSync(schemaDir)) {
1131
+ if (!fs5__namespace.existsSync(schemaDir)) {
1122
1132
  throw new FileSystemError(`Schema directory not found: ${schemaDir}`, schemaDir, "access", "ENOENT");
1123
1133
  }
1124
- const files = fs4__namespace.readdirSync(schemaDir);
1134
+ const files = fs5__namespace.readdirSync(schemaDir);
1125
1135
  const schemaFiles = files.filter((file) => {
1126
1136
  const hasValidExtension = mergedConfig.includeExtensions.some((ext) => file.endsWith(ext));
1127
1137
  if (!hasValidExtension) return false;
@@ -1137,7 +1147,7 @@ function discoverSchemaFiles(config) {
1137
1147
  });
1138
1148
  return schemaFiles.map((file) => {
1139
1149
  const ext = mergedConfig.includeExtensions.find((ext2) => file.endsWith(ext2)) || ".ts";
1140
- return path4__namespace.join(schemaDir, file.replace(new RegExp(`\\${ext}$`), ""));
1150
+ return path5__namespace.join(schemaDir, file.replace(new RegExp(`\\${ext}$`), ""));
1141
1151
  });
1142
1152
  } catch (error) {
1143
1153
  if (error instanceof FileSystemError) {
@@ -1171,40 +1181,66 @@ async function importSchemaModule(filePath, config) {
1171
1181
  let resolvedPath = null;
1172
1182
  const jsPath = `${importPath}.js`;
1173
1183
  const tsPath = `${importPath}.ts`;
1174
- if (fs4__namespace.existsSync(jsPath)) {
1184
+ if (fs5__namespace.existsSync(jsPath)) {
1175
1185
  resolvedPath = jsPath;
1176
- } else if (fs4__namespace.existsSync(tsPath)) {
1186
+ } else if (fs5__namespace.existsSync(tsPath)) {
1177
1187
  resolvedPath = tsPath;
1178
1188
  } else {
1179
1189
  resolvedPath = jsPath;
1180
1190
  }
1181
- const fileUrl = new URL(`file://${path4__namespace.resolve(resolvedPath)}`);
1191
+ if (resolvedPath.endsWith(".ts")) {
1192
+ await ensureTsxLoader();
1193
+ if (!tsxLoaderRegistered) {
1194
+ throw new SchemaParsingError(
1195
+ `Failed to import TypeScript schema file. The 'tsx' package is required to load TypeScript files.
1196
+ Please install tsx: npm install tsx (or yarn add tsx, or pnpm add tsx)
1197
+ Alternatively, compile your schema files to JavaScript first.`,
1198
+ filePath
1199
+ );
1200
+ }
1201
+ }
1202
+ const fileUrl = new URL(`file://${path5__namespace.resolve(resolvedPath)}`);
1182
1203
  const module = await import(fileUrl.href);
1183
1204
  return module;
1184
1205
  } catch (error) {
1185
1206
  const tsPath = `${filePath}.ts`;
1186
- const isTypeScriptFile = fs4__namespace.existsSync(tsPath);
1207
+ const isTypeScriptFile = fs5__namespace.existsSync(tsPath);
1208
+ if (isTypeScriptFile && error instanceof SchemaParsingError) {
1209
+ throw error;
1210
+ }
1187
1211
  if (isTypeScriptFile) {
1188
1212
  throw new SchemaParsingError(
1189
- `Failed to import TypeScript schema file. Node.js cannot import TypeScript files directly.
1190
- Please either:
1191
- 1. Compile your schema files to JavaScript first, or
1192
- 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")`,
1213
+ `Failed to import TypeScript schema file. The 'tsx' package is required to load TypeScript files.
1214
+ Please install tsx: npm install tsx (or yarn add tsx, or pnpm add tsx)
1215
+ Alternatively, compile your schema files to JavaScript first.`,
1193
1216
  filePath,
1194
1217
  error
1195
1218
  );
1196
1219
  }
1197
1220
  throw new SchemaParsingError(
1198
- `Failed to import schema module. Make sure the schema files are compiled to JavaScript.`,
1221
+ `Failed to import schema module. Make sure the schema files exist and are valid.`,
1199
1222
  filePath,
1200
1223
  error
1201
1224
  );
1202
1225
  }
1203
1226
  }
1204
1227
  function getCollectionNameFromFile(filePath) {
1205
- const filename = path4__namespace.basename(filePath).replace(/\.(ts|js)$/, "");
1228
+ const filename = path5__namespace.basename(filePath).replace(/\.(ts|js)$/, "");
1206
1229
  return toCollectionName(filename);
1207
1230
  }
1231
+ function extractCollectionNameFromSchema(zodSchema) {
1232
+ if (!zodSchema.description) {
1233
+ return null;
1234
+ }
1235
+ try {
1236
+ const metadata = JSON.parse(zodSchema.description);
1237
+ if (metadata.collectionName && typeof metadata.collectionName === "string") {
1238
+ return metadata.collectionName;
1239
+ }
1240
+ } catch {
1241
+ }
1242
+ return null;
1243
+ }
1208
1244
  function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema"]) {
1209
1245
  const result = {};
1210
1246
  for (const [key, value] of Object.entries(module)) {
@@ -1367,7 +1403,7 @@ async function buildSchemaDefinition(config) {
1367
1403
  importPath = normalizedConfig.pathTransformer(filePath);
1368
1404
  } else if (mergedConfig.useCompiledFiles) {
1369
1405
  const distPath = filePath.replace(/\/src\//, "/dist/");
1370
- if (fs4__namespace.existsSync(`${distPath}.js`) || fs4__namespace.existsSync(`${distPath}.mjs`)) {
1406
+ if (fs5__namespace.existsSync(`${distPath}.js`) || fs5__namespace.existsSync(`${distPath}.mjs`)) {
1371
1407
  importPath = distPath;
1372
1408
  } else {
1373
1409
  importPath = filePath;
@@ -1380,7 +1416,8 @@ async function buildSchemaDefinition(config) {
1380
1416
  console.warn(`No valid schema found in ${filePath}, skipping...`);
1381
1417
  continue;
1382
1418
  }
1383
- const collectionName = getCollectionNameFromFile(filePath);
1419
+ const collectionNameFromSchema = extractCollectionNameFromSchema(zodSchema);
1420
+ const collectionName = collectionNameFromSchema ?? getCollectionNameFromFile(filePath);
1384
1421
  const collectionSchema = convertZodSchemaToCollectionSchema(collectionName, zodSchema);
1385
1422
  collections.set(collectionName, collectionSchema);
1386
1423
  } catch (error) {
@@ -1544,6 +1581,9 @@ function compareFieldOptions(currentField, previousField) {
1544
1581
  for (const key of allKeys) {
1545
1582
  const currentValue = currentOptions[key];
1546
1583
  const previousValue = previousOptions[key];
1584
+ if (currentValue === void 0 && previousValue === void 0) {
1585
+ continue;
1586
+ }
1547
1587
  if (!areValuesEqual(currentValue, previousValue)) {
1548
1588
  changes.push({
1549
1589
  property: `options.${key}`,
@@ -1564,11 +1604,26 @@ function compareRelationConfigurations(currentField, previousField) {
1564
1604
  if (!currentRelation || !previousRelation) {
1565
1605
  return changes;
1566
1606
  }
1567
- if (currentRelation.collection !== previousRelation.collection) {
1607
+ const normalizeCollection = (collection) => {
1608
+ if (!collection) return collection;
1609
+ if (collection === "_pb_users_auth_") {
1610
+ return "Users";
1611
+ }
1612
+ const nameMatch = collection.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
1613
+ if (nameMatch) {
1614
+ return nameMatch[1];
1615
+ }
1616
+ return collection;
1617
+ };
1618
+ const normalizedCurrent = normalizeCollection(currentRelation.collection);
1619
+ const normalizedPrevious = normalizeCollection(previousRelation.collection);
1620
+ if (normalizedCurrent !== normalizedPrevious) {
1568
1621
  changes.push({
1569
1622
  property: "relation.collection",
1570
- oldValue: previousRelation.collection,
1571
- newValue: currentRelation.collection
1623
+ oldValue: normalizedPrevious,
1624
+ // Use normalized value for clarity
1625
+ newValue: normalizedCurrent
1626
+ // Use normalized value for clarity
1572
1627
  });
1573
1628
  }
1574
1629
  if (currentRelation.cascadeDelete !== previousRelation.cascadeDelete) {
@@ -1788,10 +1843,10 @@ function mergeConfig3(config) {
1788
1843
  }
1789
1844
  function resolveMigrationDir(config) {
1790
1845
  const workspaceRoot = config.workspaceRoot || process.cwd();
1791
- if (path4__namespace.isAbsolute(config.migrationDir)) {
1846
+ if (path5__namespace.isAbsolute(config.migrationDir)) {
1792
1847
  return config.migrationDir;
1793
1848
  }
1794
- return path4__namespace.join(workspaceRoot, config.migrationDir);
1849
+ return path5__namespace.join(workspaceRoot, config.migrationDir);
1795
1850
  }
1796
1851
  function generateTimestamp(config) {
1797
1852
  if (config?.timestampGenerator) {
@@ -1849,9 +1904,9 @@ function createMigrationFileStructure(upCode, downCode, config) {
1849
1904
  }
1850
1905
  function writeMigrationFile(migrationDir, filename, content) {
1851
1906
  try {
1852
- if (!fs4__namespace.existsSync(migrationDir)) {
1907
+ if (!fs5__namespace.existsSync(migrationDir)) {
1853
1908
  try {
1854
- fs4__namespace.mkdirSync(migrationDir, { recursive: true });
1909
+ fs5__namespace.mkdirSync(migrationDir, { recursive: true });
1855
1910
  } catch (error) {
1856
1911
  const fsError = error;
1857
1912
  if (fsError.code === "EACCES" || fsError.code === "EPERM") {
@@ -1872,15 +1927,15 @@ function writeMigrationFile(migrationDir, filename, content) {
1872
1927
  );
1873
1928
  }
1874
1929
  }
1875
- const filePath = path4__namespace.join(migrationDir, filename);
1876
- fs4__namespace.writeFileSync(filePath, content, "utf-8");
1930
+ const filePath = path5__namespace.join(migrationDir, filename);
1931
+ fs5__namespace.writeFileSync(filePath, content, "utf-8");
1877
1932
  return filePath;
1878
1933
  } catch (error) {
1879
1934
  if (error instanceof FileSystemError) {
1880
1935
  throw error;
1881
1936
  }
1882
1937
  const fsError = error;
1883
- const filePath = path4__namespace.join(migrationDir, filename);
1938
+ const filePath = path5__namespace.join(migrationDir, filename);
1884
1939
  if (fsError.code === "EACCES" || fsError.code === "EPERM") {
1885
1940
  throw new FileSystemError(
1886
1941
  `Permission denied writing migration file. Check file and directory permissions.`,
@@ -2425,57 +2480,18 @@ function generate(diff, config) {
2425
2480
  );
2426
2481
  }
2427
2482
  }
2483
+
2484
+ // src/migration/pocketbase-converter.ts
2428
2485
  var SNAPSHOT_VERSION = "1.0.0";
2429
- ({
2430
- workspaceRoot: process.cwd()});
2431
- function findLatestSnapshot(migrationsPath) {
2432
- try {
2433
- if (!fs4__namespace.existsSync(migrationsPath)) {
2434
- return null;
2435
- }
2436
- const files = fs4__namespace.readdirSync(migrationsPath);
2437
- const snapshotFiles = files.filter(
2438
- (file) => file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")
2439
- );
2440
- if (snapshotFiles.length === 0) {
2441
- return null;
2442
- }
2443
- snapshotFiles.sort().reverse();
2444
- const latestSnapshot = snapshotFiles[0];
2445
- if (!latestSnapshot) {
2446
- return null;
2447
- }
2448
- return path4__namespace.join(migrationsPath, latestSnapshot);
2449
- } catch (error) {
2450
- console.warn(`Error finding latest snapshot: ${error}`);
2451
- return null;
2486
+ function resolveCollectionIdToName(collectionId) {
2487
+ if (collectionId === "_pb_users_auth_") {
2488
+ return "Users";
2452
2489
  }
2453
- }
2454
- function loadSnapshotIfExists(config = {}) {
2455
- const migrationsPath = config.migrationsPath;
2456
- if (!migrationsPath) {
2457
- return null;
2458
- }
2459
- if (fs4__namespace.existsSync(migrationsPath) && fs4__namespace.statSync(migrationsPath).isFile()) {
2460
- try {
2461
- const migrationContent = fs4__namespace.readFileSync(migrationsPath, "utf-8");
2462
- return convertPocketBaseMigration(migrationContent);
2463
- } catch (error) {
2464
- console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
2465
- return null;
2466
- }
2490
+ const nameMatch = collectionId.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
2491
+ if (nameMatch) {
2492
+ return nameMatch[1];
2467
2493
  }
2468
- const latestSnapshotPath = findLatestSnapshot(migrationsPath);
2469
- if (latestSnapshotPath) {
2470
- try {
2471
- const migrationContent = fs4__namespace.readFileSync(latestSnapshotPath, "utf-8");
2472
- return convertPocketBaseMigration(migrationContent);
2473
- } catch (error) {
2474
- console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
2475
- return null;
2476
- }
2477
- }
2478
- return null;
2494
+ return collectionId;
2479
2495
  }
2480
2496
  function convertPocketBaseCollection(pbCollection) {
2481
2497
  const fields = [];
@@ -2494,17 +2510,28 @@ function convertPocketBaseCollection(pbCollection) {
2494
2510
  type: pbField.type,
2495
2511
  required: pbField.required || false
2496
2512
  };
2497
- if (pbField.options) {
2498
- field.options = pbField.options;
2513
+ field.options = pbField.options ? { ...pbField.options } : {};
2514
+ if (pbField.type === "select") {
2515
+ if (pbField.values && Array.isArray(pbField.values)) {
2516
+ field.options.values = pbField.values;
2517
+ } else if (pbField.options?.values && Array.isArray(pbField.options.values)) {
2518
+ field.options.values = pbField.options.values;
2519
+ }
2499
2520
  }
2500
2521
  if (pbField.type === "relation") {
2522
+ const collectionId = pbField.collectionId || pbField.options?.collectionId || "";
2523
+ const collectionName = resolveCollectionIdToName(collectionId);
2501
2524
  field.relation = {
2502
- collection: pbField.options?.collectionId || "",
2503
- cascadeDelete: pbField.options?.cascadeDelete || false,
2504
- maxSelect: pbField.options?.maxSelect,
2505
- minSelect: pbField.options?.minSelect
2525
+ collection: collectionName,
2526
+ cascadeDelete: pbField.cascadeDelete ?? pbField.options?.cascadeDelete ?? false,
2527
+ maxSelect: pbField.maxSelect ?? pbField.options?.maxSelect,
2528
+ minSelect: pbField.minSelect ?? pbField.options?.minSelect
2506
2529
  };
2507
2530
  }
2531
+ const hasOnlyValues = Object.keys(field.options).length === 1 && field.options.values !== void 0;
2532
+ if (Object.keys(field.options).length === 0) {
2533
+ delete field.options;
2534
+ } else if (pbField.type === "select" && hasOnlyValues) ;
2508
2535
  fields.push(field);
2509
2536
  }
2510
2537
  }
@@ -2569,6 +2596,320 @@ function convertPocketBaseMigration(migrationContent) {
2569
2596
  }
2570
2597
  }
2571
2598
 
2599
+ // src/migration/migration-parser.ts
2600
+ function extractTimestampFromFilename(filename) {
2601
+ const match = filename.match(/^(\d+)_/);
2602
+ if (match) {
2603
+ return parseInt(match[1], 10);
2604
+ }
2605
+ return null;
2606
+ }
2607
+ function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
2608
+ try {
2609
+ if (!fs5__namespace.existsSync(migrationsPath)) {
2610
+ return [];
2611
+ }
2612
+ const files = fs5__namespace.readdirSync(migrationsPath);
2613
+ const migrationFiles = [];
2614
+ for (const file of files) {
2615
+ if (file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")) {
2616
+ continue;
2617
+ }
2618
+ if (!file.endsWith(".js")) {
2619
+ continue;
2620
+ }
2621
+ const timestamp = extractTimestampFromFilename(file);
2622
+ if (timestamp && timestamp > snapshotTimestamp) {
2623
+ migrationFiles.push({
2624
+ path: path5__namespace.join(migrationsPath, file),
2625
+ timestamp
2626
+ });
2627
+ }
2628
+ }
2629
+ migrationFiles.sort((a, b) => a.timestamp - b.timestamp);
2630
+ return migrationFiles.map((f) => f.path);
2631
+ } catch (error) {
2632
+ console.warn(`Error finding migrations after snapshot: ${error}`);
2633
+ return [];
2634
+ }
2635
+ }
2636
+ function parseMigrationOperationsFromContent(content) {
2637
+ const collectionsToCreate = [];
2638
+ const collectionsToDelete = [];
2639
+ try {
2640
+ let searchIndex = 0;
2641
+ while (true) {
2642
+ const collectionStart = content.indexOf("new Collection(", searchIndex);
2643
+ if (collectionStart === -1) {
2644
+ break;
2645
+ }
2646
+ const openParen = collectionStart + "new Collection(".length;
2647
+ let braceCount = 0;
2648
+ let parenCount = 1;
2649
+ let inString = false;
2650
+ let stringChar = null;
2651
+ let i = openParen;
2652
+ while (i < content.length && /\s/.test(content[i])) {
2653
+ i++;
2654
+ }
2655
+ if (content[i] !== "{") {
2656
+ searchIndex = i + 1;
2657
+ continue;
2658
+ }
2659
+ const objectStart = i;
2660
+ braceCount = 1;
2661
+ i++;
2662
+ while (i < content.length && (braceCount > 0 || parenCount > 0)) {
2663
+ const char = content[i];
2664
+ const prevChar = i > 0 ? content[i - 1] : "";
2665
+ if (!inString && (char === '"' || char === "'")) {
2666
+ inString = true;
2667
+ stringChar = char;
2668
+ } else if (inString && char === stringChar && prevChar !== "\\") {
2669
+ inString = false;
2670
+ stringChar = null;
2671
+ }
2672
+ if (!inString) {
2673
+ if (char === "{") braceCount++;
2674
+ if (char === "}") braceCount--;
2675
+ if (char === "(") parenCount++;
2676
+ if (char === ")") parenCount--;
2677
+ }
2678
+ i++;
2679
+ }
2680
+ if (braceCount === 0 && parenCount === 0) {
2681
+ const objectContent = content.substring(objectStart, i - 1);
2682
+ try {
2683
+ const collectionObj = new Function(`return ${objectContent}`)();
2684
+ if (collectionObj && collectionObj.name) {
2685
+ const schema = convertPocketBaseCollection(collectionObj);
2686
+ collectionsToCreate.push(schema);
2687
+ }
2688
+ } catch (error) {
2689
+ console.warn(`Failed to parse collection definition: ${error}`);
2690
+ }
2691
+ }
2692
+ searchIndex = i;
2693
+ }
2694
+ const deleteMatches = content.matchAll(
2695
+ /app\.delete\s*\(\s*(?:collection_\w+|app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\))\s*\)/g
2696
+ );
2697
+ for (const match of deleteMatches) {
2698
+ if (match[1]) {
2699
+ collectionsToDelete.push(match[1]);
2700
+ } else {
2701
+ const varNameMatch = match[0].match(/collection_(\w+)/);
2702
+ if (varNameMatch) {
2703
+ const varName = `collection_${varNameMatch[1]}`;
2704
+ const deleteIndex = content.indexOf(match[0]);
2705
+ const beforeDelete = content.substring(0, deleteIndex);
2706
+ const varDefMatch = beforeDelete.match(
2707
+ new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`, "g")
2708
+ );
2709
+ if (varDefMatch && varDefMatch.length > 0) {
2710
+ const collectionDefMatch = beforeDelete.match(
2711
+ new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`)
2712
+ );
2713
+ if (collectionDefMatch) {
2714
+ try {
2715
+ const collectionDefStr = collectionDefMatch[1];
2716
+ const collectionObj = new Function(`return ${collectionDefStr}`)();
2717
+ if (collectionObj && collectionObj.name) {
2718
+ collectionsToDelete.push(collectionObj.name);
2719
+ }
2720
+ } catch {
2721
+ }
2722
+ }
2723
+ }
2724
+ }
2725
+ }
2726
+ }
2727
+ const findAndDeleteMatches = content.matchAll(
2728
+ /app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)[\s\S]*?app\.delete/g
2729
+ );
2730
+ for (const match of findAndDeleteMatches) {
2731
+ collectionsToDelete.push(match[1]);
2732
+ }
2733
+ } catch (error) {
2734
+ console.warn(`Failed to parse migration operations from content: ${error}`);
2735
+ }
2736
+ return { collectionsToCreate, collectionsToDelete };
2737
+ }
2738
+ function parseMigrationOperations(migrationContent) {
2739
+ try {
2740
+ const migrateMatch = migrationContent.match(/migrate\s*\(\s*/);
2741
+ if (!migrateMatch) {
2742
+ return parseMigrationOperationsFromContent(migrationContent);
2743
+ }
2744
+ const startIndex = migrateMatch.index + migrateMatch[0].length;
2745
+ let i = startIndex;
2746
+ let parenCount = 0;
2747
+ let foundFirstParen = false;
2748
+ while (i < migrationContent.length) {
2749
+ const char = migrationContent[i];
2750
+ if (char === "(") {
2751
+ parenCount++;
2752
+ foundFirstParen = true;
2753
+ i++;
2754
+ break;
2755
+ }
2756
+ i++;
2757
+ }
2758
+ if (!foundFirstParen) {
2759
+ return parseMigrationOperationsFromContent(migrationContent);
2760
+ }
2761
+ let inString = false;
2762
+ let stringChar = null;
2763
+ let foundBrace = false;
2764
+ let braceStart = -1;
2765
+ while (i < migrationContent.length && !foundBrace) {
2766
+ const char = migrationContent[i];
2767
+ const prevChar = i > 0 ? migrationContent[i - 1] : "";
2768
+ if (!inString && (char === '"' || char === "'")) {
2769
+ inString = true;
2770
+ stringChar = char;
2771
+ } else if (inString && char === stringChar && prevChar !== "\\") {
2772
+ inString = false;
2773
+ stringChar = null;
2774
+ }
2775
+ if (!inString) {
2776
+ if (char === "(") parenCount++;
2777
+ if (char === ")") {
2778
+ parenCount--;
2779
+ if (parenCount === 0) {
2780
+ i++;
2781
+ while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
2782
+ i++;
2783
+ }
2784
+ if (i < migrationContent.length - 1 && migrationContent[i] === "=" && migrationContent[i + 1] === ">") {
2785
+ i += 2;
2786
+ while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
2787
+ i++;
2788
+ }
2789
+ if (i < migrationContent.length && migrationContent[i] === "{") {
2790
+ foundBrace = true;
2791
+ braceStart = i + 1;
2792
+ break;
2793
+ }
2794
+ }
2795
+ }
2796
+ }
2797
+ }
2798
+ i++;
2799
+ }
2800
+ if (!foundBrace || braceStart === -1) {
2801
+ return parseMigrationOperationsFromContent(migrationContent);
2802
+ }
2803
+ let braceCount = 1;
2804
+ i = braceStart;
2805
+ inString = false;
2806
+ stringChar = null;
2807
+ while (i < migrationContent.length && braceCount > 0) {
2808
+ const char = migrationContent[i];
2809
+ const prevChar = i > 0 ? migrationContent[i - 1] : "";
2810
+ if (!inString && (char === '"' || char === "'")) {
2811
+ inString = true;
2812
+ stringChar = char;
2813
+ } else if (inString && char === stringChar && prevChar !== "\\") {
2814
+ inString = false;
2815
+ stringChar = null;
2816
+ }
2817
+ if (!inString) {
2818
+ if (char === "{") braceCount++;
2819
+ if (char === "}") braceCount--;
2820
+ }
2821
+ i++;
2822
+ }
2823
+ if (braceCount === 0) {
2824
+ const upMigrationContent = migrationContent.substring(braceStart, i - 1);
2825
+ return parseMigrationOperationsFromContent(upMigrationContent);
2826
+ }
2827
+ return parseMigrationOperationsFromContent(migrationContent);
2828
+ } catch (error) {
2829
+ console.warn(`Failed to parse migration operations: ${error}`);
2830
+ return { collectionsToCreate: [], collectionsToDelete: [] };
2831
+ }
2832
+ }
2833
+ ({
2834
+ workspaceRoot: process.cwd()});
2835
+ function findLatestSnapshot(migrationsPath) {
2836
+ try {
2837
+ if (!fs5__namespace.existsSync(migrationsPath)) {
2838
+ return null;
2839
+ }
2840
+ const files = fs5__namespace.readdirSync(migrationsPath);
2841
+ const snapshotFiles = files.filter(
2842
+ (file) => file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")
2843
+ );
2844
+ if (snapshotFiles.length === 0) {
2845
+ return null;
2846
+ }
2847
+ snapshotFiles.sort().reverse();
2848
+ const latestSnapshot = snapshotFiles[0];
2849
+ if (!latestSnapshot) {
2850
+ return null;
2851
+ }
2852
+ return path5__namespace.join(migrationsPath, latestSnapshot);
2853
+ } catch (error) {
2854
+ console.warn(`Error finding latest snapshot: ${error}`);
2855
+ return null;
2856
+ }
2857
+ }
2858
+ function applyMigrationOperations(snapshot, operations) {
2859
+ const updatedCollections = new Map(snapshot.collections);
2860
+ for (const collectionName of operations.collectionsToDelete) {
2861
+ updatedCollections.delete(collectionName);
2862
+ }
2863
+ for (const collection of operations.collectionsToCreate) {
2864
+ updatedCollections.set(collection.name, collection);
2865
+ }
2866
+ return {
2867
+ ...snapshot,
2868
+ collections: updatedCollections
2869
+ };
2870
+ }
2871
+ function loadSnapshotWithMigrations(config = {}) {
2872
+ const migrationsPath = config.migrationsPath;
2873
+ if (!migrationsPath) {
2874
+ return null;
2875
+ }
2876
+ if (fs5__namespace.existsSync(migrationsPath) && fs5__namespace.statSync(migrationsPath).isFile()) {
2877
+ try {
2878
+ const migrationContent = fs5__namespace.readFileSync(migrationsPath, "utf-8");
2879
+ return convertPocketBaseMigration(migrationContent);
2880
+ } catch (error) {
2881
+ console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
2882
+ return null;
2883
+ }
2884
+ }
2885
+ const latestSnapshotPath = findLatestSnapshot(migrationsPath);
2886
+ if (!latestSnapshotPath) {
2887
+ return null;
2888
+ }
2889
+ try {
2890
+ const migrationContent = fs5__namespace.readFileSync(latestSnapshotPath, "utf-8");
2891
+ let snapshot = convertPocketBaseMigration(migrationContent);
2892
+ const snapshotFilename = path5__namespace.basename(latestSnapshotPath);
2893
+ const snapshotTimestamp = extractTimestampFromFilename(snapshotFilename);
2894
+ if (snapshotTimestamp) {
2895
+ const migrationFiles = findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp);
2896
+ for (const migrationFile of migrationFiles) {
2897
+ try {
2898
+ const migrationContent2 = fs5__namespace.readFileSync(migrationFile, "utf-8");
2899
+ const operations = parseMigrationOperations(migrationContent2);
2900
+ snapshot = applyMigrationOperations(snapshot, operations);
2901
+ } catch (error) {
2902
+ console.warn(`Failed to apply migration ${migrationFile}: ${error}`);
2903
+ }
2904
+ }
2905
+ }
2906
+ return snapshot;
2907
+ } catch (error) {
2908
+ console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
2909
+ return null;
2910
+ }
2911
+ }
2912
+
2572
2913
  // src/migration/validation.ts
2573
2914
  function detectCollectionDeletions(diff) {
2574
2915
  const changes = [];
@@ -2737,8 +3078,8 @@ var DEFAULT_CONFIG5 = {
2737
3078
  };
2738
3079
  function findConfigFile(directory) {
2739
3080
  for (const fileName of CONFIG_FILE_NAMES) {
2740
- const filePath = path4__namespace.join(directory, fileName);
2741
- if (fs4__namespace.existsSync(filePath)) {
3081
+ const filePath = path5__namespace.join(directory, fileName);
3082
+ if (fs5__namespace.existsSync(filePath)) {
2742
3083
  return filePath;
2743
3084
  }
2744
3085
  }
@@ -2746,7 +3087,7 @@ function findConfigFile(directory) {
2746
3087
  }
2747
3088
  function loadJsonConfig(configPath) {
2748
3089
  try {
2749
- const content = fs4__namespace.readFileSync(configPath, "utf-8");
3090
+ const content = fs5__namespace.readFileSync(configPath, "utf-8");
2750
3091
  return JSON.parse(content);
2751
3092
  } catch (error) {
2752
3093
  if (error instanceof SyntaxError) {
@@ -2775,10 +3116,10 @@ async function loadJsConfig(configPath) {
2775
3116
  }
2776
3117
  }
2777
3118
  async function loadConfigFile(configPath) {
2778
- if (!fs4__namespace.existsSync(configPath)) {
3119
+ if (!fs5__namespace.existsSync(configPath)) {
2779
3120
  return null;
2780
3121
  }
2781
- const ext = path4__namespace.extname(configPath).toLowerCase();
3122
+ const ext = path5__namespace.extname(configPath).toLowerCase();
2782
3123
  if (ext === ".json") {
2783
3124
  return loadJsonConfig(configPath);
2784
3125
  } else if (ext === ".js" || ext === ".mjs") {
@@ -2845,10 +3186,10 @@ function validateConfig(config, configPath) {
2845
3186
  }
2846
3187
  const cwd = process.cwd();
2847
3188
  const possiblePaths = [
2848
- path4__namespace.resolve(cwd, config.schema.directory),
2849
- path4__namespace.resolve(cwd, "shared", config.schema.directory)
3189
+ path5__namespace.resolve(cwd, config.schema.directory),
3190
+ path5__namespace.resolve(cwd, "shared", config.schema.directory)
2850
3191
  ];
2851
- const schemaDir = possiblePaths.find((p) => fs4__namespace.existsSync(p));
3192
+ const schemaDir = possiblePaths.find((p) => fs5__namespace.existsSync(p));
2852
3193
  if (!schemaDir) {
2853
3194
  throw new ConfigurationError(`Schema directory not found. Tried: ${possiblePaths.join(", ")}`, configPath, [
2854
3195
  "schema.directory"
@@ -2860,15 +3201,15 @@ async function loadConfig(options = {}) {
2860
3201
  let configFilePath;
2861
3202
  const cwd = process.cwd();
2862
3203
  if (options.config) {
2863
- const explicitPath = path4__namespace.resolve(cwd, options.config);
2864
- if (!fs4__namespace.existsSync(explicitPath)) {
3204
+ const explicitPath = path5__namespace.resolve(cwd, options.config);
3205
+ if (!fs5__namespace.existsSync(explicitPath)) {
2865
3206
  throw new ConfigurationError(`Configuration file not found: ${explicitPath}`, explicitPath);
2866
3207
  }
2867
3208
  configFilePath = explicitPath;
2868
3209
  } else {
2869
- const searchDirs = [cwd, path4__namespace.join(cwd, "shared")];
3210
+ const searchDirs = [cwd, path5__namespace.join(cwd, "shared")];
2870
3211
  for (const dir of searchDirs) {
2871
- if (fs4__namespace.existsSync(dir)) {
3212
+ if (fs5__namespace.existsSync(dir)) {
2872
3213
  const found = findConfigFile(dir);
2873
3214
  if (found) {
2874
3215
  configFilePath = found;
@@ -2897,18 +3238,18 @@ async function loadConfig(options = {}) {
2897
3238
  function getSchemaDirectory(config) {
2898
3239
  const cwd = process.cwd();
2899
3240
  const possiblePaths = [
2900
- path4__namespace.resolve(cwd, config.schema.directory),
2901
- path4__namespace.resolve(cwd, "shared", config.schema.directory)
3241
+ path5__namespace.resolve(cwd, config.schema.directory),
3242
+ path5__namespace.resolve(cwd, "shared", config.schema.directory)
2902
3243
  ];
2903
- return possiblePaths.find((p) => fs4__namespace.existsSync(p)) || possiblePaths[0];
3244
+ return possiblePaths.find((p) => fs5__namespace.existsSync(p)) || possiblePaths[0];
2904
3245
  }
2905
3246
  function getMigrationsDirectory(config) {
2906
3247
  const cwd = process.cwd();
2907
3248
  const possiblePaths = [
2908
- path4__namespace.resolve(cwd, config.migrations.directory),
2909
- path4__namespace.resolve(cwd, "shared", config.migrations.directory)
3249
+ path5__namespace.resolve(cwd, config.migrations.directory),
3250
+ path5__namespace.resolve(cwd, "shared", config.migrations.directory)
2910
3251
  ];
2911
- return possiblePaths.find((p) => fs4__namespace.existsSync(p)) || possiblePaths[0];
3252
+ return possiblePaths.find((p) => fs5__namespace.existsSync(p)) || possiblePaths[0];
2912
3253
  }
2913
3254
  var currentVerbosity = "normal";
2914
3255
  function setVerbosity(level) {
@@ -3125,7 +3466,7 @@ async function executeGenerate(options) {
3125
3466
  const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
3126
3467
  logSuccess(`Found ${currentSchema.collections.size} collection(s)`);
3127
3468
  logInfo("Loading previous snapshot...");
3128
- const previousSnapshot = loadSnapshotIfExists({
3469
+ const previousSnapshot = loadSnapshotWithMigrations({
3129
3470
  migrationsPath: migrationsDir,
3130
3471
  workspaceRoot: process.cwd()
3131
3472
  });
@@ -3152,7 +3493,7 @@ async function executeGenerate(options) {
3152
3493
  "Creating migration file...",
3153
3494
  () => Promise.resolve(generate(diff, migrationsDir))
3154
3495
  );
3155
- logSuccess(`Migration file created: ${path4__namespace.basename(migrationPath)}`);
3496
+ logSuccess(`Migration file created: ${path5__namespace.basename(migrationPath)}`);
3156
3497
  logSection("\u2705 Next Steps");
3157
3498
  console.log();
3158
3499
  console.log(" 1. Review the generated migration file:");
@@ -3330,7 +3671,7 @@ async function executeStatus(options) {
3330
3671
  const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
3331
3672
  logSuccess(`Found ${currentSchema.collections.size} collection(s) in schema`);
3332
3673
  logInfo("Loading previous snapshot...");
3333
- const previousSnapshot = loadSnapshotIfExists({
3674
+ const previousSnapshot = loadSnapshotWithMigrations({
3334
3675
  migrationsPath: migrationsDir,
3335
3676
  workspaceRoot: process.cwd()
3336
3677
  });
@@ -3446,9 +3787,9 @@ Examples:
3446
3787
  function getVersion() {
3447
3788
  try {
3448
3789
  const __filename2 = url.fileURLToPath(importMetaUrl);
3449
- const __dirname = path4.dirname(__filename2);
3450
- const packageJsonPath = path4.join(__dirname, "../../package.json");
3451
- const packageJson = JSON.parse(fs4.readFileSync(packageJsonPath, "utf-8"));
3790
+ const __dirname = path5.dirname(__filename2);
3791
+ const packageJsonPath = path5.join(__dirname, "../../package.json");
3792
+ const packageJson = JSON.parse(fs5.readFileSync(packageJsonPath, "utf-8"));
3452
3793
  return packageJson.version || "0.0.0";
3453
3794
  } catch {
3454
3795
  console.warn("Warning: Could not read version from package.json");