Skip to content

feat(openapi): multiple success response support#490

Merged
dinwwwh merged 6 commits into
mainfrom
feat/openapi/multiple-success-status
May 14, 2025
Merged

feat(openapi): multiple success response support#490
dinwwwh merged 6 commits into
mainfrom
feat/openapi/multiple-success-status

Conversation

@dinwwwh
Copy link
Copy Markdown
Member

@dinwwwh dinwwwh commented May 13, 2025

Summary by CodeRabbit

  • New Features

    • Added support for handling multiple success status codes and complex response structures in OpenAPI generation when using detailed output mode.
    • Introduced a utility function to flatten nested union schemas for better schema processing.
  • Bug Fixes

    • Improved validation and error messages for invalid or duplicate status codes in detailed output structures.
  • Documentation

    • Enhanced documentation for input/output structure options and route configuration with clearer explanations and richer examples.
  • Tests

    • Expanded test coverage for input/output merging, custom status codes, headers, error scenarios, and union schema expansion in encoding/decoding and OpenAPI generation.
  • Refactor

    • Improved internal validation logic for detailed output structures and encapsulated it in a dedicated method.

@vercel
Copy link
Copy Markdown

vercel Bot commented May 13, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
orpc ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 14, 2025 8:43am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2025

Walkthrough

The 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

File(s) Change Summary
apps/content/docs/openapi/input-output-structure.md Revised documentation for inputStructure and outputStructure for clarity, structured sections, removal of explicit type aliases, and richer examples, especially for detailed output with multiple statuses.
packages/contract/src/route.ts Improved documentation for successStatus and outputStructure in the Route interface, specifying valid status code ranges and detailed structure expectations.
packages/openapi-client/src/adapters/standard/openapi-link-codec.test.ts Modified test to assert the entire decoded output object (including status, headers, and body) instead of just headers, increasing test coverage for detailed output structure.
packages/openapi-client/src/adapters/standard/openapi-link-codec.ts Updated the decode method to include the HTTP status code in the returned object for non-compact output structures.
packages/openapi/src/adapters/standard/openapi-codec.test.ts Expanded and restructured tests for .decode and .encode methods to cover parameter merging, query property handling, empty/custom output, custom status codes, headers, and invalid output formats. Removed one invalid output test, added parameterized tests for error cases.
packages/openapi/src/adapters/standard/openapi-codec.ts Replaced previous output validation with a new private method #isDetailedOutput for stricter type checking and clearer error messages. Adjusted response construction to use provided status and headers or defaults.
packages/openapi/src/openapi-generator.test.ts Added and restructured tests for multiple success statuses, duplicate/invalid status codes, and OpenAPI generation without base docs. Moved some tests into a new describe block. No core logic changes.
packages/openapi/src/openapi-generator.ts Enhanced #successResponse to support union schemas for detailed output, validate status codes, ensure uniqueness, and improve error reporting. Updated imports to support new logic.
packages/openapi/src/schema-utils.test.ts Added tests for new expandUnionSchema function, verifying flattening of union schemas and handling of various schema constructs.
packages/openapi/src/schema-utils.ts Added exported expandUnionSchema function to flatten union schemas (anyOf/oneOf) into arrays of base schemas, or wrap non-unions as single-element arrays.

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
Loading
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
Loading

Possibly related PRs

  • unnoq/orpc#319: Focuses on fixes and improvements in the #successResponse method of the OpenAPIGenerator class, closely related to the enhancements for handling multiple success statuses and schema validation in this PR.

Poem

🐇
In fields of schema, unions bloom,
Status codes now find their room.
Headers, bodies, all in line,
OpenAPI docs refined.
Tests abound, and code is neat—
This change makes structure quite complete!
🌱

Tip

⚡️ Faster reviews with caching
  • CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.

Enjoy the performance boost—your workflow just got faster.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3b9aa50 and c51c003.

📒 Files selected for processing (2)
  • packages/openapi/src/openapi-generator.test.ts (3 hunks)
  • packages/openapi/src/openapi-generator.ts (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/openapi/src/openapi-generator.test.ts
  • packages/openapi/src/openapi-generator.ts
⏰ Context from checks skipped due to timeout of 90000ms (2)
  • GitHub Check: publish-commit
  • GitHub Check: lint
✨ Finishing Touches
  • 📝 Generate Docstrings

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need 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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented May 13, 2025

More templates

@orpc/arktype

npm i https://pkg.pr.new/@orpc/arktype@490

@orpc/client

npm i https://pkg.pr.new/@orpc/client@490

@orpc/contract

npm i https://pkg.pr.new/@orpc/contract@490

@orpc/nest

npm i https://pkg.pr.new/@orpc/nest@490

@orpc/openapi

npm i https://pkg.pr.new/@orpc/openapi@490

@orpc/openapi-client

npm i https://pkg.pr.new/@orpc/openapi-client@490

@orpc/react

npm i https://pkg.pr.new/@orpc/react@490

@orpc/react-query

npm i https://pkg.pr.new/@orpc/react-query@490

@orpc/shared

npm i https://pkg.pr.new/@orpc/shared@490

@orpc/server

npm i https://pkg.pr.new/@orpc/server@490

@orpc/solid-query

npm i https://pkg.pr.new/@orpc/solid-query@490

@orpc/standard-server

npm i https://pkg.pr.new/@orpc/standard-server@490

@orpc/standard-server-fetch

npm i https://pkg.pr.new/@orpc/standard-server-fetch@490

@orpc/standard-server-node

npm i https://pkg.pr.new/@orpc/standard-server-node@490

@orpc/standard-server-peer

npm i https://pkg.pr.new/@orpc/standard-server-peer@490

@orpc/svelte-query

npm i https://pkg.pr.new/@orpc/svelte-query@490

@orpc/valibot

npm i https://pkg.pr.new/@orpc/valibot@490

@orpc/vue-colada

npm i https://pkg.pr.new/@orpc/vue-colada@490

@orpc/vue-query

npm i https://pkg.pr.new/@orpc/vue-query@490

@orpc/zod

npm i https://pkg.pr.new/@orpc/zod@490

commit: c51c003

@dinwwwh dinwwwh force-pushed the feat/openapi/multiple-success-status branch from 088961e to e1a2ab2 Compare May 13, 2025 03:23
@codecov
Copy link
Copy Markdown

codecov Bot commented May 13, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

📢 Thoughts on this report? Let us know!

@dinwwwh dinwwwh force-pushed the feat/openapi/multiple-success-status branch from e1a2ab2 to a2eb212 Compare May 13, 2025 03:56
@dinwwwh dinwwwh marked this pull request as ready for review May 13, 2025 08:43
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?: number is 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 in mergeRoute.

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 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)

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d888fab and 3b9aa50.

📒 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 normalization

The expandUnionSchema function provides a clean way to flatten union schemas into an array of base schemas. The implementation is efficient, using recursive flattening with flatMap to handle nested unions. The JSDoc comments are clear and explain the purpose well.

The function correctly:

  • Handles both anyOf and oneOf union 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 structure

The test has been enhanced to properly verify all properties of the detailed output structure, including the newly added status property. This provides better coverage and aligns with the implementation changes in openapi-link-codec.ts.

packages/openapi-client/src/adapters/standard/openapi-link-codec.ts (1)

243-243: Added status code to detailed output structure

Adding 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 expandUnionSchema

The tests for the new expandUnionSchema function are thorough and cover all important scenarios:

  • Simple primitives and objects
  • Basic union schemas with anyOf and oneOf
  • 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 here

The “detailed” mode doc now explicitly enumerates status, headers, body, but the runtime guard in openapi-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:

  1. Union schema expansions for multiple responses
  2. Proper status code documentation
  3. Different body schemas for each status
  4. 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:

  1. How to define a union schema for multiple response types
  2. The required structure for each response variant
  3. How to add descriptions for status codes
  4. 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.

Comment thread packages/openapi/src/adapters/standard/openapi-codec.ts
Comment thread packages/openapi/src/adapters/standard/openapi-codec.ts
Comment thread packages/openapi/src/openapi-generator.ts
Comment thread packages/openapi/src/openapi-generator.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant