@gabrielbryk/json-schema-to-zod 2.7.2

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 (99) hide show
  1. package/.prettierrc.json +3 -0
  2. package/CONTRIBUTING.md +9 -0
  3. package/LICENSE +15 -0
  4. package/README.md +157 -0
  5. package/createIndex.ts +32 -0
  6. package/dist/cjs/Types.js +2 -0
  7. package/dist/cjs/cli.js +70 -0
  8. package/dist/cjs/index.js +44 -0
  9. package/dist/cjs/jsonSchemaToZod.js +78 -0
  10. package/dist/cjs/package.json +1 -0
  11. package/dist/cjs/parsers/parseAllOf.js +40 -0
  12. package/dist/cjs/parsers/parseAnyOf.js +18 -0
  13. package/dist/cjs/parsers/parseArray.js +71 -0
  14. package/dist/cjs/parsers/parseBoolean.js +7 -0
  15. package/dist/cjs/parsers/parseConst.js +7 -0
  16. package/dist/cjs/parsers/parseDefault.js +8 -0
  17. package/dist/cjs/parsers/parseEnum.js +21 -0
  18. package/dist/cjs/parsers/parseIfThenElse.js +34 -0
  19. package/dist/cjs/parsers/parseMultipleType.js +10 -0
  20. package/dist/cjs/parsers/parseNot.js +12 -0
  21. package/dist/cjs/parsers/parseNull.js +7 -0
  22. package/dist/cjs/parsers/parseNullable.js +12 -0
  23. package/dist/cjs/parsers/parseNumber.js +74 -0
  24. package/dist/cjs/parsers/parseObject.js +286 -0
  25. package/dist/cjs/parsers/parseOneOf.js +53 -0
  26. package/dist/cjs/parsers/parseSchema.js +285 -0
  27. package/dist/cjs/parsers/parseSimpleDiscriminatedOneOf.js +29 -0
  28. package/dist/cjs/parsers/parseString.js +77 -0
  29. package/dist/cjs/utils/anyOrUnknown.js +14 -0
  30. package/dist/cjs/utils/cliTools.js +108 -0
  31. package/dist/cjs/utils/half.js +7 -0
  32. package/dist/cjs/utils/jsdocs.js +20 -0
  33. package/dist/cjs/utils/omit.js +10 -0
  34. package/dist/cjs/utils/withMessage.js +22 -0
  35. package/dist/cjs/zodToJsonSchema.js +89 -0
  36. package/dist/esm/Types.js +1 -0
  37. package/dist/esm/cli.js +68 -0
  38. package/dist/esm/index.js +28 -0
  39. package/dist/esm/jsonSchemaToZod.js +74 -0
  40. package/dist/esm/package.json +1 -0
  41. package/dist/esm/parsers/parseAllOf.js +37 -0
  42. package/dist/esm/parsers/parseAnyOf.js +14 -0
  43. package/dist/esm/parsers/parseArray.js +67 -0
  44. package/dist/esm/parsers/parseBoolean.js +3 -0
  45. package/dist/esm/parsers/parseConst.js +3 -0
  46. package/dist/esm/parsers/parseDefault.js +4 -0
  47. package/dist/esm/parsers/parseEnum.js +17 -0
  48. package/dist/esm/parsers/parseIfThenElse.js +30 -0
  49. package/dist/esm/parsers/parseMultipleType.js +6 -0
  50. package/dist/esm/parsers/parseNot.js +8 -0
  51. package/dist/esm/parsers/parseNull.js +3 -0
  52. package/dist/esm/parsers/parseNullable.js +8 -0
  53. package/dist/esm/parsers/parseNumber.js +70 -0
  54. package/dist/esm/parsers/parseObject.js +283 -0
  55. package/dist/esm/parsers/parseOneOf.js +49 -0
  56. package/dist/esm/parsers/parseSchema.js +281 -0
  57. package/dist/esm/parsers/parseSimpleDiscriminatedOneOf.js +25 -0
  58. package/dist/esm/parsers/parseString.js +73 -0
  59. package/dist/esm/utils/anyOrUnknown.js +10 -0
  60. package/dist/esm/utils/cliTools.js +102 -0
  61. package/dist/esm/utils/half.js +3 -0
  62. package/dist/esm/utils/jsdocs.js +15 -0
  63. package/dist/esm/utils/omit.js +6 -0
  64. package/dist/esm/utils/withMessage.js +19 -0
  65. package/dist/esm/zodToJsonSchema.js +86 -0
  66. package/dist/types/Types.d.ts +125 -0
  67. package/dist/types/cli.d.ts +2 -0
  68. package/dist/types/index.d.ts +28 -0
  69. package/dist/types/jsonSchemaToZod.d.ts +2 -0
  70. package/dist/types/parsers/parseAllOf.d.ts +4 -0
  71. package/dist/types/parsers/parseAnyOf.d.ts +4 -0
  72. package/dist/types/parsers/parseArray.d.ts +4 -0
  73. package/dist/types/parsers/parseBoolean.d.ts +4 -0
  74. package/dist/types/parsers/parseConst.d.ts +4 -0
  75. package/dist/types/parsers/parseDefault.d.ts +2 -0
  76. package/dist/types/parsers/parseEnum.d.ts +4 -0
  77. package/dist/types/parsers/parseIfThenElse.d.ts +6 -0
  78. package/dist/types/parsers/parseMultipleType.d.ts +4 -0
  79. package/dist/types/parsers/parseNot.d.ts +4 -0
  80. package/dist/types/parsers/parseNull.d.ts +4 -0
  81. package/dist/types/parsers/parseNullable.d.ts +7 -0
  82. package/dist/types/parsers/parseNumber.d.ts +4 -0
  83. package/dist/types/parsers/parseObject.d.ts +4 -0
  84. package/dist/types/parsers/parseOneOf.d.ts +4 -0
  85. package/dist/types/parsers/parseSchema.d.ts +50 -0
  86. package/dist/types/parsers/parseSimpleDiscriminatedOneOf.d.ts +2 -0
  87. package/dist/types/parsers/parseString.d.ts +4 -0
  88. package/dist/types/utils/anyOrUnknown.d.ts +9 -0
  89. package/dist/types/utils/cliTools.d.ts +28 -0
  90. package/dist/types/utils/half.d.ts +1 -0
  91. package/dist/types/utils/jsdocs.d.ts +3 -0
  92. package/dist/types/utils/omit.d.ts +1 -0
  93. package/dist/types/utils/withMessage.d.ts +10 -0
  94. package/dist/types/zodToJsonSchema.d.ts +26 -0
  95. package/jest.config.js +4 -0
  96. package/package.json +83 -0
  97. package/postcjs.js +1 -0
  98. package/postesm.js +1 -0
  99. package/scripts/generateWorkflowSchema.ts +82 -0
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ import { jsonSchemaToZod } from "./jsonSchemaToZod.js";
3
+ import { writeFileSync, mkdirSync } from "fs";
4
+ import { dirname } from "path";
5
+ import { parseArgs, parseOrReadJSON, readPipe } from "./utils/cliTools.js";
6
+ const params = {
7
+ input: {
8
+ shorthand: "i",
9
+ value: "string",
10
+ required: process.stdin.isTTY &&
11
+ "input is required when no JSON or file path is piped",
12
+ description: "JSON or a source file path. Required if no data is piped.",
13
+ },
14
+ output: {
15
+ shorthand: "o",
16
+ value: "string",
17
+ description: "A file path to write to. If not supplied stdout will be used.",
18
+ },
19
+ name: {
20
+ shorthand: "n",
21
+ value: "string",
22
+ description: "The name of the schema in the output.",
23
+ },
24
+ depth: {
25
+ shorthand: "d",
26
+ value: "number",
27
+ description: "Maximum depth of recursion before falling back to z.any(). Defaults to 0.",
28
+ },
29
+ module: {
30
+ shorthand: "m",
31
+ value: ["esm", "cjs", "none"],
32
+ description: "Module syntax; 'esm', 'cjs' or 'none'. Defaults to 'esm'.",
33
+ },
34
+ type: {
35
+ shorthand: "t",
36
+ value: "string",
37
+ description: "The name of the (optional) inferred type export."
38
+ },
39
+ noImport: {
40
+ shorthand: "ni",
41
+ description: "Removes the `import { z } from 'zod';` or equivalent from the output."
42
+ },
43
+ withJsdocs: {
44
+ shorthand: "wj",
45
+ description: "Generate jsdocs off of the description property.",
46
+ },
47
+ };
48
+ async function main() {
49
+ const args = parseArgs(params, process.argv, true);
50
+ const input = args.input || (await readPipe());
51
+ const jsonSchema = parseOrReadJSON(input);
52
+ const zodSchema = jsonSchemaToZod(jsonSchema, {
53
+ name: args.name,
54
+ depth: args.depth,
55
+ module: args.module || "esm",
56
+ noImport: args.noImport,
57
+ type: args.type,
58
+ withJsdocs: args.withJsdocs,
59
+ });
60
+ if (args.output) {
61
+ mkdirSync(dirname(args.output), { recursive: true });
62
+ writeFileSync(args.output, zodSchema);
63
+ }
64
+ else {
65
+ console.log(zodSchema);
66
+ }
67
+ }
68
+ void main();
@@ -0,0 +1,28 @@
1
+ export * from "./Types.js";
2
+ export * from "./jsonSchemaToZod.js";
3
+ export * from "./parsers/parseAllOf.js";
4
+ export * from "./parsers/parseAnyOf.js";
5
+ export * from "./parsers/parseArray.js";
6
+ export * from "./parsers/parseBoolean.js";
7
+ export * from "./parsers/parseConst.js";
8
+ export * from "./parsers/parseDefault.js";
9
+ export * from "./parsers/parseEnum.js";
10
+ export * from "./parsers/parseIfThenElse.js";
11
+ export * from "./parsers/parseMultipleType.js";
12
+ export * from "./parsers/parseNot.js";
13
+ export * from "./parsers/parseNull.js";
14
+ export * from "./parsers/parseNullable.js";
15
+ export * from "./parsers/parseNumber.js";
16
+ export * from "./parsers/parseObject.js";
17
+ export * from "./parsers/parseOneOf.js";
18
+ export * from "./parsers/parseSchema.js";
19
+ export * from "./parsers/parseSimpleDiscriminatedOneOf.js";
20
+ export * from "./parsers/parseString.js";
21
+ export * from "./utils/anyOrUnknown.js";
22
+ export * from "./utils/half.js";
23
+ export * from "./utils/jsdocs.js";
24
+ export * from "./utils/omit.js";
25
+ export * from "./utils/withMessage.js";
26
+ export * from "./zodToJsonSchema.js";
27
+ import { jsonSchemaToZod } from "./jsonSchemaToZod.js";
28
+ export default jsonSchemaToZod;
@@ -0,0 +1,74 @@
1
+ import { parseSchema } from "./parsers/parseSchema.js";
2
+ import { expandJsdocs } from "./utils/jsdocs.js";
3
+ export const jsonSchemaToZod = (schema, { module, name, type, noImport, ...rest } = {}) => {
4
+ if (type && (!name || module !== "esm")) {
5
+ throw new Error("Option `type` requires `name` to be set and `module` to be `esm`");
6
+ }
7
+ const declarations = new Map();
8
+ const refNameByPointer = new Map();
9
+ const usedNames = new Set();
10
+ const exportRefs = rest.exportRefs ?? true;
11
+ const withMeta = rest.withMeta ?? true;
12
+ if (name)
13
+ usedNames.add(name);
14
+ const parsedSchema = parseSchema(schema, {
15
+ module,
16
+ name,
17
+ path: [],
18
+ seen: new Map(),
19
+ declarations,
20
+ inProgress: new Set(),
21
+ refNameByPointer,
22
+ usedNames,
23
+ root: schema,
24
+ currentSchemaName: name,
25
+ ...rest,
26
+ withMeta,
27
+ });
28
+ const declarationBlock = declarations.size
29
+ ? Array.from(declarations.entries())
30
+ .map(([refName, value]) => {
31
+ const shouldExport = exportRefs && module === "esm";
32
+ const decl = `${shouldExport ? "export " : ""}const ${refName} = ${value}`;
33
+ return decl;
34
+ })
35
+ .join("\n")
36
+ : "";
37
+ const jsdocs = rest.withJsdocs && typeof schema !== "boolean" && schema.description
38
+ ? expandJsdocs(schema.description)
39
+ : "";
40
+ const lines = [];
41
+ if (module === "cjs" && !noImport) {
42
+ lines.push(`const { z } = require("zod")`);
43
+ }
44
+ if (module === "esm" && !noImport) {
45
+ lines.push(`import { z } from "zod"`);
46
+ }
47
+ if (declarationBlock) {
48
+ lines.push(declarationBlock);
49
+ }
50
+ if (module === "cjs") {
51
+ const payload = name ? `{ ${JSON.stringify(name)}: ${parsedSchema} }` : parsedSchema;
52
+ lines.push(`${jsdocs}module.exports = ${payload}`);
53
+ }
54
+ else if (module === "esm") {
55
+ lines.push(`${jsdocs}export ${name ? `const ${name} =` : `default`} ${parsedSchema}`);
56
+ }
57
+ else if (name) {
58
+ lines.push(`${jsdocs}const ${name} = ${parsedSchema}`);
59
+ }
60
+ else {
61
+ lines.push(`${jsdocs}${parsedSchema}`);
62
+ }
63
+ let typeLine;
64
+ if (type && name) {
65
+ let typeName = typeof type === "string"
66
+ ? type
67
+ : `${name[0].toUpperCase()}${name.substring(1)}`;
68
+ typeLine = `export type ${typeName} = z.infer<typeof ${name}>`;
69
+ }
70
+ const joined = lines.filter(Boolean).join("\n\n");
71
+ const combined = typeLine ? `${joined}\n${typeLine}` : joined;
72
+ const shouldEndWithNewline = module === "esm" || module === "cjs";
73
+ return `${combined}${shouldEndWithNewline ? "\n" : ""}`;
74
+ };
@@ -0,0 +1 @@
1
+ {"type":"module"}
@@ -0,0 +1,37 @@
1
+ import { parseSchema } from "./parseSchema.js";
2
+ import { half } from "../utils/half.js";
3
+ const originalIndex = Symbol("Original index");
4
+ const ensureOriginalIndex = (arr) => {
5
+ let newArr = [];
6
+ for (let i = 0; i < arr.length; i++) {
7
+ const item = arr[i];
8
+ if (typeof item === "boolean") {
9
+ newArr.push(item ? { [originalIndex]: i } : { [originalIndex]: i, not: {} });
10
+ }
11
+ else if (originalIndex in item) {
12
+ return arr;
13
+ }
14
+ else {
15
+ newArr.push({ ...item, [originalIndex]: i });
16
+ }
17
+ }
18
+ return newArr;
19
+ };
20
+ export function parseAllOf(schema, refs) {
21
+ if (schema.allOf.length === 0) {
22
+ return "z.never()";
23
+ }
24
+ else if (schema.allOf.length === 1) {
25
+ const item = schema.allOf[0];
26
+ return parseSchema(item, {
27
+ ...refs,
28
+ path: [...refs.path, "allOf", item[originalIndex]],
29
+ });
30
+ }
31
+ else {
32
+ const [left, right] = half(ensureOriginalIndex(schema.allOf));
33
+ return `z.intersection(${parseAllOf({ allOf: left }, refs)}, ${parseAllOf({
34
+ allOf: right,
35
+ }, refs)})`;
36
+ }
37
+ }
@@ -0,0 +1,14 @@
1
+ import { parseSchema } from "./parseSchema.js";
2
+ import { anyOrUnknown } from "../utils/anyOrUnknown.js";
3
+ export const parseAnyOf = (schema, refs) => {
4
+ return schema.anyOf.length
5
+ ? schema.anyOf.length === 1
6
+ ? parseSchema(schema.anyOf[0], {
7
+ ...refs,
8
+ path: [...refs.path, "anyOf", 0],
9
+ })
10
+ : `z.union([${schema.anyOf
11
+ .map((schema, i) => parseSchema(schema, { ...refs, path: [...refs.path, "anyOf", i] }))
12
+ .join(", ")}])`
13
+ : anyOrUnknown(refs);
14
+ };
@@ -0,0 +1,67 @@
1
+ import { withMessage } from "../utils/withMessage.js";
2
+ import { parseSchema } from "./parseSchema.js";
3
+ import { anyOrUnknown } from "../utils/anyOrUnknown.js";
4
+ export const parseArray = (schema, refs) => {
5
+ if (Array.isArray(schema.items)) {
6
+ let tuple = `z.tuple([${schema.items.map((v, i) => parseSchema(v, { ...refs, path: [...refs.path, "items", i] }))}])`;
7
+ if (schema.contains) {
8
+ const containsSchema = parseSchema(schema.contains, {
9
+ ...refs,
10
+ path: [...refs.path, "contains"],
11
+ });
12
+ const minContains = schema.minContains ?? (schema.contains ? 1 : undefined);
13
+ const maxContains = schema.maxContains;
14
+ tuple += `.superRefine((arr, ctx) => {
15
+ const matches = arr.filter((item) => ${containsSchema}.safeParse(item).success).length;
16
+ if (${minContains ?? 0} && matches < ${minContains ?? 0}) {
17
+ ctx.addIssue({ code: "custom", message: "Array contains too few matching items" });
18
+ }
19
+ if (${maxContains ?? "undefined"} !== undefined && matches > ${maxContains ?? "undefined"}) {
20
+ ctx.addIssue({ code: "custom", message: "Array contains too many matching items" });
21
+ }
22
+ })`;
23
+ }
24
+ return tuple;
25
+ }
26
+ let r = !schema.items
27
+ ? `z.array(${anyOrUnknown(refs)})`
28
+ : `z.array(${parseSchema(schema.items, {
29
+ ...refs,
30
+ path: [...refs.path, "items"],
31
+ })})`;
32
+ r += withMessage(schema, "minItems", ({ json }) => [
33
+ `.min(${json}`,
34
+ ", ",
35
+ ")",
36
+ ]);
37
+ r += withMessage(schema, "maxItems", ({ json }) => [
38
+ `.max(${json}`,
39
+ ", ",
40
+ ")",
41
+ ]);
42
+ if (schema.uniqueItems === true) {
43
+ r += withMessage(schema, "uniqueItems", () => [
44
+ ".unique(",
45
+ "",
46
+ ")",
47
+ ]);
48
+ }
49
+ if (schema.contains) {
50
+ const containsSchema = parseSchema(schema.contains, {
51
+ ...refs,
52
+ path: [...refs.path, "contains"],
53
+ });
54
+ const minContains = schema.minContains ?? (schema.contains ? 1 : undefined);
55
+ const maxContains = schema.maxContains;
56
+ r += `.superRefine((arr, ctx) => {
57
+ const matches = arr.filter((item) => ${containsSchema}.safeParse(item).success).length;
58
+ if (${minContains ?? 0} && matches < ${minContains ?? 0}) {
59
+ ctx.addIssue({ code: "custom", message: "Array contains too few matching items" });
60
+ }
61
+ if (${maxContains ?? "undefined"} !== undefined && matches > ${maxContains ?? "undefined"}) {
62
+ ctx.addIssue({ code: "custom", message: "Array contains too many matching items" });
63
+ }
64
+ })`;
65
+ }
66
+ return r;
67
+ };
@@ -0,0 +1,3 @@
1
+ export const parseBoolean = (_schema) => {
2
+ return "z.boolean()";
3
+ };
@@ -0,0 +1,3 @@
1
+ export const parseConst = (schema) => {
2
+ return `z.literal(${JSON.stringify(schema.const)})`;
3
+ };
@@ -0,0 +1,4 @@
1
+ import { anyOrUnknown } from "../utils/anyOrUnknown.js";
2
+ export const parseDefault = (_schema, refs) => {
3
+ return anyOrUnknown(refs);
4
+ };
@@ -0,0 +1,17 @@
1
+ export const parseEnum = (schema) => {
2
+ if (schema.enum.length === 0) {
3
+ return "z.never()";
4
+ }
5
+ else if (schema.enum.length === 1) {
6
+ // union does not work when there is only one element
7
+ return `z.literal(${JSON.stringify(schema.enum[0])})`;
8
+ }
9
+ else if (schema.enum.every((x) => typeof x === "string")) {
10
+ return `z.enum([${schema.enum.map((x) => JSON.stringify(x))}])`;
11
+ }
12
+ else {
13
+ return `z.union([${schema.enum
14
+ .map((x) => `z.literal(${JSON.stringify(x)})`)
15
+ .join(", ")}])`;
16
+ }
17
+ };
@@ -0,0 +1,30 @@
1
+ import { parseSchema } from "./parseSchema.js";
2
+ export const parseIfThenElse = (schema, refs) => {
3
+ const $if = parseSchema(schema.if, { ...refs, path: [...refs.path, "if"] });
4
+ const $then = parseSchema(schema.then, {
5
+ ...refs,
6
+ path: [...refs.path, "then"],
7
+ });
8
+ const $else = parseSchema(schema.else, {
9
+ ...refs,
10
+ path: [...refs.path, "else"],
11
+ });
12
+ let result = `z.union([${$then}, ${$else}]).superRefine((value,ctx) => {
13
+ const result = ${$if}.safeParse(value).success
14
+ ? ${$then}.safeParse(value)
15
+ : ${$else}.safeParse(value);
16
+ if (!result.success) {
17
+ result.error.issues.forEach((issue) => ctx.addIssue({...issue}))
18
+ }
19
+ })`;
20
+ // Store original if/then/else for JSON Schema round-trip
21
+ if (refs.preserveJsonSchemaForRoundTrip) {
22
+ const conditionalMeta = JSON.stringify({
23
+ if: schema.if,
24
+ then: schema.then,
25
+ else: schema.else,
26
+ });
27
+ result += `.meta({ __jsonSchema: { conditional: ${conditionalMeta} } })`;
28
+ }
29
+ return result;
30
+ };
@@ -0,0 +1,6 @@
1
+ import { parseSchema } from "./parseSchema.js";
2
+ export const parseMultipleType = (schema, refs) => {
3
+ return `z.union([${schema.type
4
+ .map((type) => parseSchema({ ...schema, type }, { ...refs, withoutDefaults: true }))
5
+ .join(", ")}])`;
6
+ };
@@ -0,0 +1,8 @@
1
+ import { parseSchema } from "./parseSchema.js";
2
+ import { anyOrUnknown } from "../utils/anyOrUnknown.js";
3
+ export const parseNot = (schema, refs) => {
4
+ return `${anyOrUnknown(refs)}.refine((value) => !${parseSchema(schema.not, {
5
+ ...refs,
6
+ path: [...refs.path, "not"],
7
+ })}.safeParse(value).success, "Invalid input: Should NOT be valid against schema")`;
8
+ };
@@ -0,0 +1,3 @@
1
+ export const parseNull = (_schema) => {
2
+ return "z.null()";
3
+ };
@@ -0,0 +1,8 @@
1
+ import { omit } from "../utils/omit.js";
2
+ import { parseSchema } from "./parseSchema.js";
3
+ /**
4
+ * For compatibility with open api 3.0 nullable
5
+ */
6
+ export const parseNullable = (schema, refs) => {
7
+ return `${parseSchema(omit(schema, "nullable"), refs, true)}.nullable()`;
8
+ };
@@ -0,0 +1,70 @@
1
+ import { withMessage } from "../utils/withMessage.js";
2
+ export const parseNumber = (schema) => {
3
+ let r = "z.number()";
4
+ if (schema.type === "integer") {
5
+ r += withMessage(schema, "type", () => [".int(", ")"]);
6
+ }
7
+ else {
8
+ r += withMessage(schema, "format", ({ value }) => {
9
+ if (value === "int64") {
10
+ return [".int(", ")"];
11
+ }
12
+ });
13
+ }
14
+ r += withMessage(schema, "multipleOf", ({ value, json }) => {
15
+ if (value === 1) {
16
+ if (r.startsWith("z.number().int(")) {
17
+ return;
18
+ }
19
+ return [".int(", ")"];
20
+ }
21
+ return [`.multipleOf(${json}`, ", ", ")"];
22
+ });
23
+ if (typeof schema.minimum === "number") {
24
+ if (schema.exclusiveMinimum === true) {
25
+ r += withMessage(schema, "minimum", ({ json }) => [
26
+ `.gt(${json}`,
27
+ ", ",
28
+ ")",
29
+ ]);
30
+ }
31
+ else {
32
+ r += withMessage(schema, "minimum", ({ json }) => [
33
+ `.gte(${json}`,
34
+ ", ",
35
+ ")",
36
+ ]);
37
+ }
38
+ }
39
+ else if (typeof schema.exclusiveMinimum === "number") {
40
+ r += withMessage(schema, "exclusiveMinimum", ({ json }) => [
41
+ `.gt(${json}`,
42
+ ", ",
43
+ ")",
44
+ ]);
45
+ }
46
+ if (typeof schema.maximum === "number") {
47
+ if (schema.exclusiveMaximum === true) {
48
+ r += withMessage(schema, "maximum", ({ json }) => [
49
+ `.lt(${json}`,
50
+ ", ",
51
+ ")",
52
+ ]);
53
+ }
54
+ else {
55
+ r += withMessage(schema, "maximum", ({ json }) => [
56
+ `.lte(${json}`,
57
+ ", ",
58
+ ")",
59
+ ]);
60
+ }
61
+ }
62
+ else if (typeof schema.exclusiveMaximum === "number") {
63
+ r += withMessage(schema, "exclusiveMaximum", ({ json }) => [
64
+ `.lt(${json}`,
65
+ ", ",
66
+ ")",
67
+ ]);
68
+ }
69
+ return r;
70
+ };