-
-
Notifications
You must be signed in to change notification settings - Fork 272
Fix missing defaults in Zod generation for $ref and anyOf schemas (OpenAPI 3.1.x only) #2946
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
|
🦋 Changeset detectedLatest commit: fcf0e90 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
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.
|
Co-authored-by: mrlubos <12529395+mrlubos@users.noreply.github.com>
Co-authored-by: mrlubos <12529395+mrlubos@users.noreply.github.com>
|
@copilot this fix should be applied only to OpenAPI 3.1. In prior versions, the |
…to 3.1.x Co-authored-by: mrlubos <12529395+mrlubos@users.noreply.github.com>
You're correct. I've reverted the changes to OpenAPI 2.0.x and 3.0.x parsers in commit ce08e9b. The fix now only applies to OpenAPI 3.1.x, which is the first version that allows combining Changes:
All tests pass (784 main + 78 Zod tests). |
mrlubos
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well done!
|
@copilot run |
Co-authored-by: mrlubos <12529395+mrlubos@users.noreply.github.com>
|
@copilot I don't think you updated everything because tests wouldn't be failing. Make sure everything has been updated, including Valibot, with |
Co-authored-by: mrlubos <12529395+mrlubos@users.noreply.github.com>
Updated all snapshots including Valibot in commit fcf0e90. The Valibot snapshots now show defaults being applied to $ref schemas with the correct syntax: All test suites pass:
|
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2946 +/- ##
==========================================
+ Coverage 28.27% 28.52% +0.24%
==========================================
Files 389 394 +5
Lines 35223 35171 -52
Branches 1933 1934 +1
==========================================
+ Hits 9959 10031 +72
+ Misses 25237 25113 -124
Partials 27 27
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:
|
commit: |
Fix Missing Defaults in Zod generation for
$refandanyOfSchemas (OpenAPI 3.1.x Only)Problem
When generating Zod schemas, default values are lost when properties use
$reforanyOf.Root Cause
The OpenAPI parser's
parseSchemaMetafunction (which extractsdefaultvalues) is only called for schemas with atypeproperty. It's not called in composition functions (parseRef,parseAnyOf,parseAllOf,parseOneOf).OpenAPI Specification Constraint
$refkeyword must appear standalone and cannot be combined with other keywords likedefault. This restriction was lifted in OpenAPI 3.1.Therefore, this fix only applies to OpenAPI 3.1.x.
Solution
Added
parseSchemaMeta({ irSchema, schema })calls afterinitIrSchemain all composition functions in the OpenAPI 3.1.x parser only. This ensures that metadata likedefaultvalues are preserved for all schema types in OpenAPI 3.1.x.Implementation
parseSchemaMetacall to 3.1.xparseReffunction to preserve defaults on$refschemasparseSchemaMetacall to 3.1.xparseAnyOffunction to preserve defaults onanyOfschemasparseSchemaMetacall to 3.1.xparseAllOfandparseOneOffunctions for consistencyChanges Made
Parser fix (1 file):
packages/openapi-ts/src/openApi/3.1.x/parser/schema.ts(4 functions: parseRef, parseAnyOf, parseAllOf, parseOneOf)Tests:
specs/3.1.x/defaults-with-ref-and-anyof.jsonspecs/3.0.x/defaults-with-ref-and-anyof.jsonpackages/openapi-ts-tests/zod/v4/test/3.1.x.test.tspackages/openapi-ts-tests/zod/v4/test/3.0.x.test.tsValidation Results
Verification Examples (OpenAPI 3.1.x Only)
All the cases from the issue now correctly generate
.default()calls:Zod:
Valibot:
Security Summary
No security vulnerabilities were found during CodeQL analysis.
Original prompt
This section details on the original issue you should resolve
<issue_title>Missing defaults in Zod generation for
$refandanyOfschemas</issue_title><issue_description>### Description
When generating Zod schemas, defaults are lost when the property uses
$reforanyOf.Reproduction
See below attached OpenAPI spec for minimum reproducible example.
Issue 1:
$refwith default valueOpenAPI Schema:
{ "refWithPrimitiveDefault": { "$ref": "#/components/schemas/AudioFormat", "default": "pcm_16bit_44.1khz" } }Expected Zod:
Actual Zod:
This also affects
$refwith object defaults:{ "refWithObjectDefault": { "$ref": "#/components/schemas/NestedConfig", "default": { "model": "gpt-4", "temperature": 1 } } }Issue 2:
anyOfwith default valueOpenAPI Schema:
{ "anyOfWithNullDefault": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "default": null } }Expected Zod:
Actual Zod:
This also affects
anyOfcontaining$ref:{ "anyOfWithRefAndNullDefault": { "anyOf": [ { "$ref": "#/components/schemas/Language" }, { "type": "null" } ], "default": null } }Working Case
Primitive types without
$reforanyOfwork correctly:{ "primitiveDefault": { "type": "number", "default": 42 } }Generates correctly:
OpenAPI specification
{ "openapi": "3.1.0", "info": { "title": "Default Bug Repro", "version": "1.0.0" }, "paths": {}, "components": { "schemas": { "AudioFormat": { "type": "string", "enum": ["pcm_16bit_44.1khz", "pcm_16bit_24khz"] }, "Language": { "type": "string", "enum": ["en", "es", "fr"] }, "NestedConfig": { "type": "object", "properties": { "model": { "type": "string", "default": "gpt-4" }, "temperature": { "type": "number", "default": 1 } }, "required": ["model", "temperature"] }, "TestSchema": { "type": "object", "properties": { "primitiveDefault": { "type": "number", "default": 42 }, "refWithPrimitiveDefault": { "$ref": "#/components/schemas/AudioFormat", "default": "pcm_16bit_44.1khz" }, "refWithObjectDefault": { "$ref": "#/components/schemas/NestedConfig", "default": { "model": "gpt-4", "temperature": 1 } }, "anyOfWithNullDefault": { "anyOf": [ { "type": "number" }, { "type": "null" } ], "default": null }, "anyOfWithRefAndNullDefault": { "anyOf": [ { "$ref": "#/components/schemas/Language" }, { "type": "null" } ], "default": null }, "optionalAnyOfWithDefault": { "anyOf": [ { "type": "string" }, { "type": "null" } ], "default": null } }, "required": [ "primitiveDefault", "refWithPrimitiveDefault", "refWithObjectDefault", "anyOfWithNullDefault", "anyOfWithRefAndNullDefault" ] } } } }This generates the following incorrect
zod.gen.ts:Expected zod schema: