pocketbase-zod-schema 0.1.3 → 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 (46) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/cli/index.cjs +406 -102
  3. package/dist/cli/index.cjs.map +1 -1
  4. package/dist/cli/index.js +404 -100
  5. package/dist/cli/index.js.map +1 -1
  6. package/dist/cli/migrate.cjs +409 -105
  7. package/dist/cli/migrate.cjs.map +1 -1
  8. package/dist/cli/migrate.js +404 -100
  9. package/dist/cli/migrate.js.map +1 -1
  10. package/dist/index.cjs +515 -159
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +3 -3
  13. package/dist/index.d.ts +3 -3
  14. package/dist/index.js +511 -158
  15. package/dist/index.js.map +1 -1
  16. package/dist/migration/diff.cjs +21 -3
  17. package/dist/migration/diff.cjs.map +1 -1
  18. package/dist/migration/diff.js +21 -3
  19. package/dist/migration/diff.js.map +1 -1
  20. package/dist/migration/index.cjs +457 -123
  21. package/dist/migration/index.cjs.map +1 -1
  22. package/dist/migration/index.d.cts +1 -1
  23. package/dist/migration/index.d.ts +1 -1
  24. package/dist/migration/index.js +456 -123
  25. package/dist/migration/index.js.map +1 -1
  26. package/dist/migration/snapshot.cjs +432 -118
  27. package/dist/migration/snapshot.cjs.map +1 -1
  28. package/dist/migration/snapshot.d.cts +34 -12
  29. package/dist/migration/snapshot.d.ts +34 -12
  30. package/dist/migration/snapshot.js +430 -117
  31. package/dist/migration/snapshot.js.map +1 -1
  32. package/dist/mutator.d.cts +3 -3
  33. package/dist/mutator.d.ts +3 -3
  34. package/dist/schema.cjs +34 -0
  35. package/dist/schema.cjs.map +1 -1
  36. package/dist/schema.d.cts +1 -1
  37. package/dist/schema.d.ts +1 -1
  38. package/dist/schema.js +33 -1
  39. package/dist/schema.js.map +1 -1
  40. package/dist/types.d.cts +5 -2
  41. package/dist/types.d.ts +5 -2
  42. package/dist/user-_AM523hb.d.cts +123 -0
  43. package/dist/user-_AM523hb.d.ts +123 -0
  44. package/package.json +2 -3
  45. package/dist/user-C39DQ40N.d.cts +0 -53
  46. package/dist/user-C39DQ40N.d.ts +0 -53
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var path4 = require('path');
4
- var fs4 = require('fs');
3
+ var path5 = require('path');
4
+ var fs5 = require('fs');
5
5
  var zod = require('zod');
6
6
  var chalk = require('chalk');
7
7
  var ora = require('ora');
@@ -26,8 +26,8 @@ function _interopNamespace(e) {
26
26
  return Object.freeze(n);
27
27
  }
28
28
 
29
- var path4__namespace = /*#__PURE__*/_interopNamespace(path4);
30
- var fs4__namespace = /*#__PURE__*/_interopNamespace(fs4);
29
+ var path5__namespace = /*#__PURE__*/_interopNamespace(path5);
30
+ var fs5__namespace = /*#__PURE__*/_interopNamespace(fs5);
31
31
  var chalk__default = /*#__PURE__*/_interopDefault(chalk);
32
32
  var ora__default = /*#__PURE__*/_interopDefault(ora);
33
33
 
@@ -159,10 +159,10 @@ var FileSystemError = class _FileSystemError extends MigrationError {
159
159
  operation;
160
160
  code;
161
161
  originalError;
162
- constructor(message, path6, operation, code, originalError) {
162
+ constructor(message, path7, operation, code, originalError) {
163
163
  super(message);
164
164
  this.name = "FileSystemError";
165
- this.path = path6;
165
+ this.path = path7;
166
166
  this.operation = operation;
167
167
  this.code = code;
168
168
  this.originalError = originalError;
@@ -1103,20 +1103,20 @@ function mergeConfig(config) {
1103
1103
  }
1104
1104
  function resolveSchemaDir(config) {
1105
1105
  const workspaceRoot = config.workspaceRoot || process.cwd();
1106
- if (path4__namespace.isAbsolute(config.schemaDir)) {
1106
+ if (path5__namespace.isAbsolute(config.schemaDir)) {
1107
1107
  return config.schemaDir;
1108
1108
  }
1109
- return path4__namespace.join(workspaceRoot, config.schemaDir);
1109
+ return path5__namespace.join(workspaceRoot, config.schemaDir);
1110
1110
  }
1111
1111
  function discoverSchemaFiles(config) {
1112
1112
  const normalizedConfig = typeof config === "string" ? { schemaDir: config } : config;
1113
1113
  const mergedConfig = mergeConfig(normalizedConfig);
1114
1114
  const schemaDir = resolveSchemaDir(normalizedConfig);
1115
1115
  try {
1116
- if (!fs4__namespace.existsSync(schemaDir)) {
1116
+ if (!fs5__namespace.existsSync(schemaDir)) {
1117
1117
  throw new FileSystemError(`Schema directory not found: ${schemaDir}`, schemaDir, "access", "ENOENT");
1118
1118
  }
1119
- const files = fs4__namespace.readdirSync(schemaDir);
1119
+ const files = fs5__namespace.readdirSync(schemaDir);
1120
1120
  const schemaFiles = files.filter((file) => {
1121
1121
  const hasValidExtension = mergedConfig.includeExtensions.some((ext) => file.endsWith(ext));
1122
1122
  if (!hasValidExtension) return false;
@@ -1132,7 +1132,7 @@ function discoverSchemaFiles(config) {
1132
1132
  });
1133
1133
  return schemaFiles.map((file) => {
1134
1134
  const ext = mergedConfig.includeExtensions.find((ext2) => file.endsWith(ext2)) || ".ts";
1135
- return path4__namespace.join(schemaDir, file.replace(new RegExp(`\\${ext}$`), ""));
1135
+ return path5__namespace.join(schemaDir, file.replace(new RegExp(`\\${ext}$`), ""));
1136
1136
  });
1137
1137
  } catch (error) {
1138
1138
  if (error instanceof FileSystemError) {
@@ -1166,19 +1166,19 @@ async function importSchemaModule(filePath, config) {
1166
1166
  let resolvedPath = null;
1167
1167
  const jsPath = `${importPath}.js`;
1168
1168
  const tsPath = `${importPath}.ts`;
1169
- if (fs4__namespace.existsSync(jsPath)) {
1169
+ if (fs5__namespace.existsSync(jsPath)) {
1170
1170
  resolvedPath = jsPath;
1171
- } else if (fs4__namespace.existsSync(tsPath)) {
1171
+ } else if (fs5__namespace.existsSync(tsPath)) {
1172
1172
  resolvedPath = tsPath;
1173
1173
  } else {
1174
1174
  resolvedPath = jsPath;
1175
1175
  }
1176
- const fileUrl = new URL(`file://${path4__namespace.resolve(resolvedPath)}`);
1176
+ const fileUrl = new URL(`file://${path5__namespace.resolve(resolvedPath)}`);
1177
1177
  const module = await import(fileUrl.href);
1178
1178
  return module;
1179
1179
  } catch (error) {
1180
1180
  const tsPath = `${filePath}.ts`;
1181
- const isTypeScriptFile = fs4__namespace.existsSync(tsPath);
1181
+ const isTypeScriptFile = fs5__namespace.existsSync(tsPath);
1182
1182
  if (isTypeScriptFile) {
1183
1183
  throw new SchemaParsingError(
1184
1184
  `Failed to import TypeScript schema file. Node.js cannot import TypeScript files directly.
@@ -1197,7 +1197,7 @@ Please either:
1197
1197
  }
1198
1198
  }
1199
1199
  function getCollectionNameFromFile(filePath) {
1200
- const filename = path4__namespace.basename(filePath).replace(/\.(ts|js)$/, "");
1200
+ const filename = path5__namespace.basename(filePath).replace(/\.(ts|js)$/, "");
1201
1201
  return toCollectionName(filename);
1202
1202
  }
1203
1203
  function extractSchemaDefinitions(module, patterns = ["Schema", "InputSchema"]) {
@@ -1362,7 +1362,7 @@ async function buildSchemaDefinition(config) {
1362
1362
  importPath = normalizedConfig.pathTransformer(filePath);
1363
1363
  } else if (mergedConfig.useCompiledFiles) {
1364
1364
  const distPath = filePath.replace(/\/src\//, "/dist/");
1365
- if (fs4__namespace.existsSync(`${distPath}.js`) || fs4__namespace.existsSync(`${distPath}.mjs`)) {
1365
+ if (fs5__namespace.existsSync(`${distPath}.js`) || fs5__namespace.existsSync(`${distPath}.mjs`)) {
1366
1366
  importPath = distPath;
1367
1367
  } else {
1368
1368
  importPath = filePath;
@@ -1539,6 +1539,9 @@ function compareFieldOptions(currentField, previousField) {
1539
1539
  for (const key of allKeys) {
1540
1540
  const currentValue = currentOptions[key];
1541
1541
  const previousValue = previousOptions[key];
1542
+ if (currentValue === void 0 && previousValue === void 0) {
1543
+ continue;
1544
+ }
1542
1545
  if (!areValuesEqual(currentValue, previousValue)) {
1543
1546
  changes.push({
1544
1547
  property: `options.${key}`,
@@ -1559,11 +1562,26 @@ function compareRelationConfigurations(currentField, previousField) {
1559
1562
  if (!currentRelation || !previousRelation) {
1560
1563
  return changes;
1561
1564
  }
1562
- if (currentRelation.collection !== previousRelation.collection) {
1565
+ const normalizeCollection = (collection) => {
1566
+ if (!collection) return collection;
1567
+ if (collection === "_pb_users_auth_") {
1568
+ return "Users";
1569
+ }
1570
+ const nameMatch = collection.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
1571
+ if (nameMatch) {
1572
+ return nameMatch[1];
1573
+ }
1574
+ return collection;
1575
+ };
1576
+ const normalizedCurrent = normalizeCollection(currentRelation.collection);
1577
+ const normalizedPrevious = normalizeCollection(previousRelation.collection);
1578
+ if (normalizedCurrent !== normalizedPrevious) {
1563
1579
  changes.push({
1564
1580
  property: "relation.collection",
1565
- oldValue: previousRelation.collection,
1566
- newValue: currentRelation.collection
1581
+ oldValue: normalizedPrevious,
1582
+ // Use normalized value for clarity
1583
+ newValue: normalizedCurrent
1584
+ // Use normalized value for clarity
1567
1585
  });
1568
1586
  }
1569
1587
  if (currentRelation.cascadeDelete !== previousRelation.cascadeDelete) {
@@ -1783,10 +1801,10 @@ function mergeConfig3(config) {
1783
1801
  }
1784
1802
  function resolveMigrationDir(config) {
1785
1803
  const workspaceRoot = config.workspaceRoot || process.cwd();
1786
- if (path4__namespace.isAbsolute(config.migrationDir)) {
1804
+ if (path5__namespace.isAbsolute(config.migrationDir)) {
1787
1805
  return config.migrationDir;
1788
1806
  }
1789
- return path4__namespace.join(workspaceRoot, config.migrationDir);
1807
+ return path5__namespace.join(workspaceRoot, config.migrationDir);
1790
1808
  }
1791
1809
  function generateTimestamp(config) {
1792
1810
  if (config?.timestampGenerator) {
@@ -1844,9 +1862,9 @@ function createMigrationFileStructure(upCode, downCode, config) {
1844
1862
  }
1845
1863
  function writeMigrationFile(migrationDir, filename, content) {
1846
1864
  try {
1847
- if (!fs4__namespace.existsSync(migrationDir)) {
1865
+ if (!fs5__namespace.existsSync(migrationDir)) {
1848
1866
  try {
1849
- fs4__namespace.mkdirSync(migrationDir, { recursive: true });
1867
+ fs5__namespace.mkdirSync(migrationDir, { recursive: true });
1850
1868
  } catch (error) {
1851
1869
  const fsError = error;
1852
1870
  if (fsError.code === "EACCES" || fsError.code === "EPERM") {
@@ -1867,15 +1885,15 @@ function writeMigrationFile(migrationDir, filename, content) {
1867
1885
  );
1868
1886
  }
1869
1887
  }
1870
- const filePath = path4__namespace.join(migrationDir, filename);
1871
- fs4__namespace.writeFileSync(filePath, content, "utf-8");
1888
+ const filePath = path5__namespace.join(migrationDir, filename);
1889
+ fs5__namespace.writeFileSync(filePath, content, "utf-8");
1872
1890
  return filePath;
1873
1891
  } catch (error) {
1874
1892
  if (error instanceof FileSystemError) {
1875
1893
  throw error;
1876
1894
  }
1877
1895
  const fsError = error;
1878
- const filePath = path4__namespace.join(migrationDir, filename);
1896
+ const filePath = path5__namespace.join(migrationDir, filename);
1879
1897
  if (fsError.code === "EACCES" || fsError.code === "EPERM") {
1880
1898
  throw new FileSystemError(
1881
1899
  `Permission denied writing migration file. Check file and directory permissions.`,
@@ -2420,57 +2438,18 @@ function generate(diff, config) {
2420
2438
  );
2421
2439
  }
2422
2440
  }
2441
+
2442
+ // src/migration/pocketbase-converter.ts
2423
2443
  var SNAPSHOT_VERSION = "1.0.0";
2424
- ({
2425
- workspaceRoot: process.cwd()});
2426
- function findLatestSnapshot(migrationsPath) {
2427
- try {
2428
- if (!fs4__namespace.existsSync(migrationsPath)) {
2429
- return null;
2430
- }
2431
- const files = fs4__namespace.readdirSync(migrationsPath);
2432
- const snapshotFiles = files.filter(
2433
- (file) => file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")
2434
- );
2435
- if (snapshotFiles.length === 0) {
2436
- return null;
2437
- }
2438
- snapshotFiles.sort().reverse();
2439
- const latestSnapshot = snapshotFiles[0];
2440
- if (!latestSnapshot) {
2441
- return null;
2442
- }
2443
- return path4__namespace.join(migrationsPath, latestSnapshot);
2444
- } catch (error) {
2445
- console.warn(`Error finding latest snapshot: ${error}`);
2446
- return null;
2444
+ function resolveCollectionIdToName(collectionId) {
2445
+ if (collectionId === "_pb_users_auth_") {
2446
+ return "Users";
2447
2447
  }
2448
- }
2449
- function loadSnapshotIfExists(config = {}) {
2450
- const migrationsPath = config.migrationsPath;
2451
- if (!migrationsPath) {
2452
- return null;
2448
+ const nameMatch = collectionId.match(/app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)/);
2449
+ if (nameMatch) {
2450
+ return nameMatch[1];
2453
2451
  }
2454
- if (fs4__namespace.existsSync(migrationsPath) && fs4__namespace.statSync(migrationsPath).isFile()) {
2455
- try {
2456
- const migrationContent = fs4__namespace.readFileSync(migrationsPath, "utf-8");
2457
- return convertPocketBaseMigration(migrationContent);
2458
- } catch (error) {
2459
- console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
2460
- return null;
2461
- }
2462
- }
2463
- const latestSnapshotPath = findLatestSnapshot(migrationsPath);
2464
- if (latestSnapshotPath) {
2465
- try {
2466
- const migrationContent = fs4__namespace.readFileSync(latestSnapshotPath, "utf-8");
2467
- return convertPocketBaseMigration(migrationContent);
2468
- } catch (error) {
2469
- console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
2470
- return null;
2471
- }
2472
- }
2473
- return null;
2452
+ return collectionId;
2474
2453
  }
2475
2454
  function convertPocketBaseCollection(pbCollection) {
2476
2455
  const fields = [];
@@ -2489,17 +2468,28 @@ function convertPocketBaseCollection(pbCollection) {
2489
2468
  type: pbField.type,
2490
2469
  required: pbField.required || false
2491
2470
  };
2492
- if (pbField.options) {
2493
- field.options = pbField.options;
2471
+ field.options = pbField.options ? { ...pbField.options } : {};
2472
+ if (pbField.type === "select") {
2473
+ if (pbField.values && Array.isArray(pbField.values)) {
2474
+ field.options.values = pbField.values;
2475
+ } else if (pbField.options?.values && Array.isArray(pbField.options.values)) {
2476
+ field.options.values = pbField.options.values;
2477
+ }
2494
2478
  }
2495
2479
  if (pbField.type === "relation") {
2480
+ const collectionId = pbField.collectionId || pbField.options?.collectionId || "";
2481
+ const collectionName = resolveCollectionIdToName(collectionId);
2496
2482
  field.relation = {
2497
- collection: pbField.options?.collectionId || "",
2498
- cascadeDelete: pbField.options?.cascadeDelete || false,
2499
- maxSelect: pbField.options?.maxSelect,
2500
- minSelect: pbField.options?.minSelect
2483
+ collection: collectionName,
2484
+ cascadeDelete: pbField.cascadeDelete ?? pbField.options?.cascadeDelete ?? false,
2485
+ maxSelect: pbField.maxSelect ?? pbField.options?.maxSelect,
2486
+ minSelect: pbField.minSelect ?? pbField.options?.minSelect
2501
2487
  };
2502
2488
  }
2489
+ const hasOnlyValues = Object.keys(field.options).length === 1 && field.options.values !== void 0;
2490
+ if (Object.keys(field.options).length === 0) {
2491
+ delete field.options;
2492
+ } else if (pbField.type === "select" && hasOnlyValues) ;
2503
2493
  fields.push(field);
2504
2494
  }
2505
2495
  }
@@ -2564,6 +2554,320 @@ function convertPocketBaseMigration(migrationContent) {
2564
2554
  }
2565
2555
  }
2566
2556
 
2557
+ // src/migration/migration-parser.ts
2558
+ function extractTimestampFromFilename(filename) {
2559
+ const match = filename.match(/^(\d+)_/);
2560
+ if (match) {
2561
+ return parseInt(match[1], 10);
2562
+ }
2563
+ return null;
2564
+ }
2565
+ function findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp) {
2566
+ try {
2567
+ if (!fs5__namespace.existsSync(migrationsPath)) {
2568
+ return [];
2569
+ }
2570
+ const files = fs5__namespace.readdirSync(migrationsPath);
2571
+ const migrationFiles = [];
2572
+ for (const file of files) {
2573
+ if (file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")) {
2574
+ continue;
2575
+ }
2576
+ if (!file.endsWith(".js")) {
2577
+ continue;
2578
+ }
2579
+ const timestamp = extractTimestampFromFilename(file);
2580
+ if (timestamp && timestamp > snapshotTimestamp) {
2581
+ migrationFiles.push({
2582
+ path: path5__namespace.join(migrationsPath, file),
2583
+ timestamp
2584
+ });
2585
+ }
2586
+ }
2587
+ migrationFiles.sort((a, b) => a.timestamp - b.timestamp);
2588
+ return migrationFiles.map((f) => f.path);
2589
+ } catch (error) {
2590
+ console.warn(`Error finding migrations after snapshot: ${error}`);
2591
+ return [];
2592
+ }
2593
+ }
2594
+ function parseMigrationOperationsFromContent(content) {
2595
+ const collectionsToCreate = [];
2596
+ const collectionsToDelete = [];
2597
+ try {
2598
+ let searchIndex = 0;
2599
+ while (true) {
2600
+ const collectionStart = content.indexOf("new Collection(", searchIndex);
2601
+ if (collectionStart === -1) {
2602
+ break;
2603
+ }
2604
+ const openParen = collectionStart + "new Collection(".length;
2605
+ let braceCount = 0;
2606
+ let parenCount = 1;
2607
+ let inString = false;
2608
+ let stringChar = null;
2609
+ let i = openParen;
2610
+ while (i < content.length && /\s/.test(content[i])) {
2611
+ i++;
2612
+ }
2613
+ if (content[i] !== "{") {
2614
+ searchIndex = i + 1;
2615
+ continue;
2616
+ }
2617
+ const objectStart = i;
2618
+ braceCount = 1;
2619
+ i++;
2620
+ while (i < content.length && (braceCount > 0 || parenCount > 0)) {
2621
+ const char = content[i];
2622
+ const prevChar = i > 0 ? content[i - 1] : "";
2623
+ if (!inString && (char === '"' || char === "'")) {
2624
+ inString = true;
2625
+ stringChar = char;
2626
+ } else if (inString && char === stringChar && prevChar !== "\\") {
2627
+ inString = false;
2628
+ stringChar = null;
2629
+ }
2630
+ if (!inString) {
2631
+ if (char === "{") braceCount++;
2632
+ if (char === "}") braceCount--;
2633
+ if (char === "(") parenCount++;
2634
+ if (char === ")") parenCount--;
2635
+ }
2636
+ i++;
2637
+ }
2638
+ if (braceCount === 0 && parenCount === 0) {
2639
+ const objectContent = content.substring(objectStart, i - 1);
2640
+ try {
2641
+ const collectionObj = new Function(`return ${objectContent}`)();
2642
+ if (collectionObj && collectionObj.name) {
2643
+ const schema = convertPocketBaseCollection(collectionObj);
2644
+ collectionsToCreate.push(schema);
2645
+ }
2646
+ } catch (error) {
2647
+ console.warn(`Failed to parse collection definition: ${error}`);
2648
+ }
2649
+ }
2650
+ searchIndex = i;
2651
+ }
2652
+ const deleteMatches = content.matchAll(
2653
+ /app\.delete\s*\(\s*(?:collection_\w+|app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\))\s*\)/g
2654
+ );
2655
+ for (const match of deleteMatches) {
2656
+ if (match[1]) {
2657
+ collectionsToDelete.push(match[1]);
2658
+ } else {
2659
+ const varNameMatch = match[0].match(/collection_(\w+)/);
2660
+ if (varNameMatch) {
2661
+ const varName = `collection_${varNameMatch[1]}`;
2662
+ const deleteIndex = content.indexOf(match[0]);
2663
+ const beforeDelete = content.substring(0, deleteIndex);
2664
+ const varDefMatch = beforeDelete.match(
2665
+ new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`, "g")
2666
+ );
2667
+ if (varDefMatch && varDefMatch.length > 0) {
2668
+ const collectionDefMatch = beforeDelete.match(
2669
+ new RegExp(`const\\s+${varName}\\s*=\\s*new\\s+Collection\\(\\s*(\\{[\\s\\S]*?\\})\\s*\\)`)
2670
+ );
2671
+ if (collectionDefMatch) {
2672
+ try {
2673
+ const collectionDefStr = collectionDefMatch[1];
2674
+ const collectionObj = new Function(`return ${collectionDefStr}`)();
2675
+ if (collectionObj && collectionObj.name) {
2676
+ collectionsToDelete.push(collectionObj.name);
2677
+ }
2678
+ } catch {
2679
+ }
2680
+ }
2681
+ }
2682
+ }
2683
+ }
2684
+ }
2685
+ const findAndDeleteMatches = content.matchAll(
2686
+ /app\.findCollectionByNameOrId\s*\(\s*["']([^"']+)["']\s*\)[\s\S]*?app\.delete/g
2687
+ );
2688
+ for (const match of findAndDeleteMatches) {
2689
+ collectionsToDelete.push(match[1]);
2690
+ }
2691
+ } catch (error) {
2692
+ console.warn(`Failed to parse migration operations from content: ${error}`);
2693
+ }
2694
+ return { collectionsToCreate, collectionsToDelete };
2695
+ }
2696
+ function parseMigrationOperations(migrationContent) {
2697
+ try {
2698
+ const migrateMatch = migrationContent.match(/migrate\s*\(\s*/);
2699
+ if (!migrateMatch) {
2700
+ return parseMigrationOperationsFromContent(migrationContent);
2701
+ }
2702
+ const startIndex = migrateMatch.index + migrateMatch[0].length;
2703
+ let i = startIndex;
2704
+ let parenCount = 0;
2705
+ let foundFirstParen = false;
2706
+ while (i < migrationContent.length) {
2707
+ const char = migrationContent[i];
2708
+ if (char === "(") {
2709
+ parenCount++;
2710
+ foundFirstParen = true;
2711
+ i++;
2712
+ break;
2713
+ }
2714
+ i++;
2715
+ }
2716
+ if (!foundFirstParen) {
2717
+ return parseMigrationOperationsFromContent(migrationContent);
2718
+ }
2719
+ let inString = false;
2720
+ let stringChar = null;
2721
+ let foundBrace = false;
2722
+ let braceStart = -1;
2723
+ while (i < migrationContent.length && !foundBrace) {
2724
+ const char = migrationContent[i];
2725
+ const prevChar = i > 0 ? migrationContent[i - 1] : "";
2726
+ if (!inString && (char === '"' || char === "'")) {
2727
+ inString = true;
2728
+ stringChar = char;
2729
+ } else if (inString && char === stringChar && prevChar !== "\\") {
2730
+ inString = false;
2731
+ stringChar = null;
2732
+ }
2733
+ if (!inString) {
2734
+ if (char === "(") parenCount++;
2735
+ if (char === ")") {
2736
+ parenCount--;
2737
+ if (parenCount === 0) {
2738
+ i++;
2739
+ while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
2740
+ i++;
2741
+ }
2742
+ if (i < migrationContent.length - 1 && migrationContent[i] === "=" && migrationContent[i + 1] === ">") {
2743
+ i += 2;
2744
+ while (i < migrationContent.length && /\s/.test(migrationContent[i])) {
2745
+ i++;
2746
+ }
2747
+ if (i < migrationContent.length && migrationContent[i] === "{") {
2748
+ foundBrace = true;
2749
+ braceStart = i + 1;
2750
+ break;
2751
+ }
2752
+ }
2753
+ }
2754
+ }
2755
+ }
2756
+ i++;
2757
+ }
2758
+ if (!foundBrace || braceStart === -1) {
2759
+ return parseMigrationOperationsFromContent(migrationContent);
2760
+ }
2761
+ let braceCount = 1;
2762
+ i = braceStart;
2763
+ inString = false;
2764
+ stringChar = null;
2765
+ while (i < migrationContent.length && braceCount > 0) {
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 === "{") braceCount++;
2777
+ if (char === "}") braceCount--;
2778
+ }
2779
+ i++;
2780
+ }
2781
+ if (braceCount === 0) {
2782
+ const upMigrationContent = migrationContent.substring(braceStart, i - 1);
2783
+ return parseMigrationOperationsFromContent(upMigrationContent);
2784
+ }
2785
+ return parseMigrationOperationsFromContent(migrationContent);
2786
+ } catch (error) {
2787
+ console.warn(`Failed to parse migration operations: ${error}`);
2788
+ return { collectionsToCreate: [], collectionsToDelete: [] };
2789
+ }
2790
+ }
2791
+ ({
2792
+ workspaceRoot: process.cwd()});
2793
+ function findLatestSnapshot(migrationsPath) {
2794
+ try {
2795
+ if (!fs5__namespace.existsSync(migrationsPath)) {
2796
+ return null;
2797
+ }
2798
+ const files = fs5__namespace.readdirSync(migrationsPath);
2799
+ const snapshotFiles = files.filter(
2800
+ (file) => file.endsWith("_collections_snapshot.js") || file.endsWith("_snapshot.js")
2801
+ );
2802
+ if (snapshotFiles.length === 0) {
2803
+ return null;
2804
+ }
2805
+ snapshotFiles.sort().reverse();
2806
+ const latestSnapshot = snapshotFiles[0];
2807
+ if (!latestSnapshot) {
2808
+ return null;
2809
+ }
2810
+ return path5__namespace.join(migrationsPath, latestSnapshot);
2811
+ } catch (error) {
2812
+ console.warn(`Error finding latest snapshot: ${error}`);
2813
+ return null;
2814
+ }
2815
+ }
2816
+ function applyMigrationOperations(snapshot, operations) {
2817
+ const updatedCollections = new Map(snapshot.collections);
2818
+ for (const collectionName of operations.collectionsToDelete) {
2819
+ updatedCollections.delete(collectionName);
2820
+ }
2821
+ for (const collection of operations.collectionsToCreate) {
2822
+ updatedCollections.set(collection.name, collection);
2823
+ }
2824
+ return {
2825
+ ...snapshot,
2826
+ collections: updatedCollections
2827
+ };
2828
+ }
2829
+ function loadSnapshotWithMigrations(config = {}) {
2830
+ const migrationsPath = config.migrationsPath;
2831
+ if (!migrationsPath) {
2832
+ return null;
2833
+ }
2834
+ if (fs5__namespace.existsSync(migrationsPath) && fs5__namespace.statSync(migrationsPath).isFile()) {
2835
+ try {
2836
+ const migrationContent = fs5__namespace.readFileSync(migrationsPath, "utf-8");
2837
+ return convertPocketBaseMigration(migrationContent);
2838
+ } catch (error) {
2839
+ console.warn(`Failed to load snapshot from ${migrationsPath}: ${error}`);
2840
+ return null;
2841
+ }
2842
+ }
2843
+ const latestSnapshotPath = findLatestSnapshot(migrationsPath);
2844
+ if (!latestSnapshotPath) {
2845
+ return null;
2846
+ }
2847
+ try {
2848
+ const migrationContent = fs5__namespace.readFileSync(latestSnapshotPath, "utf-8");
2849
+ let snapshot = convertPocketBaseMigration(migrationContent);
2850
+ const snapshotFilename = path5__namespace.basename(latestSnapshotPath);
2851
+ const snapshotTimestamp = extractTimestampFromFilename(snapshotFilename);
2852
+ if (snapshotTimestamp) {
2853
+ const migrationFiles = findMigrationsAfterSnapshot(migrationsPath, snapshotTimestamp);
2854
+ for (const migrationFile of migrationFiles) {
2855
+ try {
2856
+ const migrationContent2 = fs5__namespace.readFileSync(migrationFile, "utf-8");
2857
+ const operations = parseMigrationOperations(migrationContent2);
2858
+ snapshot = applyMigrationOperations(snapshot, operations);
2859
+ } catch (error) {
2860
+ console.warn(`Failed to apply migration ${migrationFile}: ${error}`);
2861
+ }
2862
+ }
2863
+ }
2864
+ return snapshot;
2865
+ } catch (error) {
2866
+ console.warn(`Failed to load snapshot from ${latestSnapshotPath}: ${error}`);
2867
+ return null;
2868
+ }
2869
+ }
2870
+
2567
2871
  // src/migration/validation.ts
2568
2872
  function detectCollectionDeletions(diff) {
2569
2873
  const changes = [];
@@ -2732,8 +3036,8 @@ var DEFAULT_CONFIG5 = {
2732
3036
  };
2733
3037
  function findConfigFile(directory) {
2734
3038
  for (const fileName of CONFIG_FILE_NAMES) {
2735
- const filePath = path4__namespace.join(directory, fileName);
2736
- if (fs4__namespace.existsSync(filePath)) {
3039
+ const filePath = path5__namespace.join(directory, fileName);
3040
+ if (fs5__namespace.existsSync(filePath)) {
2737
3041
  return filePath;
2738
3042
  }
2739
3043
  }
@@ -2741,7 +3045,7 @@ function findConfigFile(directory) {
2741
3045
  }
2742
3046
  function loadJsonConfig(configPath) {
2743
3047
  try {
2744
- const content = fs4__namespace.readFileSync(configPath, "utf-8");
3048
+ const content = fs5__namespace.readFileSync(configPath, "utf-8");
2745
3049
  return JSON.parse(content);
2746
3050
  } catch (error) {
2747
3051
  if (error instanceof SyntaxError) {
@@ -2770,10 +3074,10 @@ async function loadJsConfig(configPath) {
2770
3074
  }
2771
3075
  }
2772
3076
  async function loadConfigFile(configPath) {
2773
- if (!fs4__namespace.existsSync(configPath)) {
3077
+ if (!fs5__namespace.existsSync(configPath)) {
2774
3078
  return null;
2775
3079
  }
2776
- const ext = path4__namespace.extname(configPath).toLowerCase();
3080
+ const ext = path5__namespace.extname(configPath).toLowerCase();
2777
3081
  if (ext === ".json") {
2778
3082
  return loadJsonConfig(configPath);
2779
3083
  } else if (ext === ".js" || ext === ".mjs") {
@@ -2840,10 +3144,10 @@ function validateConfig(config, configPath) {
2840
3144
  }
2841
3145
  const cwd = process.cwd();
2842
3146
  const possiblePaths = [
2843
- path4__namespace.resolve(cwd, config.schema.directory),
2844
- path4__namespace.resolve(cwd, "shared", config.schema.directory)
3147
+ path5__namespace.resolve(cwd, config.schema.directory),
3148
+ path5__namespace.resolve(cwd, "shared", config.schema.directory)
2845
3149
  ];
2846
- const schemaDir = possiblePaths.find((p) => fs4__namespace.existsSync(p));
3150
+ const schemaDir = possiblePaths.find((p) => fs5__namespace.existsSync(p));
2847
3151
  if (!schemaDir) {
2848
3152
  throw new ConfigurationError(`Schema directory not found. Tried: ${possiblePaths.join(", ")}`, configPath, [
2849
3153
  "schema.directory"
@@ -2855,15 +3159,15 @@ async function loadConfig(options = {}) {
2855
3159
  let configFilePath;
2856
3160
  const cwd = process.cwd();
2857
3161
  if (options.config) {
2858
- const explicitPath = path4__namespace.resolve(cwd, options.config);
2859
- if (!fs4__namespace.existsSync(explicitPath)) {
3162
+ const explicitPath = path5__namespace.resolve(cwd, options.config);
3163
+ if (!fs5__namespace.existsSync(explicitPath)) {
2860
3164
  throw new ConfigurationError(`Configuration file not found: ${explicitPath}`, explicitPath);
2861
3165
  }
2862
3166
  configFilePath = explicitPath;
2863
3167
  } else {
2864
- const searchDirs = [cwd, path4__namespace.join(cwd, "shared")];
3168
+ const searchDirs = [cwd, path5__namespace.join(cwd, "shared")];
2865
3169
  for (const dir of searchDirs) {
2866
- if (fs4__namespace.existsSync(dir)) {
3170
+ if (fs5__namespace.existsSync(dir)) {
2867
3171
  const found = findConfigFile(dir);
2868
3172
  if (found) {
2869
3173
  configFilePath = found;
@@ -2892,18 +3196,18 @@ async function loadConfig(options = {}) {
2892
3196
  function getSchemaDirectory(config) {
2893
3197
  const cwd = process.cwd();
2894
3198
  const possiblePaths = [
2895
- path4__namespace.resolve(cwd, config.schema.directory),
2896
- path4__namespace.resolve(cwd, "shared", config.schema.directory)
3199
+ path5__namespace.resolve(cwd, config.schema.directory),
3200
+ path5__namespace.resolve(cwd, "shared", config.schema.directory)
2897
3201
  ];
2898
- return possiblePaths.find((p) => fs4__namespace.existsSync(p)) || possiblePaths[0];
3202
+ return possiblePaths.find((p) => fs5__namespace.existsSync(p)) || possiblePaths[0];
2899
3203
  }
2900
3204
  function getMigrationsDirectory(config) {
2901
3205
  const cwd = process.cwd();
2902
3206
  const possiblePaths = [
2903
- path4__namespace.resolve(cwd, config.migrations.directory),
2904
- path4__namespace.resolve(cwd, "shared", config.migrations.directory)
3207
+ path5__namespace.resolve(cwd, config.migrations.directory),
3208
+ path5__namespace.resolve(cwd, "shared", config.migrations.directory)
2905
3209
  ];
2906
- return possiblePaths.find((p) => fs4__namespace.existsSync(p)) || possiblePaths[0];
3210
+ return possiblePaths.find((p) => fs5__namespace.existsSync(p)) || possiblePaths[0];
2907
3211
  }
2908
3212
  var currentVerbosity = "normal";
2909
3213
  function setVerbosity(level) {
@@ -3180,7 +3484,7 @@ async function executeGenerate(options) {
3180
3484
  const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
3181
3485
  logSuccess(`Found ${currentSchema.collections.size} collection(s)`);
3182
3486
  logInfo("Loading previous snapshot...");
3183
- const previousSnapshot = loadSnapshotIfExists({
3487
+ const previousSnapshot = loadSnapshotWithMigrations({
3184
3488
  migrationsPath: migrationsDir,
3185
3489
  workspaceRoot: process.cwd()
3186
3490
  });
@@ -3207,7 +3511,7 @@ async function executeGenerate(options) {
3207
3511
  "Creating migration file...",
3208
3512
  () => Promise.resolve(generate(diff, migrationsDir))
3209
3513
  );
3210
- logSuccess(`Migration file created: ${path4__namespace.basename(migrationPath)}`);
3514
+ logSuccess(`Migration file created: ${path5__namespace.basename(migrationPath)}`);
3211
3515
  logSection("\u2705 Next Steps");
3212
3516
  console.log();
3213
3517
  console.log(" 1. Review the generated migration file:");
@@ -3373,7 +3677,7 @@ async function executeStatus(options) {
3373
3677
  const currentSchema = await withProgress("Parsing Zod schemas...", () => parseSchemaFiles(analyzerConfig));
3374
3678
  logSuccess(`Found ${currentSchema.collections.size} collection(s) in schema`);
3375
3679
  logInfo("Loading previous snapshot...");
3376
- const previousSnapshot = loadSnapshotIfExists({
3680
+ const previousSnapshot = loadSnapshotWithMigrations({
3377
3681
  migrationsPath: migrationsDir,
3378
3682
  workspaceRoot: process.cwd()
3379
3683
  });