feat(openapi): multiple success response support#490
Conversation
|
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThe changes introduce enhanced support for "detailed" output structures in OpenAPI generation and response handling. They add union schema expansion, stricter validation of status codes, and improved documentation. Tests are updated and expanded to cover new scenarios, including multiple success statuses, invalid output formats, and schema normalization utilities. Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant OpenAPIClient
participant Codec
participant Server
Client->>OpenAPIClient: Make API request
OpenAPIClient->>Codec: decode(response, outputStructure)
Codec->>Codec: If outputStructure == 'detailed', include status, headers, body
Codec-->>OpenAPIClient: { status, headers, body }
OpenAPIClient-->>Client: Return full detailed output
sequenceDiagram
participant Dev
participant OpenAPIGenerator
Dev->>OpenAPIGenerator: Define route with detailed output (union of responses)
OpenAPIGenerator->>OpenAPIGenerator: expandUnionSchema(outputSchema)
OpenAPIGenerator->>OpenAPIGenerator: Validate each schema for status, headers, body
OpenAPIGenerator-->>Dev: Generate OpenAPI spec with multiple success responses
Possibly related PRs
Poem
Tip ⚡️ Faster reviews with caching
Enjoy the performance boost—your workflow just got faster. 📜 Recent review detailsConfiguration used: CodeRabbit UI 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
⏰ Context from checks skipped due to timeout of 90000ms (2)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
More templates
@orpc/arktype
@orpc/client
@orpc/contract
@orpc/nest
@orpc/openapi
@orpc/openapi-client
@orpc/react
@orpc/react-query
@orpc/shared
@orpc/server
@orpc/solid-query
@orpc/standard-server
@orpc/standard-server-fetch
@orpc/standard-server-node
@orpc/standard-server-peer
@orpc/svelte-query
@orpc/valibot
@orpc/vue-colada
@orpc/vue-query
@orpc/zod
commit: |
088961e to
e1a2ab2
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅ 📢 Thoughts on this report? Let us know! |
e1a2ab2 to
a2eb212
Compare
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (3)
packages/contract/src/route.ts (1)
55-63: Comment/documentation says “200-399”, but the type still allows every number
successStatus?: numberis not constrained at type-level or runtime, yet the docstring claims the value must be 200-399.
Down-stream code (e.g.#isDetailedOutput,isORPCErrorStatus) does enforce this at runtime, so consider tightening the contract here too to avoid silent misuse – e.g. a branded type or a validation utility inmergeRoute.apps/content/docs/openapi/input-output-structure.md (2)
31-37: Fix formatting in the detailed mode list.The list items after "Provide an object whose fields correspond to each part of the request:" have incorrect formatting with a space between the dash and the backtick.
-Provide an object whose fields correspond to each part of the request: - -- `params`: Path parameters (`Record<string, string> | undefined`) -- `query`: Query string data (`any`) -- `headers`: Headers (`Record<string, string | string[] | undefined>`) -- `body`: Body data (`any`) +Provide an object whose fields correspond to each part of the request: + +- `params`: Path parameters (`Record<string, string> | undefined`) +- `query`: Query string data (`any`) +- `headers`: Headers (`Record<string, string | string[] | undefined>`) +- `body`: Body data (`any`)🧰 Tools
🪛 LanguageTool
[uncategorized] ~33-~33: Loose punctuation mark.
Context: ...to each part of the request: -params: Path parameters (`Record<string, string...(UNLIKELY_OPENING_PUNCTUATION)
69-74: Fix formatting in the detailed mode output properties list.The list items have incorrect formatting with a space between the dash and the backtick.
-Returns an object with these optional properties: - -- `status`: The response status (must be in 200-399 range) if not set fallback to `successStatus`. -- `headers`: Custom headers to merge with the response headers (`Record<string, string | string[] | undefined>`). -- `body`: The response body. +Returns an object with these optional properties: + +- `status`: The response status (must be in 200-399 range) if not set fallback to `successStatus`. +- `headers`: Custom headers to merge with the response headers (`Record<string, string | string[] | undefined>`). +- `body`: The response body.🧰 Tools
🪛 LanguageTool
[uncategorized] ~71-~71: Loose punctuation mark.
Context: ...h these optional properties: -status: The response status (must be in 200-399...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~72-~72: Loose punctuation mark.
Context: ...fallback tosuccessStatus. -headers: Custom headers to merge with the respon...(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~73-~73: Loose punctuation mark.
Context: ...ring | string[] | undefined>). -body`: The response body. ```ts const detaile...(UNLIKELY_OPENING_PUNCTUATION)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (10)
apps/content/docs/openapi/input-output-structure.md(5 hunks)packages/contract/src/route.ts(2 hunks)packages/openapi-client/src/adapters/standard/openapi-link-codec.test.ts(1 hunks)packages/openapi-client/src/adapters/standard/openapi-link-codec.ts(1 hunks)packages/openapi/src/adapters/standard/openapi-codec.test.ts(5 hunks)packages/openapi/src/adapters/standard/openapi-codec.ts(3 hunks)packages/openapi/src/openapi-generator.test.ts(2 hunks)packages/openapi/src/openapi-generator.ts(2 hunks)packages/openapi/src/schema-utils.test.ts(2 hunks)packages/openapi/src/schema-utils.ts(1 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (4)
packages/openapi/src/schema-utils.test.ts (1)
packages/openapi/src/schema-utils.ts (1)
expandUnionSchema(145-157)
packages/openapi-client/src/adapters/standard/openapi-link-codec.test.ts (2)
packages/openapi/src/adapters/standard/openapi-codec.ts (1)
output(98-112)packages/openapi-client/src/adapters/standard/openapi-serializer.ts (1)
deserialize(71-90)
packages/openapi/src/openapi-generator.ts (4)
packages/openapi/src/openapi-utils.ts (2)
toOpenAPIContent(25-51)toOpenAPISchema(143-149)packages/openapi/src/schema-utils.ts (3)
applySchemaOptionality(127-138)expandUnionSchema(145-157)isObjectSchema(15-17)packages/shared/src/json.ts (1)
stringifyJSON(9-12)packages/client/src/error.ts (1)
isORPCErrorStatus(148-150)
packages/openapi/src/adapters/standard/openapi-codec.ts (4)
packages/shared/src/json.ts (1)
stringifyJSON(9-12)packages/standard-server/src/types.ts (1)
StandardHeaders(1-3)packages/shared/src/object.ts (1)
isObject(31-39)packages/client/src/error.ts (1)
isORPCErrorStatus(148-150)
🪛 LanguageTool
apps/content/docs/openapi/input-output-structure.md
[uncategorized] ~33-~33: Loose punctuation mark.
Context: ...to each part of the request: - params: Path parameters (`Record<string, string...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~71-~71: Loose punctuation mark.
Context: ...h these optional properties: - status: The response status (must be in 200-399...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~72-~72: Loose punctuation mark.
Context: ...fallback to successStatus. - headers: Custom headers to merge with the respon...
(UNLIKELY_OPENING_PUNCTUATION)
[uncategorized] ~73-~73: Loose punctuation mark.
Context: ...ring | string[] | undefined>). - body`: The response body. ```ts const detaile...
(UNLIKELY_OPENING_PUNCTUATION)
🔇 Additional comments (16)
packages/openapi/src/schema-utils.ts (1)
140-157: Well-designed utility function for union schema normalizationThe
expandUnionSchemafunction provides a clean way to flatten union schemas into an array of base schemas. The implementation is efficient, using recursive flattening withflatMapto handle nested unions. The JSDoc comments are clear and explain the purpose well.The function correctly:
- Handles both
anyOfandoneOfunion types- Only processes schemas where the union keyword is the only logical keyword
- Recursively processes nested unions
- Returns single-element arrays for non-union schemas
packages/openapi-client/src/adapters/standard/openapi-link-codec.test.ts (1)
337-341: Improved test assertions for detailed output structureThe test has been enhanced to properly verify all properties of the detailed output structure, including the newly added
statusproperty. This provides better coverage and aligns with the implementation changes inopenapi-link-codec.ts.packages/openapi-client/src/adapters/standard/openapi-link-codec.ts (1)
243-243: Added status code to detailed output structureAdding the HTTP response status code to the detailed output structure is a good enhancement. This provides more complete information about the response and aligns with the broader improvements to support multiple success responses.
packages/openapi/src/schema-utils.test.ts (1)
206-216: Comprehensive test coverage for expandUnionSchemaThe tests for the new
expandUnionSchemafunction are thorough and cover all important scenarios:
- Simple primitives and objects
- Basic union schemas with
anyOfandoneOf- Unions with additional properties like descriptions
- Nested union schemas
- Non-union schemas with logical keywords
This provides good confidence in the function's correctness and will help maintain it as the codebase evolves.
packages/contract/src/route.ts (1)
101-109: Docstring & runtime guard mismatch – “no extra keys” not stated hereThe “detailed” mode doc now explicitly enumerates
status,headers,body, but the runtime guard inopenapi-codec.ts(see comment there) still permits arbitrary extra keys. Keep comments and validation in sync so that users do not rely on accidental extra properties.packages/openapi/src/openapi-generator.test.ts (5)
574-620: Great addition of tests for multiple status code support in detailed output structure.The test case thoroughly validates that the OpenAPI generator correctly handles multiple success response variants with different status codes, bodies, and headers in detailed output mode. The test checks:
- Union schema expansions for multiple responses
- Proper status code documentation
- Different body schemas for each status
- Response-specific headers
621-628: Good validation test for duplicate status codes.This test ensures the generator properly rejects response schemas with duplicate status codes, which would create ambiguity in the OpenAPI specification.
629-660: Comprehensive validation tests for invalid status codes.These tests effectively verify that the generator enforces proper status code validation rules, covering:
- Non-literal status codes (like
z.number())- Non-numeric status codes (string literals)
- Non-integer status codes (decimal values)
- Out-of-range values (400+, which aren't success codes)
This ensures robust error handling for detailed output structures.
842-854: Good addition of default generation test.This test verifies that the OpenAPI generator works with minimal configuration, correctly falling back to default values for title and version when no base documentation is provided.
856-875: Good refactoring of error handling test.Moving this test into the describe block improves test organization while maintaining the original test behavior. The test ensures that unknown errors from schema converters propagate correctly.
apps/content/docs/openapi/input-output-structure.md (1)
85-109: Excellent example of multiple status responses.The addition of this example clearly demonstrates the new capability of handling multiple status codes in detailed output mode. It shows:
- How to define a union schema for multiple response types
- The required structure for each response variant
- How to add descriptions for status codes
- How to conditionally return different statuses in your handler
This will be very helpful for users implementing this pattern.
packages/openapi/src/adapters/standard/openapi-codec.test.ts (5)
59-76: Good test for parameters and body merging.This test verifies that when using the compact structure, route parameters and deserialized body content are correctly merged into a single input object. This is important for ensuring the codec properly combines data from different sources.
147-165: Good test for query manipulation.This test ensures the query property can be set and accessed properly in the detailed structure mode, validating that the internal data structure correctly handles property assignments.
217-228: Good edge case test for empty output.This test verifies that the encoder properly handles an empty output object in detailed mode, correctly falling back to default status and serializing an undefined body. This ensures robustness when handlers return minimal responses.
230-252: Good test for custom status codes.This test verifies that the encoder properly uses custom status codes from the detailed output, preserving them in the final response. This is critical for supporting the multiple success response feature.
254-263: Comprehensive parameterized test for invalid outputs.This test efficiently verifies that the encoder rejects various invalid output formats:
- Non-object values
- Invalid status types (string instead of number)
- Out-of-range status codes (400)
- Non-integer status codes (200.1)
- Invalid headers format
Using parameterized tests is an excellent approach for testing multiple error cases concisely.
Summary by CodeRabbit
New Features
Bug Fixes
Documentation
Tests
Refactor