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
@@ -133,6 +133,53 @@ function generateTimestamp(config) {
133
133
  }
134
134
  return Math.floor(Date.now() / 1e3).toString();
135
135
  }
136
+ function splitDiffByCollection(diff, baseTimestamp) {
137
+ const operations = [];
138
+ let currentTimestamp = parseInt(baseTimestamp, 10);
139
+ for (const collection of diff.collectionsToCreate) {
140
+ operations.push({
141
+ type: "create",
142
+ collection,
143
+ timestamp: currentTimestamp.toString()
144
+ });
145
+ currentTimestamp += 1;
146
+ }
147
+ for (const modification of diff.collectionsToModify) {
148
+ operations.push({
149
+ type: "modify",
150
+ collection: modification.collection,
151
+ modifications: modification,
152
+ timestamp: currentTimestamp.toString()
153
+ });
154
+ currentTimestamp += 1;
155
+ }
156
+ for (const collection of diff.collectionsToDelete) {
157
+ operations.push({
158
+ type: "delete",
159
+ collection: collection.name || collection,
160
+ // Handle both object and string
161
+ timestamp: currentTimestamp.toString()
162
+ });
163
+ currentTimestamp += 1;
164
+ }
165
+ return operations;
166
+ }
167
+ function generateCollectionMigrationFilename(operation) {
168
+ const timestamp = operation.timestamp;
169
+ const operationType = operation.type === "modify" ? "updated" : operation.type === "create" ? "created" : "deleted";
170
+ let collectionName;
171
+ if (typeof operation.collection === "string") {
172
+ collectionName = operation.collection;
173
+ } else {
174
+ collectionName = operation.collection.name;
175
+ }
176
+ const sanitizedName = collectionName.replace(/[^a-zA-Z0-9_]/g, "_").toLowerCase();
177
+ return `${timestamp}_${operationType}_${sanitizedName}.js`;
178
+ }
179
+ function incrementTimestamp(timestamp) {
180
+ const currentTimestamp = parseInt(timestamp, 10);
181
+ return (currentTimestamp + 1).toString();
182
+ }
136
183
  function generateMigrationDescription(diff) {
137
184
  const parts = [];
138
185
  if (diff.collectionsToCreate.length > 0) {
@@ -240,14 +287,13 @@ function formatValue(value) {
240
287
  return "null";
241
288
  }
242
289
  if (typeof value === "string") {
243
- return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`;
290
+ return JSON.stringify(value);
244
291
  }
245
292
  if (typeof value === "number" || typeof value === "boolean") {
246
293
  return String(value);
247
294
  }
248
295
  if (Array.isArray(value)) {
249
- const items = value.map((v) => formatValue(v)).join(", ");
250
- return `[${items}]`;
296
+ return JSON.stringify(value).replace(/","/g, '", "');
251
297
  }
252
298
  if (typeof value === "object") {
253
299
  const entries = Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
@@ -255,7 +301,7 @@ function formatValue(value) {
255
301
  }
256
302
  return String(value);
257
303
  }
258
- function generateFieldDefinitionObject(field) {
304
+ function generateFieldDefinitionObject(field, collectionIdMap) {
259
305
  const parts = [];
260
306
  parts.push(` name: "${field.name}"`);
261
307
  parts.push(` type: "${field.type}"`);
@@ -263,34 +309,47 @@ function generateFieldDefinitionObject(field) {
263
309
  if (field.unique !== void 0) {
264
310
  parts.push(` unique: ${field.unique}`);
265
311
  }
312
+ if (field.type === "select") {
313
+ const maxSelect = field.options?.maxSelect ?? 1;
314
+ parts.push(` maxSelect: ${maxSelect}`);
315
+ const values = field.options?.values ?? [];
316
+ parts.push(` values: ${formatValue(values)}`);
317
+ }
266
318
  if (field.options && Object.keys(field.options).length > 0) {
267
319
  for (const [key, value] of Object.entries(field.options)) {
320
+ if (field.type === "select" && (key === "maxSelect" || key === "values")) {
321
+ continue;
322
+ }
268
323
  parts.push(` ${key}: ${formatValue(value)}`);
269
324
  }
270
325
  }
271
326
  if (field.relation) {
272
327
  const isUsersCollection = field.relation.collection.toLowerCase() === "users";
273
- const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
274
- parts.push(` collectionId: ${collectionIdPlaceholder}`);
275
- if (field.relation.maxSelect !== void 0) {
276
- parts.push(` maxSelect: ${field.relation.maxSelect}`);
277
- }
278
- if (field.relation.minSelect !== void 0) {
279
- parts.push(` minSelect: ${field.relation.minSelect}`);
280
- }
281
- if (field.relation.cascadeDelete !== void 0) {
282
- parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
328
+ let collectionIdValue;
329
+ if (isUsersCollection) {
330
+ collectionIdValue = '"_pb_users_auth_"';
331
+ } else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
332
+ collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
333
+ } else {
334
+ collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
283
335
  }
336
+ parts.push(` collectionId: ${collectionIdValue}`);
337
+ const maxSelect = field.relation.maxSelect ?? 1;
338
+ parts.push(` maxSelect: ${maxSelect}`);
339
+ const minSelect = field.relation.minSelect ?? null;
340
+ parts.push(` minSelect: ${minSelect}`);
341
+ const cascadeDelete = field.relation.cascadeDelete ?? false;
342
+ parts.push(` cascadeDelete: ${cascadeDelete}`);
284
343
  }
285
344
  return ` {
286
345
  ${parts.join(",\n")},
287
346
  }`;
288
347
  }
289
- function generateFieldsArray(fields) {
348
+ function generateFieldsArray(fields, collectionIdMap) {
290
349
  if (fields.length === 0) {
291
350
  return "[]";
292
351
  }
293
- const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field));
352
+ const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field, collectionIdMap));
294
353
  return `[
295
354
  ${fieldObjects.join(",\n")},
296
355
  ]`;
@@ -349,7 +408,7 @@ function generateIndexesArray(indexes) {
349
408
  if (!indexes || indexes.length === 0) {
350
409
  return "[]";
351
410
  }
352
- const indexStrings = indexes.map((idx) => `"${idx}"`);
411
+ const indexStrings = indexes.map((idx) => JSON.stringify(idx));
353
412
  return `[
354
413
  ${indexStrings.join(",\n ")},
355
414
  ]`;
@@ -403,9 +462,12 @@ function getSystemFields() {
403
462
  }
404
463
  ];
405
464
  }
406
- function generateCollectionCreation(collection, varName = "collection", isLast = false) {
465
+ function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
407
466
  const lines = [];
408
467
  lines.push(` const ${varName} = new Collection({`);
468
+ if (collection.id) {
469
+ lines.push(` id: ${formatValue(collection.id)},`);
470
+ }
409
471
  lines.push(` name: "${collection.name}",`);
410
472
  lines.push(` type: "${collection.type}",`);
411
473
  const permissionsCode = generateCollectionPermissions(collection.permissions);
@@ -417,7 +479,7 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
417
479
  }
418
480
  const systemFields = getSystemFields();
419
481
  const allFields = [...systemFields, ...collection.fields];
420
- lines.push(` fields: ${generateFieldsArray(allFields)},`);
482
+ lines.push(` fields: ${generateFieldsArray(allFields, collectionIdMap)},`);
421
483
  lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
422
484
  lines.push(` });`);
423
485
  lines.push(``);
@@ -439,42 +501,59 @@ function getFieldConstructorName(fieldType) {
439
501
  };
440
502
  return constructorMap[fieldType] || "TextField";
441
503
  }
442
- function generateFieldConstructorOptions(field) {
504
+ function generateFieldConstructorOptions(field, collectionIdMap) {
443
505
  const parts = [];
444
506
  parts.push(` name: "${field.name}"`);
445
507
  parts.push(` required: ${field.required}`);
446
508
  if (field.unique !== void 0) {
447
509
  parts.push(` unique: ${field.unique}`);
448
510
  }
511
+ if (field.type === "select") {
512
+ const maxSelect = field.options?.maxSelect ?? 1;
513
+ parts.push(` maxSelect: ${maxSelect}`);
514
+ const values = field.options?.values ?? [];
515
+ parts.push(` values: ${formatValue(values)}`);
516
+ }
449
517
  if (field.options && Object.keys(field.options).length > 0) {
450
518
  for (const [key, value] of Object.entries(field.options)) {
451
- parts.push(` ${key}: ${formatValue(value)}`);
519
+ if (field.type === "select" && (key === "maxSelect" || key === "values")) {
520
+ continue;
521
+ }
522
+ if (field.type === "number" && key === "noDecimal") {
523
+ parts.push(` onlyInt: ${formatValue(value)}`);
524
+ } else {
525
+ parts.push(` ${key}: ${formatValue(value)}`);
526
+ }
452
527
  }
453
528
  }
454
529
  if (field.relation && field.type === "relation") {
455
530
  const isUsersCollection = field.relation.collection.toLowerCase() === "users";
456
- const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
457
- parts.push(` collectionId: ${collectionIdPlaceholder}`);
458
- if (field.relation.maxSelect !== void 0) {
459
- parts.push(` maxSelect: ${field.relation.maxSelect}`);
460
- }
461
- if (field.relation.minSelect !== void 0) {
462
- parts.push(` minSelect: ${field.relation.minSelect}`);
463
- }
464
- if (field.relation.cascadeDelete !== void 0) {
465
- parts.push(` cascadeDelete: ${field.relation.cascadeDelete}`);
531
+ let collectionIdValue;
532
+ if (isUsersCollection) {
533
+ collectionIdValue = '"_pb_users_auth_"';
534
+ } else if (collectionIdMap && collectionIdMap.has(field.relation.collection)) {
535
+ collectionIdValue = `"${collectionIdMap.get(field.relation.collection)}"`;
536
+ } else {
537
+ collectionIdValue = `app.findCollectionByNameOrId("${field.relation.collection}").id`;
466
538
  }
539
+ parts.push(` collectionId: ${collectionIdValue}`);
540
+ const maxSelect = field.relation.maxSelect ?? 1;
541
+ parts.push(` maxSelect: ${maxSelect}`);
542
+ const minSelect = field.relation.minSelect ?? null;
543
+ parts.push(` minSelect: ${minSelect}`);
544
+ const cascadeDelete = field.relation.cascadeDelete ?? false;
545
+ parts.push(` cascadeDelete: ${cascadeDelete}`);
467
546
  }
468
547
  return parts.join(",\n");
469
548
  }
470
- function generateFieldAddition(collectionName, field, varName, isLast = false) {
549
+ function generateFieldAddition(collectionName, field, varName, isLast = false, collectionIdMap) {
471
550
  const lines = [];
472
551
  const constructorName = getFieldConstructorName(field.type);
473
552
  const collectionVar = varName || `collection_${collectionName}_${field.name}`;
474
553
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
475
554
  lines.push(``);
476
555
  lines.push(` ${collectionVar}.fields.add(new ${constructorName}({`);
477
- lines.push(generateFieldConstructorOptions(field));
556
+ lines.push(generateFieldConstructorOptions(field, collectionIdMap));
478
557
  lines.push(` }));`);
479
558
  lines.push(``);
480
559
  lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
@@ -524,7 +603,7 @@ function generateIndexAddition(collectionName, index, varName, isLast = false) {
524
603
  const lines = [];
525
604
  const collectionVar = varName || `collection_${collectionName}_idx`;
526
605
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
527
- lines.push(` ${collectionVar}.indexes.push("${index}");`);
606
+ lines.push(` ${collectionVar}.indexes.push(${JSON.stringify(index)});`);
528
607
  lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
529
608
  return lines.join("\n");
530
609
  }
@@ -533,7 +612,7 @@ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
533
612
  const collectionVar = varName || `collection_${collectionName}_idx`;
534
613
  const indexVar = `${collectionVar}_indexToRemove`;
535
614
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
536
- lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === "${index}");`);
615
+ lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === ${JSON.stringify(index)});`);
537
616
  lines.push(` if (${indexVar} !== -1) {`);
538
617
  lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
539
618
  lines.push(` }`);
@@ -562,16 +641,213 @@ function generateCollectionDeletion(collectionName, varName = "collection", isLa
562
641
  lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
563
642
  return lines.join("\n");
564
643
  }
644
+ function generateOperationUpMigration(operation, collectionIdMap) {
645
+ const lines = [];
646
+ if (operation.type === "create") {
647
+ const collection = operation.collection;
648
+ const varName = `collection_${collection.name}`;
649
+ lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
650
+ } else if (operation.type === "modify") {
651
+ const modification = operation.modifications;
652
+ const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
653
+ let operationCount = 0;
654
+ const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
655
+ for (const field of modification.fieldsToAdd) {
656
+ operationCount++;
657
+ const varName = `collection_${collectionName}_add_${field.name}`;
658
+ const isLast = operationCount === totalOperations;
659
+ lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
660
+ if (!isLast) lines.push("");
661
+ }
662
+ for (const fieldMod of modification.fieldsToModify) {
663
+ operationCount++;
664
+ const varName = `collection_${collectionName}_modify_${fieldMod.fieldName}`;
665
+ const isLast = operationCount === totalOperations;
666
+ lines.push(generateFieldModification(collectionName, fieldMod, varName, isLast));
667
+ if (!isLast) lines.push("");
668
+ }
669
+ for (const field of modification.fieldsToRemove) {
670
+ operationCount++;
671
+ const varName = `collection_${collectionName}_remove_${field.name}`;
672
+ const isLast = operationCount === totalOperations;
673
+ lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
674
+ if (!isLast) lines.push("");
675
+ }
676
+ for (let i = 0; i < modification.indexesToAdd.length; i++) {
677
+ operationCount++;
678
+ const index = modification.indexesToAdd[i];
679
+ const varName = `collection_${collectionName}_addidx_${i}`;
680
+ const isLast = operationCount === totalOperations;
681
+ lines.push(generateIndexAddition(collectionName, index, varName, isLast));
682
+ if (!isLast) lines.push("");
683
+ }
684
+ for (let i = 0; i < modification.indexesToRemove.length; i++) {
685
+ operationCount++;
686
+ const index = modification.indexesToRemove[i];
687
+ const varName = `collection_${collectionName}_rmidx_${i}`;
688
+ const isLast = operationCount === totalOperations;
689
+ lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
690
+ if (!isLast) lines.push("");
691
+ }
692
+ if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
693
+ for (const permission of modification.permissionsToUpdate) {
694
+ operationCount++;
695
+ const varName = `collection_${collectionName}_perm_${permission.ruleType}`;
696
+ const isLast = operationCount === totalOperations;
697
+ lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.newValue, varName, isLast));
698
+ if (!isLast) lines.push("");
699
+ }
700
+ } else if (modification.rulesToUpdate.length > 0) {
701
+ for (const rule of modification.rulesToUpdate) {
702
+ operationCount++;
703
+ const varName = `collection_${collectionName}_rule_${rule.ruleType}`;
704
+ const isLast = operationCount === totalOperations;
705
+ lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.newValue, varName, isLast));
706
+ if (!isLast) lines.push("");
707
+ }
708
+ }
709
+ } else if (operation.type === "delete") {
710
+ const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection.name;
711
+ const varName = `collection_${collectionName}`;
712
+ lines.push(generateCollectionDeletion(collectionName, varName, true));
713
+ }
714
+ let code = lines.join("\n");
715
+ const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
716
+ const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
717
+ const saveMatches = [...code.matchAll(savePattern)];
718
+ const deleteMatches = [...code.matchAll(deletePattern)];
719
+ const allMatches = [
720
+ ...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
721
+ ...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
722
+ ].sort((a, b) => b.index - a.index);
723
+ if (allMatches.length > 0) {
724
+ const lastMatch = allMatches[0];
725
+ if (lastMatch.type === "save") {
726
+ 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);
727
+ } else {
728
+ 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);
729
+ }
730
+ }
731
+ return code;
732
+ }
733
+ function generateOperationDownMigration(operation, collectionIdMap) {
734
+ const lines = [];
735
+ if (operation.type === "create") {
736
+ const collection = operation.collection;
737
+ const varName = `collection_${collection.name}`;
738
+ lines.push(generateCollectionDeletion(collection.name, varName, true));
739
+ } else if (operation.type === "modify") {
740
+ const modification = operation.modifications;
741
+ const collectionName = typeof operation.collection === "string" ? operation.collection : operation.collection?.name ?? modification.collection;
742
+ let operationCount = 0;
743
+ const totalOperations = modification.fieldsToAdd.length + modification.fieldsToModify.length + modification.fieldsToRemove.length + modification.indexesToAdd.length + modification.indexesToRemove.length + modification.rulesToUpdate.length + modification.permissionsToUpdate.length;
744
+ if (modification.permissionsToUpdate && modification.permissionsToUpdate.length > 0) {
745
+ for (const permission of modification.permissionsToUpdate) {
746
+ operationCount++;
747
+ const varName = `collection_${collectionName}_revert_perm_${permission.ruleType}`;
748
+ const isLast = operationCount === totalOperations;
749
+ lines.push(generatePermissionUpdate(collectionName, permission.ruleType, permission.oldValue, varName, isLast));
750
+ if (!isLast) lines.push("");
751
+ }
752
+ } else if (modification.rulesToUpdate.length > 0) {
753
+ for (const rule of modification.rulesToUpdate) {
754
+ operationCount++;
755
+ const varName = `collection_${collectionName}_revert_rule_${rule.ruleType}`;
756
+ const isLast = operationCount === totalOperations;
757
+ lines.push(generateRuleUpdate(collectionName, rule.ruleType, rule.oldValue, varName, isLast));
758
+ if (!isLast) lines.push("");
759
+ }
760
+ }
761
+ for (let i = 0; i < modification.indexesToRemove.length; i++) {
762
+ operationCount++;
763
+ const index = modification.indexesToRemove[i];
764
+ const varName = `collection_${collectionName}_restore_idx_${i}`;
765
+ const isLast = operationCount === totalOperations;
766
+ lines.push(generateIndexAddition(collectionName, index, varName, isLast));
767
+ if (!isLast) lines.push("");
768
+ }
769
+ for (let i = 0; i < modification.indexesToAdd.length; i++) {
770
+ operationCount++;
771
+ const index = modification.indexesToAdd[i];
772
+ const varName = `collection_${collectionName}_revert_idx_${i}`;
773
+ const isLast = operationCount === totalOperations;
774
+ lines.push(generateIndexRemoval(collectionName, index, varName, isLast));
775
+ if (!isLast) lines.push("");
776
+ }
777
+ for (const field of modification.fieldsToRemove) {
778
+ operationCount++;
779
+ const varName = `collection_${collectionName}_restore_${field.name}`;
780
+ const isLast = operationCount === totalOperations;
781
+ lines.push(generateFieldAddition(collectionName, field, varName, isLast, collectionIdMap));
782
+ if (!isLast) lines.push("");
783
+ }
784
+ for (const fieldMod of modification.fieldsToModify) {
785
+ operationCount++;
786
+ const reverseChanges = fieldMod.changes.map((change) => ({
787
+ property: change.property,
788
+ oldValue: change.newValue,
789
+ newValue: change.oldValue
790
+ }));
791
+ const reverseMod = {
792
+ fieldName: fieldMod.fieldName,
793
+ currentDefinition: fieldMod.newDefinition,
794
+ newDefinition: fieldMod.currentDefinition,
795
+ changes: reverseChanges
796
+ };
797
+ const varName = `collection_${collectionName}_revert_${fieldMod.fieldName}`;
798
+ const isLast = operationCount === totalOperations;
799
+ lines.push(generateFieldModification(collectionName, reverseMod, varName, isLast));
800
+ if (!isLast) lines.push("");
801
+ }
802
+ for (const field of modification.fieldsToAdd) {
803
+ operationCount++;
804
+ const varName = `collection_${collectionName}_revert_add_${field.name}`;
805
+ const isLast = operationCount === totalOperations;
806
+ lines.push(generateFieldDeletion(collectionName, field.name, varName, isLast));
807
+ if (!isLast) lines.push("");
808
+ }
809
+ } else if (operation.type === "delete") {
810
+ const collection = operation.collection;
811
+ if (typeof collection !== "string") {
812
+ const varName = `collection_${collection.name}`;
813
+ lines.push(generateCollectionCreation(collection, varName, true, collectionIdMap));
814
+ }
815
+ }
816
+ let code = lines.join("\n");
817
+ const savePattern = /^(\s*)app\.save\((\w+)\);$/gm;
818
+ const deletePattern = /^(\s*)app\.delete\((\w+)\);$/gm;
819
+ const saveMatches = [...code.matchAll(savePattern)];
820
+ const deleteMatches = [...code.matchAll(deletePattern)];
821
+ const allMatches = [
822
+ ...saveMatches.map((m) => ({ match: m, type: "save", index: m.index })),
823
+ ...deleteMatches.map((m) => ({ match: m, type: "delete", index: m.index }))
824
+ ].sort((a, b) => b.index - a.index);
825
+ if (allMatches.length > 0) {
826
+ const lastMatch = allMatches[0];
827
+ if (lastMatch.type === "save") {
828
+ 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);
829
+ } else {
830
+ 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);
831
+ }
832
+ }
833
+ return code;
834
+ }
565
835
  function generateUpMigration(diff) {
566
836
  const lines = [];
567
837
  lines.push(` // UP MIGRATION`);
568
838
  lines.push(``);
839
+ const collectionIdMap = /* @__PURE__ */ new Map();
840
+ for (const collection of diff.collectionsToCreate) {
841
+ if (collection.id) {
842
+ collectionIdMap.set(collection.name, collection.id);
843
+ }
844
+ }
569
845
  if (diff.collectionsToCreate.length > 0) {
570
846
  lines.push(` // Create new collections`);
571
847
  for (let i = 0; i < diff.collectionsToCreate.length; i++) {
572
848
  const collection = diff.collectionsToCreate[i];
573
849
  const varName = `collection_${collection.name}_create`;
574
- lines.push(generateCollectionCreation(collection, varName));
850
+ lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
575
851
  lines.push(``);
576
852
  }
577
853
  }
@@ -583,7 +859,7 @@ function generateUpMigration(diff) {
583
859
  lines.push(` // Add fields to ${collectionName}`);
584
860
  for (const field of modification.fieldsToAdd) {
585
861
  const varName = `collection_${collectionName}_add_${field.name}`;
586
- lines.push(generateFieldAddition(collectionName, field, varName));
862
+ lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
587
863
  lines.push(``);
588
864
  }
589
865
  }
@@ -674,12 +950,23 @@ function generateDownMigration(diff) {
674
950
  const lines = [];
675
951
  lines.push(` // DOWN MIGRATION (ROLLBACK)`);
676
952
  lines.push(``);
953
+ const collectionIdMap = /* @__PURE__ */ new Map();
954
+ for (const collection of diff.collectionsToCreate) {
955
+ if (collection.id) {
956
+ collectionIdMap.set(collection.name, collection.id);
957
+ }
958
+ }
959
+ for (const collection of diff.collectionsToDelete) {
960
+ if (collection.id) {
961
+ collectionIdMap.set(collection.name, collection.id);
962
+ }
963
+ }
677
964
  if (diff.collectionsToDelete.length > 0) {
678
965
  lines.push(` // Recreate deleted collections`);
679
966
  for (let i = 0; i < diff.collectionsToDelete.length; i++) {
680
967
  const collection = diff.collectionsToDelete[i];
681
968
  const varName = `collection_${collection.name}_recreate`;
682
- lines.push(generateCollectionCreation(collection, varName));
969
+ lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
683
970
  lines.push(``);
684
971
  }
685
972
  }
@@ -724,7 +1011,7 @@ function generateDownMigration(diff) {
724
1011
  lines.push(` // Restore fields to ${collectionName}`);
725
1012
  for (const field of modification.fieldsToRemove) {
726
1013
  const varName = `collection_${collectionName}_restore_${field.name}`;
727
- lines.push(generateFieldAddition(collectionName, field, varName));
1014
+ lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
728
1015
  lines.push(``);
729
1016
  }
730
1017
  }
@@ -793,12 +1080,33 @@ function generate(diff, config) {
793
1080
  const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
794
1081
  try {
795
1082
  const migrationDir = resolveMigrationDir(normalizedConfig);
796
- const upCode = generateUpMigration(diff);
797
- const downCode = generateDownMigration(diff);
798
- const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
799
- const filename = generateMigrationFilename(diff, normalizedConfig);
800
- const filePath = writeMigrationFile(migrationDir, filename, content);
801
- return filePath;
1083
+ const hasChanges = diff.collectionsToCreate.length > 0 || diff.collectionsToModify.length > 0 || diff.collectionsToDelete.length > 0;
1084
+ if (!hasChanges) {
1085
+ return [];
1086
+ }
1087
+ const collectionIdMap = /* @__PURE__ */ new Map();
1088
+ for (const collection of diff.collectionsToCreate) {
1089
+ if (collection.id) {
1090
+ collectionIdMap.set(collection.name, collection.id);
1091
+ }
1092
+ }
1093
+ for (const collection of diff.collectionsToDelete) {
1094
+ if (collection.id) {
1095
+ collectionIdMap.set(collection.name, collection.id);
1096
+ }
1097
+ }
1098
+ const baseTimestamp = generateTimestamp(normalizedConfig);
1099
+ const operations = splitDiffByCollection(diff, baseTimestamp);
1100
+ const filePaths = [];
1101
+ for (const operation of operations) {
1102
+ const upCode = generateOperationUpMigration(operation, collectionIdMap);
1103
+ const downCode = generateOperationDownMigration(operation, collectionIdMap);
1104
+ const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
1105
+ const filename = generateCollectionMigrationFilename(operation);
1106
+ const filePath = writeMigrationFile(migrationDir, filename, content);
1107
+ filePaths.push(filePath);
1108
+ }
1109
+ return filePaths;
802
1110
  } catch (error) {
803
1111
  if (error instanceof MigrationGenerationError || error instanceof FileSystemError) {
804
1112
  throw error;
@@ -816,7 +1124,8 @@ var MigrationGenerator = class {
816
1124
  this.config = mergeConfig(config);
817
1125
  }
818
1126
  /**
819
- * Generates a migration file from a schema diff
1127
+ * Generates migration files from a schema diff
1128
+ * Returns array of file paths (one per collection operation)
820
1129
  */
821
1130
  generate(diff) {
822
1131
  return generate(diff, this.config);
@@ -845,6 +1154,7 @@ exports.MigrationGenerator = MigrationGenerator;
845
1154
  exports.createMigrationFileStructure = createMigrationFileStructure;
846
1155
  exports.generate = generate;
847
1156
  exports.generateCollectionCreation = generateCollectionCreation;
1157
+ exports.generateCollectionMigrationFilename = generateCollectionMigrationFilename;
848
1158
  exports.generateCollectionPermissions = generateCollectionPermissions;
849
1159
  exports.generateCollectionRules = generateCollectionRules;
850
1160
  exports.generateDownMigration = generateDownMigration;
@@ -856,9 +1166,13 @@ exports.generateFieldsArray = generateFieldsArray;
856
1166
  exports.generateIndexesArray = generateIndexesArray;
857
1167
  exports.generateMigrationDescription = generateMigrationDescription;
858
1168
  exports.generateMigrationFilename = generateMigrationFilename;
1169
+ exports.generateOperationDownMigration = generateOperationDownMigration;
1170
+ exports.generateOperationUpMigration = generateOperationUpMigration;
859
1171
  exports.generatePermissionUpdate = generatePermissionUpdate;
860
1172
  exports.generateTimestamp = generateTimestamp;
861
1173
  exports.generateUpMigration = generateUpMigration;
1174
+ exports.incrementTimestamp = incrementTimestamp;
1175
+ exports.splitDiffByCollection = splitDiffByCollection;
862
1176
  exports.writeMigrationFile = writeMigrationFile;
863
1177
  //# sourceMappingURL=generator.cjs.map
864
1178
  //# sourceMappingURL=generator.cjs.map