Skip to content

fix(sdk): preserve optional TypeScript request bodies - #5383

Merged
tothandras merged 2 commits into
mainfrom
feat/sdk-optional-request-bodies
Oct 27, 2026
Merged

tothandras merged 2 commits into
mainfrom
feat/sdk-optional-request-bodies

Conversation

@turip

@turip turip commented Oct 27, 2026 •

Copy link
Copy Markdown
Member

Overview

The TypeScript SDK requires bodies that TypeSpec declares optional, and strict request validation rejects calls that omit them. Preserve body optionality in request types and facade arguments, and validate optional bodies only when present. Required bodies retain their existing validation.

Regenerated SDK output corrects entitlement usage resets, credit grant voiding, and feature cost queries. Regression tests cover omitted bodies with validation enabled and disabled, provided-body mapping and validation, and missing required bodies.

Notes for reviewer

This branch starts directly from main and is independent of the invoice-charges endpoint PR. Both v3 SDKs were regenerated; Go already handles optional bodies, so its generated output is unchanged.

Validation passed:

  • TypeScript generator checks: 35 tests.
  • Generated TypeScript SDK tests: 557 tests, plus SDK/test type checks.
  • Generated Go SDK build, vet, and tests (make test-go-sdk).
  • Prettier checks for affected sources and generated SDK.

Affected v3 generation and formatting completed successfully. Full make gen-api stopped in the unrelated legacy Python generator because its local virtual-environment executable is missing.

Summary by CodeRabbit

  • New Features
    • Request bodies can now be omitted for supported customer entitlement, credit grant, and feature cost operations. Generated client request types reflect this optionality. Supplied request bodies continue to be serialized for transmission.
  • Bug Fixes
    • Omitting an optional request body no longer triggers a validation error. Required request bodies remain required, and invalid supplied bodies are still rejected when validation is enabled.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge; no blocking issues were found.

Summary

Preserves optional TypeScript request bodies in generated request types and method arguments.

  • TypeScript requests can leave optional API bodies out.

No actionable new issues or repository-rule violations were found. Tests were not run during this review.

Reviews (2) · Last reviewed commit: "refactor(sdk): derive body optionality u..." · Reviewed by Greptile

@turip
turip requested a review from a team as a code owner October 27, 2026 13:44
@coderabbitai

coderabbitai Bot commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between ecfa5d6 and 47658d3.

Files selected for processing: 2
  • api/spec/packages/typespec-typescript/src/sdk-operations.ts
  • api/spec/packages/typespec-typescript/test/optional-body.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 7 remain after this review.

Walkthrough

The TypeScript SDK generator now carries optional request-body metadata into request types and function signatures, and skips validation when an optional body is absent. The JavaScript client supports omitted bodies for selected customer and feature operations, with tests for serialization and required-body validation.

Changes: Optional Request Body Support

Layer / File(s) Summary
Body optionality contract
api/spec/packages/typespec-typescript/src/sdk-operations.ts, api/spec/packages/typespec-typescript/src/request-types.ts
The generator records body optionality and uses it to produce optional body fields and body-only request types.
Generated request signatures and validation
api/spec/packages/typespec-typescript/src/sdk-files.ts, api/spec/packages/typespec-typescript/test/optional-body.test.ts
Generated functions and SDK facades accept omitted bodies for body-optional operations. Generated validation runs only when an optional body is defined. Compiler tests check generated output for optional and required bodies.
JavaScript client optional bodies
api/spec/packages/aip-client-javascript/src/models/operations/*, api/spec/packages/aip-client-javascript/src/funcs/*, api/spec/packages/aip-client-javascript/tests/validation.spec.ts, api/spec/packages/typespec-typescript/templates/tests/validation.spec.ts
Selected customer and feature request bodies are optional. Their client functions skip validation when serialization returns no body. Tests cover omitted and supplied bodies, invalid input, and a still-required body.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Possibly related PRs

  • openmeterio/openmeter#5381: Adds an operation with an optional TypeSpec request body and identifies the generated TypeScript request body as incorrectly required.

Suggested labels: area/api, kind/bug, release-note/bug-fix

Suggested reviewers: tothandras, borosr

Merge Risk: Minimal · up to 47658

No actionable merge-blocking risk remains in the reviewed change.

Pre-merge checks: Passed 4
Check name Status Explanation
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: preserving optional TypeScript request bodies in the SDK.
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

Comment @coderabbitai help to get the list of available commands.

@tothandras tothandras left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks good. I checked the server side: reset-customer-entitlement-usage, void-credit-grant and query-feature-cost all decode with request.ParseOptionalBody, which treats an empty body (EOF) as "no body". So when the SDK leaves the body out, the server gets the call it expects. Validation is still skipped only for optional bodies, and the createMeter(undefined) test shows required bodies are still checked.

Two small, non-blocking notes are inline. CI also still needs a release-note/* label (release-note/bug-fix fits).

httpOp.parameters.body?.type !== undefined || bodyOverrides.has(base),
bodyOptional:
!bodyOverrides.has(base) &&
(httpOp.parameters.body?.property?.optional ?? false),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Is the !bodyOverrides.has(base) guard needed? The CSV @sharedRoute variant declares no body, so body?.property?.optional would already give false there. On the JSON variant, the guard makes an override body required even if the spec marks it optional. That's fine for query-meter today, but if it's deliberate, a short comment would help. If it isn't, dropping the guard keeps one rule for every operation.

optionalOnly(@body request?: Options): void;
@post @route("/required") @operationId("required-widgets")
required(@body request: Options): void;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: requestDecl emits a third shape this fixture doesn't cover: an optional body together with query params and no path (AcceptDateStrings<{ body?: X } & Query>). In that shape req/request stays required, and bodyValue is req.body. An extra op such as @post @route("/optional-query") optionalQuery(@query q?: string, @body request?: Options): void; would lock that in.

…ing optional bodies

Shared-route body overrides no longer force a required body; the declared
body's optionality applies to every operation. Generated output is unchanged.

Add a fixture operation with an optional body plus query parameters to lock
in the remaining request shape.
@tothandras
tothandras enabled auto-merge (squash) October 27, 2026 14:02
@tothandras tothandras added the release-note/bug-fix Release note: Bug Fixes label Oct 27, 2026
@tothandras
tothandras merged commit 9b1736d into main Oct 27, 2026
37 of 38 checks passed
@tothandras
tothandras deleted the feat/sdk-optional-request-bodies branch October 27, 2026 14:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-note/bug-fix Release note: Bug Fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants