pocketbase-zod-schema 0.2.4 → 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 (67) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +209 -24
  3. package/dist/cli/index.cjs +406 -294
  4. package/dist/cli/index.cjs.map +1 -1
  5. package/dist/cli/index.d.cts +3 -1
  6. package/dist/cli/index.d.ts +3 -1
  7. package/dist/cli/index.js +406 -294
  8. package/dist/cli/index.js.map +1 -1
  9. package/dist/cli/migrate.cjs +406 -294
  10. package/dist/cli/migrate.cjs.map +1 -1
  11. package/dist/cli/migrate.js +406 -294
  12. package/dist/cli/migrate.js.map +1 -1
  13. package/dist/cli/utils/index.d.cts +3 -1
  14. package/dist/cli/utils/index.d.ts +3 -1
  15. package/dist/fields-UcOPu1OQ.d.cts +364 -0
  16. package/dist/fields-UcOPu1OQ.d.ts +364 -0
  17. package/dist/index.cjs +633 -112
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.d.cts +4 -3
  20. package/dist/index.d.ts +4 -3
  21. package/dist/index.js +619 -101
  22. package/dist/index.js.map +1 -1
  23. package/dist/migration/analyzer.cjs +44 -0
  24. package/dist/migration/analyzer.cjs.map +1 -1
  25. package/dist/migration/analyzer.d.cts +2 -1
  26. package/dist/migration/analyzer.d.ts +2 -1
  27. package/dist/migration/analyzer.js +44 -0
  28. package/dist/migration/analyzer.js.map +1 -1
  29. package/dist/migration/diff.cjs +76 -1
  30. package/dist/migration/diff.cjs.map +1 -1
  31. package/dist/migration/diff.d.cts +3 -1
  32. package/dist/migration/diff.d.ts +3 -1
  33. package/dist/migration/diff.js +76 -1
  34. package/dist/migration/diff.js.map +1 -1
  35. package/dist/migration/generator.cjs +323 -46
  36. package/dist/migration/generator.cjs.map +1 -1
  37. package/dist/migration/generator.d.cts +60 -11
  38. package/dist/migration/generator.d.ts +60 -11
  39. package/dist/migration/generator.js +319 -47
  40. package/dist/migration/generator.js.map +1 -1
  41. package/dist/migration/index.cjs +433 -47
  42. package/dist/migration/index.cjs.map +1 -1
  43. package/dist/migration/index.d.cts +3 -2
  44. package/dist/migration/index.d.ts +3 -2
  45. package/dist/migration/index.js +432 -48
  46. package/dist/migration/index.js.map +1 -1
  47. package/dist/migration/snapshot.cjs.map +1 -1
  48. package/dist/migration/snapshot.d.cts +3 -1
  49. package/dist/migration/snapshot.d.ts +3 -1
  50. package/dist/migration/snapshot.js.map +1 -1
  51. package/dist/migration/utils/index.cjs +80 -0
  52. package/dist/migration/utils/index.cjs.map +1 -1
  53. package/dist/migration/utils/index.d.cts +39 -202
  54. package/dist/migration/utils/index.d.ts +39 -202
  55. package/dist/migration/utils/index.js +77 -1
  56. package/dist/migration/utils/index.js.map +1 -1
  57. package/dist/schema.cjs +200 -61
  58. package/dist/schema.cjs.map +1 -1
  59. package/dist/schema.d.cts +2 -85
  60. package/dist/schema.d.ts +2 -85
  61. package/dist/schema.js +186 -50
  62. package/dist/schema.js.map +1 -1
  63. package/dist/type-mapper-DrQmtznD.d.cts +208 -0
  64. package/dist/type-mapper-n231Fspm.d.ts +208 -0
  65. package/dist/{types-z1Dkjg8m.d.ts → types-Ds3NQvny.d.ts} +33 -2
  66. package/dist/{types-BbTgmg6H.d.cts → types-YoBjsa-A.d.cts} +33 -2
  67. 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
  ({
@@ -34,6 +35,18 @@ function extractRelationMetadata(description) {
34
35
  }
35
36
  return null;
36
37
  }
38
+ var FIELD_METADATA_KEY = "__pocketbase_field__";
39
+ function extractFieldMetadata(description) {
40
+ if (!description) return null;
41
+ try {
42
+ const parsed = JSON.parse(description);
43
+ if (parsed[FIELD_METADATA_KEY]) {
44
+ return parsed[FIELD_METADATA_KEY];
45
+ }
46
+ } catch {
47
+ }
48
+ return null;
49
+ }
37
50
 
38
51
  // src/migration/errors.ts
39
52
  var MigrationError = class _MigrationError extends Error {
@@ -1544,6 +1557,38 @@ function isAuthCollection(fields) {
1544
1557
  return hasEmail && hasPassword;
1545
1558
  }
1546
1559
  function buildFieldDefinition(fieldName, zodType) {
1560
+ const fieldMetadata = extractFieldMetadata(zodType.description);
1561
+ if (fieldMetadata) {
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 || {};
1573
+ const fieldDef2 = {
1574
+ name: fieldName,
1575
+ type: fieldMetadata.type,
1576
+ required: required2,
1577
+ options: Object.keys(options2).length > 0 ? options2 : void 0
1578
+ };
1579
+ if (fieldMetadata.type === "relation") {
1580
+ const relationMetadata2 = extractRelationMetadata(zodType.description);
1581
+ if (relationMetadata2) {
1582
+ fieldDef2.relation = {
1583
+ collection: relationMetadata2.collection,
1584
+ maxSelect: relationMetadata2.maxSelect,
1585
+ minSelect: relationMetadata2.minSelect,
1586
+ cascadeDelete: relationMetadata2.cascadeDelete
1587
+ };
1588
+ }
1589
+ }
1590
+ return fieldDef2;
1591
+ }
1547
1592
  const fieldType = mapZodTypeToPocketBase(zodType, fieldName);
1548
1593
  const required = isFieldRequired(zodType);
1549
1594
  const options = extractFieldOptions(zodType);
@@ -2525,6 +2570,65 @@ var SnapshotManager = class {
2525
2570
  return validateSnapshot(snapshot);
2526
2571
  }
2527
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
+ };
2528
2632
 
2529
2633
  // src/migration/diff.ts
2530
2634
  var DEFAULT_CONFIG3 = {
@@ -2867,6 +2971,18 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
2867
2971
  const filteredCollectionsToDelete = collectionsToDelete.filter(
2868
2972
  (collection) => !isSystemCollection(collection.name, config)
2869
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
+ });
2870
2986
  const collectionsToModify = [];
2871
2987
  const matchedCollections = matchCollectionsByName(currentSchema, previousSnapshot);
2872
2988
  for (const [currentCollection, previousCollection] of matchedCollections) {
@@ -2876,7 +2992,7 @@ function aggregateChanges(currentSchema, previousSnapshot, config) {
2876
2992
  }
2877
2993
  }
2878
2994
  return {
2879
- collectionsToCreate: filteredCollectionsToCreate,
2995
+ collectionsToCreate: collectionsWithIds,
2880
2996
  collectionsToDelete: filteredCollectionsToDelete,
2881
2997
  collectionsToModify
2882
2998
  };
@@ -3112,6 +3228,49 @@ function generateTimestamp(config) {
3112
3228
  }
3113
3229
  return Math.floor(Date.now() / 1e3).toString();
3114
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
+ }
3115
3274
  function generateMigrationDescription(diff) {
3116
3275
  const parts = [];
3117
3276
  if (diff.collectionsToCreate.length > 0) {
@@ -3219,14 +3378,13 @@ function formatValue(value) {
3219
3378
  return "null";
3220
3379
  }
3221
3380
  if (typeof value === "string") {
3222
- return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n")}"`;
3381
+ return JSON.stringify(value);
3223
3382
  }
3224
3383
  if (typeof value === "number" || typeof value === "boolean") {
3225
3384
  return String(value);
3226
3385
  }
3227
3386
  if (Array.isArray(value)) {
3228
- const items = value.map((v) => formatValue(v)).join(", ");
3229
- return `[${items}]`;
3387
+ return JSON.stringify(value).replace(/","/g, '", "');
3230
3388
  }
3231
3389
  if (typeof value === "object") {
3232
3390
  const entries = Object.entries(value).map(([k, v]) => `${k}: ${formatValue(v)}`).join(", ");
@@ -3234,7 +3392,7 @@ function formatValue(value) {
3234
3392
  }
3235
3393
  return String(value);
3236
3394
  }
3237
- function generateFieldDefinitionObject(field) {
3395
+ function generateFieldDefinitionObject(field, collectionIdMap) {
3238
3396
  const parts = [];
3239
3397
  parts.push(` name: "${field.name}"`);
3240
3398
  parts.push(` type: "${field.type}"`);
@@ -3242,34 +3400,47 @@ function generateFieldDefinitionObject(field) {
3242
3400
  if (field.unique !== void 0) {
3243
3401
  parts.push(` unique: ${field.unique}`);
3244
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
+ }
3245
3409
  if (field.options && Object.keys(field.options).length > 0) {
3246
3410
  for (const [key, value] of Object.entries(field.options)) {
3411
+ if (field.type === "select" && (key === "maxSelect" || key === "values")) {
3412
+ continue;
3413
+ }
3247
3414
  parts.push(` ${key}: ${formatValue(value)}`);
3248
3415
  }
3249
3416
  }
3250
3417
  if (field.relation) {
3251
3418
  const isUsersCollection = field.relation.collection.toLowerCase() === "users";
3252
- const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3253
- parts.push(` collectionId: ${collectionIdPlaceholder}`);
3254
- if (field.relation.maxSelect !== void 0) {
3255
- parts.push(` maxSelect: ${field.relation.maxSelect}`);
3256
- }
3257
- if (field.relation.minSelect !== void 0) {
3258
- parts.push(` minSelect: ${field.relation.minSelect}`);
3259
- }
3260
- if (field.relation.cascadeDelete !== void 0) {
3261
- 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`;
3262
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}`);
3263
3434
  }
3264
3435
  return ` {
3265
3436
  ${parts.join(",\n")},
3266
3437
  }`;
3267
3438
  }
3268
- function generateFieldsArray(fields) {
3439
+ function generateFieldsArray(fields, collectionIdMap) {
3269
3440
  if (fields.length === 0) {
3270
3441
  return "[]";
3271
3442
  }
3272
- const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field));
3443
+ const fieldObjects = fields.map((field) => generateFieldDefinitionObject(field, collectionIdMap));
3273
3444
  return `[
3274
3445
  ${fieldObjects.join(",\n")},
3275
3446
  ]`;
@@ -3328,7 +3499,7 @@ function generateIndexesArray(indexes) {
3328
3499
  if (!indexes || indexes.length === 0) {
3329
3500
  return "[]";
3330
3501
  }
3331
- const indexStrings = indexes.map((idx) => `"${idx}"`);
3502
+ const indexStrings = indexes.map((idx) => JSON.stringify(idx));
3332
3503
  return `[
3333
3504
  ${indexStrings.join(",\n ")},
3334
3505
  ]`;
@@ -3382,7 +3553,7 @@ function getSystemFields() {
3382
3553
  }
3383
3554
  ];
3384
3555
  }
3385
- function generateCollectionCreation(collection, varName = "collection", isLast = false) {
3556
+ function generateCollectionCreation(collection, varName = "collection", isLast = false, collectionIdMap) {
3386
3557
  const lines = [];
3387
3558
  lines.push(` const ${varName} = new Collection({`);
3388
3559
  lines.push(` name: "${collection.name}",`);
@@ -3396,7 +3567,7 @@ function generateCollectionCreation(collection, varName = "collection", isLast =
3396
3567
  }
3397
3568
  const systemFields = getSystemFields();
3398
3569
  const allFields = [...systemFields, ...collection.fields];
3399
- lines.push(` fields: ${generateFieldsArray(allFields)},`);
3570
+ lines.push(` fields: ${generateFieldsArray(allFields, collectionIdMap)},`);
3400
3571
  lines.push(` indexes: ${generateIndexesArray(collection.indexes)},`);
3401
3572
  lines.push(` });`);
3402
3573
  lines.push(``);
@@ -3418,42 +3589,59 @@ function getFieldConstructorName(fieldType) {
3418
3589
  };
3419
3590
  return constructorMap[fieldType] || "TextField";
3420
3591
  }
3421
- function generateFieldConstructorOptions(field) {
3592
+ function generateFieldConstructorOptions(field, collectionIdMap) {
3422
3593
  const parts = [];
3423
3594
  parts.push(` name: "${field.name}"`);
3424
3595
  parts.push(` required: ${field.required}`);
3425
3596
  if (field.unique !== void 0) {
3426
3597
  parts.push(` unique: ${field.unique}`);
3427
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
+ }
3428
3605
  if (field.options && Object.keys(field.options).length > 0) {
3429
3606
  for (const [key, value] of Object.entries(field.options)) {
3430
- 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
+ }
3431
3615
  }
3432
3616
  }
3433
3617
  if (field.relation && field.type === "relation") {
3434
3618
  const isUsersCollection = field.relation.collection.toLowerCase() === "users";
3435
- const collectionIdPlaceholder = isUsersCollection ? '"_pb_users_auth_"' : `app.findCollectionByNameOrId("${field.relation.collection}").id`;
3436
- parts.push(` collectionId: ${collectionIdPlaceholder}`);
3437
- if (field.relation.maxSelect !== void 0) {
3438
- parts.push(` maxSelect: ${field.relation.maxSelect}`);
3439
- }
3440
- if (field.relation.minSelect !== void 0) {
3441
- parts.push(` minSelect: ${field.relation.minSelect}`);
3442
- }
3443
- if (field.relation.cascadeDelete !== void 0) {
3444
- 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`;
3445
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}`);
3446
3634
  }
3447
3635
  return parts.join(",\n");
3448
3636
  }
3449
- function generateFieldAddition(collectionName, field, varName, isLast = false) {
3637
+ function generateFieldAddition(collectionName, field, varName, isLast = false, collectionIdMap) {
3450
3638
  const lines = [];
3451
3639
  const constructorName = getFieldConstructorName(field.type);
3452
3640
  const collectionVar = varName || `collection_${collectionName}_${field.name}`;
3453
3641
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3454
3642
  lines.push(``);
3455
3643
  lines.push(` ${collectionVar}.fields.add(new ${constructorName}({`);
3456
- lines.push(generateFieldConstructorOptions(field));
3644
+ lines.push(generateFieldConstructorOptions(field, collectionIdMap));
3457
3645
  lines.push(` }));`);
3458
3646
  lines.push(``);
3459
3647
  lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
@@ -3503,7 +3691,7 @@ function generateIndexAddition(collectionName, index, varName, isLast = false) {
3503
3691
  const lines = [];
3504
3692
  const collectionVar = varName || `collection_${collectionName}_idx`;
3505
3693
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3506
- lines.push(` ${collectionVar}.indexes.push("${index}");`);
3694
+ lines.push(` ${collectionVar}.indexes.push(${JSON.stringify(index)});`);
3507
3695
  lines.push(isLast ? ` return app.save(${collectionVar});` : ` app.save(${collectionVar});`);
3508
3696
  return lines.join("\n");
3509
3697
  }
@@ -3512,7 +3700,7 @@ function generateIndexRemoval(collectionName, index, varName, isLast = false) {
3512
3700
  const collectionVar = varName || `collection_${collectionName}_idx`;
3513
3701
  const indexVar = `${collectionVar}_indexToRemove`;
3514
3702
  lines.push(` const ${collectionVar} = app.findCollectionByNameOrId("${collectionName}");`);
3515
- lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === "${index}");`);
3703
+ lines.push(` const ${indexVar} = ${collectionVar}.indexes.findIndex(idx => idx === ${JSON.stringify(index)});`);
3516
3704
  lines.push(` if (${indexVar} !== -1) {`);
3517
3705
  lines.push(` ${collectionVar}.indexes.splice(${indexVar}, 1);`);
3518
3706
  lines.push(` }`);
@@ -3541,16 +3729,179 @@ function generateCollectionDeletion(collectionName, varName = "collection", isLa
3541
3729
  lines.push(isLast ? ` return app.delete(${varName});` : ` app.delete(${varName});`);
3542
3730
  return lines.join("\n");
3543
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
+ }
3544
3889
  function generateUpMigration(diff) {
3545
3890
  const lines = [];
3546
3891
  lines.push(` // UP MIGRATION`);
3547
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
+ }
3548
3899
  if (diff.collectionsToCreate.length > 0) {
3549
3900
  lines.push(` // Create new collections`);
3550
3901
  for (let i = 0; i < diff.collectionsToCreate.length; i++) {
3551
3902
  const collection = diff.collectionsToCreate[i];
3552
3903
  const varName = `collection_${collection.name}_create`;
3553
- lines.push(generateCollectionCreation(collection, varName));
3904
+ lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
3554
3905
  lines.push(``);
3555
3906
  }
3556
3907
  }
@@ -3562,7 +3913,7 @@ function generateUpMigration(diff) {
3562
3913
  lines.push(` // Add fields to ${collectionName}`);
3563
3914
  for (const field of modification.fieldsToAdd) {
3564
3915
  const varName = `collection_${collectionName}_add_${field.name}`;
3565
- lines.push(generateFieldAddition(collectionName, field, varName));
3916
+ lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
3566
3917
  lines.push(``);
3567
3918
  }
3568
3919
  }
@@ -3653,12 +4004,23 @@ function generateDownMigration(diff) {
3653
4004
  const lines = [];
3654
4005
  lines.push(` // DOWN MIGRATION (ROLLBACK)`);
3655
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
+ }
3656
4018
  if (diff.collectionsToDelete.length > 0) {
3657
4019
  lines.push(` // Recreate deleted collections`);
3658
4020
  for (let i = 0; i < diff.collectionsToDelete.length; i++) {
3659
4021
  const collection = diff.collectionsToDelete[i];
3660
4022
  const varName = `collection_${collection.name}_recreate`;
3661
- lines.push(generateCollectionCreation(collection, varName));
4023
+ lines.push(generateCollectionCreation(collection, varName, false, collectionIdMap));
3662
4024
  lines.push(``);
3663
4025
  }
3664
4026
  }
@@ -3703,7 +4065,7 @@ function generateDownMigration(diff) {
3703
4065
  lines.push(` // Restore fields to ${collectionName}`);
3704
4066
  for (const field of modification.fieldsToRemove) {
3705
4067
  const varName = `collection_${collectionName}_restore_${field.name}`;
3706
- lines.push(generateFieldAddition(collectionName, field, varName));
4068
+ lines.push(generateFieldAddition(collectionName, field, varName, false, collectionIdMap));
3707
4069
  lines.push(``);
3708
4070
  }
3709
4071
  }
@@ -3772,12 +4134,33 @@ function generate(diff, config) {
3772
4134
  const normalizedConfig = typeof config === "string" ? { migrationDir: config } : config;
3773
4135
  try {
3774
4136
  const migrationDir = resolveMigrationDir(normalizedConfig);
3775
- const upCode = generateUpMigration(diff);
3776
- const downCode = generateDownMigration(diff);
3777
- const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
3778
- const filename = generateMigrationFilename(diff, normalizedConfig);
3779
- const filePath = writeMigrationFile(migrationDir, filename, content);
3780
- 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;
3781
4164
  } catch (error) {
3782
4165
  if (error instanceof MigrationGenerationError || error instanceof FileSystemError) {
3783
4166
  throw error;
@@ -3795,7 +4178,8 @@ var MigrationGenerator = class {
3795
4178
  this.config = mergeConfig4(config);
3796
4179
  }
3797
4180
  /**
3798
- * 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)
3799
4183
  */
3800
4184
  generate(diff) {
3801
4185
  return generate(diff, this.config);
@@ -3820,6 +4204,6 @@ var MigrationGenerator = class {
3820
4204
  }
3821
4205
  };
3822
4206
 
3823
- export { CLIUsageError, ConfigurationError, DiffEngine, FIELD_TYPE_INFO, FileSystemError, MigrationError, MigrationGenerationError, MigrationGenerator, POCKETBASE_FIELD_TYPES, SchemaAnalyzer, SchemaParsingError, SnapshotError, SnapshotManager, aggregateChanges, buildFieldDefinition, buildSchemaDefinition, categorizeChangesBySeverity, compare, compareFieldConstraints, compareFieldOptions, compareFieldTypes, comparePermissions, compareRelationConfigurations, convertPocketBaseMigration, convertZodSchemaToCollectionSchema, createMigrationFileStructure, detectDestructiveChanges, detectFieldChanges, discoverSchemaFiles, extractComprehensiveFieldOptions, extractFieldDefinitions, extractFieldOptions, extractIndexes, extractSchemaDefinitions, filterSystemCollections, findLatestSnapshot, findNewCollections, findNewFields, findRemovedCollections, findRemovedFields, generate, generateChangeSummary, generateCollectionCreation, generateCollectionPermissions, generateCollectionRules, generateDownMigration, generateFieldAddition, generateFieldDefinitionObject, generateFieldDeletion, generateFieldModification, generateFieldsArray, generateIndexesArray, generateMigrationDescription, generateMigrationFilename, generatePermissionUpdate, generateTimestamp, generateUpMigration, getArrayElementType, getCollectionNameFromFile, getDefaultValue, getFieldTypeInfo, getMaxSelect, getMinSelect, getSnapshotPath, getSnapshotVersion, getUsersSystemFields, importSchemaModule, isArrayType, isAuthCollection, isEditorField, isFieldRequired, isFileFieldByName, isGeoPointType, isMultipleRelationField, isRelationField, isSingleRelationField, isSystemCollection, loadBaseMigration, loadSnapshot, loadSnapshotIfExists, loadSnapshotWithMigrations, mapZodArrayType, mapZodBooleanType, mapZodDateType, mapZodEnumType, mapZodNumberType, mapZodRecordType, mapZodStringType, mapZodTypeToPocketBase, matchCollectionsByName, matchFieldsByName, mergeSnapshots, parseSchemaFiles, pluralize, requiresForceFlag, resolveTargetCollection, saveSnapshot, selectSchemaForCollection, singularize, snapshotExists, toCollectionName, unwrapZodType, validateSnapshot, writeMigrationFile };
4207
+ export { CLIUsageError, ConfigurationError, DiffEngine, FIELD_METADATA_KEY, FIELD_TYPE_INFO, FileSystemError, MigrationError, MigrationGenerationError, MigrationGenerator, POCKETBASE_FIELD_TYPES, SchemaAnalyzer, SchemaParsingError, SnapshotError, SnapshotManager, aggregateChanges, buildFieldDefinition, buildSchemaDefinition, categorizeChangesBySeverity, compare, compareFieldConstraints, compareFieldOptions, compareFieldTypes, comparePermissions, compareRelationConfigurations, convertPocketBaseMigration, convertZodSchemaToCollectionSchema, createMigrationFileStructure, detectDestructiveChanges, detectFieldChanges, discoverSchemaFiles, extractComprehensiveFieldOptions, extractFieldDefinitions, extractFieldMetadata, extractFieldOptions, extractIndexes, extractSchemaDefinitions, filterSystemCollections, findLatestSnapshot, findNewCollections, findNewFields, findRemovedCollections, findRemovedFields, generate, generateChangeSummary, generateCollectionCreation, generateCollectionPermissions, generateCollectionRules, generateDownMigration, generateFieldAddition, generateFieldDefinitionObject, generateFieldDeletion, generateFieldModification, generateFieldsArray, generateIndexesArray, generateMigrationDescription, generateMigrationFilename, generatePermissionUpdate, generateTimestamp, generateUpMigration, getArrayElementType, getCollectionNameFromFile, getDefaultValue, getFieldTypeInfo, getMaxSelect, getMinSelect, getSnapshotPath, getSnapshotVersion, getUsersSystemFields, importSchemaModule, isArrayType, isAuthCollection, isEditorField, isFieldRequired, isFileFieldByName, isGeoPointType, isMultipleRelationField, isRelationField, isSingleRelationField, isSystemCollection, loadBaseMigration, loadSnapshot, loadSnapshotIfExists, loadSnapshotWithMigrations, mapZodArrayType, mapZodBooleanType, mapZodDateType, mapZodEnumType, mapZodNumberType, mapZodRecordType, mapZodStringType, mapZodTypeToPocketBase, matchCollectionsByName, matchFieldsByName, mergeSnapshots, parseSchemaFiles, pluralize, requiresForceFlag, resolveTargetCollection, saveSnapshot, selectSchemaForCollection, singularize, snapshotExists, toCollectionName, unwrapZodType, validateSnapshot, writeMigrationFile };
3824
4208
  //# sourceMappingURL=index.js.map
3825
4209
  //# sourceMappingURL=index.js.map