Skip to content

feat: infer types for serverFetch#4399

Draft
p-dubovitsky wants to merge 1 commit into
nitrojs:mainfrom
p-dubovitsky:typed-server-fetch
Draft

feat: infer types for serverFetch#4399
p-dubovitsky wants to merge 1 commit into
nitrojs:mainfrom
p-dubovitsky:typed-server-fetch

Conversation

@p-dubovitsky

Copy link
Copy Markdown
Contributor

🔗 Linked issue

Partially addresses #2758

❓ Type of change

  • 📖 Documentation (updates to the documentation, readme, or JSdoc annotations)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality like performance)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

This PR adds generated-route type inference for serverFetch.

serverFetch now uses the generated Nitro route declarations to infer response JSON types for known routes and narrow the method option to methods supported by the matched route. Unknown routes still fall back to unknown, preserving compatibility for dynamic or untyped paths.

This is intended to be runtime-compatible, but it may expose type-level incompatibilities in code that relied on overly broad serverFetch inputs. In particular, known routes now narrow accepted methods to the methods declared by the route, and URL/Request are no longer part of the typed serverFetch request input.

The PR also adds Vitest type tests covering response inference, method narrowing, and unknown-route fallback against the existing test fixture app.

Documentation and the server-fetch example were updated to use serverFetch as the recommended API for internal server-to-server route calls. A separate note documents the exported fetch helper as a broader fetch-compatible API that can still use the internal server fetch mechanism for relative Nitro routes, while keeping serverFetch as the typed route-aware API.

Typed fetch/$fetch, route input typing, and serialization-related improvements remain follow-up work for #2758.

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@p-dubovitsky p-dubovitsky requested a review from pi0 as a code owner June 30, 2026 17:30
@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

@p-dubovitsky is attempting to deploy a commit to the Nitro Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5a7e4d12-07f9-4c8b-a0a2-4766f5b44d13

📥 Commits

Reviewing files that changed from the base of the PR and between 000d7d1 and c3a088f.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (12)
  • docs/4.examples/server-fetch.md
  • examples/server-fetch/README.md
  • examples/server-fetch/routes/index.ts
  • examples/server-fetch/tsconfig.json
  • package.json
  • src/runtime/internal/app.ts
  • src/runtime/nitro.ts
  • src/types/fetch/fetch.ts
  • test/tsconfig.json
  • test/unit/server-fetch-types.test-d.ts
  • tsconfig.json
  • vitest.config.ts
✅ Files skipped from review due to trivial changes (3)
  • test/tsconfig.json
  • examples/server-fetch/tsconfig.json
  • examples/server-fetch/README.md
🚧 Files skipped from review as they are similar to previous changes (9)
  • examples/server-fetch/routes/index.ts
  • vitest.config.ts
  • test/unit/server-fetch-types.test-d.ts
  • package.json
  • tsconfig.json
  • docs/4.examples/server-fetch.md
  • src/runtime/nitro.ts
  • src/runtime/internal/app.ts
  • src/types/fetch/fetch.ts

📝 Walkthrough

Walkthrough

Refactors serverFetch into a typed const backed by serverFetchImpl, updates internal fetch typing and method inference, adds type coverage, and switches the server-fetch example and docs to serverFetch.

Changes

serverFetch typed export and fetch type fixes

Layer / File(s) Summary
ExtractedRouteMethod and ServerFetch type fixes
src/types/fetch/fetch.ts
Narrows ExtractedRouteMethod to a single options-only generic with lowercase method extraction; updates Base$Fetch, $Fetch.raw, and ServerFetch return types to use ExtractedRouteMethod<O>; adds missing type imports.
serverFetchImpl runtime refactor
src/runtime/internal/app.ts, src/runtime/nitro.ts
Extracts serverFetchImpl as a non-exported implementation in both runtime files; re-exports serverFetch as a typed ServerFetch const; wires resolveWebsocketHooks and the internal fetch wrapper to call serverFetchImpl directly.
Type tests and test infra
test/unit/server-fetch-types.test-d.ts, tsconfig.json, package.json, vitest.config.ts, test/tsconfig.json
Adds serverFetch type test assertions for inferred JSON response types and method narrowing; excludes test-d files from main tsconfig; adds test:types script, fetchdts dependency, and vitest typecheck config.
Example and docs update
examples/server-fetch/routes/index.ts, examples/server-fetch/tsconfig.json, examples/server-fetch/README.md, docs/4.examples/server-fetch.md
Switches example route from fetch to serverFetch; adds generated type declarations to the example tsconfig; rewrites README and full docs page to describe serverFetch, type safety, and the fetch helper.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% 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
Title check ✅ Passed The title uses conventional commit format and accurately describes the PR's main change.
Description check ✅ Passed The description is directly related to the serverFetch type inference and docs updates in this PR.
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 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.

@pkg-pr-new

pkg-pr-new Bot commented Jun 30, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/nitro@4399

commit: c3a088f

@coderabbitai coderabbitai 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.

Actionable comments posted: 1

🧹 Nitpick comments (1)
test/unit/server-fetch-types.test-d.ts (1)

13-14: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cover uppercase methods with a positive assertion.

This suite exercises lowercase "post" and an invalid uppercase "GET", but the new Lowercase<...> path is what makes uppercase "POST" work for known routes. Add one passing uppercase case so that compatibility surface stays pinned.

Suggested addition
     const upload = await serverFetch("/api/upload", { method: "post" });
     expectTypeOf(await upload.json()).toEqualTypeOf<string>();
+
+    const uploadUpper = await serverFetch("/api/upload", { method: "POST" });
+    expectTypeOf(await uploadUpper.json()).toEqualTypeOf<string>();
🤖 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 `@test/unit/server-fetch-types.test-d.ts` around lines 13 - 14, Add a positive
type assertion in server-fetch-types.test-d.ts that exercises an uppercase known
method, not just lowercase "post" and invalid "GET"; update the serverFetch test
case to call a known route like /api/upload with method "POST" and assert the
returned JSON type, so the Lowercase<...> behavior stays covered in the
serverFetch test suite.
🤖 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 `@vitest.config.ts`:
- Around line 13-15: The Vitest typecheck config is hiding diagnostics from
imported source files because `typecheck.ignoreSourceErrors` is enabled, so
source regressions can slip through even when the test d.ts files pass. Update
`vitest.config.ts` to stop suppressing source-file errors in the `typecheck`
block, and if you still need separate source validation, move that
responsibility to a dedicated source typecheck step rather than `vitest
--typecheck.only`.

---

Nitpick comments:
In `@test/unit/server-fetch-types.test-d.ts`:
- Around line 13-14: Add a positive type assertion in
server-fetch-types.test-d.ts that exercises an uppercase known method, not just
lowercase "post" and invalid "GET"; update the serverFetch test case to call a
known route like /api/upload with method "POST" and assert the returned JSON
type, so the Lowercase<...> behavior stays covered in the serverFetch test
suite.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 12c2b568-f63b-49b1-91d2-19e0f483a1e9

📥 Commits

Reviewing files that changed from the base of the PR and between 5e3284e and 135b0f3.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (11)
  • docs/4.examples/server-fetch.md
  • examples/server-fetch/README.md
  • examples/server-fetch/routes/index.ts
  • examples/server-fetch/tsconfig.json
  • package.json
  • src/runtime/internal/app.ts
  • src/runtime/nitro.ts
  • src/types/fetch/fetch.ts
  • test/unit/server-fetch-types.test-d.ts
  • tsconfig.json
  • vitest.config.ts

Comment thread vitest.config.ts
Comment on lines +13 to +15
typecheck: {
ignoreSourceErrors: true,
},

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

In Vitest 4.1.8, what does test.typecheck.ignoreSourceErrorsdo duringvitest --typecheck.only? Does it suppress TypeScript errors originating from imported source files used by *.test-d.ts tests?

💡 Result:

In Vitest 4.1.8, the typecheck.ignoreSourceErrors option is used to prevent the test suite from failing when TypeScript errors are detected in your project's source files [1][2]. By default, Vitest treats source code errors as test failures, even if the errors are not within your *.test-d.ts test files [1][3]. Yes, typecheck.ignoreSourceErrors effectively suppresses TypeScript errors that originate from imported source files [1][2]. When enabled, Vitest will not fail the suite due to these "non-test" errors, and it will essentially hide them from the output [1][2]. This is particularly useful when your type tests (e.g., in *.test-d.ts files) depend on or extend global types that may cause compilation errors in your source code, but you want to focus exclusively on the success of your type assertions [3][4]. When running vitest --typecheck.only, Vitest performs static analysis on your project using a type checker like tsc or vue-tsc [3]. Enabling typecheck.ignoreSourceErrors ensures that the results of this analysis do not cause a non-zero exit code if only source files (as opposed to actual type tests) contain errors [1][5]. Note that this behavior is intended to allow you to run type tests in environments where source code might have unresolved type issues [4][5].

Citations:


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'FILES:\n'
git ls-files | rg '(^|/)(vitest\.config\.ts|package\.json|.*\.test-d\.ts)$'

printf '\nVITEST CONFIG:\n'
cat -n vitest.config.ts

printf '\nTYPECHECK REFERENCES:\n'
rg -n --hidden --glob '!node_modules' --glob '!dist' --glob '!build' 'typecheck|serverFetch|test-d\.ts' .

Repository: nitrojs/nitro

Length of output: 10955


Keep source-file errors visible in the type suite

ignoreSourceErrors: true suppresses diagnostics from imported source files, so a regression in src/types/fetch/fetch.ts can still pass if test/unit/server-fetch-types.test-d.ts parses. Remove this here, or run source typechecks separately from vitest --typecheck.only.

🤖 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 `@vitest.config.ts` around lines 13 - 15, The Vitest typecheck config is hiding
diagnostics from imported source files because `typecheck.ignoreSourceErrors` is
enabled, so source regressions can slip through even when the test d.ts files
pass. Update `vitest.config.ts` to stop suppressing source-file errors in the
`typecheck` block, and if you still need separate source validation, move that
responsibility to a dedicated source typecheck step rather than `vitest
--typecheck.only`.

@pi0

pi0 commented Jun 30, 2026

Copy link
Copy Markdown
Member

Hi @p-dubovitsky really appreciate what you are working on! ❤️

Just a headsup since don't want your efforts to be wasted. It is very likely we will extract typed fetch into a nitro module out of the core before RC. I think we might use parts of your code but not fully.

In meantime i will convert PR to draft.

(please feel free to drop me a DM in X or Discord (pi0) if wanted to chat.

@pi0 pi0 marked this pull request as draft June 30, 2026 19:41
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.

2 participants