Skip to content

Commit 36ebf4f

Browse files
authored
fix(zod): date format now respects useDates override (#1406)
* fix(zod): date format now respects useDates override * chore(zod): get tests passing, fix coercion issue and incorperate feedback
1 parent 3dd831b commit 36ebf4f

File tree

5 files changed

+73
-13
lines changed

5 files changed

+73
-13
lines changed

packages/zod/src/index.ts

+34-6
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ const COERCEABLE_TYPES = ['string', 'number', 'boolean', 'bigint', 'date'];
7373

7474
export const generateZodValidationSchemaDefinition = (
7575
schema: SchemaObject | undefined,
76+
context: ContextSpecs,
7677
_required: boolean | undefined,
7778
name: string,
7879
strict: boolean,
@@ -118,6 +119,7 @@ export const generateZodValidationSchemaDefinition = (
118119
'array',
119120
generateZodValidationSchemaDefinition(
120121
items,
122+
context,
121123
true,
122124
camel(`${name}-item`),
123125
strict,
@@ -129,13 +131,21 @@ export const generateZodValidationSchemaDefinition = (
129131
break;
130132
}
131133

132-
if (schema.format === 'date') {
134+
if (
135+
context.output.override.useDates &&
136+
(schema.format === 'date' || schema.format === 'date-time')
137+
) {
133138
functions.push(['date', undefined]);
134139
break;
135140
}
136141

137142
functions.push([type as string, undefined]);
138143

144+
if (schema.format === 'date') {
145+
functions.push(['date', undefined]);
146+
break;
147+
}
148+
139149
if (schema.format === 'date-time') {
140150
functions.push(['datetime', undefined]);
141151
break;
@@ -177,6 +187,7 @@ export const generateZodValidationSchemaDefinition = (
177187
schemas.map((schema) =>
178188
generateZodValidationSchemaDefinition(
179189
schema as SchemaObject,
190+
context,
180191
true,
181192
camel(name),
182193
strict,
@@ -193,6 +204,7 @@ export const generateZodValidationSchemaDefinition = (
193204
.map((key) => ({
194205
[key]: generateZodValidationSchemaDefinition(
195206
schema.properties?.[key] as any,
207+
context,
196208
schema.required?.includes(key),
197209
camel(`${name}-${key}`),
198210
strict,
@@ -215,6 +227,7 @@ export const generateZodValidationSchemaDefinition = (
215227
? schema.additionalProperties
216228
: generateZodValidationSchemaDefinition(
217229
schema.additionalProperties as SchemaObject,
230+
context,
218231
true,
219232
name,
220233
strict,
@@ -285,6 +298,7 @@ export type ZodValidationSchemaDefinitionInput = {
285298

286299
export const parseZodValidationSchemaDefinition = (
287300
input: ZodValidationSchemaDefinitionInput,
301+
contex: ContextSpecs,
288302
coerceTypes: boolean | ZodCoerceType[] = false,
289303
preprocessResponse?: GeneratorMutator,
290304
): { zod: string; consts: string } => {
@@ -368,11 +382,15 @@ ${Object.entries(args)
368382
return '.strict()';
369383
}
370384

371-
if (
385+
const shouldCoerceType =
372386
coerceTypes &&
373387
(Array.isArray(coerceTypes)
374388
? coerceTypes.includes(fn as ZodCoerceType)
375-
: COERCEABLE_TYPES.includes(fn))
389+
: COERCEABLE_TYPES.includes(fn));
390+
391+
if (
392+
(fn !== 'date' && shouldCoerceType) ||
393+
(fn === 'date' && shouldCoerceType && contex.output.override.useDates)
376394
) {
377395
return `.coerce.${fn}(${args})`;
378396
}
@@ -474,6 +492,7 @@ const parseBodyAndResponse = ({
474492
return {
475493
input: generateZodValidationSchemaDefinition(
476494
resolvedJsonSchema.items as SchemaObject,
495+
context,
477496
true,
478497
name,
479498
strict,
@@ -485,6 +504,7 @@ const parseBodyAndResponse = ({
485504
return {
486505
input: generateZodValidationSchemaDefinition(
487506
resolvedJsonSchema,
507+
context,
488508
true,
489509
name,
490510
strict,
@@ -549,6 +569,7 @@ const parseParameters = ({
549569

550570
const definition = generateZodValidationSchemaDefinition(
551571
schema,
572+
context,
552573
parameter.required,
553574
camel(`${operationName}-${parameter.in}-${parameter.name}`),
554575
mapStrict[parameter.in as 'path' | 'query' | 'header'] ?? false,
@@ -641,6 +662,8 @@ const generateZodRoute = async (
641662
| PathItemObject
642663
| undefined;
643664

665+
override.useDates;
666+
644667
const parameters = spec?.[verb]?.parameters;
645668
const requestBody = spec?.[verb]?.requestBody;
646669
const response = spec?.[verb]?.responses?.['200'] as
@@ -654,7 +677,7 @@ const generateZodRoute = async (
654677
strict: override.zod.strict.response,
655678
});
656679

657-
const parsedPody = parseBodyAndResponse({
680+
const parsedBody = parseBodyAndResponse({
658681
data: requestBody,
659682
context,
660683
name: camel(`${operationName}-body`),
@@ -670,6 +693,7 @@ const generateZodRoute = async (
670693

671694
const inputParams = parseZodValidationSchemaDefinition(
672695
parsedParameters.params,
696+
context,
673697
override.zod.coerce.param,
674698
);
675699

@@ -681,15 +705,18 @@ const generateZodRoute = async (
681705

682706
const inputQueryParams = parseZodValidationSchemaDefinition(
683707
parsedParameters.queryParams,
708+
context,
684709
override.zod.coerce.query ?? override.coerceTypes,
685710
);
686711
const inputHeaders = parseZodValidationSchemaDefinition(
687712
parsedParameters.headers,
713+
context,
688714
override.zod.coerce.header,
689715
);
690716

691717
const inputBody = parseZodValidationSchemaDefinition(
692-
parsedPody.input,
718+
parsedBody.input,
719+
context,
693720
override.zod.coerce.body,
694721
);
695722

@@ -705,6 +732,7 @@ const generateZodRoute = async (
705732

706733
const inputResponse = parseZodValidationSchemaDefinition(
707734
parsedResponse.input,
735+
context,
708736
override.zod.coerce.response,
709737
preprocessResponse,
710738
);
@@ -739,7 +767,7 @@ const generateZodRoute = async (
739767
...(inputBody.consts ? [inputBody.consts] : []),
740768
...(inputBody.zod
741769
? [
742-
parsedPody.isArray
770+
parsedBody.isArray
743771
? `export const ${operationName}BodyItem = ${inputBody.zod}
744772
export const ${operationName}Body = zod.array(${operationName}BodyItem)`
745773
: `export const ${operationName}Body = ${inputBody.zod}`,

packages/zod/src/zod.test.ts

+33-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
generateZodValidationSchemaDefinition,
66
} from '.';
77
import { SchemaObject } from 'openapi3-ts/oas30';
8+
import { ContextSpecs } from '@orval/core';
89

910
const queryParams: ZodValidationSchemaDefinitionInput = {
1011
functions: [
@@ -46,6 +47,13 @@ describe('parseZodValidationSchemaDefinition', () => {
4647
it('does not emit coerced zod property schemas', () => {
4748
const parseResult = parseZodValidationSchemaDefinition(
4849
queryParams,
50+
{
51+
output: {
52+
override: {
53+
useDates: false,
54+
},
55+
},
56+
} as ContextSpecs,
4957
false,
5058
);
5159

@@ -57,7 +65,17 @@ describe('parseZodValidationSchemaDefinition', () => {
5765

5866
describe('with `override.coerceTypes = true`', () => {
5967
it('emits coerced zod property schemas', () => {
60-
const parseResult = parseZodValidationSchemaDefinition(queryParams, true);
68+
const parseResult = parseZodValidationSchemaDefinition(
69+
queryParams,
70+
{
71+
output: {
72+
override: {
73+
useDates: false,
74+
},
75+
},
76+
} as ContextSpecs,
77+
true,
78+
);
6179

6280
expect(parseResult.zod).toBe(
6381
'zod.object({\n "limit": zod.coerce.number().optional().null(),\n "q": zod.array(zod.coerce.string()).optional()\n})',
@@ -105,6 +123,13 @@ describe('generateZodValidationSchemaDefinition`', () => {
105123
it('required', () => {
106124
const result = generateZodValidationSchemaDefinition(
107125
deepRequiredSchema,
126+
{
127+
output: {
128+
override: {
129+
useDates: false,
130+
},
131+
},
132+
} as ContextSpecs,
108133
true,
109134
'strict',
110135
true,
@@ -149,6 +174,13 @@ describe('generateZodValidationSchemaDefinition`', () => {
149174
it('generates a strict zod schema', () => {
150175
const result = generateZodValidationSchemaDefinition(
151176
objectIntoObjectSchema,
177+
{
178+
output: {
179+
override: {
180+
useDates: false,
181+
},
182+
},
183+
} as ContextSpecs,
152184
true,
153185
'strict',
154186
true,

samples/hono/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
"dependencies": {
1010
"@hono/zod-validator": "^0.2.0",
1111
"hono": "^4.0.4",
12-
"zod": "^3.22.4"
12+
"zod": "^3.23.8"
1313
},
1414
"devDependencies": {
1515
"@cloudflare/workers-types": "^4.20240208.0",

tests/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,6 @@
3939
"react": "^18.3.1",
4040
"swr": "^2.2.4",
4141
"vue": "^3.3.4",
42-
"zod": "^3.21.4"
42+
"zod": "^3.23.8"
4343
}
4444
}

tests/yarn.lock

+4-4
Original file line numberDiff line numberDiff line change
@@ -1411,7 +1411,7 @@ yargs@^17.3.1:
14111411
y18n "^5.0.5"
14121412
yargs-parser "^21.1.1"
14131413

1414-
zod@^3.21.4:
1415-
version "3.21.4"
1416-
resolved "https://registry.yarnpkg.com/zod/-/zod-3.21.4.tgz#10882231d992519f0a10b5dd58a38c9dabbb64db"
1417-
integrity sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==
1414+
zod@^3.23.8:
1415+
version "3.23.8"
1416+
resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
1417+
integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==

0 commit comments

Comments
 (0)