@gabrielbryk/json-schema-to-zod 2.12.1 → 2.13.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 (53) hide show
  1. package/.github/RELEASE_SETUP.md +120 -0
  2. package/.github/TOOLING_GUIDE.md +169 -0
  3. package/.github/dependabot.yml +52 -0
  4. package/.github/workflows/ci.yml +33 -0
  5. package/.github/workflows/release.yml +12 -4
  6. package/.github/workflows/security.yml +40 -0
  7. package/.husky/commit-msg +1 -0
  8. package/.husky/pre-commit +1 -0
  9. package/.lintstagedrc.json +3 -0
  10. package/.prettierrc +20 -0
  11. package/AGENTS.md +7 -0
  12. package/CHANGELOG.md +7 -4
  13. package/README.md +9 -9
  14. package/commitlint.config.js +24 -0
  15. package/createIndex.ts +4 -4
  16. package/dist/cli.js +3 -4
  17. package/dist/core/analyzeSchema.js +28 -5
  18. package/dist/core/emitZod.js +11 -4
  19. package/dist/generators/generateBundle.js +67 -92
  20. package/dist/parsers/parseAllOf.js +11 -12
  21. package/dist/parsers/parseAnyOf.js +2 -2
  22. package/dist/parsers/parseArray.js +38 -12
  23. package/dist/parsers/parseMultipleType.js +2 -2
  24. package/dist/parsers/parseNumber.js +44 -102
  25. package/dist/parsers/parseObject.js +136 -443
  26. package/dist/parsers/parseOneOf.js +57 -110
  27. package/dist/parsers/parseSchema.js +132 -55
  28. package/dist/parsers/parseSimpleDiscriminatedOneOf.js +2 -2
  29. package/dist/parsers/parseString.js +113 -253
  30. package/dist/types/Types.d.ts +22 -1
  31. package/dist/types/core/analyzeSchema.d.ts +1 -0
  32. package/dist/types/generators/generateBundle.d.ts +1 -1
  33. package/dist/utils/cliTools.js +1 -2
  34. package/dist/utils/esmEmitter.js +6 -2
  35. package/dist/utils/extractInlineObject.js +1 -3
  36. package/dist/utils/jsdocs.js +1 -4
  37. package/dist/utils/liftInlineObjects.js +76 -15
  38. package/dist/utils/resolveRef.js +35 -10
  39. package/dist/utils/schemaRepresentation.js +35 -66
  40. package/dist/zodToJsonSchema.js +1 -2
  41. package/docs/IMPROVEMENT-PLAN.md +30 -12
  42. package/docs/ZOD-V4-RECURSIVE-TYPE-LIMITATIONS.md +70 -25
  43. package/docs/proposals/allof-required-merging.md +10 -4
  44. package/docs/proposals/bundle-refactor.md +10 -4
  45. package/docs/proposals/discriminated-union-with-default.md +18 -14
  46. package/docs/proposals/inline-object-lifting.md +15 -5
  47. package/docs/proposals/ref-anchor-support.md +11 -0
  48. package/output.txt +67 -0
  49. package/package.json +18 -5
  50. package/scripts/generateWorkflowSchema.ts +5 -14
  51. package/scripts/regenerate_bundle.ts +25 -0
  52. package/tsc_output.txt +542 -0
  53. package/tsc_output_2.txt +489 -0
@@ -1,115 +1,57 @@
1
1
  import { withMessage } from "../utils/withMessage.js";
2
2
  export const parseNumber = (schema) => {
3
- const formatError = schema.errorMessage?.format;
4
- const numericFormatMap = {
5
- int32: "z.int32",
6
- uint32: "z.uint32",
7
- float32: "z.float32",
8
- float64: "z.float64",
9
- safeint: "z.safeint",
10
- int64: "z.int64",
11
- uint64: "z.uint64",
3
+ const formatMessage = schema.errorMessage?.format;
4
+ const formatParams = formatMessage ? `{ message: ${JSON.stringify(formatMessage)} }` : "";
5
+ const formatMap = {
6
+ int32: { expression: `z.int32(${formatParams})`, type: "z.ZodNumber" },
7
+ uint32: { expression: `z.uint32(${formatParams})`, type: "z.ZodNumber" },
8
+ float32: { expression: `z.float32(${formatParams})`, type: "z.ZodNumber" },
9
+ float64: { expression: `z.float64(${formatParams})`, type: "z.ZodNumber" },
10
+ safeint: { expression: `z.safeint(${formatParams})`, type: "z.ZodNumber" },
11
+ int64: { expression: `z.int64(${formatParams})`, type: "z.ZodBigInt" },
12
+ uint64: { expression: `z.uint64(${formatParams})`, type: "z.ZodBigInt" },
12
13
  };
13
- const mappedFormat = schema.format && numericFormatMap[schema.format] ? numericFormatMap[schema.format] : undefined;
14
- const formatParams = formatError !== undefined ? `{ error: ${JSON.stringify(formatError)} }` : "";
15
- let r = mappedFormat ? `${mappedFormat}(${formatParams})` : "z.number()";
16
- if (schema.type === "integer") {
17
- if (!mappedFormat) {
18
- r += withMessage(schema, "type", () => ({
19
- opener: ".int(",
20
- closer: ")",
21
- messagePrefix: "{ error: ",
22
- messageCloser: " })",
23
- }));
24
- }
14
+ let r = schema.type === "integer" ? "z.int()" : "z.number()";
15
+ let zodType = schema.type === "integer" ? "z.ZodInt" : "z.ZodNumber";
16
+ if (schema.format && formatMap[schema.format]) {
17
+ const mapped = formatMap[schema.format];
18
+ r = mapped.expression;
19
+ zodType = mapped.type;
25
20
  }
26
- else {
27
- if (!mappedFormat) {
28
- r += withMessage(schema, "format", ({ value }) => {
29
- if (value === "int64") {
30
- return {
31
- opener: ".int(",
32
- closer: ")",
33
- messagePrefix: "{ error: ",
34
- messageCloser: " })",
35
- };
36
- }
37
- });
38
- }
21
+ r += withMessage(schema, "multipleOf", ({ json }) => ({
22
+ opener: `.multipleOf(${json}`,
23
+ closer: ")",
24
+ messagePrefix: ", { message: ",
25
+ messageCloser: " })",
26
+ }));
27
+ const minimum = schema.minimum;
28
+ const maximum = schema.maximum;
29
+ const exclusiveMinimum = schema.exclusiveMinimum;
30
+ const exclusiveMaximum = schema.exclusiveMaximum;
31
+ const minMessage = schema.errorMessage?.minimum;
32
+ const maxMessage = schema.errorMessage?.maximum;
33
+ const exclMinMessage = schema.errorMessage?.exclusiveMinimum;
34
+ const exclMaxMessage = schema.errorMessage?.exclusiveMaximum;
35
+ if (typeof exclusiveMinimum === "number") {
36
+ r += `.gt(${exclusiveMinimum}${exclMinMessage ? `, { message: ${JSON.stringify(exclMinMessage)} }` : ""})`;
39
37
  }
40
- r += withMessage(schema, "multipleOf", ({ value, json }) => {
41
- if (value === 1) {
42
- if (r.startsWith("z.number().int(")) {
43
- return;
44
- }
45
- return {
46
- opener: ".int(",
47
- closer: ")",
48
- messagePrefix: "{ error: ",
49
- messageCloser: " })",
50
- };
51
- }
52
- return {
53
- opener: `.multipleOf(${json}`,
54
- closer: ")",
55
- messagePrefix: ", { error: ",
56
- messageCloser: " })",
57
- };
58
- });
59
- if (typeof schema.minimum === "number") {
60
- if (schema.exclusiveMinimum === true) {
61
- r += withMessage(schema, "minimum", ({ json }) => ({
62
- opener: `.gt(${json}`,
63
- closer: ")",
64
- messagePrefix: ", { error: ",
65
- messageCloser: " })",
66
- }));
67
- }
68
- else {
69
- r += withMessage(schema, "minimum", ({ json }) => ({
70
- opener: `.gte(${json}`,
71
- closer: ")",
72
- messagePrefix: ", { error: ",
73
- messageCloser: " })",
74
- }));
75
- }
38
+ else if (exclusiveMinimum === true && typeof minimum === "number") {
39
+ r += `.gt(${minimum}${exclMinMessage ? `, { message: ${JSON.stringify(exclMinMessage)} }` : ""})`;
76
40
  }
77
- else if (typeof schema.exclusiveMinimum === "number") {
78
- r += withMessage(schema, "exclusiveMinimum", ({ json }) => ({
79
- opener: `.gt(${json}`,
80
- closer: ")",
81
- messagePrefix: ", { error: ",
82
- messageCloser: " })",
83
- }));
41
+ else if (typeof minimum === "number") {
42
+ r += `.min(${minimum}${minMessage ? `, { message: ${JSON.stringify(minMessage)} }` : ""})`;
84
43
  }
85
- if (typeof schema.maximum === "number") {
86
- if (schema.exclusiveMaximum === true) {
87
- r += withMessage(schema, "maximum", ({ json }) => ({
88
- opener: `.lt(${json}`,
89
- closer: ")",
90
- messagePrefix: ", { error: ",
91
- messageCloser: " })",
92
- }));
93
- }
94
- else {
95
- r += withMessage(schema, "maximum", ({ json }) => ({
96
- opener: `.lte(${json}`,
97
- closer: ")",
98
- messagePrefix: ", { error: ",
99
- messageCloser: " })",
100
- }));
101
- }
44
+ if (typeof exclusiveMaximum === "number") {
45
+ r += `.lt(${exclusiveMaximum}${exclMaxMessage ? `, { message: ${JSON.stringify(exclMaxMessage)} }` : ""})`;
102
46
  }
103
- else if (typeof schema.exclusiveMaximum === "number") {
104
- r += withMessage(schema, "exclusiveMaximum", ({ json }) => ({
105
- opener: `.lt(${json}`,
106
- closer: ")",
107
- messagePrefix: ", { error: ",
108
- messageCloser: " })",
109
- }));
47
+ else if (exclusiveMaximum === true && typeof maximum === "number") {
48
+ r += `.lt(${maximum}${exclMaxMessage ? `, { message: ${JSON.stringify(exclMaxMessage)} }` : ""})`;
49
+ }
50
+ else if (typeof maximum === "number") {
51
+ r += `.max(${maximum}${maxMessage ? `, { message: ${JSON.stringify(maxMessage)} }` : ""})`;
110
52
  }
111
53
  return {
112
54
  expression: r,
113
- type: "z.ZodNumber",
55
+ type: zodType,
114
56
  };
115
57
  };