Skip to content

Commit a39a1cd

Browse files
authored
Merge pull request #75 from JanTvrdik/number-min-max
Fix exclusive minimum and maximum checks for numbers
2 parents a8e2680 + 9e2fb52 commit a39a1cd

File tree

2 files changed

+97
-2
lines changed

2 files changed

+97
-2
lines changed

spec/types/number.spec.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,68 @@ describe('number', () => {
1919
Literal: { type: 'number', enum: [42] },
2020
});
2121
});
22+
23+
it('supports minimum in open api 3.0.0', () => {
24+
expectSchema([registerSchema('SimpleInteger', z.number().int().gte(0))], {
25+
SimpleInteger: { type: 'integer', minimum: 0 },
26+
});
27+
});
28+
29+
it('supports exclusive minimum in open api 3.0.0', () => {
30+
expectSchema([registerSchema('SimpleInteger', z.number().int().gt(0))], {
31+
SimpleInteger: { type: 'integer', minimum: 0, exclusiveMinimum: true },
32+
});
33+
});
34+
35+
it('supports maximum in open api 3.0.0', () => {
36+
expectSchema([registerSchema('SimpleInteger', z.number().int().lte(0))], {
37+
SimpleInteger: { type: 'integer', maximum: 0 },
38+
});
39+
});
40+
41+
it('supports exclusive maximum in open api 3.0.0', () => {
42+
expectSchema([registerSchema('SimpleInteger', z.number().int().lt(0))], {
43+
SimpleInteger: { type: 'integer', maximum: 0, exclusiveMaximum: true },
44+
});
45+
});
46+
47+
it('supports minimum in open api 3.1.0', () => {
48+
expectSchema(
49+
[registerSchema('SimpleInteger', z.number().int().gte(0))],
50+
{
51+
SimpleInteger: { type: 'integer', minimum: 0 },
52+
},
53+
'3.1.0'
54+
);
55+
});
56+
57+
it('supports exclusive minimum in open api 3.1.0', () => {
58+
expectSchema(
59+
[registerSchema('SimpleInteger', z.number().int().gt(0))],
60+
{
61+
SimpleInteger: { type: 'integer', exclusiveMinimum: 0 },
62+
},
63+
'3.1.0'
64+
);
65+
});
66+
67+
it('supports maximum in open api 3.1.0', () => {
68+
expectSchema(
69+
[registerSchema('SimpleInteger', z.number().int().lte(0))],
70+
{
71+
SimpleInteger: { type: 'integer', maximum: 0 },
72+
},
73+
'3.1.0'
74+
);
75+
});
76+
77+
it('supports exclusive maximum in open api 3.1.0', () => {
78+
expectSchema(
79+
[registerSchema('SimpleInteger', z.number().int().lt(0))],
80+
{
81+
SimpleInteger: { type: 'integer', exclusiveMaximum: 0 },
82+
},
83+
'3.1.0'
84+
);
85+
});
2286
});

src/openapi-generator.ts

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
} from 'openapi3-ts';
1414
import type {
1515
AnyZodObject,
16+
ZodNumberDef,
1617
ZodObject,
1718
ZodRawShape,
1819
ZodSchema,
@@ -662,6 +663,37 @@ export class OpenAPIGenerator {
662663
};
663664
}
664665

666+
private getNumberChecks(
667+
checks: ZodNumberDef['checks']
668+
): Pick<
669+
SchemaObject,
670+
'minimum' | 'exclusiveMinimum' | 'maximum' | 'exclusiveMaximum'
671+
> {
672+
return Object.assign(
673+
{},
674+
...checks.map<SchemaObject>(check => {
675+
switch (check.kind) {
676+
case 'min':
677+
return check.inclusive
678+
? { minimum: check.value }
679+
: this.openApiVersionSatisfies(this.openAPIVersion, '3.1.0')
680+
? { exclusiveMinimum: check.value }
681+
: { minimum: check.value, exclusiveMinimum: true };
682+
683+
case 'max':
684+
return check.inclusive
685+
? { maximum: check.value }
686+
: this.openApiVersionSatisfies(this.openAPIVersion, '3.1.0')
687+
? { exclusiveMaximum: check.value }
688+
: { maximum: check.value, exclusiveMaximum: true };
689+
690+
default:
691+
return {};
692+
}
693+
})
694+
);
695+
}
696+
665697
private constructReferencedOpenAPISchema<T>(
666698
zodSchema: ZodSchema<T>,
667699
innerSchema: ZodSchema<T>,
@@ -709,8 +741,7 @@ export class OpenAPIGenerator {
709741
zodSchema.isInt ? 'integer' : 'number',
710742
isNullable
711743
),
712-
minimum: zodSchema.minValue ?? undefined,
713-
maximum: zodSchema.maxValue ?? undefined,
744+
...this.getNumberChecks(zodSchema._def.checks),
714745
default: defaultValue,
715746
};
716747
}

0 commit comments

Comments
 (0)