pocketbase-zod-schema 0.2.5 → 0.3.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 (66) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/cli/index.cjs +374 -296
  3. package/dist/cli/index.cjs.map +1 -1
  4. package/dist/cli/index.d.cts +2 -2
  5. package/dist/cli/index.d.ts +2 -2
  6. package/dist/cli/index.js +374 -296
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/cli/migrate.cjs +374 -296
  9. package/dist/cli/migrate.cjs.map +1 -1
  10. package/dist/cli/migrate.js +374 -296
  11. package/dist/cli/migrate.js.map +1 -1
  12. package/dist/cli/utils/index.d.cts +2 -2
  13. package/dist/cli/utils/index.d.ts +2 -2
  14. package/dist/{fields-YjcpBXVp.d.cts → fields-UcOPu1OQ.d.cts} +16 -0
  15. package/dist/{fields-YjcpBXVp.d.ts → fields-UcOPu1OQ.d.ts} +16 -0
  16. package/dist/index.cjs +413 -114
  17. package/dist/index.cjs.map +1 -1
  18. package/dist/index.d.cts +4 -4
  19. package/dist/index.d.ts +4 -4
  20. package/dist/index.js +414 -103
  21. package/dist/index.js.map +1 -1
  22. package/dist/migration/analyzer.cjs +12 -2
  23. package/dist/migration/analyzer.cjs.map +1 -1
  24. package/dist/migration/analyzer.d.cts +2 -2
  25. package/dist/migration/analyzer.d.ts +2 -2
  26. package/dist/migration/analyzer.js +12 -2
  27. package/dist/migration/analyzer.js.map +1 -1
  28. package/dist/migration/diff.cjs +76 -1
  29. package/dist/migration/diff.cjs.map +1 -1
  30. package/dist/migration/diff.d.cts +2 -2
  31. package/dist/migration/diff.d.ts +2 -2
  32. package/dist/migration/diff.js +76 -1
  33. package/dist/migration/diff.js.map +1 -1
  34. package/dist/migration/generator.cjs +323 -46
  35. package/dist/migration/generator.cjs.map +1 -1
  36. package/dist/migration/generator.d.cts +59 -12
  37. package/dist/migration/generator.d.ts +59 -12
  38. package/dist/migration/generator.js +319 -47
  39. package/dist/migration/generator.js.map +1 -1
  40. package/dist/migration/index.cjs +399 -49
  41. package/dist/migration/index.cjs.map +1 -1
  42. package/dist/migration/index.d.cts +3 -3
  43. package/dist/migration/index.d.ts +3 -3
  44. package/dist/migration/index.js +399 -49
  45. package/dist/migration/index.js.map +1 -1
  46. package/dist/migration/snapshot.cjs.map +1 -1
  47. package/dist/migration/snapshot.d.cts +2 -2
  48. package/dist/migration/snapshot.d.ts +2 -2
  49. package/dist/migration/snapshot.js.map +1 -1
  50. package/dist/migration/utils/index.cjs +64 -0
  51. package/dist/migration/utils/index.cjs.map +1 -1
  52. package/dist/migration/utils/index.d.cts +39 -202
  53. package/dist/migration/utils/index.d.ts +39 -202
  54. package/dist/migration/utils/index.js +63 -1
  55. package/dist/migration/utils/index.js.map +1 -1
  56. package/dist/schema.cjs +0 -61
  57. package/dist/schema.cjs.map +1 -1
  58. package/dist/schema.d.cts +2 -86
  59. package/dist/schema.d.ts +2 -86
  60. package/dist/schema.js +1 -50
  61. package/dist/schema.js.map +1 -1
  62. package/dist/type-mapper-DrQmtznD.d.cts +208 -0
  63. package/dist/type-mapper-n231Fspm.d.ts +208 -0
  64. package/dist/{types-LFBGHl9Y.d.ts → types-Ds3NQvny.d.ts} +33 -2
  65. package/dist/{types-mhQXWNi3.d.cts → types-YoBjsa-A.d.cts} +33 -2
  66. package/package.json +1 -1
@@ -3,6 +3,7 @@
3
3
  var fs3 = require('fs');
4
4
  var path = require('path');
5
5
  var zod = require('zod');
6
+ var crypto = require('crypto');
6
7
 
7
8
  function _interopNamespace(e) {
8
9
  if (e && e.__esModule) return e;
@@ -1581,12 +1582,22 @@ function isAuthCollection(fields) {
1581
1582
  function buildFieldDefinition(fieldName, zodType) {
1582
1583
  const fieldMetadata = extractFieldMetadata(zodType.description);
1583
1584
  if (fieldMetadata) {
1584
- const required2 = isFieldRequired(zodType);
1585
+ let required2;
1586
+ if (fieldMetadata.type === "number") {
1587
+ if (fieldMetadata.options?.required !== void 0) {
1588
+ required2 = fieldMetadata.options.required;
1589
+ } else {
1590
+ required2 = false;
1591
+ }
1592
+ } else {
1593
+ required2 = isFieldRequired(zodType);
1594
+ }
1595
+ const { required: _required, ...options2 } = fieldMetadata.options || {};
1585
1596
  const fieldDef2 = {
1586
1597
  name: fieldName,
1587
1598
  type: fieldMetadata.type,
1588
1599
  required: required2,
1589
- options: fieldMetadata.options
1600
+ options: Object.keys(options2).length > 0 ? options2 : void 0
1590
1601
  };
1591
1602
  if (fieldMetadata.type === "relation") {
1592
1603
  const relationMetadata2 = extractRelationMetadata(zodType.description);
@@ -2582,6 +2593,65 @@ var SnapshotManager = class {
2582
2593
  return validateSnapshot(snapshot);
2583
2594
  }
2584
2595
  };
2596
+ function generateCollectionId() {
2597
+ const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
2598
+ const idLength = 15;
2599
+ const bytes = crypto.randomBytes(idLength);
2600
+ let id = "pb_";
2601
+ for (let i = 0; i < idLength; i++) {
2602
+ const index = bytes[i] % chars.length;
2603
+ id += chars[index];
2604
+ }
2605
+ return id;
2606
+ }
2607
+ var CollectionIdRegistry = class {
2608
+ ids;
2609
+ constructor() {
2610
+ this.ids = /* @__PURE__ */ new Set();
2611
+ }
2612
+ /**
2613
+ * Generates a unique collection ID for a given collection name
2614
+ * Special case: Returns constant "_pb_users_auth_" for users collection
2615
+ * Retries up to 10 times if collision occurs (extremely rare)
2616
+ *
2617
+ * @param collectionName - The name of the collection
2618
+ * @returns A unique collection ID
2619
+ * @throws Error if unable to generate unique ID after max attempts
2620
+ */
2621
+ generate(collectionName) {
2622
+ if (collectionName && collectionName.toLowerCase() === "users") {
2623
+ const usersId = "_pb_users_auth_";
2624
+ this.register(usersId);
2625
+ return usersId;
2626
+ }
2627
+ const maxAttempts = 10;
2628
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
2629
+ const id = generateCollectionId();
2630
+ if (!this.has(id)) {
2631
+ this.register(id);
2632
+ return id;
2633
+ }
2634
+ }
2635
+ throw new Error("Failed to generate unique collection ID after maximum attempts");
2636
+ }
2637
+ /**
2638
+ * Checks if an ID has already been registered
2639
+ *
2640
+ * @param id - The collection ID to check
2641
+ * @returns True if the ID exists in the registry
2642
+ */
2643
+ has(id) {
2644
+ return this.ids.has(id);
2645
+ }
2646
+ /**
2647
+ * Registers a collection ID in the registry
2648
+ *
2649
+ * @param id - The collection ID to register
2650
+ */
2651
+ register(id) {
2652
+ this.ids.add(id);
2653
+ }
2654
+ };
2585
2655
 
2586
2656
  // src/migration/diff.ts
2587
2657
  var DEFAULT_CONFIG3 = {
@@ -2924,6 +2994,18 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
2924
2994
  const filteredCollectionsToDelete = collectionsToDelete.filter(
2925
2995
  (collection) => !isSystemCollection(collection.name, config)
2926
2996
  );
2997
+ const registry = new CollectionIdRegistry();
2998
+ const collectionsWithIds = filteredCollectionsToCreate.map((collection) => {
2999
+ if (collection.id) {
3000
+ registry.register(collection.id);
3001
+ return collection;
3002
+ }
3003
+ const id = registry.generate(collection.name);
3004
+ return {
3005
+ ...collection,
3006
+ id
3007
+ };
3008
+ });
2927
3009
  const collectionsToModify = [];
2928
3010
  const matchedCollections = matchCollectionsByName(currentSchema, previousSnapshot);
2929
3011
  for (const [currentCollection, previousCollection] of matchedCollections) {
@@ -2933,7 +3015,7 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
2933
3015
  }
2934
3016
  }
2935
3017
  return {
2936
- collectionsToCreate: filteredCollectionsToCreate,
3018
+ collectionsToCreate: collectionsWithIds,
2937
3019
  collectionsToDelete: filteredCollectionsToDelete,
2938
3020
  collectionsToModify
2939
3021
  };
@@ -3169,6 +3251,49 @@ function generateTimestamp(config) {
3169
3251
  }
3170
3252
  return Math.floor(Date.now() / 1e3).toString();
3171
3253
  }
3254
+ function splitDiffByCollection(diff, baseTimestamp) {
3255
+ const operations = [];
3256
+ let currentTimestamp = parseInt(baseTimestamp, 10);
3257
+ for (const collection of diff.collectionsToCreate) {
3258
+ operations.push({
3259
+ type: "create",
3260
+ collection,
3261
+ timestamp: currentTimestamp.toString()
3262
+ });
3263
+ currentTimestamp += 1;
3264
+ }
3265
+ for (const modification of diff.collectionsToModify) {
3266
+ operations.push({
3267
+ type: "modify",
3268
+ collection: modification.collection,
3269
+ modifications: modification,
3270
+ timestamp: currentTimestamp.toString()
3271
+ });
3272
+ currentTimestamp += 1;
3273
+ }
3274
+ for (const collection of diff.collectionsToDelete) {
3275
+ operations.push({
3276
+ type: "delete",
3277
+ collection: collection.name || collection,
3278
+ // Handle both object and string
3279
+ timestamp: currentTimestamp.toString()
3280
+ });
3281
+ currentTimestamp += 1;
3282
+ }
3283
+ return operations;
3284
+ }
3285
+ function generateCollectionMigrationFilename(operation) {
3286
+ const timestamp = operation.timestamp;
3287
+ const operationType = operation.type === "modify" ? "updated" : operation.type === "create" ? "created" : "deleted";
3288
+ let collectionName;
3289
+ if (typeof operation.collection === "string") {
3290
+ collectionName = operation.collection;
3291
+ } else {
3292
+ collectionName = operation.collection.name;
3293
+ }
3294
+ const sanitizedName = collectionName.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase();
3295
+ return `${timestamp}_${operationType}_${sanitizedName}.js`;
3296
+ }
3172
3297
  function generateMigrationDescription(diff) {
3173
3298
  const parts = [];
3174
3299
  if (diff.collectionsToCreate.length > 0) {
@@ -3276,14 +3401,13 @@ function formatValue(value) {
3276
3401
  return "null";
3277
3402
  }
3278
3403
  if (typeof value === "string") {
3279
- return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`;
3404
+ return JSON.stringify(value);
3280
3405
  }
3281
3406
  if (typeof value === "number" || typeof value === "boolean") {
3282
3407
  return String(value);
3283
3408
  }
3284
3409
  if (Array.isArray(value)) {
3285
- const items = value.map((v) => formatValue(v)).join(", ");
3286
- return `[${items}]`;
3410
+ return JSON.stringify(value).replace(/","/g, '", "');
3287
3411
  }
3288
3412
  if (typeof value === "object") {
3289
3413
  const entries = Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
@@ -3291,7 +3415,7 @@ function formatValue(value) {
3291
3415
  }
3292
3416
  return String(value);
3293
3417
  }
3294
- function generateFieldDefinitionObject(field) {
3418
+ function generateFieldDefinitionObject(field, collectionIdMap) {
3295
3419
  const parts = [];
3296
3420
  parts.push(` name: "${field.name}"`);
3297
3421
  parts.push(` type: "${field.type}"`);
@@ -3299,34 +3423,47 @@ function generateFieldDefinitionObject(field) {
3299
3423
  if (field.unique !== void 0) {
3300
3424
  parts.push(` unique: ${field.unique}`);
3301
3425
  }
3426
+ if (field.type === "select") {
3427
+ const maxSelect = field.options?.maxSelect ?? 1;
3428
+ parts.push(` maxSelect: ${maxSelect}`);
3429
+ const values = field.options?.values ?? [];
3430
+ parts.push(` values: ${formatValue(values)}`);
3431
+ }
3302
3432
  if (field.options && Object.keys(field.options).length > 0) {
3303
3433
  for (const [key, value] of Object.entries(field.options)) {
3434
+ if (field.type === "select" && (key === "maxSelect" || key === "values")) {
3435
+ continue;
3436
+ }
3304
3437
  parts.push(` ${key}: ${formatValue(value)}`);
3305
3438
  }
3306
3439
  }
3307
3440
  if (field.relation) {
3308
3441
  const isUsersCollection = field.relation.collection.toLowerCase() === "users";
3309
- const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3310
- parts.push(` collectionId: ${collectionIdPlaceholder}`);
3311
- if (field.relation.maxSelect !== void 0) {
3312
- parts.push(` maxSelect: ${field.relation.maxSelect}`);
3313
- }
3314
- if (field.relation.minSelect !== void 0) {
3315
- parts.push(` minSelect: ${field.relation.minSelect}`);
3316
- }
3317
- if (field.relation.cascadeDelete !== void 0) {
3318
- parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
3442
+ let collectionIdValue;
3443
+ if (isUsersCollection) {
3444
+ collectionIdValue = '"_pb_users_auth_"';
3445
+ } else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
3446
+ collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
3447
+ } else {
3448
+ collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3319
3449
  }
3450
+ parts.push(` collectionId: ${collectionIdValue}`);
3451
+ const maxSelect = field.relation.maxSelect ?? 1;
3452
+ parts.push(` maxSelect: ${maxSelect}`);
3453
+ const minSelect = field.relation.minSelect ?? null;
3454
+ parts.push(` minSelect: ${minSelect}`);
3455
+ const cascadeDelete = field.relation.cascadeDelete ?? false;
3456
+ parts.push(` cascadeDelete: ${cascadeDelete}`);
3320
3457
  }
3321
3458
  return ` {
3322
3459
  ${parts.join(",\n")},
3323
3460
  }`;
3324
3461
  }
3325
- function generateFieldsArray(fields) {
3462
+ function generateFieldsArray(fields, collectionIdMap) {
3326
3463
  if (fields.length === 0) {
3327
3464
  return "[]";
3328
3465
  }
3329
- const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field));
3466
+ const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field, collectionIdMap));
3330
3467
  return `[
3331
3468
  ${fieldObjects.join(",\n")},
3332
3469
  ]`;
@@ -3385,7 +3522,7 @@ function generateIndexesArray(indexes) {
3385
3522
  if (!indexes || indexes.length === 0) {
3386
3523
  return "[]";
3387
3524
  }
3388
- const indexStrings = indexes.map((idx) => `"${idx}"`);
3525
+ const indexStrings = indexes.map((idx) => JSON.stringify(idx));
3389
3526
  return `[
3390
3527
  ${indexStrings.join(",\n ")},
3391
3528
  ]`;
@@ -3439,7 +3576,7 @@ function getSystemFields() {
3439
3576
  }
3440
3577
  ];
3441
3578
  }
3442
- function generateCollectionCreation(collection, varName = "collection", isLast = false) {
3579
+ function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
3443
3580
  const lines = [];
3444
3581
  lines.push(` const ${varName} = new Collection({`);
3445
3582
  lines.push(` name: "${collection.name}",`);
@@ -3453,7 +3590,7 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
3453
3590
  }
3454
3591
  const systemFields = getSystemFields();
3455
3592
  const allFields = [...systemFields, ...collection.fields];
3456
- lines.push(` fields: ${generateFieldsArray(allFields)},`);
3593
+ lines.push(` fields: ${generateFieldsArray(allFields, collectionIdMap)},`);
3457
3594
  lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
3458
3595
  lines.push(` });`);
3459
3596
  lines.push(``);
@@ -3475,42 +3612,59 @@ function getFieldConstructorName(fieldType) {
3475
3612
  };
3476
3613
  return constructorMap[fieldType] || "TextField";
3477
3614
  }
3478
- function generateFieldConstructorOptions(field) {
3615
+ function generateFieldConstructorOptions(field, collectionIdMap) {
3479
3616
  const parts = [];
3480
3617
  parts.push(` name: "${field.name}"`);
3481
3618
  parts.push(` required: ${field.required}`);
3482
3619
  if (field.unique !== void 0) {
3483
3620
  parts.push(` unique: ${field.unique}`);
3484
3621
  }
3622
+ if (field.type === "select") {
3623
+ const maxSelect = field.options?.maxSelect ?? 1;
3624
+ parts.push(` maxSelect: ${maxSelect}`);
3625
+ const values = field.options?.values ?? [];
3626
+ parts.push(` values: ${formatValue(values)}`);
3627
+ }
3485
3628
  if (field.options && Object.keys(field.options).length > 0) {
3486
3629
  for (const [key, value] of Object.entries(field.options)) {
3487
- parts.push(` ${key}: ${formatValue(value)}`);
3630
+ if (field.type === "select" && (key === "maxSelect" || key === "values")) {
3631
+ continue;
3632
+ }
3633
+ if (field.type === "number" && key === "noDecimal") {
3634
+ parts.push(` onlyInt: ${formatValue(value)}`);
3635
+ } else {
3636
+ parts.push(` ${key}: ${formatValue(value)}`);
3637
+ }
3488
3638
  }
3489
3639
  }
3490
3640
  if (field.relation && field.type === "relation") {
3491
3641
  const isUsersCollection = field.relation.collection.toLowerCase() === "users";
3492
- const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3493
- parts.push(` collectionId: ${collectionIdPlaceholder}`);
3494
- if (field.relation.maxSelect !== void 0) {
3495
- parts.push(` maxSelect: ${field.relation.maxSelect}`);
3496
- }
3497
- if (field.relation.minSelect !== void 0) {
3498
- parts.push(` minSelect: ${field.relation.minSelect}`);
3499
- }
3500
- if (field.relation.cascadeDelete !== void 0) {
3501
- parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
3642
+ let collectionIdValue;
3643
+ if (isUsersCollection) {
3644
+ collectionIdValue = '"_pb_users_auth_"';
3645
+ } else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
3646
+ collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
3647
+ } else {
3648
+ collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3502
3649
  }
3650
+ parts.push(` collectionId: ${collectionIdValue}`);
3651
+ const maxSelect = field.relation.maxSelect ?? 1;
3652
+ parts.push(` maxSelect: ${maxSelect}`);
3653
+ const minSelect = field.relation.minSelect ?? null;
3654
+ parts.push(` minSelect: ${minSelect}`);
3655
+ const cascadeDelete = field.relation.cascadeDelete ?? false;
3656
+ parts.push(` cascadeDelete: ${cascadeDelete}`);
3503
3657
  }
3504
3658
  return parts.join(",\n");
3505
3659
  }
3506
- function generateFieldAddition(collectionName, field, varName, isLast = false) {
3660
+ function generateFieldAddition(collectionName, field, varName, isLast = false, collectionIdMap) {
3507
3661
  const lines = [];
3508
3662
  const constructorName = getFieldConstructorName(field.type);
3509
3663
  const collectionVar = varName || `collection_${collectionName}_${field.name}`;
3510
3664
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3511
3665
  lines.push(``);
3512
3666
  lines.push(` ${collectionVar}.fields.add(new ${constructorName}({`);
3513
- lines.push(generateFieldConstructorOptions(field));
3667
+ lines.push(generateFieldConstructorOptions(field, collectionIdMap));
3514
3668
  lines.push(` }));`);
3515
3669
  lines.push(``);
3516
3670
  lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
@@ -3560,7 +3714,7 @@ function generateIndexAddition(collectionName, index, varName, isLast = false) {
3560
3714
  const lines = [];
3561
3715
  const collectionVar = varName || `collection_${collectionName}_idx`;
3562
3716
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3563
- lines.push(` ${collectionVar}.indexes.push("${index}");`);
3717
+ lines.push(` ${collectionVar}.indexes.push(${JSON.stringify(index)});`);
3564
3718
  lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3565
3719
  return lines.join("\n");
3566
3720
  }
@@ -3569,7 +3723,7 @@ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
3569
3723
  const collectionVar = varName || `collection_${collectionName}_idx`;
3570
3724
  const indexVar = `${collectionVar}_indexToRemove`;
3571
3725
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3572
- lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === "${index}");`);
3726
+ lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === ${JSON.stringify(index)});`);
3573
3727
  lines.push(` if (${indexVar} !== -1) {`);
3574
3728
  lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
3575
3729
  lines.push(` }`);
@@ -3598,16 +3752,179 @@ function generateCollectionDeletion(collectionName, varName = "collection", isLa
3598
3752
  lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
3599
3753
  return lines.join("\n");
3600
3754
  }
3755
+ function generateOperationUpMigration(operation, collectionIdMap) {
3756
+ const lines = [];
3757
+ if (operation.type === "create") {
3758
+ const collection = operation.collection;
3759
+ const varName = `collection_${collection.name}`;
3760
+ lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
3761
+ } else if (operation.type === "modify") {
3762
+ const modification = operation.modifications;
3763
+ const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
3764
+ let operationCount = 0;
3765
+ const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
3766
+ for (const field of modification.fieldsToAdd) {
3767
+ operationCount++;
3768
+ const varName = `collection_${collectionName}_add_${field.name}`;
3769
+ const isLast = operationCount === totalOperations;
3770
+ lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
3771
+ if (!isLast) lines.push("");
3772
+ }
3773
+ for (const fieldMod of modification.fieldsToModify) {
3774
+ operationCount++;
3775
+ const varName = `collection_${collectionName}_modify_${fieldMod.fieldName}`;
3776
+ const isLast = operationCount === totalOperations;
3777
+ lines.push(generateFieldModification(collectionName, fieldMod, varName, isLast));
3778
+ if (!isLast) lines.push("");
3779
+ }
3780
+ for (const field of modification.fieldsToRemove) {
3781
+ operationCount++;
3782
+ const varName = `collection_${collectionName}_remove_${field.name}`;
3783
+ const isLast = operationCount === totalOperations;
3784
+ lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
3785
+ if (!isLast) lines.push("");
3786
+ }
3787
+ for (let i = 0; i < modification.indexesToAdd.length; i++) {
3788
+ operationCount++;
3789
+ const index = modification.indexesToAdd[i];
3790
+ const varName = `collection_${collectionName}_addidx_${i}`;
3791
+ const isLast = operationCount === totalOperations;
3792
+ lines.push(generateIndexAddition(collectionName, index, varName, isLast));
3793
+ if (!isLast) lines.push("");
3794
+ }
3795
+ for (let i = 0; i < modification.indexesToRemove.length; i++) {
3796
+ operationCount++;
3797
+ const index = modification.indexesToRemove[i];
3798
+ const varName = `collection_${collectionName}_rmidx_${i}`;
3799
+ const isLast = operationCount === totalOperations;
3800
+ lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
3801
+ if (!isLast) lines.push("");
3802
+ }
3803
+ if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
3804
+ for (const permission of modification.permissionsToUpdate) {
3805
+ operationCount++;
3806
+ const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
3807
+ const isLast = operationCount === totalOperations;
3808
+ lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast));
3809
+ if (!isLast) lines.push("");
3810
+ }
3811
+ } else if (modification.rulesToUpdate.length > 0) {
3812
+ for (const rule of modification.rulesToUpdate) {
3813
+ operationCount++;
3814
+ const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
3815
+ const isLast = operationCount === totalOperations;
3816
+ lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast));
3817
+ if (!isLast) lines.push("");
3818
+ }
3819
+ }
3820
+ } else if (operation.type === "delete") {
3821
+ const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
3822
+ const varName = `collection_${collectionName}`;
3823
+ lines.push(generateCollectionDeletion(collectionName, varName, true));
3824
+ }
3825
+ return lines.join("\n");
3826
+ }
3827
+ function generateOperationDownMigration(operation, collectionIdMap) {
3828
+ const lines = [];
3829
+ if (operation.type === "create") {
3830
+ const collection = operation.collection;
3831
+ const varName = `collection_${collection.name}`;
3832
+ lines.push(generateCollectionDeletion(collection.name, varName, true));
3833
+ } else if (operation.type === "modify") {
3834
+ const modification = operation.modifications;
3835
+ const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
3836
+ let operationCount = 0;
3837
+ const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
3838
+ if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
3839
+ for (const permission of modification.permissionsToUpdate) {
3840
+ operationCount++;
3841
+ const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
3842
+ const isLast = operationCount === totalOperations;
3843
+ lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast));
3844
+ if (!isLast) lines.push("");
3845
+ }
3846
+ } else if (modification.rulesToUpdate.length > 0) {
3847
+ for (const rule of modification.rulesToUpdate) {
3848
+ operationCount++;
3849
+ const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
3850
+ const isLast = operationCount === totalOperations;
3851
+ lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast));
3852
+ if (!isLast) lines.push("");
3853
+ }
3854
+ }
3855
+ for (let i = 0; i < modification.indexesToRemove.length; i++) {
3856
+ operationCount++;
3857
+ const index = modification.indexesToRemove[i];
3858
+ const varName = `collection_${collectionName}_restore_idx_${i}`;
3859
+ const isLast = operationCount === totalOperations;
3860
+ lines.push(generateIndexAddition(collectionName, index, varName, isLast));
3861
+ if (!isLast) lines.push("");
3862
+ }
3863
+ for (let i = 0; i < modification.indexesToAdd.length; i++) {
3864
+ operationCount++;
3865
+ const index = modification.indexesToAdd[i];
3866
+ const varName = `collection_${collectionName}_revert_idx_${i}`;
3867
+ const isLast = operationCount === totalOperations;
3868
+ lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
3869
+ if (!isLast) lines.push("");
3870
+ }
3871
+ for (const field of modification.fieldsToRemove) {
3872
+ operationCount++;
3873
+ const varName = `collection_${collectionName}_restore_${field.name}`;
3874
+ const isLast = operationCount === totalOperations;
3875
+ lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
3876
+ if (!isLast) lines.push("");
3877
+ }
3878
+ for (const fieldMod of modification.fieldsToModify) {
3879
+ operationCount++;
3880
+ const reverseChanges = fieldMod.changes.map((change) => ({
3881
+ property: change.property,
3882
+ oldValue: change.newValue,
3883
+ newValue: change.oldValue
3884
+ }));
3885
+ const reverseMod = {
3886
+ fieldName: fieldMod.fieldName,
3887
+ currentDefinition: fieldMod.newDefinition,
3888
+ newDefinition: fieldMod.currentDefinition,
3889
+ changes: reverseChanges
3890
+ };
3891
+ const varName = `collection_${collectionName}_revert_${fieldMod.fieldName}`;
3892
+ const isLast = operationCount === totalOperations;
3893
+ lines.push(generateFieldModification(collectionName, reverseMod, varName, isLast));
3894
+ if (!isLast) lines.push("");
3895
+ }
3896
+ for (const field of modification.fieldsToAdd) {
3897
+ operationCount++;
3898
+ const varName = `collection_${collectionName}_revert_add_${field.name}`;
3899
+ const isLast = operationCount === totalOperations;
3900
+ lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
3901
+ if (!isLast) lines.push("");
3902
+ }
3903
+ } else if (operation.type === "delete") {
3904
+ const collection = operation.collection;
3905
+ if (typeof collection !== "string") {
3906
+ const varName = `collection_${collection.name}`;
3907
+ lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
3908
+ }
3909
+ }
3910
+ return lines.join("\n");
3911
+ }
3601
3912
  function generateUpMigration(diff) {
3602
3913
  const lines = [];
3603
3914
  lines.push(` // UP MIGRATION`);
3604
3915
  lines.push(``);
3916
+ const collectionIdMap = /* @__PURE__ */ new Map();
3917
+ for (const collection of diff.collectionsToCreate) {
3918
+ if (collection.id) {
3919
+ collectionIdMap.set(collection.name, collection.id);
3920
+ }
3921
+ }
3605
3922
  if (diff.collectionsToCreate.length > 0) {
3606
3923
  lines.push(` // Create new collections`);
3607
3924
  for (let i = 0; i < diff.collectionsToCreate.length; i++) {
3608
3925
  const collection = diff.collectionsToCreate[i];
3609
3926
  const varName = `collection_${collection.name}_create`;
3610
- lines.push(generateCollectionCreation(collection, varName));
3927
+ lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
3611
3928
  lines.push(``);
3612
3929
  }
3613
3930
  }
@@ -3619,7 +3936,7 @@ function generateUpMigration(diff) {
3619
3936
  lines.push(` // Add fields to ${collectionName}`);
3620
3937
  for (const field of modification.fieldsToAdd) {
3621
3938
  const varName = `collection_${collectionName}_add_${field.name}`;
3622
- lines.push(generateFieldAddition(collectionName, field, varName));
3939
+ lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
3623
3940
  lines.push(``);
3624
3941
  }
3625
3942
  }
@@ -3710,12 +4027,23 @@ function generateDownMigration(diff) {
3710
4027
  const lines = [];
3711
4028
  lines.push(` // DOWN MIGRATION (ROLLBACK)`);
3712
4029
  lines.push(``);
4030
+ const collectionIdMap = /* @__PURE__ */ new Map();
4031
+ for (const collection of diff.collectionsToCreate) {
4032
+ if (collection.id) {
4033
+ collectionIdMap.set(collection.name, collection.id);
4034
+ }
4035
+ }
4036
+ for (const collection of diff.collectionsToDelete) {
4037
+ if (collection.id) {
4038
+ collectionIdMap.set(collection.name, collection.id);
4039
+ }
4040
+ }
3713
4041
  if (diff.collectionsToDelete.length > 0) {
3714
4042
  lines.push(` // Recreate deleted collections`);
3715
4043
  for (let i = 0; i < diff.collectionsToDelete.length; i++) {
3716
4044
  const collection = diff.collectionsToDelete[i];
3717
4045
  const varName = `collection_${collection.name}_recreate`;
3718
- lines.push(generateCollectionCreation(collection, varName));
4046
+ lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
3719
4047
  lines.push(``);
3720
4048
  }
3721
4049
  }
@@ -3760,7 +4088,7 @@ function generateDownMigration(diff) {
3760
4088
  lines.push(` // Restore fields to ${collectionName}`);
3761
4089
  for (const field of modification.fieldsToRemove) {
3762
4090
  const varName = `collection_${collectionName}_restore_${field.name}`;
3763
- lines.push(generateFieldAddition(collectionName, field, varName));
4091
+ lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
3764
4092
  lines.push(``);
3765
4093
  }
3766
4094
  }
@@ -3829,12 +4157,33 @@ function generate(diff, config) {
3829
4157
  const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
3830
4158
  try {
3831
4159
  const migrationDir = resolveMigrationDir(normalizedConfig);
3832
- const upCode = generateUpMigration(diff);
3833
- const downCode = generateDownMigration(diff);
3834
- const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
3835
- const filename = generateMigrationFilename(diff, normalizedConfig);
3836
- const filePath = writeMigrationFile(migrationDir, filename, content);
3837
- return filePath;
4160
+ const hasChanges2 = diff.collectionsToCreate.length > 0 || diff.collectionsToModify.length > 0 || diff.collectionsToDelete.length > 0;
4161
+ if (!hasChanges2) {
4162
+ return [];
4163
+ }
4164
+ const collectionIdMap = /* @__PURE__ */ new Map();
4165
+ for (const collection of diff.collectionsToCreate) {
4166
+ if (collection.id) {
4167
+ collectionIdMap.set(collection.name, collection.id);
4168
+ }
4169
+ }
4170
+ for (const collection of diff.collectionsToDelete) {
4171
+ if (collection.id) {
4172
+ collectionIdMap.set(collection.name, collection.id);
4173
+ }
4174
+ }
4175
+ const baseTimestamp = generateTimestamp(normalizedConfig);
4176
+ const operations = splitDiffByCollection(diff, baseTimestamp);
4177
+ const filePaths = [];
4178
+ for (const operation of operations) {
4179
+ const upCode = generateOperationUpMigration(operation, collectionIdMap);
4180
+ const downCode = generateOperationDownMigration(operation, collectionIdMap);
4181
+ const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
4182
+ const filename = generateCollectionMigrationFilename(operation);
4183
+ const filePath = writeMigrationFile(migrationDir, filename, content);
4184
+ filePaths.push(filePath);
4185
+ }
4186
+ return filePaths;
3838
4187
  } catch (error) {
3839
4188
  if (error instanceof MigrationGenerationError || error instanceof FileSystemError) {
3840
4189
  throw error;
@@ -3852,7 +4201,8 @@ var MigrationGenerator = class {
3852
4201
  this.config = mergeConfig4(config);
3853
4202
  }
3854
4203
  /**
3855
- * Generates a migration file from a schema diff
4204
+ * Generates migration files from a schema diff
4205
+ * Returns array of file paths (one per collection operation)
3856
4206
  */
3857
4207
  generate(diff) {
3858
4208
  return generate(diff, this.config);