pocketbase-zod-schema 0.3.6 → 0.3.7

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 (64) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/cli/index.cjs +131 -91
  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 +131 -91
  7. package/dist/cli/index.js.map +1 -1
  8. package/dist/cli/migrate.cjs +131 -91
  9. package/dist/cli/migrate.cjs.map +1 -1
  10. package/dist/cli/migrate.js +131 -91
  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/enums.d.cts +6 -1
  15. package/dist/enums.d.ts +6 -1
  16. package/dist/{fields-DBBm06VU.d.cts → fields-BNoZgcfw.d.cts} +22 -4
  17. package/dist/{fields-DBBm06VU.d.ts → fields-BNoZgcfw.d.ts} +22 -4
  18. package/dist/index.cjs +198 -111
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +3 -3
  21. package/dist/index.d.ts +3 -3
  22. package/dist/index.js +197 -112
  23. package/dist/index.js.map +1 -1
  24. package/dist/migration/analyzer.cjs +128 -90
  25. package/dist/migration/analyzer.cjs.map +1 -1
  26. package/dist/migration/analyzer.d.cts +2 -2
  27. package/dist/migration/analyzer.d.ts +2 -2
  28. package/dist/migration/analyzer.js +128 -90
  29. package/dist/migration/analyzer.js.map +1 -1
  30. package/dist/migration/diff.d.cts +2 -2
  31. package/dist/migration/diff.d.ts +2 -2
  32. package/dist/migration/generator.cjs +3 -1
  33. package/dist/migration/generator.cjs.map +1 -1
  34. package/dist/migration/generator.d.cts +2 -2
  35. package/dist/migration/generator.d.ts +2 -2
  36. package/dist/migration/generator.js +3 -1
  37. package/dist/migration/generator.js.map +1 -1
  38. package/dist/migration/index.cjs +172 -107
  39. package/dist/migration/index.cjs.map +1 -1
  40. package/dist/migration/index.d.cts +3 -3
  41. package/dist/migration/index.d.ts +3 -3
  42. package/dist/migration/index.js +172 -107
  43. package/dist/migration/index.js.map +1 -1
  44. package/dist/migration/snapshot.cjs.map +1 -1
  45. package/dist/migration/snapshot.d.cts +2 -2
  46. package/dist/migration/snapshot.d.ts +2 -2
  47. package/dist/migration/snapshot.js.map +1 -1
  48. package/dist/migration/utils/index.cjs +163 -101
  49. package/dist/migration/utils/index.cjs.map +1 -1
  50. package/dist/migration/utils/index.d.cts +2 -2
  51. package/dist/migration/utils/index.d.ts +2 -2
  52. package/dist/migration/utils/index.js +163 -101
  53. package/dist/migration/utils/index.js.map +1 -1
  54. package/dist/schema.cjs +27 -5
  55. package/dist/schema.cjs.map +1 -1
  56. package/dist/schema.d.cts +4 -4
  57. package/dist/schema.d.ts +4 -4
  58. package/dist/schema.js +26 -6
  59. package/dist/schema.js.map +1 -1
  60. package/dist/{type-mapper-DsGgZwUo.d.cts → type-mapper-BlewDZpG.d.cts} +1 -5
  61. package/dist/{type-mapper-Dvh4QTM-.d.ts → type-mapper-DkIy07Eb.d.ts} +1 -5
  62. package/dist/{types-d0yBwHoN.d.cts → types-BbrRUsMM.d.cts} +1 -1
  63. package/dist/{types-BWhwQxG-.d.ts → types-CzLguhyw.d.ts} +1 -1
  64. package/package.json +22 -22
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.7](https://github.com/dastron/pocketbase-zod-schema/compare/pocketbase-zod-schema-v0.3.6...pocketbase-zod-schema-v0.3.7) (2026-01-15)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * bump deps ([4c36d1c](https://github.com/dastron/pocketbase-zod-schema/commit/4c36d1c0fbe9013ef9fac482c196adbd3878a957))
9
+
3
10
  ## [0.3.6](https://github.com/dastron/pocketbase-zod-schema/compare/pocketbase-zod-schema-v0.3.5...pocketbase-zod-schema-v0.3.6) (2026-01-14)
4
11
 
5
12
 
@@ -37,7 +37,7 @@ var ora__default = /*#__PURE__*/_interopDefault(ora);
37
37
  id: zod.z.string().describe("unique id"),
38
38
  collectionId: zod.z.string().describe("collection id"),
39
39
  collectionName: zod.z.string().describe("collection name"),
40
- expand: zod.z.record(zod.z.any()).describe("expandable fields"),
40
+ expand: zod.z.record(zod.z.string(), zod.z.any()).describe("expandable fields"),
41
41
  created: zod.z.string().describe("creation timestamp"),
42
42
  updated: zod.z.string().describe("last update timestamp")
43
43
  });
@@ -822,17 +822,33 @@ function pluralize(singular) {
822
822
  function toCollectionName(entityName) {
823
823
  return pluralize(entityName);
824
824
  }
825
- function isSingleRelationField(fieldName, zodType) {
825
+ function unwrapType(zodType) {
826
826
  let unwrappedType = zodType;
827
- if (zodType instanceof zod.z.ZodOptional) {
828
- unwrappedType = zodType._def.innerType;
827
+ if (unwrappedType instanceof zod.z.ZodOptional) {
828
+ unwrappedType = unwrappedType.unwrap();
829
829
  }
830
830
  if (unwrappedType instanceof zod.z.ZodNullable) {
831
- unwrappedType = unwrappedType._def.innerType;
831
+ unwrappedType = unwrappedType.unwrap();
832
832
  }
833
833
  if (unwrappedType instanceof zod.z.ZodDefault) {
834
- unwrappedType = unwrappedType._def.innerType;
834
+ unwrappedType = unwrappedType.unwrap();
835
+ }
836
+ return unwrappedType;
837
+ }
838
+ function getChecks(zodType) {
839
+ const def = zodType.def ?? zodType._def;
840
+ return def?.checks ?? [];
841
+ }
842
+ function getJsonSchema(zodType) {
843
+ try {
844
+ const toJSONSchema = zodType.toJSONSchema;
845
+ return typeof toJSONSchema === "function" ? toJSONSchema.call(zodType) : null;
846
+ } catch {
847
+ return null;
835
848
  }
849
+ }
850
+ function isSingleRelationField(fieldName, zodType) {
851
+ const unwrappedType = unwrapType(zodType);
836
852
  if (!(unwrappedType instanceof zod.z.ZodString)) {
837
853
  return false;
838
854
  }
@@ -842,20 +858,11 @@ function isSingleRelationField(fieldName, zodType) {
842
858
  return startsWithUppercase && !isCommonField;
843
859
  }
844
860
  function isMultipleRelationField(fieldName, zodType) {
845
- let unwrappedType = zodType;
846
- if (zodType instanceof zod.z.ZodOptional) {
847
- unwrappedType = zodType._def.innerType;
848
- }
849
- if (unwrappedType instanceof zod.z.ZodNullable) {
850
- unwrappedType = unwrappedType._def.innerType;
851
- }
852
- if (unwrappedType instanceof zod.z.ZodDefault) {
853
- unwrappedType = unwrappedType._def.innerType;
854
- }
861
+ const unwrappedType = unwrapType(zodType);
855
862
  if (!(unwrappedType instanceof zod.z.ZodArray)) {
856
863
  return false;
857
864
  }
858
- const elementType = unwrappedType._def.type;
865
+ const elementType = unwrappedType.element;
859
866
  if (!(elementType instanceof zod.z.ZodString)) {
860
867
  return false;
861
868
  }
@@ -878,20 +885,16 @@ function getMaxSelect(fieldName, zodType) {
878
885
  return 1;
879
886
  }
880
887
  if (isMultipleRelationField(fieldName, zodType)) {
881
- let unwrappedType = zodType;
882
- if (zodType instanceof zod.z.ZodOptional) {
883
- unwrappedType = zodType._def.innerType;
884
- }
885
- if (unwrappedType instanceof zod.z.ZodNullable) {
886
- unwrappedType = unwrappedType._def.innerType;
887
- }
888
- if (unwrappedType instanceof zod.z.ZodDefault) {
889
- unwrappedType = unwrappedType._def.innerType;
890
- }
888
+ const unwrappedType = unwrapType(zodType);
891
889
  if (unwrappedType instanceof zod.z.ZodArray) {
892
- const arrayDef = unwrappedType._def;
893
- if (arrayDef.maxLength) {
894
- return arrayDef.maxLength.value;
890
+ const checks = getChecks(unwrappedType);
891
+ const maxCheck = checks.find((check) => check.kind === "max");
892
+ if (maxCheck) {
893
+ return maxCheck.value;
894
+ }
895
+ const schema = getJsonSchema(unwrappedType);
896
+ if (schema && typeof schema.maxItems === "number") {
897
+ return schema.maxItems;
895
898
  }
896
899
  return 999;
897
900
  }
@@ -903,36 +906,46 @@ function getMinSelect(fieldName, zodType) {
903
906
  return 0;
904
907
  }
905
908
  if (isMultipleRelationField(fieldName, zodType)) {
906
- let unwrappedType = zodType;
907
- if (zodType instanceof zod.z.ZodOptional) {
908
- unwrappedType = zodType._def.innerType;
909
- }
910
- if (unwrappedType instanceof zod.z.ZodNullable) {
911
- unwrappedType = unwrappedType._def.innerType;
912
- }
913
- if (unwrappedType instanceof zod.z.ZodDefault) {
914
- unwrappedType = unwrappedType._def.innerType;
915
- }
909
+ const unwrappedType = unwrapType(zodType);
916
910
  if (unwrappedType instanceof zod.z.ZodArray) {
917
- const arrayDef = unwrappedType._def;
918
- if (arrayDef.minLength) {
919
- return arrayDef.minLength.value;
911
+ const checks = getChecks(unwrappedType);
912
+ const minCheck = checks.find((check) => check.kind === "min");
913
+ if (minCheck) {
914
+ return minCheck.value;
915
+ }
916
+ const schema = getJsonSchema(unwrappedType);
917
+ if (schema && typeof schema.minItems === "number") {
918
+ return schema.minItems;
920
919
  }
921
920
  }
922
921
  }
923
922
  return 0;
924
923
  }
924
+ function getChecks2(zodType) {
925
+ const def = zodType.def ?? zodType._def;
926
+ return def?.checks ?? [];
927
+ }
928
+ function getJsonSchema2(zodType) {
929
+ try {
930
+ const toJSONSchema = zodType.toJSONSchema;
931
+ return typeof toJSONSchema === "function" ? toJSONSchema.call(zodType) : null;
932
+ } catch {
933
+ return null;
934
+ }
935
+ }
925
936
  function mapZodStringType(zodType) {
926
- const checks = zodType._def.checks || [];
927
- const hasEmail = checks.some((check) => check.kind === "email");
937
+ const checks = getChecks2(zodType);
938
+ const hasEmail = checks.some((check) => check.kind === "email" || check.def?.format === "email");
928
939
  if (hasEmail) {
929
940
  return "email";
930
941
  }
931
- const hasUrl = checks.some((check) => check.kind === "url");
942
+ const hasUrl = checks.some((check) => check.kind === "url" || check.def?.format === "url");
932
943
  if (hasUrl) {
933
944
  return "url";
934
945
  }
935
- const hasDatetime = checks.some((check) => check.kind === "datetime");
946
+ const hasDatetime = checks.some(
947
+ (check) => check.kind === "datetime" || check.def?.format === "datetime" || check.def?.format === "date-time"
948
+ );
936
949
  if (hasDatetime) {
937
950
  return "date";
938
951
  }
@@ -948,21 +961,9 @@ function mapZodEnumType(_zodType) {
948
961
  return "select";
949
962
  }
950
963
  function mapZodArrayType(zodType, _fieldName) {
951
- const elementType = zodType._def.type;
952
- if (elementType instanceof zod.z.ZodType) {
953
- const typeName = elementType._def.typeName;
954
- if (typeName === "ZodType" && elementType._def?.innerType?.name === "File") {
955
- return "file";
956
- }
957
- }
958
- if (elementType._def?.typeName === "ZodType") {
959
- const checks = elementType._def?.checks || [];
960
- const isFileInstance = checks.some(
961
- (check) => check.kind === "instanceof" || elementType._def?.innerType?.name === "File"
962
- );
963
- if (isFileInstance) {
964
- return "file";
965
- }
964
+ const elementType = zodType.element;
965
+ if (elementType instanceof zod.z.ZodFile) {
966
+ return "file";
966
967
  }
967
968
  if (elementType instanceof zod.z.ZodString) {
968
969
  return "relation";
@@ -978,29 +979,16 @@ function mapZodRecordType(_zodType) {
978
979
  function mapZodTypeToPocketBase(zodType, fieldName) {
979
980
  let unwrappedType = zodType;
980
981
  if (zodType instanceof zod.z.ZodOptional) {
981
- unwrappedType = zodType._def.innerType;
982
+ unwrappedType = zodType.unwrap();
982
983
  }
983
984
  if (unwrappedType instanceof zod.z.ZodNullable) {
984
- unwrappedType = unwrappedType._def.innerType;
985
+ unwrappedType = unwrappedType.unwrap();
985
986
  }
986
987
  if (unwrappedType instanceof zod.z.ZodDefault) {
987
- unwrappedType = unwrappedType._def.innerType;
988
- }
989
- if (unwrappedType._def?.typeName === "ZodEffects") {
990
- const effect = unwrappedType._def?.effect;
991
- if (effect?.type === "refinement") {
992
- const fileFieldNames = ["avatar", "image", "file", "attachment", "photo", "picture", "document", "upload"];
993
- if (fileFieldNames.some((name) => fieldName.toLowerCase().includes(name))) {
994
- return "file";
995
- }
996
- }
988
+ unwrappedType = unwrappedType.unwrap();
997
989
  }
998
- if (unwrappedType._def?.typeName === "ZodType") {
999
- const checks = unwrappedType._def?.checks || [];
1000
- const innerType = unwrappedType._def?.innerType;
1001
- if (innerType?.name === "File" || checks.some((check) => check.kind === "instanceof")) {
1002
- return "file";
1003
- }
990
+ if (unwrappedType instanceof zod.z.ZodFile) {
991
+ return "file";
1004
992
  }
1005
993
  if (unwrappedType instanceof zod.z.ZodString) {
1006
994
  return mapZodStringType(unwrappedType);
@@ -1029,15 +1017,15 @@ function extractFieldOptions(zodType) {
1029
1017
  const options = {};
1030
1018
  let unwrappedType = zodType;
1031
1019
  if (zodType instanceof zod.z.ZodOptional) {
1032
- unwrappedType = zodType._def.innerType;
1020
+ unwrappedType = zodType.unwrap();
1033
1021
  }
1034
1022
  if (unwrappedType instanceof zod.z.ZodNullable) {
1035
- unwrappedType = unwrappedType._def.innerType;
1023
+ unwrappedType = unwrappedType.unwrap();
1036
1024
  }
1037
1025
  if (unwrappedType instanceof zod.z.ZodDefault) {
1038
- unwrappedType = unwrappedType._def.innerType;
1026
+ unwrappedType = unwrappedType.unwrap();
1039
1027
  }
1040
- const checks = unwrappedType._def?.checks || [];
1028
+ const checks = getChecks2(unwrappedType);
1041
1029
  if (unwrappedType instanceof zod.z.ZodString) {
1042
1030
  for (const check of checks) {
1043
1031
  if (check.kind === "min") {
@@ -1050,6 +1038,20 @@ function extractFieldOptions(zodType) {
1050
1038
  options.pattern = check.regex.source;
1051
1039
  }
1052
1040
  }
1041
+ if (options.min === void 0 || options.max === void 0 || options.pattern === void 0) {
1042
+ const schema = getJsonSchema2(unwrappedType);
1043
+ if (schema) {
1044
+ if (options.min === void 0 && typeof schema.minLength === "number") {
1045
+ options.min = schema.minLength;
1046
+ }
1047
+ if (options.max === void 0 && typeof schema.maxLength === "number") {
1048
+ options.max = schema.maxLength;
1049
+ }
1050
+ if (options.pattern === void 0 && typeof schema.pattern === "string") {
1051
+ options.pattern = schema.pattern;
1052
+ }
1053
+ }
1054
+ }
1053
1055
  }
1054
1056
  if (unwrappedType instanceof zod.z.ZodNumber) {
1055
1057
  for (const check of checks) {
@@ -1060,12 +1062,23 @@ function extractFieldOptions(zodType) {
1060
1062
  options.max = check.value;
1061
1063
  }
1062
1064
  }
1065
+ if (options.min === void 0 || options.max === void 0) {
1066
+ const schema = getJsonSchema2(unwrappedType);
1067
+ if (schema) {
1068
+ if (options.min === void 0 && typeof schema.minimum === "number") {
1069
+ options.min = schema.minimum;
1070
+ }
1071
+ if (options.max === void 0 && typeof schema.maximum === "number") {
1072
+ options.max = schema.maximum;
1073
+ }
1074
+ }
1075
+ }
1063
1076
  }
1064
1077
  if (unwrappedType instanceof zod.z.ZodEnum) {
1065
- options.values = unwrappedType._def.values;
1078
+ options.values = unwrappedType.options.map(String);
1066
1079
  }
1067
1080
  if (unwrappedType instanceof zod.z.ZodArray) {
1068
- const arrayChecks = unwrappedType._def?.checks || [];
1081
+ const arrayChecks = getChecks2(unwrappedType);
1069
1082
  for (const check of arrayChecks) {
1070
1083
  if (check.kind === "min") {
1071
1084
  options.minSelect = check.value;
@@ -1074,6 +1087,17 @@ function extractFieldOptions(zodType) {
1074
1087
  options.maxSelect = check.value;
1075
1088
  }
1076
1089
  }
1090
+ if (options.minSelect === void 0 || options.maxSelect === void 0) {
1091
+ const schema = getJsonSchema2(unwrappedType);
1092
+ if (schema) {
1093
+ if (options.minSelect === void 0 && typeof schema.minItems === "number") {
1094
+ options.minSelect = schema.minItems;
1095
+ }
1096
+ if (options.maxSelect === void 0 && typeof schema.maxItems === "number") {
1097
+ options.maxSelect = schema.maxItems;
1098
+ }
1099
+ }
1100
+ }
1077
1101
  }
1078
1102
  return options;
1079
1103
  }
@@ -1089,6 +1113,19 @@ function isFieldRequired(zodType) {
1089
1113
  }
1090
1114
  return true;
1091
1115
  }
1116
+ function unwrapZodType(zodType) {
1117
+ let unwrapped = zodType;
1118
+ if (unwrapped instanceof zod.z.ZodOptional) {
1119
+ unwrapped = unwrapped.unwrap();
1120
+ }
1121
+ if (unwrapped instanceof zod.z.ZodNullable) {
1122
+ unwrapped = unwrapped.unwrap();
1123
+ }
1124
+ if (unwrapped instanceof zod.z.ZodDefault) {
1125
+ unwrapped = unwrapped.unwrap();
1126
+ }
1127
+ return unwrapped;
1128
+ }
1092
1129
 
1093
1130
  // src/migration/analyzer.ts
1094
1131
  var tsxLoaderRegistered = false;
@@ -1314,7 +1351,8 @@ function isAuthCollection(fields) {
1314
1351
  return hasEmail && hasPassword;
1315
1352
  }
1316
1353
  function buildFieldDefinition(fieldName, zodType) {
1317
- const fieldMetadata = extractFieldMetadata(zodType.description);
1354
+ const unwrappedType = unwrapZodType(zodType);
1355
+ const fieldMetadata = extractFieldMetadata(unwrappedType.description ?? zodType.description);
1318
1356
  if (fieldMetadata) {
1319
1357
  let required2;
1320
1358
  if (fieldMetadata.type === "number") {
@@ -1334,7 +1372,7 @@ function buildFieldDefinition(fieldName, zodType) {
1334
1372
  options: Object.keys(options2).length > 0 ? options2 : void 0
1335
1373
  };
1336
1374
  if (fieldMetadata.type === "relation") {
1337
- const relationMetadata2 = extractRelationMetadata(zodType.description);
1375
+ const relationMetadata2 = extractRelationMetadata(unwrappedType.description ?? zodType.description);
1338
1376
  if (relationMetadata2) {
1339
1377
  fieldDef2.relation = {
1340
1378
  collection: relationMetadata2.collection,
@@ -1346,7 +1384,7 @@ function buildFieldDefinition(fieldName, zodType) {
1346
1384
  }
1347
1385
  return fieldDef2;
1348
1386
  }
1349
- const fieldType = mapZodTypeToPocketBase(zodType, fieldName);
1387
+ const fieldType = mapZodTypeToPocketBase(zodType);
1350
1388
  const required = isFieldRequired(zodType);
1351
1389
  const options = extractFieldOptions(zodType);
1352
1390
  const fieldDef = {
@@ -1355,7 +1393,7 @@ function buildFieldDefinition(fieldName, zodType) {
1355
1393
  required,
1356
1394
  options
1357
1395
  };
1358
- const relationMetadata = extractRelationMetadata(zodType.description);
1396
+ const relationMetadata = extractRelationMetadata(unwrappedType.description ?? zodType.description);
1359
1397
  if (relationMetadata) {
1360
1398
  fieldDef.type = "relation";
1361
1399
  fieldDef.relation = {
@@ -2765,7 +2803,9 @@ function generate(diff, config) {
2765
2803
  const downCode = generateOperationDownMigration(operation, collectionIdMap);
2766
2804
  const content = createMigrationFileStructure(upCode, downCode, normalizedConfig);
2767
2805
  if (!normalizedConfig.force && existingFiles.some((existingContent) => existingContent === content)) {
2768
- console.warn(`Duplicate migration detected for ${operation.type} ${typeof operation.collection === "string" ? operation.collection : operation.collection.name}. Skipping...`);
2806
+ console.warn(
2807
+ `Duplicate migration detected for ${operation.type} ${typeof operation.collection === "string" ? operation.collection : operation.collection.name}. Skipping...`
2808
+ );
2769
2809
  continue;
2770
2810
  }
2771
2811
  const filename = generateCollectionMigrationFilename(operation);