fix: zod enum properties respect the default field#3727
Conversation
|
|
|
Reviewed this WIP draft PR — it has no code changes yet (empty "Initial plan" commit). Submitted a review with root cause analysis and implementation guidance: the bug is in the parser layer where Task list (3/3 completed)
|
🦋 Changeset detectedLatest commit: 73846df The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
TL;DR — The Key changes
Summary | 172 files | 4 commits | base: Enum metadata now flows through the IR
This is a one-line fix repeated in each of the three spec-version parsers. The downstream effect is that Zod output now emits
|
There was a problem hiding this comment.
Important
This PR has no code changes yet — just an empty "Initial plan" commit. Leaving guidance on the fix below.
Root Cause
The bug is in the parser layer, not the zod plugin. The parseEnum function in all three parser versions (2.0.x, 3.0.x, 3.1.x) calls initIrSchema({ schema }) but never calls parseSchemaMeta({ irSchema, schema }). This means default (and other metadata like format, accessScope, minimum/maximum, pattern) is silently dropped for enum schemas.
The zod plugin already handles default correctly — defaultMeta(schema) reads schema.default and applyModifiers() chains .default(...) when it's defined. The value just never makes it into the IR.
Fix
Add parseSchemaMeta({ irSchema, schema }) after initIrSchema in each parser's parseEnum:
packages/shared/src/openApi/3.1.x/parser/schema.ts—parseEnum, after line 947packages/shared/src/openApi/3.0.x/parser/schema.ts—parseEnum, after line 863packages/shared/src/openApi/2.0.x/parser/schema.ts—parseEnum, after line 455
const parseEnum = ({ context, schema, state }) => {
let irSchema = initIrSchema({ schema });
parseSchemaMeta({ irSchema, schema }); // <-- add this
irSchema.type = 'enum';
// ...
};Compare with parseType in the same files — it already calls parseSchemaMeta and serves as a reference for the correct pattern.
Snapshot Updates
Existing specs already exercise this path. After the fix, expect snapshot changes where enum schemas gain .default(...) calls — e.g. zEnumWithNumbers should gain .default(200), and parameterEnum entries in CallWithDefaultParameters should gain their defaults.
Scope Consideration
parseSchemaMeta also propagates format, accessScope, range constraints, etc. Verify whether any of these are problematic on enum IR schemas, or whether the downstream consumers (zod, TypeScript plugin, etc.) gracefully ignore irrelevant fields. If not, a narrower fix that only copies default may be safer.
default field
864120b to
397b63f
Compare
|
Reviewed PR #3727. The core fix (adding Task list (4/4 completed)
|
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #3727 +/- ##
==========================================
- Coverage 40.24% 40.04% -0.21%
==========================================
Files 520 520
Lines 19302 19243 -59
Branches 5726 5720 -6
==========================================
- Hits 7769 7705 -64
- Misses 9337 9342 +5
Partials 2196 2196
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Important
The actual fix (3 added parseSchemaMeta calls) is correct and well-motivated, but it's buried in a large const => function refactor across all three parser files. This makes the diff ~900 lines when the functional change is ~6 lines. These should be separate commits or separate PRs — mixing a syntactic refactor with a behavioral fix makes the change hard to audit and bisect.
The root cause analysis is accurate: parseEnum called initIrSchema (JSDoc + extensions) but never parseSchemaMeta (which copies default, readOnly, format, etc.), so all that metadata was silently dropped. The fix correctly follows the pattern established by parseType, parseOneType, and the 3.1.x composition functions.
Snapshot changes are consistent — enums now emit .default(...), .readonly(), and readonly on TypeScript types where the spec declares them.
Tangential observation (not blocking): in the 3.0.x parser, parseAllOf, parseAnyOf, and parseOneOf still don't call parseSchemaMeta after initIrSchema, unlike their 3.1.x counterparts. That's a pre-existing gap, not something to fix here.
@hey-api/codegen-core
@hey-api/json-schema-ref-parser
@hey-api/nuxt
@hey-api/openapi-ts
@hey-api/shared
@hey-api/spec-types
@hey-api/types
@hey-api/vite-plugin
commit: |

Enum schemas with a
defaultvalue were silently dropping it, so the generated Zod schema never included.default(...). This affected all three OpenAPI spec versions (2.0.x, 3.0.x, 3.1.x).Root cause
parseEnumin each shared parser calledinitIrSchema()but notparseSchemaMeta(). Every other schema type (parseString,parseNumber, etc.) calls both.parseSchemaMetais what copiesdefault,readOnly,format, and similar fields onto the IR schema — so all of them were silently dropped for enums.Changes
packages/shared/src/openApi/{2.0.x,3.0.x,3.1.x}/parser/schema.ts— addparseSchemaMeta({ irSchema, schema })call immediately afterinitIrSchemainside eachparseEnumfunctionBefore / After
Beyond
default, this also fixes enum schemas withreadOnly: true— they now correctly produce.readonly()in Zod andreadonlyon the TypeScript type, matching behavior of all other schema types.