pocketbase-zod-schema 0.2.5 → 0.3.1

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 (68) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cli/index.cjs +497 -298
  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 +497 -298
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/cli/migrate.cjs +497 -298
  9. package/dist/cli/migrate.cjs.map +1 -1
  10. package/dist/cli/migrate.js +497 -298
  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-RVj26U-O.d.cts} +17 -0
  15. package/dist/{fields-YjcpBXVp.d.ts → fields-RVj26U-O.d.ts} +17 -0
  16. package/dist/index.cjs +575 -155
  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 +576 -144
  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 +150 -24
  29. package/dist/migration/diff.cjs.map +1 -1
  30. package/dist/migration/diff.d.cts +4 -4
  31. package/dist/migration/diff.d.ts +4 -4
  32. package/dist/migration/diff.js +150 -24
  33. package/dist/migration/diff.js.map +1 -1
  34. package/dist/migration/generator.cjs +360 -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 +356 -47
  39. package/dist/migration/generator.js.map +1 -1
  40. package/dist/migration/index.cjs +561 -90
  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 +561 -90
  45. package/dist/migration/index.js.map +1 -1
  46. package/dist/migration/snapshot.cjs +51 -18
  47. package/dist/migration/snapshot.cjs.map +1 -1
  48. package/dist/migration/snapshot.d.cts +2 -2
  49. package/dist/migration/snapshot.d.ts +2 -2
  50. package/dist/migration/snapshot.js +51 -18
  51. package/dist/migration/snapshot.js.map +1 -1
  52. package/dist/migration/utils/index.cjs +66 -0
  53. package/dist/migration/utils/index.cjs.map +1 -1
  54. package/dist/migration/utils/index.d.cts +39 -202
  55. package/dist/migration/utils/index.d.ts +39 -202
  56. package/dist/migration/utils/index.js +65 -1
  57. package/dist/migration/utils/index.js.map +1 -1
  58. package/dist/schema.cjs +0 -61
  59. package/dist/schema.cjs.map +1 -1
  60. package/dist/schema.d.cts +2 -86
  61. package/dist/schema.d.ts +2 -86
  62. package/dist/schema.js +1 -50
  63. package/dist/schema.js.map +1 -1
  64. package/dist/type-mapper-CZzVeDj7.d.ts +208 -0
  65. package/dist/type-mapper-DaBe-1ph.d.cts +208 -0
  66. package/dist/{types-LFBGHl9Y.d.ts → types-CUVzgZ9k.d.ts} +33 -2
  67. package/dist/{types-mhQXWNi3.d.cts → types-D-Fsdn_O.d.cts} +33 -2
  68. package/package.json +1 -1
@@ -110,6 +110,53 @@ function generateTimestamp(config) {
110
110
  }
111
111
  return Math.floor(Date.now() / 1e3).toString();
112
112
  }
113
+ function splitDiffByCollection(diff, baseTimestamp) {
114
+ const operations = [];
115
+ let currentTimestamp = parseInt(baseTimestamp, 10);
116
+ for (const collection of diff.collectionsToCreate) {
117
+ operations.push({
118
+ type: "create",
119
+ collection,
120
+ timestamp: currentTimestamp.toString()
121
+ });
122
+ currentTimestamp += 1;
123
+ }
124
+ for (const modification of diff.collectionsToModify) {
125
+ operations.push({
126
+ type: "modify",
127
+ collection: modification.collection,
128
+ modifications: modification,
129
+ timestamp: currentTimestamp.toString()
130
+ });
131
+ currentTimestamp += 1;
132
+ }
133
+ for (const collection of diff.collectionsToDelete) {
134
+ operations.push({
135
+ type: "delete",
136
+ collection: collection.name || collection,
137
+ // Handle both object and string
138
+ timestamp: currentTimestamp.toString()
139
+ });
140
+ currentTimestamp += 1;
141
+ }
142
+ return operations;
143
+ }
144
+ function generateCollectionMigrationFilename(operation) {
145
+ const timestamp = operation.timestamp;
146
+ const operationType = operation.type === "modify" ? "updated" : operation.type === "create" ? "created" : "deleted";
147
+ let collectionName;
148
+ if (typeof operation.collection === "string") {
149
+ collectionName = operation.collection;
150
+ } else {
151
+ collectionName = operation.collection.name;
152
+ }
153
+ const sanitizedName = collectionName.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase();
154
+ return `${timestamp}_${operationType}_${sanitizedName}.js`;
155
+ }
156
+ function incrementTimestamp(timestamp) {
157
+ const currentTimestamp = parseInt(timestamp, 10);
158
+ return (currentTimestamp + 1).toString();
159
+ }
113
160
  function generateMigrationDescription(diff) {
114
161
  const parts = [];
115
162
  if (diff.collectionsToCreate.length > 0) {
@@ -217,14 +264,13 @@ function formatValue(value) {
217
264
  return "null";
218
265
  }
219
266
  if (typeof value === "string") {
220
- return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`;
267
+ return JSON.stringify(value);
221
268
  }
222
269
  if (typeof value === "number" || typeof value === "boolean") {
223
270
  return String(value);
224
271
  }
225
272
  if (Array.isArray(value)) {
226
- const items = value.map((v) => formatValue(v)).join(", ");
227
- return `[${items}]`;
273
+ return JSON.stringify(value).replace(/","/g, '", "');
228
274
  }
229
275
  if (typeof value === "object") {
230
276
  const entries = Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
@@ -232,7 +278,7 @@ function formatValue(value) {
232
278
  }
233
279
  return String(value);
234
280
  }
235
- function generateFieldDefinitionObject(field) {
281
+ function generateFieldDefinitionObject(field, collectionIdMap) {
236
282
  const parts = [];
237
283
  parts.push(` name: "${field.name}"`);
238
284
  parts.push(` type: "${field.type}"`);
@@ -240,34 +286,47 @@ function generateFieldDefinitionObject(field) {
240
286
  if (field.unique !== void 0) {
241
287
  parts.push(` unique: ${field.unique}`);
242
288
  }
289
+ if (field.type === "select") {
290
+ const maxSelect = field.options?.maxSelect ?? 1;
291
+ parts.push(` maxSelect: ${maxSelect}`);
292
+ const values = field.options?.values ?? [];
293
+ parts.push(` values: ${formatValue(values)}`);
294
+ }
243
295
  if (field.options && Object.keys(field.options).length > 0) {
244
296
  for (const [key, value] of Object.entries(field.options)) {
297
+ if (field.type === "select" && (key === "maxSelect" || key === "values")) {
298
+ continue;
299
+ }
245
300
  parts.push(` ${key}: ${formatValue(value)}`);
246
301
  }
247
302
  }
248
303
  if (field.relation) {
249
304
  const isUsersCollection = field.relation.collection.toLowerCase() === "users";
250
- const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
251
- parts.push(` collectionId: ${collectionIdPlaceholder}`);
252
- if (field.relation.maxSelect !== void 0) {
253
- parts.push(` maxSelect: ${field.relation.maxSelect}`);
254
- }
255
- if (field.relation.minSelect !== void 0) {
256
- parts.push(` minSelect: ${field.relation.minSelect}`);
257
- }
258
- if (field.relation.cascadeDelete !== void 0) {
259
- parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
305
+ let collectionIdValue;
306
+ if (isUsersCollection) {
307
+ collectionIdValue = '"_pb_users_auth_"';
308
+ } else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
309
+ collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
310
+ } else {
311
+ collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
260
312
  }
313
+ parts.push(` collectionId: ${collectionIdValue}`);
314
+ const maxSelect = field.relation.maxSelect ?? 1;
315
+ parts.push(` maxSelect: ${maxSelect}`);
316
+ const minSelect = field.relation.minSelect ?? null;
317
+ parts.push(` minSelect: ${minSelect}`);
318
+ const cascadeDelete = field.relation.cascadeDelete ?? false;
319
+ parts.push(` cascadeDelete: ${cascadeDelete}`);
261
320
  }
262
321
  return ` {
263
322
  ${parts.join(",\n")},
264
323
  }`;
265
324
  }
266
- function generateFieldsArray(fields) {
325
+ function generateFieldsArray(fields, collectionIdMap) {
267
326
  if (fields.length === 0) {
268
327
  return "[]";
269
328
  }
270
- const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field));
329
+ const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field, collectionIdMap));
271
330
  return `[
272
331
  ${fieldObjects.join(",\n")},
273
332
  ]`;
@@ -326,7 +385,7 @@ function generateIndexesArray(indexes) {
326
385
  if (!indexes || indexes.length === 0) {
327
386
  return "[]";
328
387
  }
329
- const indexStrings = indexes.map((idx) => `"${idx}"`);
388
+ const indexStrings = indexes.map((idx) => JSON.stringify(idx));
330
389
  return `[
331
390
  ${indexStrings.join(",\n ")},
332
391
  ]`;
@@ -380,9 +439,12 @@ function getSystemFields() {
380
439
  }
381
440
  ];
382
441
  }
383
- function generateCollectionCreation(collection, varName = "collection", isLast = false) {
442
+ function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
384
443
  const lines = [];
385
444
  lines.push(` const ${varName} = new Collection({`);
445
+ if (collection.id) {
446
+ lines.push(` id: ${formatValue(collection.id)},`);
447
+ }
386
448
  lines.push(` name: "${collection.name}",`);
387
449
  lines.push(` type: "${collection.type}",`);
388
450
  const permissionsCode = generateCollectionPermissions(collection.permissions);
@@ -394,7 +456,7 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
394
456
  }
395
457
  const systemFields = getSystemFields();
396
458
  const allFields = [...systemFields, ...collection.fields];
397
- lines.push(` fields: ${generateFieldsArray(allFields)},`);
459
+ lines.push(` fields: ${generateFieldsArray(allFields, collectionIdMap)},`);
398
460
  lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
399
461
  lines.push(` });`);
400
462
  lines.push(``);
@@ -416,42 +478,59 @@ function getFieldConstructorName(fieldType) {
416
478
  };
417
479
  return constructorMap[fieldType] || "TextField";
418
480
  }
419
- function generateFieldConstructorOptions(field) {
481
+ function generateFieldConstructorOptions(field, collectionIdMap) {
420
482
  const parts = [];
421
483
  parts.push(` name: "${field.name}"`);
422
484
  parts.push(` required: ${field.required}`);
423
485
  if (field.unique !== void 0) {
424
486
  parts.push(` unique: ${field.unique}`);
425
487
  }
488
+ if (field.type === "select") {
489
+ const maxSelect = field.options?.maxSelect ?? 1;
490
+ parts.push(` maxSelect: ${maxSelect}`);
491
+ const values = field.options?.values ?? [];
492
+ parts.push(` values: ${formatValue(values)}`);
493
+ }
426
494
  if (field.options && Object.keys(field.options).length > 0) {
427
495
  for (const [key, value] of Object.entries(field.options)) {
428
- parts.push(` ${key}: ${formatValue(value)}`);
496
+ if (field.type === "select" && (key === "maxSelect" || key === "values")) {
497
+ continue;
498
+ }
499
+ if (field.type === "number" && key === "noDecimal") {
500
+ parts.push(` onlyInt: ${formatValue(value)}`);
501
+ } else {
502
+ parts.push(` ${key}: ${formatValue(value)}`);
503
+ }
429
504
  }
430
505
  }
431
506
  if (field.relation && field.type === "relation") {
432
507
  const isUsersCollection = field.relation.collection.toLowerCase() === "users";
433
- const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
434
- parts.push(` collectionId: ${collectionIdPlaceholder}`);
435
- if (field.relation.maxSelect !== void 0) {
436
- parts.push(` maxSelect: ${field.relation.maxSelect}`);
437
- }
438
- if (field.relation.minSelect !== void 0) {
439
- parts.push(` minSelect: ${field.relation.minSelect}`);
440
- }
441
- if (field.relation.cascadeDelete !== void 0) {
442
- parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
508
+ let collectionIdValue;
509
+ if (isUsersCollection) {
510
+ collectionIdValue = '"_pb_users_auth_"';
511
+ } else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
512
+ collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
513
+ } else {
514
+ collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
443
515
  }
516
+ parts.push(` collectionId: ${collectionIdValue}`);
517
+ const maxSelect = field.relation.maxSelect ?? 1;
518
+ parts.push(` maxSelect: ${maxSelect}`);
519
+ const minSelect = field.relation.minSelect ?? null;
520
+ parts.push(` minSelect: ${minSelect}`);
521
+ const cascadeDelete = field.relation.cascadeDelete ?? false;
522
+ parts.push(` cascadeDelete: ${cascadeDelete}`);
444
523
  }
445
524
  return parts.join(",\n");
446
525
  }
447
- function generateFieldAddition(collectionName, field, varName, isLast = false) {
526
+ function generateFieldAddition(collectionName, field, varName, isLast = false, collectionIdMap) {
448
527
  const lines = [];
449
528
  const constructorName = getFieldConstructorName(field.type);
450
529
  const collectionVar = varName || `collection_${collectionName}_${field.name}`;
451
530
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
452
531
  lines.push(``);
453
532
  lines.push(` ${collectionVar}.fields.add(new ${constructorName}({`);
454
- lines.push(generateFieldConstructorOptions(field));
533
+ lines.push(generateFieldConstructorOptions(field, collectionIdMap));
455
534
  lines.push(` }));`);
456
535
  lines.push(``);
457
536
  lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
@@ -501,7 +580,7 @@ function generateIndexAddition(collectionName, index, varName, isLast = false) {
501
580
  const lines = [];
502
581
  const collectionVar = varName || `collection_${collectionName}_idx`;
503
582
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
504
- lines.push(` ${collectionVar}.indexes.push("${index}");`);
583
+ lines.push(` ${collectionVar}.indexes.push(${JSON.stringify(index)});`);
505
584
  lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
506
585
  return lines.join("\n");
507
586
  }
@@ -510,7 +589,7 @@ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
510
589
  const collectionVar = varName || `collection_${collectionName}_idx`;
511
590
  const indexVar = `${collectionVar}_indexToRemove`;
512
591
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
513
- lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === "${index}");`);
592
+ lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === ${JSON.stringify(index)});`);
514
593
  lines.push(` if (${indexVar} !== -1) {`);
515
594
  lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
516
595
  lines.push(` }`);
@@ -539,16 +618,213 @@ function generateCollectionDeletion(collectionName, varName = "collection", isLa
539
618
  lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
540
619
  return lines.join("\n");
541
620
  }
621
+ function generateOperationUpMigration(operation, collectionIdMap) {
622
+ const lines = [];
623
+ if (operation.type === "create") {
624
+ const collection = operation.collection;
625
+ const varName = `collection_${collection.name}`;
626
+ lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
627
+ } else if (operation.type === "modify") {
628
+ const modification = operation.modifications;
629
+ const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
630
+ let operationCount = 0;
631
+ const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
632
+ for (const field of modification.fieldsToAdd) {
633
+ operationCount++;
634
+ const varName = `collection_${collectionName}_add_${field.name}`;
635
+ const isLast = operationCount === totalOperations;
636
+ lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
637
+ if (!isLast) lines.push("");
638
+ }
639
+ for (const fieldMod of modification.fieldsToModify) {
640
+ operationCount++;
641
+ const varName = `collection_${collectionName}_modify_${fieldMod.fieldName}`;
642
+ const isLast = operationCount === totalOperations;
643
+ lines.push(generateFieldModification(collectionName, fieldMod, varName, isLast));
644
+ if (!isLast) lines.push("");
645
+ }
646
+ for (const field of modification.fieldsToRemove) {
647
+ operationCount++;
648
+ const varName = `collection_${collectionName}_remove_${field.name}`;
649
+ const isLast = operationCount === totalOperations;
650
+ lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
651
+ if (!isLast) lines.push("");
652
+ }
653
+ for (let i = 0; i < modification.indexesToAdd.length; i++) {
654
+ operationCount++;
655
+ const index = modification.indexesToAdd[i];
656
+ const varName = `collection_${collectionName}_addidx_${i}`;
657
+ const isLast = operationCount === totalOperations;
658
+ lines.push(generateIndexAddition(collectionName, index, varName, isLast));
659
+ if (!isLast) lines.push("");
660
+ }
661
+ for (let i = 0; i < modification.indexesToRemove.length; i++) {
662
+ operationCount++;
663
+ const index = modification.indexesToRemove[i];
664
+ const varName = `collection_${collectionName}_rmidx_${i}`;
665
+ const isLast = operationCount === totalOperations;
666
+ lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
667
+ if (!isLast) lines.push("");
668
+ }
669
+ if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
670
+ for (const permission of modification.permissionsToUpdate) {
671
+ operationCount++;
672
+ const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
673
+ const isLast = operationCount === totalOperations;
674
+ lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast));
675
+ if (!isLast) lines.push("");
676
+ }
677
+ } else if (modification.rulesToUpdate.length > 0) {
678
+ for (const rule of modification.rulesToUpdate) {
679
+ operationCount++;
680
+ const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
681
+ const isLast = operationCount === totalOperations;
682
+ lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast));
683
+ if (!isLast) lines.push("");
684
+ }
685
+ }
686
+ } else if (operation.type === "delete") {
687
+ const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
688
+ const varName = `collection_${collectionName}`;
689
+ lines.push(generateCollectionDeletion(collectionName, varName, true));
690
+ }
691
+ let code = lines.join("\n");
692
+ const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
693
+ const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
694
+ const saveMatches = [...code.matchAll(savePattern)];
695
+ const deleteMatches = [...code.matchAll(deletePattern)];
696
+ const allMatches = [
697
+ ...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
698
+ ...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
699
+ ].sort((a, b) => b.index - a.index);
700
+ if (allMatches.length > 0) {
701
+ const lastMatch = allMatches[0];
702
+ if (lastMatch.type === "save") {
703
+ code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.save(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
704
+ } else {
705
+ code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.delete(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
706
+ }
707
+ }
708
+ return code;
709
+ }
710
+ function generateOperationDownMigration(operation, collectionIdMap) {
711
+ const lines = [];
712
+ if (operation.type === "create") {
713
+ const collection = operation.collection;
714
+ const varName = `collection_${collection.name}`;
715
+ lines.push(generateCollectionDeletion(collection.name, varName, true));
716
+ } else if (operation.type === "modify") {
717
+ const modification = operation.modifications;
718
+ const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
719
+ let operationCount = 0;
720
+ const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
721
+ if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
722
+ for (const permission of modification.permissionsToUpdate) {
723
+ operationCount++;
724
+ const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
725
+ const isLast = operationCount === totalOperations;
726
+ lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast));
727
+ if (!isLast) lines.push("");
728
+ }
729
+ } else if (modification.rulesToUpdate.length > 0) {
730
+ for (const rule of modification.rulesToUpdate) {
731
+ operationCount++;
732
+ const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
733
+ const isLast = operationCount === totalOperations;
734
+ lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast));
735
+ if (!isLast) lines.push("");
736
+ }
737
+ }
738
+ for (let i = 0; i < modification.indexesToRemove.length; i++) {
739
+ operationCount++;
740
+ const index = modification.indexesToRemove[i];
741
+ const varName = `collection_${collectionName}_restore_idx_${i}`;
742
+ const isLast = operationCount === totalOperations;
743
+ lines.push(generateIndexAddition(collectionName, index, varName, isLast));
744
+ if (!isLast) lines.push("");
745
+ }
746
+ for (let i = 0; i < modification.indexesToAdd.length; i++) {
747
+ operationCount++;
748
+ const index = modification.indexesToAdd[i];
749
+ const varName = `collection_${collectionName}_revert_idx_${i}`;
750
+ const isLast = operationCount === totalOperations;
751
+ lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
752
+ if (!isLast) lines.push("");
753
+ }
754
+ for (const field of modification.fieldsToRemove) {
755
+ operationCount++;
756
+ const varName = `collection_${collectionName}_restore_${field.name}`;
757
+ const isLast = operationCount === totalOperations;
758
+ lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
759
+ if (!isLast) lines.push("");
760
+ }
761
+ for (const fieldMod of modification.fieldsToModify) {
762
+ operationCount++;
763
+ const reverseChanges = fieldMod.changes.map((change) => ({
764
+ property: change.property,
765
+ oldValue: change.newValue,
766
+ newValue: change.oldValue
767
+ }));
768
+ const reverseMod = {
769
+ fieldName: fieldMod.fieldName,
770
+ currentDefinition: fieldMod.newDefinition,
771
+ newDefinition: fieldMod.currentDefinition,
772
+ changes: reverseChanges
773
+ };
774
+ const varName = `collection_${collectionName}_revert_${fieldMod.fieldName}`;
775
+ const isLast = operationCount === totalOperations;
776
+ lines.push(generateFieldModification(collectionName, reverseMod, varName, isLast));
777
+ if (!isLast) lines.push("");
778
+ }
779
+ for (const field of modification.fieldsToAdd) {
780
+ operationCount++;
781
+ const varName = `collection_${collectionName}_revert_add_${field.name}`;
782
+ const isLast = operationCount === totalOperations;
783
+ lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
784
+ if (!isLast) lines.push("");
785
+ }
786
+ } else if (operation.type === "delete") {
787
+ const collection = operation.collection;
788
+ if (typeof collection !== "string") {
789
+ const varName = `collection_${collection.name}`;
790
+ lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
791
+ }
792
+ }
793
+ let code = lines.join("\n");
794
+ const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
795
+ const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
796
+ const saveMatches = [...code.matchAll(savePattern)];
797
+ const deleteMatches = [...code.matchAll(deletePattern)];
798
+ const allMatches = [
799
+ ...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
800
+ ...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
801
+ ].sort((a, b) => b.index - a.index);
802
+ if (allMatches.length > 0) {
803
+ const lastMatch = allMatches[0];
804
+ if (lastMatch.type === "save") {
805
+ code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.save(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
806
+ } else {
807
+ code = code.substring(0, lastMatch.match.index) + lastMatch.match[1] + "return app.delete(" + lastMatch.match[2] + ");" + code.substring(lastMatch.match.index + lastMatch.match[0].length);
808
+ }
809
+ }
810
+ return code;
811
+ }
542
812
  function generateUpMigration(diff) {
543
813
  const lines = [];
544
814
  lines.push(` // UP MIGRATION`);
545
815
  lines.push(``);
816
+ const collectionIdMap = /* @__PURE__ */ new Map();
817
+ for (const collection of diff.collectionsToCreate) {
818
+ if (collection.id) {
819
+ collectionIdMap.set(collection.name, collection.id);
820
+ }
821
+ }
546
822
  if (diff.collectionsToCreate.length > 0) {
547
823
  lines.push(` // Create new collections`);
548
824
  for (let i = 0; i < diff.collectionsToCreate.length; i++) {
549
825
  const collection = diff.collectionsToCreate[i];
550
826
  const varName = `collection_${collection.name}_create`;
551
- lines.push(generateCollectionCreation(collection, varName));
827
+ lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
552
828
  lines.push(``);
553
829
  }
554
830
  }
@@ -560,7 +836,7 @@ function generateUpMigration(diff) {
560
836
  lines.push(` // Add fields to ${collectionName}`);
561
837
  for (const field of modification.fieldsToAdd) {
562
838
  const varName = `collection_${collectionName}_add_${field.name}`;
563
- lines.push(generateFieldAddition(collectionName, field, varName));
839
+ lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
564
840
  lines.push(``);
565
841
  }
566
842
  }
@@ -651,12 +927,23 @@ function generateDownMigration(diff) {
651
927
  const lines = [];
652
928
  lines.push(` // DOWN MIGRATION (ROLLBACK)`);
653
929
  lines.push(``);
930
+ const collectionIdMap = /* @__PURE__ */ new Map();
931
+ for (const collection of diff.collectionsToCreate) {
932
+ if (collection.id) {
933
+ collectionIdMap.set(collection.name, collection.id);
934
+ }
935
+ }
936
+ for (const collection of diff.collectionsToDelete) {
937
+ if (collection.id) {
938
+ collectionIdMap.set(collection.name, collection.id);
939
+ }
940
+ }
654
941
  if (diff.collectionsToDelete.length > 0) {
655
942
  lines.push(` // Recreate deleted collections`);
656
943
  for (let i = 0; i < diff.collectionsToDelete.length; i++) {
657
944
  const collection = diff.collectionsToDelete[i];
658
945
  const varName = `collection_${collection.name}_recreate`;
659
- lines.push(generateCollectionCreation(collection, varName));
946
+ lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
660
947
  lines.push(``);
661
948
  }
662
949
  }
@@ -701,7 +988,7 @@ function generateDownMigration(diff) {
701
988
  lines.push(` // Restore fields to ${collectionName}`);
702
989
  for (const field of modification.fieldsToRemove) {
703
990
  const varName = `collection_${collectionName}_restore_${field.name}`;
704
- lines.push(generateFieldAddition(collectionName, field, varName));
991
+ lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
705
992
  lines.push(``);
706
993
  }
707
994
  }
@@ -770,12 +1057,33 @@ function generate(diff, config) {
770
1057
  const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
771
1058
  try {
772
1059
  const migrationDir = resolveMigrationDir(normalizedConfig);
773
- const upCode = generateUpMigration(diff);
774
- const downCode = generateDownMigration(diff);
775
- const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
776
- const filename = generateMigrationFilename(diff, normalizedConfig);
777
- const filePath = writeMigrationFile(migrationDir, filename, content);
778
- return filePath;
1060
+ const hasChanges = diff.collectionsToCreate.length > 0 || diff.collectionsToModify.length > 0 || diff.collectionsToDelete.length > 0;
1061
+ if (!hasChanges) {
1062
+ return [];
1063
+ }
1064
+ const collectionIdMap = /* @__PURE__ */ new Map();
1065
+ for (const collection of diff.collectionsToCreate) {
1066
+ if (collection.id) {
1067
+ collectionIdMap.set(collection.name, collection.id);
1068
+ }
1069
+ }
1070
+ for (const collection of diff.collectionsToDelete) {
1071
+ if (collection.id) {
1072
+ collectionIdMap.set(collection.name, collection.id);
1073
+ }
1074
+ }
1075
+ const baseTimestamp = generateTimestamp(normalizedConfig);
1076
+ const operations = splitDiffByCollection(diff, baseTimestamp);
1077
+ const filePaths = [];
1078
+ for (const operation of operations) {
1079
+ const upCode = generateOperationUpMigration(operation, collectionIdMap);
1080
+ const downCode = generateOperationDownMigration(operation, collectionIdMap);
1081
+ const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
1082
+ const filename = generateCollectionMigrationFilename(operation);
1083
+ const filePath = writeMigrationFile(migrationDir, filename, content);
1084
+ filePaths.push(filePath);
1085
+ }
1086
+ return filePaths;
779
1087
  } catch (error) {
780
1088
  if (error instanceof MigrationGenerationError || error instanceof FileSystemError) {
781
1089
  throw error;
@@ -793,7 +1101,8 @@ var MigrationGenerator = class {
793
1101
  this.config = mergeConfig(config);
794
1102
  }
795
1103
  /**
796
- * Generates a migration file from a schema diff
1104
+ * Generates migration files from a schema diff
1105
+ * Returns array of file paths (one per collection operation)
797
1106
  */
798
1107
  generate(diff) {
799
1108
  return generate(diff, this.config);
@@ -818,6 +1127,6 @@ var MigrationGenerator = class {
818
1127
  }
819
1128
  };
820
1129
 
821
- export { MigrationGenerator, createMigrationFileStructure, generate, generateCollectionCreation, generateCollectionPermissions, generateCollectionRules, generateDownMigration, generateFieldAddition, generateFieldDefinitionObject, generateFieldDeletion, generateFieldModification, generateFieldsArray, generateIndexesArray, generateMigrationDescription, generateMigrationFilename, generatePermissionUpdate, generateTimestamp, generateUpMigration, writeMigrationFile };
1130
+ export { MigrationGenerator, createMigrationFileStructure, generate, generateCollectionCreation, generateCollectionMigrationFilename, generateCollectionPermissions, generateCollectionRules, generateDownMigration, generateFieldAddition, generateFieldDefinitionObject, generateFieldDeletion, generateFieldModification, generateFieldsArray, generateIndexesArray, generateMigrationDescription, generateMigrationFilename, generateOperationDownMigration, generateOperationUpMigration, generatePermissionUpdate, generateTimestamp, generateUpMigration, incrementTimestamp, splitDiffByCollection, writeMigrationFile };
822
1131
  //# sourceMappingURL=generator.js.map
823
1132
  //# sourceMappingURL=generator.js.map