Skip to content

Commit 70ea7a5

Browse files
the-ultclaude
andcommitted
docs(zod): document override.zod.version targeting and per-op/tag scoping
Add a "Zod version" section (Zod 4 default baseline, override.zod.version 3 | 4 | 'auto', and the auto->Zod 4 fallback) plus a per-operation/tag scoping section to the Zod guide, and a `### version` subsection to the output reference. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent dda8dc1 commit 70ea7a5

2 files changed

Lines changed: 93 additions & 0 deletions

File tree

docs/content/docs/guides/zod.mdx

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,84 @@ export const createPetsBody = zod.object({
3838
});
3939
```
4040

41+
## Zod version
42+
43+
Orval generates **Zod 4** output by default (`z.strictObject`, `z.looseObject`, `z.iso.datetime()`, `.meta()`, …). Projects still on Zod 3 are fully supported.
44+
45+
With the default (`'auto'`), Orval infers the target from the `zod` version resolved in your project's `package.json`. When no `zod` package can be detected — for example in a fresh or partially-installed workspace — it falls back to **Zod 4**.
46+
47+
To make generation deterministic, pin the target with `override.zod.version`:
48+
49+
```ts title="orval.config.ts"
50+
import { defineConfig } from 'orval';
51+
52+
export default defineConfig({
53+
petstore: {
54+
output: {
55+
client: 'zod',
56+
target: './src/api/schemas',
57+
override: {
58+
zod: {
59+
version: 4, // 3 | 4 | 'auto'
60+
},
61+
},
62+
},
63+
input: {
64+
target: './petstore.yaml',
65+
},
66+
},
67+
});
68+
```
69+
70+
| Value | Output |
71+
| -------- | -------------------------------------------------------------------------------- |
72+
| `4` | Always emit Zod 4 syntax, regardless of the installed `zod` version. |
73+
| `3` | Always emit Zod 3-compatible syntax, regardless of the installed `zod` version. |
74+
| `'auto'` | (default) Infer from the resolved `zod` version; fall back to Zod 4 when none is detected. |
75+
76+
Pinning the version keeps output stable: the same spec produces the same schemas on every machine and in CI, independent of which `zod` version happens to be installed.
77+
78+
## Scoping options per operation or tag
79+
80+
Most `override.zod` settings can be applied to part of your API instead of globally, via `override.operations[operationId].zod` (a single operation) or `override.tags[tagName].zod` (every operation sharing a tag):
81+
82+
```ts title="orval.config.ts"
83+
export default defineConfig({
84+
petstore: {
85+
output: {
86+
client: 'zod',
87+
override: {
88+
zod: {
89+
strict: { response: true }, // applies everywhere
90+
},
91+
operations: {
92+
listPets: {
93+
zod: {
94+
coerce: { query: ['number'] }, // only this operation
95+
},
96+
},
97+
},
98+
tags: {
99+
admin: {
100+
zod: {
101+
strict: { body: true }, // every operation tagged "admin"
102+
},
103+
},
104+
},
105+
},
106+
},
107+
},
108+
});
109+
```
110+
111+
Per-operation and per-tag overrides accept the settings that apply to an individual schema: `strict`, `generate`, `coerce`, `preprocess`, `params`, and `useBrandedTypes`.
112+
113+
Output-wide settings — `version`, `dateTimeOptions`, `timeOptions`, `generateEachHttpStatus`, `generateReusableSchemas`, and `generateMeta` — only make sense for the whole output and must stay on `override.zod`. If you place one on an operation or tag it is ignored — the value from `override.zod` still applies — and Orval prints a build warning:
114+
115+
```
116+
⚠️ override.operations.listPets.zod only supports strict, generate, coerce, preprocess, params, and useBrandedTypes. Ignoring unsupported field: zod.version.
117+
```
118+
41119
## Usage
42120

43121
### Parsing Data

docs/content/docs/reference/configuration/output.mdx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1362,6 +1362,7 @@ export default defineConfig({
13621362
output: {
13631363
override: {
13641364
zod: {
1365+
version: 4,
13651366
strict: {
13661367
response: true,
13671368
query: true,
@@ -1389,6 +1390,20 @@ export default defineConfig({
13891390
});
13901391
```
13911392

1393+
### version
1394+
1395+
**Type:** `3 | 4 | 'auto'` — defaults to `'auto'`
1396+
1397+
Pin the Zod major version that generated output targets, so generation is deterministic instead of inferred from the installed `zod` package.
1398+
1399+
| Value | Output |
1400+
| -------- | ------------------------------------------------------------------------------- |
1401+
| `4` | Always emit Zod 4 syntax (`z.strictObject`, `z.iso.datetime()`, `.meta()`, …). |
1402+
| `3` | Always emit Zod 3-compatible syntax (`.strict()`, `z.string().datetime()`, …). |
1403+
| `'auto'` | Infer from the resolved `zod` version; fall back to Zod 4 when none is detected. |
1404+
1405+
Unlike most `override.zod` options, `version` is output-wide and cannot be set per operation or tag. See the [Zod guide](/docs/guides/zod#zod-version) for details.
1406+
13921407
### strict
13931408

13941409
**Type:** `Object`

0 commit comments

Comments
 (0)