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
@@ -1,6 +1,7 @@
1
1
  import * as fs3 from 'fs';
2
2
  import * as path from 'path';
3
3
  import { z } from 'zod';
4
+ import { randomBytes } from 'crypto';
4
5
 
5
6
  // src/migration/analyzer.ts
6
7
  ({
@@ -1558,12 +1559,22 @@ function isAuthCollection(fields) {
1558
1559
  function buildFieldDefinition(fieldName, zodType) {
1559
1560
  const fieldMetadata = extractFieldMetadata(zodType.description);
1560
1561
  if (fieldMetadata) {
1561
- const required2 = isFieldRequired(zodType);
1562
+ let required2;
1563
+ if (fieldMetadata.type === "number") {
1564
+ if (fieldMetadata.options?.required !== void 0) {
1565
+ required2 = fieldMetadata.options.required;
1566
+ } else {
1567
+ required2 = false;
1568
+ }
1569
+ } else {
1570
+ required2 = isFieldRequired(zodType);
1571
+ }
1572
+ const { required: _required, ...options2 } = fieldMetadata.options || {};
1562
1573
  const fieldDef2 = {
1563
1574
  name: fieldName,
1564
1575
  type: fieldMetadata.type,
1565
1576
  required: required2,
1566
- options: fieldMetadata.options
1577
+ options: Object.keys(options2).length > 0 ? options2 : void 0
1567
1578
  };
1568
1579
  if (fieldMetadata.type === "relation") {
1569
1580
  const relationMetadata2 = extractRelationMetadata(zodType.description);
@@ -2559,6 +2570,65 @@ var SnapshotManager = class {
2559
2570
  return validateSnapshot(snapshot);
2560
2571
  }
2561
2572
  };
2573
+ function generateCollectionId() {
2574
+ const chars = "abcdefghijklmnopqrstuvwxyz0123456789";
2575
+ const idLength = 15;
2576
+ const bytes = randomBytes(idLength);
2577
+ let id = "pb_";
2578
+ for (let i = 0; i < idLength; i++) {
2579
+ const index = bytes[i] % chars.length;
2580
+ id += chars[index];
2581
+ }
2582
+ return id;
2583
+ }
2584
+ var CollectionIdRegistry = class {
2585
+ ids;
2586
+ constructor() {
2587
+ this.ids = /* @__PURE__ */ new Set();
2588
+ }
2589
+ /**
2590
+ * Generates a unique collection ID for a given collection name
2591
+ * Special case: Returns constant "_pb_users_auth_" for users collection
2592
+ * Retries up to 10 times if collision occurs (extremely rare)
2593
+ *
2594
+ * @param collectionName - The name of the collection
2595
+ * @returns A unique collection ID
2596
+ * @throws Error if unable to generate unique ID after max attempts
2597
+ */
2598
+ generate(collectionName) {
2599
+ if (collectionName && collectionName.toLowerCase() === "users") {
2600
+ const usersId = "_pb_users_auth_";
2601
+ this.register(usersId);
2602
+ return usersId;
2603
+ }
2604
+ const maxAttempts = 10;
2605
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
2606
+ const id = generateCollectionId();
2607
+ if (!this.has(id)) {
2608
+ this.register(id);
2609
+ return id;
2610
+ }
2611
+ }
2612
+ throw new Error("Failed to generate unique collection ID after maximum attempts");
2613
+ }
2614
+ /**
2615
+ * Checks if an ID has already been registered
2616
+ *
2617
+ * @param id - The collection ID to check
2618
+ * @returns True if the ID exists in the registry
2619
+ */
2620
+ has(id) {
2621
+ return this.ids.has(id);
2622
+ }
2623
+ /**
2624
+ * Registers a collection ID in the registry
2625
+ *
2626
+ * @param id - The collection ID to register
2627
+ */
2628
+ register(id) {
2629
+ this.ids.add(id);
2630
+ }
2631
+ };
2562
2632
 
2563
2633
  // src/migration/diff.ts
2564
2634
  var DEFAULT_CONFIG3 = {
@@ -2901,6 +2971,18 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
2901
2971
  const filteredCollectionsToDelete = collectionsToDelete.filter(
2902
2972
  (collection) => !isSystemCollection(collection.name, config)
2903
2973
  );
2974
+ const registry = new CollectionIdRegistry();
2975
+ const collectionsWithIds = filteredCollectionsToCreate.map((collection) => {
2976
+ if (collection.id) {
2977
+ registry.register(collection.id);
2978
+ return collection;
2979
+ }
2980
+ const id = registry.generate(collection.name);
2981
+ return {
2982
+ ...collection,
2983
+ id
2984
+ };
2985
+ });
2904
2986
  const collectionsToModify = [];
2905
2987
  const matchedCollections = matchCollectionsByName(currentSchema, previousSnapshot);
2906
2988
  for (const [currentCollection, previousCollection] of matchedCollections) {
@@ -2910,7 +2992,7 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
2910
2992
  }
2911
2993
  }
2912
2994
  return {
2913
- collectionsToCreate: filteredCollectionsToCreate,
2995
+ collectionsToCreate: collectionsWithIds,
2914
2996
  collectionsToDelete: filteredCollectionsToDelete,
2915
2997
  collectionsToModify
2916
2998
  };
@@ -3146,6 +3228,49 @@ function generateTimestamp(config) {
3146
3228
  }
3147
3229
  return Math.floor(Date.now() / 1e3).toString();
3148
3230
  }
3231
+ function splitDiffByCollection(diff, baseTimestamp) {
3232
+ const operations = [];
3233
+ let currentTimestamp = parseInt(baseTimestamp, 10);
3234
+ for (const collection of diff.collectionsToCreate) {
3235
+ operations.push({
3236
+ type: "create",
3237
+ collection,
3238
+ timestamp: currentTimestamp.toString()
3239
+ });
3240
+ currentTimestamp += 1;
3241
+ }
3242
+ for (const modification of diff.collectionsToModify) {
3243
+ operations.push({
3244
+ type: "modify",
3245
+ collection: modification.collection,
3246
+ modifications: modification,
3247
+ timestamp: currentTimestamp.toString()
3248
+ });
3249
+ currentTimestamp += 1;
3250
+ }
3251
+ for (const collection of diff.collectionsToDelete) {
3252
+ operations.push({
3253
+ type: "delete",
3254
+ collection: collection.name || collection,
3255
+ // Handle both object and string
3256
+ timestamp: currentTimestamp.toString()
3257
+ });
3258
+ currentTimestamp += 1;
3259
+ }
3260
+ return operations;
3261
+ }
3262
+ function generateCollectionMigrationFilename(operation) {
3263
+ const timestamp = operation.timestamp;
3264
+ const operationType = operation.type === "modify" ? "updated" : operation.type === "create" ? "created" : "deleted";
3265
+ let collectionName;
3266
+ if (typeof operation.collection === "string") {
3267
+ collectionName = operation.collection;
3268
+ } else {
3269
+ collectionName = operation.collection.name;
3270
+ }
3271
+ const sanitizedName = collectionName.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase();
3272
+ return `${timestamp}_${operationType}_${sanitizedName}.js`;
3273
+ }
3149
3274
  function generateMigrationDescription(diff) {
3150
3275
  const parts = [];
3151
3276
  if (diff.collectionsToCreate.length > 0) {
@@ -3253,14 +3378,13 @@ function formatValue(value) {
3253
3378
  return "null";
3254
3379
  }
3255
3380
  if (typeof value === "string") {
3256
- return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`;
3381
+ return JSON.stringify(value);
3257
3382
  }
3258
3383
  if (typeof value === "number" || typeof value === "boolean") {
3259
3384
  return String(value);
3260
3385
  }
3261
3386
  if (Array.isArray(value)) {
3262
- const items = value.map((v) => formatValue(v)).join(", ");
3263
- return `[${items}]`;
3387
+ return JSON.stringify(value).replace(/","/g, '", "');
3264
3388
  }
3265
3389
  if (typeof value === "object") {
3266
3390
  const entries = Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
@@ -3268,7 +3392,7 @@ function formatValue(value) {
3268
3392
  }
3269
3393
  return String(value);
3270
3394
  }
3271
- function generateFieldDefinitionObject(field) {
3395
+ function generateFieldDefinitionObject(field, collectionIdMap) {
3272
3396
  const parts = [];
3273
3397
  parts.push(` name: "${field.name}"`);
3274
3398
  parts.push(` type: "${field.type}"`);
@@ -3276,34 +3400,47 @@ function generateFieldDefinitionObject(field) {
3276
3400
  if (field.unique !== void 0) {
3277
3401
  parts.push(` unique: ${field.unique}`);
3278
3402
  }
3403
+ if (field.type === "select") {
3404
+ const maxSelect = field.options?.maxSelect ?? 1;
3405
+ parts.push(` maxSelect: ${maxSelect}`);
3406
+ const values = field.options?.values ?? [];
3407
+ parts.push(` values: ${formatValue(values)}`);
3408
+ }
3279
3409
  if (field.options && Object.keys(field.options).length > 0) {
3280
3410
  for (const [key, value] of Object.entries(field.options)) {
3411
+ if (field.type === "select" && (key === "maxSelect" || key === "values")) {
3412
+ continue;
3413
+ }
3281
3414
  parts.push(` ${key}: ${formatValue(value)}`);
3282
3415
  }
3283
3416
  }
3284
3417
  if (field.relation) {
3285
3418
  const isUsersCollection = field.relation.collection.toLowerCase() === "users";
3286
- const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3287
- parts.push(` collectionId: ${collectionIdPlaceholder}`);
3288
- if (field.relation.maxSelect !== void 0) {
3289
- parts.push(` maxSelect: ${field.relation.maxSelect}`);
3290
- }
3291
- if (field.relation.minSelect !== void 0) {
3292
- parts.push(` minSelect: ${field.relation.minSelect}`);
3293
- }
3294
- if (field.relation.cascadeDelete !== void 0) {
3295
- parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
3419
+ let collectionIdValue;
3420
+ if (isUsersCollection) {
3421
+ collectionIdValue = '"_pb_users_auth_"';
3422
+ } else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
3423
+ collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
3424
+ } else {
3425
+ collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3296
3426
  }
3427
+ parts.push(` collectionId: ${collectionIdValue}`);
3428
+ const maxSelect = field.relation.maxSelect ?? 1;
3429
+ parts.push(` maxSelect: ${maxSelect}`);
3430
+ const minSelect = field.relation.minSelect ?? null;
3431
+ parts.push(` minSelect: ${minSelect}`);
3432
+ const cascadeDelete = field.relation.cascadeDelete ?? false;
3433
+ parts.push(` cascadeDelete: ${cascadeDelete}`);
3297
3434
  }
3298
3435
  return ` {
3299
3436
  ${parts.join(",\n")},
3300
3437
  }`;
3301
3438
  }
3302
- function generateFieldsArray(fields) {
3439
+ function generateFieldsArray(fields, collectionIdMap) {
3303
3440
  if (fields.length === 0) {
3304
3441
  return "[]";
3305
3442
  }
3306
- const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field));
3443
+ const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field, collectionIdMap));
3307
3444
  return `[
3308
3445
  ${fieldObjects.join(",\n")},
3309
3446
  ]`;
@@ -3362,7 +3499,7 @@ function generateIndexesArray(indexes) {
3362
3499
  if (!indexes || indexes.length === 0) {
3363
3500
  return "[]";
3364
3501
  }
3365
- const indexStrings = indexes.map((idx) => `"${idx}"`);
3502
+ const indexStrings = indexes.map((idx) => JSON.stringify(idx));
3366
3503
  return `[
3367
3504
  ${indexStrings.join(",\n ")},
3368
3505
  ]`;
@@ -3416,7 +3553,7 @@ function getSystemFields() {
3416
3553
  }
3417
3554
  ];
3418
3555
  }
3419
- function generateCollectionCreation(collection, varName = "collection", isLast = false) {
3556
+ function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
3420
3557
  const lines = [];
3421
3558
  lines.push(` const ${varName} = new Collection({`);
3422
3559
  lines.push(` name: "${collection.name}",`);
@@ -3430,7 +3567,7 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
3430
3567
  }
3431
3568
  const systemFields = getSystemFields();
3432
3569
  const allFields = [...systemFields, ...collection.fields];
3433
- lines.push(` fields: ${generateFieldsArray(allFields)},`);
3570
+ lines.push(` fields: ${generateFieldsArray(allFields, collectionIdMap)},`);
3434
3571
  lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
3435
3572
  lines.push(` });`);
3436
3573
  lines.push(``);
@@ -3452,42 +3589,59 @@ function getFieldConstructorName(fieldType) {
3452
3589
  };
3453
3590
  return constructorMap[fieldType] || "TextField";
3454
3591
  }
3455
- function generateFieldConstructorOptions(field) {
3592
+ function generateFieldConstructorOptions(field, collectionIdMap) {
3456
3593
  const parts = [];
3457
3594
  parts.push(` name: "${field.name}"`);
3458
3595
  parts.push(` required: ${field.required}`);
3459
3596
  if (field.unique !== void 0) {
3460
3597
  parts.push(` unique: ${field.unique}`);
3461
3598
  }
3599
+ if (field.type === "select") {
3600
+ const maxSelect = field.options?.maxSelect ?? 1;
3601
+ parts.push(` maxSelect: ${maxSelect}`);
3602
+ const values = field.options?.values ?? [];
3603
+ parts.push(` values: ${formatValue(values)}`);
3604
+ }
3462
3605
  if (field.options && Object.keys(field.options).length > 0) {
3463
3606
  for (const [key, value] of Object.entries(field.options)) {
3464
- parts.push(` ${key}: ${formatValue(value)}`);
3607
+ if (field.type === "select" && (key === "maxSelect" || key === "values")) {
3608
+ continue;
3609
+ }
3610
+ if (field.type === "number" && key === "noDecimal") {
3611
+ parts.push(` onlyInt: ${formatValue(value)}`);
3612
+ } else {
3613
+ parts.push(` ${key}: ${formatValue(value)}`);
3614
+ }
3465
3615
  }
3466
3616
  }
3467
3617
  if (field.relation && field.type === "relation") {
3468
3618
  const isUsersCollection = field.relation.collection.toLowerCase() === "users";
3469
- const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3470
- parts.push(` collectionId: ${collectionIdPlaceholder}`);
3471
- if (field.relation.maxSelect !== void 0) {
3472
- parts.push(` maxSelect: ${field.relation.maxSelect}`);
3473
- }
3474
- if (field.relation.minSelect !== void 0) {
3475
- parts.push(` minSelect: ${field.relation.minSelect}`);
3476
- }
3477
- if (field.relation.cascadeDelete !== void 0) {
3478
- parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
3619
+ let collectionIdValue;
3620
+ if (isUsersCollection) {
3621
+ collectionIdValue = '"_pb_users_auth_"';
3622
+ } else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
3623
+ collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
3624
+ } else {
3625
+ collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3479
3626
  }
3627
+ parts.push(` collectionId: ${collectionIdValue}`);
3628
+ const maxSelect = field.relation.maxSelect ?? 1;
3629
+ parts.push(` maxSelect: ${maxSelect}`);
3630
+ const minSelect = field.relation.minSelect ?? null;
3631
+ parts.push(` minSelect: ${minSelect}`);
3632
+ const cascadeDelete = field.relation.cascadeDelete ?? false;
3633
+ parts.push(` cascadeDelete: ${cascadeDelete}`);
3480
3634
  }
3481
3635
  return parts.join(",\n");
3482
3636
  }
3483
- function generateFieldAddition(collectionName, field, varName, isLast = false) {
3637
+ function generateFieldAddition(collectionName, field, varName, isLast = false, collectionIdMap) {
3484
3638
  const lines = [];
3485
3639
  const constructorName = getFieldConstructorName(field.type);
3486
3640
  const collectionVar = varName || `collection_${collectionName}_${field.name}`;
3487
3641
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3488
3642
  lines.push(``);
3489
3643
  lines.push(` ${collectionVar}.fields.add(new ${constructorName}({`);
3490
- lines.push(generateFieldConstructorOptions(field));
3644
+ lines.push(generateFieldConstructorOptions(field, collectionIdMap));
3491
3645
  lines.push(` }));`);
3492
3646
  lines.push(``);
3493
3647
  lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
@@ -3537,7 +3691,7 @@ function generateIndexAddition(collectionName, index, varName, isLast = false) {
3537
3691
  const lines = [];
3538
3692
  const collectionVar = varName || `collection_${collectionName}_idx`;
3539
3693
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3540
- lines.push(` ${collectionVar}.indexes.push("${index}");`);
3694
+ lines.push(` ${collectionVar}.indexes.push(${JSON.stringify(index)});`);
3541
3695
  lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3542
3696
  return lines.join("\n");
3543
3697
  }
@@ -3546,7 +3700,7 @@ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
3546
3700
  const collectionVar = varName || `collection_${collectionName}_idx`;
3547
3701
  const indexVar = `${collectionVar}_indexToRemove`;
3548
3702
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3549
- lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === "${index}");`);
3703
+ lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === ${JSON.stringify(index)});`);
3550
3704
  lines.push(` if (${indexVar} !== -1) {`);
3551
3705
  lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
3552
3706
  lines.push(` }`);
@@ -3575,16 +3729,179 @@ function generateCollectionDeletion(collectionName, varName = "collection", isLa
3575
3729
  lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
3576
3730
  return lines.join("\n");
3577
3731
  }
3732
+ function generateOperationUpMigration(operation, collectionIdMap) {
3733
+ const lines = [];
3734
+ if (operation.type === "create") {
3735
+ const collection = operation.collection;
3736
+ const varName = `collection_${collection.name}`;
3737
+ lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
3738
+ } else if (operation.type === "modify") {
3739
+ const modification = operation.modifications;
3740
+ const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
3741
+ let operationCount = 0;
3742
+ const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
3743
+ for (const field of modification.fieldsToAdd) {
3744
+ operationCount++;
3745
+ const varName = `collection_${collectionName}_add_${field.name}`;
3746
+ const isLast = operationCount === totalOperations;
3747
+ lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
3748
+ if (!isLast) lines.push("");
3749
+ }
3750
+ for (const fieldMod of modification.fieldsToModify) {
3751
+ operationCount++;
3752
+ const varName = `collection_${collectionName}_modify_${fieldMod.fieldName}`;
3753
+ const isLast = operationCount === totalOperations;
3754
+ lines.push(generateFieldModification(collectionName, fieldMod, varName, isLast));
3755
+ if (!isLast) lines.push("");
3756
+ }
3757
+ for (const field of modification.fieldsToRemove) {
3758
+ operationCount++;
3759
+ const varName = `collection_${collectionName}_remove_${field.name}`;
3760
+ const isLast = operationCount === totalOperations;
3761
+ lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
3762
+ if (!isLast) lines.push("");
3763
+ }
3764
+ for (let i = 0; i < modification.indexesToAdd.length; i++) {
3765
+ operationCount++;
3766
+ const index = modification.indexesToAdd[i];
3767
+ const varName = `collection_${collectionName}_addidx_${i}`;
3768
+ const isLast = operationCount === totalOperations;
3769
+ lines.push(generateIndexAddition(collectionName, index, varName, isLast));
3770
+ if (!isLast) lines.push("");
3771
+ }
3772
+ for (let i = 0; i < modification.indexesToRemove.length; i++) {
3773
+ operationCount++;
3774
+ const index = modification.indexesToRemove[i];
3775
+ const varName = `collection_${collectionName}_rmidx_${i}`;
3776
+ const isLast = operationCount === totalOperations;
3777
+ lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
3778
+ if (!isLast) lines.push("");
3779
+ }
3780
+ if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
3781
+ for (const permission of modification.permissionsToUpdate) {
3782
+ operationCount++;
3783
+ const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
3784
+ const isLast = operationCount === totalOperations;
3785
+ lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast));
3786
+ if (!isLast) lines.push("");
3787
+ }
3788
+ } else if (modification.rulesToUpdate.length > 0) {
3789
+ for (const rule of modification.rulesToUpdate) {
3790
+ operationCount++;
3791
+ const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
3792
+ const isLast = operationCount === totalOperations;
3793
+ lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast));
3794
+ if (!isLast) lines.push("");
3795
+ }
3796
+ }
3797
+ } else if (operation.type === "delete") {
3798
+ const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
3799
+ const varName = `collection_${collectionName}`;
3800
+ lines.push(generateCollectionDeletion(collectionName, varName, true));
3801
+ }
3802
+ return lines.join("\n");
3803
+ }
3804
+ function generateOperationDownMigration(operation, collectionIdMap) {
3805
+ const lines = [];
3806
+ if (operation.type === "create") {
3807
+ const collection = operation.collection;
3808
+ const varName = `collection_${collection.name}`;
3809
+ lines.push(generateCollectionDeletion(collection.name, varName, true));
3810
+ } else if (operation.type === "modify") {
3811
+ const modification = operation.modifications;
3812
+ const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
3813
+ let operationCount = 0;
3814
+ const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
3815
+ if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
3816
+ for (const permission of modification.permissionsToUpdate) {
3817
+ operationCount++;
3818
+ const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
3819
+ const isLast = operationCount === totalOperations;
3820
+ lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast));
3821
+ if (!isLast) lines.push("");
3822
+ }
3823
+ } else if (modification.rulesToUpdate.length > 0) {
3824
+ for (const rule of modification.rulesToUpdate) {
3825
+ operationCount++;
3826
+ const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
3827
+ const isLast = operationCount === totalOperations;
3828
+ lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast));
3829
+ if (!isLast) lines.push("");
3830
+ }
3831
+ }
3832
+ for (let i = 0; i < modification.indexesToRemove.length; i++) {
3833
+ operationCount++;
3834
+ const index = modification.indexesToRemove[i];
3835
+ const varName = `collection_${collectionName}_restore_idx_${i}`;
3836
+ const isLast = operationCount === totalOperations;
3837
+ lines.push(generateIndexAddition(collectionName, index, varName, isLast));
3838
+ if (!isLast) lines.push("");
3839
+ }
3840
+ for (let i = 0; i < modification.indexesToAdd.length; i++) {
3841
+ operationCount++;
3842
+ const index = modification.indexesToAdd[i];
3843
+ const varName = `collection_${collectionName}_revert_idx_${i}`;
3844
+ const isLast = operationCount === totalOperations;
3845
+ lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
3846
+ if (!isLast) lines.push("");
3847
+ }
3848
+ for (const field of modification.fieldsToRemove) {
3849
+ operationCount++;
3850
+ const varName = `collection_${collectionName}_restore_${field.name}`;
3851
+ const isLast = operationCount === totalOperations;
3852
+ lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
3853
+ if (!isLast) lines.push("");
3854
+ }
3855
+ for (const fieldMod of modification.fieldsToModify) {
3856
+ operationCount++;
3857
+ const reverseChanges = fieldMod.changes.map((change) => ({
3858
+ property: change.property,
3859
+ oldValue: change.newValue,
3860
+ newValue: change.oldValue
3861
+ }));
3862
+ const reverseMod = {
3863
+ fieldName: fieldMod.fieldName,
3864
+ currentDefinition: fieldMod.newDefinition,
3865
+ newDefinition: fieldMod.currentDefinition,
3866
+ changes: reverseChanges
3867
+ };
3868
+ const varName = `collection_${collectionName}_revert_${fieldMod.fieldName}`;
3869
+ const isLast = operationCount === totalOperations;
3870
+ lines.push(generateFieldModification(collectionName, reverseMod, varName, isLast));
3871
+ if (!isLast) lines.push("");
3872
+ }
3873
+ for (const field of modification.fieldsToAdd) {
3874
+ operationCount++;
3875
+ const varName = `collection_${collectionName}_revert_add_${field.name}`;
3876
+ const isLast = operationCount === totalOperations;
3877
+ lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
3878
+ if (!isLast) lines.push("");
3879
+ }
3880
+ } else if (operation.type === "delete") {
3881
+ const collection = operation.collection;
3882
+ if (typeof collection !== "string") {
3883
+ const varName = `collection_${collection.name}`;
3884
+ lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
3885
+ }
3886
+ }
3887
+ return lines.join("\n");
3888
+ }
3578
3889
  function generateUpMigration(diff) {
3579
3890
  const lines = [];
3580
3891
  lines.push(` // UP MIGRATION`);
3581
3892
  lines.push(``);
3893
+ const collectionIdMap = /* @__PURE__ */ new Map();
3894
+ for (const collection of diff.collectionsToCreate) {
3895
+ if (collection.id) {
3896
+ collectionIdMap.set(collection.name, collection.id);
3897
+ }
3898
+ }
3582
3899
  if (diff.collectionsToCreate.length > 0) {
3583
3900
  lines.push(` // Create new collections`);
3584
3901
  for (let i = 0; i < diff.collectionsToCreate.length; i++) {
3585
3902
  const collection = diff.collectionsToCreate[i];
3586
3903
  const varName = `collection_${collection.name}_create`;
3587
- lines.push(generateCollectionCreation(collection, varName));
3904
+ lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
3588
3905
  lines.push(``);
3589
3906
  }
3590
3907
  }
@@ -3596,7 +3913,7 @@ function generateUpMigration(diff) {
3596
3913
  lines.push(` // Add fields to ${collectionName}`);
3597
3914
  for (const field of modification.fieldsToAdd) {
3598
3915
  const varName = `collection_${collectionName}_add_${field.name}`;
3599
- lines.push(generateFieldAddition(collectionName, field, varName));
3916
+ lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
3600
3917
  lines.push(``);
3601
3918
  }
3602
3919
  }
@@ -3687,12 +4004,23 @@ function generateDownMigration(diff) {
3687
4004
  const lines = [];
3688
4005
  lines.push(` // DOWN MIGRATION (ROLLBACK)`);
3689
4006
  lines.push(``);
4007
+ const collectionIdMap = /* @__PURE__ */ new Map();
4008
+ for (const collection of diff.collectionsToCreate) {
4009
+ if (collection.id) {
4010
+ collectionIdMap.set(collection.name, collection.id);
4011
+ }
4012
+ }
4013
+ for (const collection of diff.collectionsToDelete) {
4014
+ if (collection.id) {
4015
+ collectionIdMap.set(collection.name, collection.id);
4016
+ }
4017
+ }
3690
4018
  if (diff.collectionsToDelete.length > 0) {
3691
4019
  lines.push(` // Recreate deleted collections`);
3692
4020
  for (let i = 0; i < diff.collectionsToDelete.length; i++) {
3693
4021
  const collection = diff.collectionsToDelete[i];
3694
4022
  const varName = `collection_${collection.name}_recreate`;
3695
- lines.push(generateCollectionCreation(collection, varName));
4023
+ lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
3696
4024
  lines.push(``);
3697
4025
  }
3698
4026
  }
@@ -3737,7 +4065,7 @@ function generateDownMigration(diff) {
3737
4065
  lines.push(` // Restore fields to ${collectionName}`);
3738
4066
  for (const field of modification.fieldsToRemove) {
3739
4067
  const varName = `collection_${collectionName}_restore_${field.name}`;
3740
- lines.push(generateFieldAddition(collectionName, field, varName));
4068
+ lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
3741
4069
  lines.push(``);
3742
4070
  }
3743
4071
  }
@@ -3806,12 +4134,33 @@ function generate(diff, config) {
3806
4134
  const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
3807
4135
  try {
3808
4136
  const migrationDir = resolveMigrationDir(normalizedConfig);
3809
- const upCode = generateUpMigration(diff);
3810
- const downCode = generateDownMigration(diff);
3811
- const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
3812
- const filename = generateMigrationFilename(diff, normalizedConfig);
3813
- const filePath = writeMigrationFile(migrationDir, filename, content);
3814
- return filePath;
4137
+ const hasChanges2 = diff.collectionsToCreate.length > 0 || diff.collectionsToModify.length > 0 || diff.collectionsToDelete.length > 0;
4138
+ if (!hasChanges2) {
4139
+ return [];
4140
+ }
4141
+ const collectionIdMap = /* @__PURE__ */ new Map();
4142
+ for (const collection of diff.collectionsToCreate) {
4143
+ if (collection.id) {
4144
+ collectionIdMap.set(collection.name, collection.id);
4145
+ }
4146
+ }
4147
+ for (const collection of diff.collectionsToDelete) {
4148
+ if (collection.id) {
4149
+ collectionIdMap.set(collection.name, collection.id);
4150
+ }
4151
+ }
4152
+ const baseTimestamp = generateTimestamp(normalizedConfig);
4153
+ const operations = splitDiffByCollection(diff, baseTimestamp);
4154
+ const filePaths = [];
4155
+ for (const operation of operations) {
4156
+ const upCode = generateOperationUpMigration(operation, collectionIdMap);
4157
+ const downCode = generateOperationDownMigration(operation, collectionIdMap);
4158
+ const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
4159
+ const filename = generateCollectionMigrationFilename(operation);
4160
+ const filePath = writeMigrationFile(migrationDir, filename, content);
4161
+ filePaths.push(filePath);
4162
+ }
4163
+ return filePaths;
3815
4164
  } catch (error) {
3816
4165
  if (error instanceof MigrationGenerationError || error instanceof FileSystemError) {
3817
4166
  throw error;
@@ -3829,7 +4178,8 @@ var MigrationGenerator = class {
3829
4178
  this.config = mergeConfig4(config);
3830
4179
  }
3831
4180
  /**
3832
- * Generates a migration file from a schema diff
4181
+ * Generates migration files from a schema diff
4182
+ * Returns array of file paths (one per collection operation)
3833
4183
  */
3834
4184
  generate(diff) {
3835
4185
  return generate(diff, this.config);