Skip to content

fix(ws): expose crossws on app.fetch response#1306

Open
ahmetguness wants to merge 3 commits intoh3js:mainfrom
ahmetguness:fix/ws-crossws-typing
Open

fix(ws): expose crossws on app.fetch response#1306
ahmetguness wants to merge 3 commits intoh3js:mainfrom
ahmetguness:fix/ws-crossws-typing

Conversation

@ahmetguness
Copy link

@ahmetguness ahmetguness commented Mar 1, 2026

When using defineWebSocketHandler, the returned Response includes a crossws property.
However, app.fetch() is typed as returning Response, so res.crossws is not visible in TypeScript without casting.

  • Introduces a small H3Response type (Response with optional crossws)
  • Updates fetch / toResponse to return H3Response
  • Removes (res as any).crossws from tests
  • Adds type tests to make sure this stays correct

All checks pass locally (lint, typecheck, vitest).

Closes #1258

Summary by CodeRabbit

  • New Features

    • Introduced H3Response (Response with optional WebSocket hooks) and WebSocketResponse for safer WebSocket responses.
    • Core request/response APIs and WebSocket handler creator updated to use the new response types and improved generics.
    • Re-exported the new response types from the public API surface.
  • Tests

    • Added and updated type tests validating H3Response, WebSocketResponse and WebSocket handler typings.

@ahmetguness ahmetguness requested a review from pi0 as a code owner March 1, 2026 17:26
@coderabbitai
Copy link

coderabbitai bot commented Mar 1, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 74fc495 and 86f1f44.

📒 Files selected for processing (2)
  • src/index.ts
  • src/response.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/index.ts
  • src/response.ts

📝 Walkthrough

Walkthrough

Updated type system to introduce H3Response and WebSocketResponse (Response augmented with a crossws property) and retyped public APIs and handlers to return these types. Tests and public exports updated to reflect the new types; docs file had a formatting/no-op change.

Changes

Cohort / File(s) Summary
Type Definitions
src/types/h3.ts, src/utils/ws.ts
Added H3Response and WebSocketResponse types (Response + crossws). Imported WebSocketHooks and adjusted handler/response typings accordingly.
Core API
src/h3.ts, src/response.ts
Updated signatures: fetch, ~request, request, and toResponse now return `H3Response
Public Exports
src/index.ts
Re-exported H3Response and WebSocketResponse from the public barrel.
WebSocket Helpers
src/utils/ws.ts
Made defineWebSocketHandler generic to return EventHandler<EventHandlerRequest, WebSocketResponse> and adjusted handler creation/returns to WebSocketResponse.
Tests
test/unit/types.test-d.ts, test/ws.test.ts
Extended type tests for new exports; removed any casts and accessed crossws directly in websocket tests.
Docs (minor)
docs/5.migration/0.index.md
Minor line-ending/formatting replacement (no functional change).

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • pi0

Poem

🐇 I nibble types beneath the moonlight,
crossws stitched into responses—so bright.
Handlers hop out with clearer intent,
No casts, just type-sure merriment.
Hooray — a rabbit-approved type delight!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.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.
Title check ✅ Passed The title accurately describes the main change: exposing the crossws property on the fetch response with proper typing through the new H3Response type.
Linked Issues check ✅ Passed The PR successfully implements the fix for issue #1258 by introducing H3Response type and updating fetch/toResponse signatures to expose crossws with proper TypeScript support.
Out of Scope Changes check ✅ Passed All changes are directly related to addressing the linked issue #1258 and exposing the crossws property with proper typing; no out-of-scope modifications detected.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

Copy link

@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: 1

🧹 Nitpick comments (1)
src/response.ts (1)

15-19: Consider updating internal cast for consistency.

The return type is now H3Response | Promise<H3Response>, but line 19 still casts to Promise<Response>. While this works due to structural typing (the recursive toResponse call returns the correct type), updating the cast would improve code consistency.

Proposed fix
   if (typeof (val as PromiseLike<unknown>)?.then === "function") {
     return ((val as Promise<unknown>).catch?.((error) => error) || Promise.resolve(val)).then(
       (resolvedVal) => toResponse(resolvedVal, event, config),
-    ) as Promise<Response>;
+    ) as Promise<H3Response>;
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/response.ts` around lines 15 - 19, The return type cast at the end of the
async branch in toResponse is inconsistent: it currently casts to
Promise<Response> even though the function signature and recursive toResponse
call use H3Response; update the cast to Promise<H3Response> (or remove the cast
entirely) so the expression returns the correct Promise<H3Response> type
consistently with toResponse and the function signature.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/index.ts`:
- Around line 194-195: There are two identical `// WebSocket` comments
duplicated in src/index.ts; remove one so only a single `// WebSocket` comment
remains above the WebSocket-related code (e.g., the WebSocket server/handler
block) to avoid redundancy — locate the duplicate `// WebSocket` markers and
delete the extra one.

---

Nitpick comments:
In `@src/response.ts`:
- Around line 15-19: The return type cast at the end of the async branch in
toResponse is inconsistent: it currently casts to Promise<Response> even though
the function signature and recursive toResponse call use H3Response; update the
cast to Promise<H3Response> (or remove the cast entirely) so the expression
returns the correct Promise<H3Response> type consistently with toResponse and
the function signature.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 52c82e1 and 74fc495.

📒 Files selected for processing (8)
  • docs/5.migration/0.index.md
  • src/h3.ts
  • src/index.ts
  • src/response.ts
  • src/types/h3.ts
  • src/utils/ws.ts
  • test/unit/types.test-d.ts
  • test/ws.test.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.

Type mismatch occurred when using crossws

1 participant