Skip to content

feat(openapi): cookie parameters#1582

Open
RafalFilipek wants to merge 7 commits into
middleapi:mainfrom
RafalFilipek:feat/openapi-cookie-parameters
Open

feat(openapi): cookie parameters#1582
RafalFilipek wants to merge 7 commits into
middleapi:mainfrom
RafalFilipek:feat/openapi-cookie-parameters

Conversation

@RafalFilipek

@RafalFilipek RafalFilipek commented Jun 11, 2026

Copy link
Copy Markdown

Motivation

When building a server with endpoints that must explicitly declare which cookies they require — and receive typed access to those values as part of the request input — there was no way to express this through oRPC's OpenAPI integration. The generated spec had no in: cookie parameter entries, and the decoded input object had no cookies key.

While oRPC provides cookie helpers (getCookie, setCookie, deleteCookie) for manual cookie access within handlers, this PR addresses a different need: treating cookies as first-class, typed input parameters — declared in the schema, validated at the boundary, and visible in the generated OpenAPI spec — in the same way query, headers, and params are handled today.

What this does

Adds cookies as a supported key in inputStructure: 'detailed' mode:

Spec generation (openapi-generator.ts): the generator now recognises cookies as a fifth top-level key alongside params, query, headers, and body. Each property of the cookies schema is emitted as an in: cookie parameter object in the OpenAPI spec.

Server-side decode (openapi-codec.ts): the decode() method now exposes a lazy cookies getter on the detailed input object. It parses the incoming Cookie request header (using the same lazy-evaluation pattern already used for query) and returns a Record<string, string>. Uses flattenHeader from @orpc/standard-server for correct header normalisation.

Usage

const getUser = os
  .route({ method: 'GET', path: '/me', inputStructure: 'detailed' })
  .input(z.object({
    cookies: z.object({
      session_id: z.string(),
      theme: z.string().optional(),
    }),
  }))
  .handler(({ input }) => {
    const { session_id, theme } = input.cookies // fully typed
    // ...
  })

Generated spec:

parameters:
  - name: session_id
    in: cookie
    required: true
    schema:
      type: string
  - name: theme
    in: cookie
    required: false
    schema:
      type: string

What is NOT included in this PR (initial implementation)

  • inputStructure: 'compact' — cookies are not supported in compact mode; they only make sense in detailed mode where input fields are explicitly mapped to HTTP locations
  • Client-side encoding (openapi-link-codec.ts) — the client does not yet encode input.cookies into outgoing Cookie headers
  • Set-Cookie in output structure — response cookies are out of scope for this PR

I'd love to hear your feedback on this approach. If there are aspects of the design you'd like to see changed, or if you have suggestions on how to best continue this work (e.g. compact mode support, client-side encoding), I'm happy to follow your guidance.

Thank you,

Rafał

Summary by CodeRabbit

  • Documentation

    • Added a design spec and implementation plan for OpenAPI cookie-parameter support with usage examples and testing guidance.
  • New Features

    • Enabled cookie parameters for detailed input structures and exposed parsed request cookies alongside params/query/headers.
  • Tests

    • Added tests covering cookie parameter generation, parsing from request headers, empty/missing behavior, decoding edge cases, and validation rules.

Copilot AI review requested due to automatic review settings June 11, 2026 17:10
@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds server-side OpenAPI cookie-parameter support for inputStructure: 'detailed': design/docs, generator emits in: cookie parameters, standard codec parses the Cookie header into a lazy cookies accessor (getter/setter), and tests for generator, utils, and codec behavior.

Changes

OpenAPI Cookie Parameter Support

Layer / File(s) Summary
Design & Planning Documentation
docs/superpowers/specs/2026-06-11-openapi-cookie-parameters-design.md, docs/superpowers/plans/2026-06-11-openapi-cookie-parameters.md
Design spec and implementation plan defining scope (server-side generation + decode), architecture (Zod shapes → OpenAPI generator → codec parsing), file map, task breakdown, tests, usage example, and out-of-scope items.
OpenAPI Generator Cookie Parameter Mapping
packages/openapi/src/openapi-generator.ts, packages/openapi/src/openapi-generator.test.ts
Updated detailed-input validation message to include cookies?; extended parameter iteration to treat cookies and map it to OpenAPI in: 'cookie'. Added tests for cookie-only fields, mixed inputs, and invalid cookies shape.
Standard Codec Cookie Header Parsing
packages/openapi/src/adapters/standard/openapi-codec.ts, packages/openapi/src/adapters/standard/openapi-codec.test.ts
Imported header flattening and cookie parsing, implemented lazy cookies getter/setter on detailed-mode decode (caching parsed cookies), and added decode tests covering parsing, missing header default {}, overrides, and edge cases.
Parameter Utility Test for Cookies
packages/openapi/src/openapi-utils.test.ts
Added toOpenAPIParameters(schema, 'cookie') test verifying generated cookie parameter definitions and required/optional handling.
Package Dependency
packages/openapi/package.json
Added runtime dependency on the cookie package (^1.1.1) to support Cookie header parsing.

Sequence Diagram

sequenceDiagram
  participant Client
  participant Server
  participant StandardOpenAPICodec
  participant ZodValidator
  Client->>Server: HTTP request with Cookie header
  Server->>StandardOpenAPICodec: decode(request) for detailed input
  StandardOpenAPICodec->>StandardOpenAPICodec: flatten Cookie header and parse into cookies object
  StandardOpenAPICodec->>ZodValidator: provide decoded input including lazy cookies accessor
  ZodValidator->>Server: validation result
  Server->>Client: response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 A cookie jar for API specs so fine,
Generator marks them in: cookie in line,
Codec peeks headers with a lazy getter bright,
Parsed crumbs cached tidy, ready for Zod's sight.
Hop, test, and ship — sweet bytes in the night.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
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.
Title check ✅ Passed The title 'feat(openapi): cookie parameters' clearly and concisely describes the main change: adding cookie parameter support to the OpenAPI package.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

@dosubot dosubot Bot added size:L This PR changes 100-499 lines, ignoring generated files. enhancement New feature or request javascript Pull requests that update javascript code labels Jun 11, 2026

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request implements support for cookie parameters in the OpenAPI generator and codec when using inputStructure: 'detailed'. It extends the generator loop to map cookies to cookie parameters, parses the Cookie header in the standard codec, and adds corresponding tests. Feedback is provided to improve the parseCookieHeader implementation by handling URL-encoded keys/values and stripping wrapping double quotes to ensure RFC 6265 compliance and robust validation.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread packages/openapi/src/adapters/standard/openapi-codec.ts Outdated

Copilot AI 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.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Adds first-class cookie support to OpenAPI generation and the standard OpenAPI codec when inputStructure: 'detailed', so cookie inputs can be validated and documented as in: cookie parameters.

Changes:

  • Generate OpenAPI in: cookie parameters from a cookies key in detailed input schemas.
  • Decode the Cookie header into a lazily-evaluated cookies object on the server-side codec.
  • Add generator/utility/codec tests plus design/plan docs for the feature.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/openapi/src/openapi-utils.test.ts Adds coverage for toOpenAPIParameters(..., 'cookie').
packages/openapi/src/openapi-generator.ts Extends detailed input handling to include cookiescookie.
packages/openapi/src/openapi-generator.test.ts Adds detailed-input generator tests for cookie parameters + invalid cookies schema.
packages/openapi/src/adapters/standard/openapi-codec.ts Parses the Cookie header and exposes it as input.cookies via a lazy getter.
packages/openapi/src/adapters/standard/openapi-codec.test.ts Adds decode tests validating cookie parsing behavior and mutability.
docs/superpowers/specs/2026-06-11-openapi-cookie-parameters-design.md Documents the design and scope for cookie parameter support.
docs/superpowers/plans/2026-06-11-openapi-cookie-parameters.md Implementation plan with steps/tests for cookie parameter support.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/openapi/src/adapters/standard/openapi-codec.ts Outdated
Comment thread packages/openapi/src/adapters/standard/openapi-codec.ts Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 5

🧹 Nitpick comments (2)
docs/superpowers/specs/2026-06-11-openapi-cookie-parameters-design.md (1)

23-38: 💤 Low value

Optional: Add language specifier to fenced code block.

The architecture diagram code block lacks a language specifier. While this is a minor formatting issue, adding one (e.g., ```text or ```plaintext) improves consistency.

As per static analysis hints: "Fenced code blocks should have a language specified (MD040)."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/specs/2026-06-11-openapi-cookie-parameters-design.md` around
lines 23 - 38, Add a language specifier to the fenced code block that begins
with "User Schema (Zod)" so the block is tagged (for example `text` or
`plaintext`); locate the triple-backtick block containing the architecture
diagram lines ("User Schema (Zod) z.object({ session_id: z.string() }) ..."
through "validates cookies like any other input field") and change the opening
fence to include a language (e.g., ```text) to satisfy the MD040 lint rule.

Source: Linters/SAST tools

docs/superpowers/plans/2026-06-11-openapi-cookie-parameters.md (1)

416-416: ⚡ Quick win

Remove hardcoded absolute path.

The command uses an environment-specific absolute path /Users/me/Projects/github/orpc that won't work for other developers.

💡 Proposed fix
-cd /Users/me/Projects/github/orpc && pnpm test --filter `@orpc/openapi`
+pnpm --filter `@orpc/openapi` test

or use repository root variable:

-cd /Users/me/Projects/github/orpc && pnpm test --filter `@orpc/openapi`
+cd $(git rev-parse --show-toplevel) && pnpm --filter `@orpc/openapi` test
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-06-11-openapi-cookie-parameters.md` at line 416,
The hardcoded absolute path in the test command ("cd
/Users/me/Projects/github/orpc && pnpm test --filter `@orpc/openapi`") will fail
for other devs; change it to use the repository root dynamically (for example by
using git rev-parse --show-toplevel or an environment variable like
REPO_ROOT/GITHUB_WORKSPACE) or run pnpm from the repo root via pnpm's directory
option, so the command becomes portable and no longer depends on
/Users/me/Projects/github/orpc.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/superpowers/plans/2026-06-11-openapi-cookie-parameters.md`:
- Around line 263-314: Add two unit tests after the existing cookie tests that
call codec.decode (using serializer.deserialize.mockReturnValue(undefined), the
same URL/procedure setup and headers) to cover malformed cookie pairs and values
containing '=': one test with header 'cookie': 'valid=value;
malformed_no_equals; another=good' expecting input.cookies toEqual { valid:
'value', another: 'good' }, and another with header 'cookie': 'token=eyJhbGc=;
session=base64data==' expecting input.cookies toEqual { token: 'eyJhbGc=',
session: 'base64data==' }; keep the same use of input.cookies, serializer,
codec.decode and procedure identifiers as in existing tests.

In `@docs/superpowers/specs/2026-06-11-openapi-cookie-parameters-design.md`:
- Line 113: Update the examples to normalize the Cookie header before parsing:
replace direct access to request.headers['cookie'] with
flattenHeader(request.headers['cookie']) and use that result as the argument to
parseCookieHeader; ensure the examples import or reference flattenHeader from
'`@orpc/standard-server`' so the code demonstrates proper normalization of string
| string[] | undefined per RFC 6265.
- Around line 132-149: Add a new test block in
packages/openapi/src/adapters/standard/openapi-codec.test.ts that exercises
parseCookieHeader (and the higher-level decode() path that uses it) with the
listed edge cases: malformed pairs without '=', values containing '=', empty
values, leading/trailing whitespace in keys and values, and multiple Cookie
headers (use flattenHeader behavior). For each case assert that decode(...)
(with inputStructure: 'detailed') produces the expected cookies object (graceful
handling for malformed pairs, correct splitting when '=' is in the value, empty
string for empty values, trimmed keys/values, and merged results for multiple
headers). Ensure tests also include the no-Cookie and malformed-header
expectations already described so coverage is complete.
- Around line 87-95: The parseCookieHeader function mishandles pairs without '='
because it uses indexOf('=') slicing even when idx === -1; update
parseCookieHeader to detect idx === -1 and handle it safely by trimming the
pair, skipping empty strings, and treating a no-equals token as a key with an
empty string value (or skipping entirely if the key is empty); keep the normal
behavior when idx >= 0 (key = slice(0, idx).trim(), value = slice(idx+1).trim())
and return the resulting Record<string,string> accordingly.

In `@packages/openapi/src/adapters/standard/openapi-codec.ts`:
- Around line 24-35: The current parseCookieHeader function incorrectly handles
URL-decoding and quoted cookie values; replace its manual split/indexOf logic in
parseCookieHeader with the cookie library's parsing (use cookie.parse) so values
are URL-decoded and quotes handled consistently with `@orpc/server`, and update
any imports to include cookie; also add unit tests covering URL-encoded and
quoted cookie values to validate input.cookies behavior matches
packages/server's cookie handling.

---

Nitpick comments:
In `@docs/superpowers/plans/2026-06-11-openapi-cookie-parameters.md`:
- Line 416: The hardcoded absolute path in the test command ("cd
/Users/me/Projects/github/orpc && pnpm test --filter `@orpc/openapi`") will fail
for other devs; change it to use the repository root dynamically (for example by
using git rev-parse --show-toplevel or an environment variable like
REPO_ROOT/GITHUB_WORKSPACE) or run pnpm from the repo root via pnpm's directory
option, so the command becomes portable and no longer depends on
/Users/me/Projects/github/orpc.

In `@docs/superpowers/specs/2026-06-11-openapi-cookie-parameters-design.md`:
- Around line 23-38: Add a language specifier to the fenced code block that
begins with "User Schema (Zod)" so the block is tagged (for example `text` or
`plaintext`); locate the triple-backtick block containing the architecture
diagram lines ("User Schema (Zod) z.object({ session_id: z.string() }) ..."
through "validates cookies like any other input field") and change the opening
fence to include a language (e.g., ```text) to satisfy the MD040 lint rule.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 98147f30-2739-4d52-a9a3-6c8410a7370e

📥 Commits

Reviewing files that changed from the base of the PR and between e801713 and 92bf405.

📒 Files selected for processing (7)
  • docs/superpowers/plans/2026-06-11-openapi-cookie-parameters.md
  • docs/superpowers/specs/2026-06-11-openapi-cookie-parameters-design.md
  • packages/openapi/src/adapters/standard/openapi-codec.test.ts
  • packages/openapi/src/adapters/standard/openapi-codec.ts
  • packages/openapi/src/openapi-generator.test.ts
  • packages/openapi/src/openapi-generator.ts
  • packages/openapi/src/openapi-utils.test.ts

Comment thread docs/superpowers/plans/2026-06-11-openapi-cookie-parameters.md
Comment thread packages/openapi/src/adapters/standard/openapi-codec.ts Outdated

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes — adds cookies as a supported key in inputStructure: 'detailed' mode, generating in: cookie OpenAPI parameters and parsing the Cookie request header during server-side decode.

  • Add cookies to generator loop — extended the 'params', 'query', 'headers' array to include 'cookies' in openapi-generator.ts, mapping it to parameterIn: 'cookie'. Updated the detailed-input error message to document the new key.
  • Parse Cookie header in codec — added parseCookieHeader helper (splits on ;, handles missing =, trims, skips empty segments) and a lazy cookies getter/setter on the detailed decode return object in openapi-codec.ts, using flattenHeader from @orpc/standard-server for header normalization.
  • Test coverage — generator tests for cookies-only, combined cookies+headers+query+body, and invalid non-object cookies; codec tests for parsing, absent header, settability, pairs without =, and values containing =; toOpenAPIParameters cookie test verifying no style/explode/allowEmptyValue/allowReserved are emitted.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

- Replace custom parseCookieHeader with cookie.parse to align with
  @orpc/server cookie helper behaviour (RFC 6265 compliant)
- Add cookie as a dependency of @orpc/openapi
- Add tests for URL-encoded values and base64 values with = padding
@RafalFilipek RafalFilipek requested a review from Copilot June 11, 2026 18:05

Copilot AI 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.

Pull request overview

Copilot reviewed 8 out of 9 changed files in this pull request and generated 2 comments.

Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

Comment thread packages/openapi/src/adapters/standard/openapi-codec.ts
Comment thread packages/openapi/src/adapters/standard/openapi-codec.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/openapi/src/adapters/standard/openapi-codec.ts (1)

72-76: [openapi-codec] Cookie header lookup is safe for standard-server inputs; consider a small case-insensitive fallback

Node’s IncomingMessage.headers and Fastify’s raw.headers expose lowercased header keys, and the standard-server-node/standard-server-fastify adapters pass those through. For fetch-style inputs and API Gateway HTTP API (v2) events, header keys are also lowercased in practice, so request.headers.cookie should work with real adapter-produced requests. Since StandardHeaders itself doesn’t enforce casing and the unit tests use lowercase cookie, adding a fallback like request.headers.cookie ?? request.headers['Cookie'] would improve robustness for manually-constructed inputs.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/openapi/src/adapters/standard/openapi-codec.ts` around lines 72 -
76, The cookies getter (get cookies) uses
flattenHeader(parseCookie(flattenHeader(request.headers.cookie) ?? '')) which
assumes a lowercase 'cookie' header; update it to fall back to a
case-insensitive lookup (e.g., use request.headers.cookie ??
request.headers['Cookie'] or check both keys) before calling
flattenHeader/parseCookie, and then store the parsed value via
Object.defineProperty as before so manually-constructed or differently-cased
headers still produce correct cookies; refer to the getter name "cookies",
helper "flattenHeader", and "parseCookie" to locate the code to change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@packages/openapi/src/adapters/standard/openapi-codec.ts`:
- Around line 72-76: The cookies getter (get cookies) uses
flattenHeader(parseCookie(flattenHeader(request.headers.cookie) ?? '')) which
assumes a lowercase 'cookie' header; update it to fall back to a
case-insensitive lookup (e.g., use request.headers.cookie ??
request.headers['Cookie'] or check both keys) before calling
flattenHeader/parseCookie, and then store the parsed value via
Object.defineProperty as before so manually-constructed or differently-cased
headers still produce correct cookies; refer to the getter name "cookies",
helper "flattenHeader", and "parseCookie" to locate the code to change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9ae6c1e4-d699-4aba-b088-75aabc7944dd

📥 Commits

Reviewing files that changed from the base of the PR and between 92bf405 and b7564b9.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (3)
  • packages/openapi/package.json
  • packages/openapi/src/adapters/standard/openapi-codec.test.ts
  • packages/openapi/src/adapters/standard/openapi-codec.ts
✅ Files skipped from review due to trivial changes (1)
  • packages/openapi/package.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/openapi/src/adapters/standard/openapi-codec.test.ts

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes — replaced the hand-rolled parseCookieHeader with the cookie npm package for RFC 6265-compliant cookie parsing, added tests for URL-decoded and base64-padded values, and added the cookie dependency.

  • Switched to cookie for header parsing — removed the custom parseCookieHeader helper in openapi-codec.ts and replaced it with parse from the cookie package, which handles URL-decoding, quoted values, and other edge cases that the hand-rolled parser did not.
  • Extended test coverage — added tests for URL-encoded values (hello%20worldhello world), percent-encoded special chars (%40@), and base64 values with trailing = padding, all validated by the cookie package's parsing behavior.

Pullfrog  | View workflow run | Using DeepSeek Pro (free via Pullfrog for OSS) | 𝕏

@dinwwwh dinwwwh changed the title Feat/openapi cookie parameters feat(openapi): cookie parameters Jun 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request javascript Pull requests that update javascript code size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants