Skip to content

chore: upgrade and unpin h3 in start-server-core#7044

Open
ulrichstark wants to merge 2 commits intoTanStack:mainfrom
ulrichstark:chore-upgrade-and-unpin-h3
Open

chore: upgrade and unpin h3 in start-server-core#7044
ulrichstark wants to merge 2 commits intoTanStack:mainfrom
ulrichstark:chore-upgrade-and-unpin-h3

Conversation

@ulrichstark
Copy link
Contributor

@ulrichstark ulrichstark commented Mar 26, 2026

Closes #7043

The function h3_parseCookies now returns Record<string, string | undefined> instead of Record<string, string>. I handled that by filtering out the undefined values to keep the function signature unchanged to avoid breaking changes. Also inlined code from getCookies into getCookie to avoid the unnecessary execution of the for loop.

Summary by CodeRabbit

  • Chores

    • Updated core dependencies to latest compatible versions.
  • Bug Fixes

    • Enhanced cookie handling to properly parse and normalize cookies from requests, ensuring consistent behavior across the application.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 26, 2026

📝 Walkthrough

Walkthrough

Updated h3 dependency in start-server-core from version 2.0.1-rc.16 (aliased as h3-v2) to 2.0.1-rc.19, and refactored cookie handling in request-response.ts to use the updated package while maintaining API compatibility.

Changes

Cohort / File(s) Summary
Dependency Update
packages/start-server-core/package.json
Replaced aliased h3-v2 dependency (npm:h3@2.0.1-rc.16) with direct h3 dependency at version 2.0.1-rc.19, addressing multiple security vulnerabilities.
Import & Cookie Handling Refactor
packages/start-server-core/src/request-response.ts
Updated imports from h3-v2 to h3. Refactored getCookies() to filter out undefined values from parsed cookies. Modified getCookie(name) to parse cookies inline rather than delegating to getCookies().

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 A hop, a skip, and a security fix,
From rc.16 to rc.19, vulnerabilities mix!
New cookies are parsed with care and delight,
No h3-v2 alias—just h3 shining bright! 🌟

🚥 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 PR title accurately describes the main change: upgrading and unpinning the h3 dependency in start-server-core, which matches the changeset modifications.
Linked Issues check ✅ Passed The PR successfully addresses issue #7043 by upgrading h3 from 2.0.1-rc.16 to 2.0.1-rc.19, which resolves all three reported vulnerabilities and handles API changes appropriately.
Out of Scope Changes check ✅ Passed All changes are directly scoped to addressing the h3 upgrade: dependency update in package.json, import changes, and necessary code adjustments for the h3_parseCookies API change.

✏️ 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.

@nx-cloud
Copy link

nx-cloud bot commented Mar 26, 2026

🤖 Nx Cloud AI Fix Eligible

An automatically generated fix could have helped fix failing tasks for this run, but Self-healing CI is disabled for this workspace. Visit workspace settings to enable it and get automatic fixes in future runs.

To disable these notifications, a workspace admin can disable them in workspace settings.


View your CI Pipeline Execution ↗ for commit 0713e9b

Command Status Duration Result
nx affected --targets=test:eslint,test:unit,tes... ❌ Failed 11m 2s View ↗
nx run-many --target=build --exclude=examples/*... ✅ Succeeded 1m 54s View ↗

☁️ Nx Cloud last updated this comment at 2026-03-26 07:55:06 UTC

@github-actions
Copy link
Contributor

Bundle Size Benchmarks

  • Commit: 87a51603981e
  • Measured at: 2026-03-26T07:44:48.288Z
  • Baseline source: history:5016e4e4c738
  • Dashboard: bundle-size history
Scenario Current (gzip) Delta vs baseline Raw Brotli Trend
react-router.minimal 87.68 KiB 0 B (0.00%) 276.45 KiB 76.18 KiB ██▅▅▅▅▅▄▄▁▁
react-router.full 90.91 KiB 0 B (0.00%) 287.44 KiB 78.81 KiB ██▄▄▅▅▅▄▄▁▁
solid-router.minimal 35.67 KiB 0 B (0.00%) 107.58 KiB 32.03 KiB ██▃▃▃▃▃▁▁▁▁
solid-router.full 40.07 KiB 0 B (0.00%) 120.98 KiB 35.88 KiB ██▂▂▃▃▃▁▁▁▁
vue-router.minimal 53.42 KiB 0 B (0.00%) 153.38 KiB 47.83 KiB ██▅▅▅▅▅▅▅▁▁
vue-router.full 58.31 KiB 0 B (0.00%) 168.85 KiB 52.13 KiB ██▄▄▅▅▅▅▅▁▁
react-start.minimal 102.09 KiB 0 B (0.00%) 324.47 KiB 88.22 KiB ██▄▄▅▅▅▃▃▁▁
react-start.full 105.48 KiB 0 B (0.00%) 334.78 KiB 91.21 KiB ██▄▄▅▅▅▄▄▁▁
solid-start.minimal 49.74 KiB 0 B (0.00%) 153.76 KiB 43.89 KiB ██▃▃▃▃▃▁▁▁▁
solid-start.full 55.22 KiB 0 B (0.00%) 169.86 KiB 48.53 KiB ██▂▂▃▃▃▁▁▁▁

Trend sparkline is historical gzip bytes ending with this PR measurement; lower is better.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 26, 2026

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/@tanstack/arktype-adapter@7044

@tanstack/eslint-plugin-router

npm i https://pkg.pr.new/@tanstack/eslint-plugin-router@7044

@tanstack/history

npm i https://pkg.pr.new/@tanstack/history@7044

@tanstack/nitro-v2-vite-plugin

npm i https://pkg.pr.new/@tanstack/nitro-v2-vite-plugin@7044

@tanstack/react-router

npm i https://pkg.pr.new/@tanstack/react-router@7044

@tanstack/react-router-devtools

npm i https://pkg.pr.new/@tanstack/react-router-devtools@7044

@tanstack/react-router-ssr-query

npm i https://pkg.pr.new/@tanstack/react-router-ssr-query@7044

@tanstack/react-start

npm i https://pkg.pr.new/@tanstack/react-start@7044

@tanstack/react-start-client

npm i https://pkg.pr.new/@tanstack/react-start-client@7044

@tanstack/react-start-server

npm i https://pkg.pr.new/@tanstack/react-start-server@7044

@tanstack/router-cli

npm i https://pkg.pr.new/@tanstack/router-cli@7044

@tanstack/router-core

npm i https://pkg.pr.new/@tanstack/router-core@7044

@tanstack/router-devtools

npm i https://pkg.pr.new/@tanstack/router-devtools@7044

@tanstack/router-devtools-core

npm i https://pkg.pr.new/@tanstack/router-devtools-core@7044

@tanstack/router-generator

npm i https://pkg.pr.new/@tanstack/router-generator@7044

@tanstack/router-plugin

npm i https://pkg.pr.new/@tanstack/router-plugin@7044

@tanstack/router-ssr-query-core

npm i https://pkg.pr.new/@tanstack/router-ssr-query-core@7044

@tanstack/router-utils

npm i https://pkg.pr.new/@tanstack/router-utils@7044

@tanstack/router-vite-plugin

npm i https://pkg.pr.new/@tanstack/router-vite-plugin@7044

@tanstack/solid-router

npm i https://pkg.pr.new/@tanstack/solid-router@7044

@tanstack/solid-router-devtools

npm i https://pkg.pr.new/@tanstack/solid-router-devtools@7044

@tanstack/solid-router-ssr-query

npm i https://pkg.pr.new/@tanstack/solid-router-ssr-query@7044

@tanstack/solid-start

npm i https://pkg.pr.new/@tanstack/solid-start@7044

@tanstack/solid-start-client

npm i https://pkg.pr.new/@tanstack/solid-start-client@7044

@tanstack/solid-start-server

npm i https://pkg.pr.new/@tanstack/solid-start-server@7044

@tanstack/start-client-core

npm i https://pkg.pr.new/@tanstack/start-client-core@7044

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/@tanstack/start-fn-stubs@7044

@tanstack/start-plugin-core

npm i https://pkg.pr.new/@tanstack/start-plugin-core@7044

@tanstack/start-server-core

npm i https://pkg.pr.new/@tanstack/start-server-core@7044

@tanstack/start-static-server-functions

npm i https://pkg.pr.new/@tanstack/start-static-server-functions@7044

@tanstack/start-storage-context

npm i https://pkg.pr.new/@tanstack/start-storage-context@7044

@tanstack/valibot-adapter

npm i https://pkg.pr.new/@tanstack/valibot-adapter@7044

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/@tanstack/virtual-file-routes@7044

@tanstack/vue-router

npm i https://pkg.pr.new/@tanstack/vue-router@7044

@tanstack/vue-router-devtools

npm i https://pkg.pr.new/@tanstack/vue-router-devtools@7044

@tanstack/vue-router-ssr-query

npm i https://pkg.pr.new/@tanstack/vue-router-ssr-query@7044

@tanstack/vue-start

npm i https://pkg.pr.new/@tanstack/vue-start@7044

@tanstack/vue-start-client

npm i https://pkg.pr.new/@tanstack/vue-start-client@7044

@tanstack/vue-start-server

npm i https://pkg.pr.new/@tanstack/vue-start-server@7044

@tanstack/zod-adapter

npm i https://pkg.pr.new/@tanstack/zod-adapter@7044

commit: 0713e9b

Copy link
Contributor

@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)
packages/start-server-core/package.json (1)

85-85: Dependency is upgraded, but still pinned exactly.

Line 85 uses an exact version (2.0.1-rc.19). If the intent is to also unpin, switch to the repo’s preferred range style (for example ^2.0.1-rc.19).

Suggested change
-    "h3": "2.0.1-rc.19",
+    "h3": "^2.0.1-rc.19",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-server-core/package.json` at line 85, The h3 dependency is
pinned to an exact version ("h3": "2.0.1-rc.19"); change that entry in
package.json to use the repo's preferred semver range (e.g., "h3":
"^2.0.1-rc.19") so the dependency is unpinned and follow-up package installs
pick up compatible updates.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/start-server-core/src/request-response.ts`:
- Around line 307-309: The getCookie implementation is converting empty-string
cookie values to undefined by using "cookies[name] || undefined"; update
getCookie to return the indexed value directly (i.e., return cookies[name]) so
that explicit empty values are preserved; locate the getCookie function where
getH3Event() and h3_parseCookies(event) are used and remove the "|| undefined"
fallback.

---

Nitpick comments:
In `@packages/start-server-core/package.json`:
- Line 85: The h3 dependency is pinned to an exact version ("h3":
"2.0.1-rc.19"); change that entry in package.json to use the repo's preferred
semver range (e.g., "h3": "^2.0.1-rc.19") so the dependency is unpinned and
follow-up package installs pick up compatible updates.
🪄 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: e2a7c156-ee4d-481d-be81-705786a19f55

📥 Commits

Reviewing files that changed from the base of the PR and between 87a5160 and 0713e9b.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (2)
  • packages/start-server-core/package.json
  • packages/start-server-core/src/request-response.ts

Comment on lines +307 to +309
const event = getH3Event()
const cookies = h3_parseCookies(event)
return cookies[name] || undefined
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# Check the file exists and view lines 307-309
wc -l packages/start-server-core/src/request-response.ts
sed -n '305,315p' packages/start-server-core/src/request-response.ts

Repository: TanStack/router

Length of output: 407


🏁 Script executed:

# Let's also look for the getCookie function definition and context
sed -n '305,320p' packages/start-server-core/src/request-response.ts

Repository: TanStack/router

Length of output: 493


🏁 Script executed:

# Search for where h3_parseCookies is imported from
rg "h3_parseCookies" packages/start-server-core/src/request-response.ts -B 5 -A 5

Repository: TanStack/router

Length of output: 1108


🏁 Script executed:

# Check package.json to find h3 version
rg '"h3"' packages/start-server-core/package.json

Repository: TanStack/router

Length of output: 83


🏁 Script executed:

# Search for any tests or usage examples of getCookie with empty values
rg "getCookie" packages/start-server-core --type ts -A 3 -B 1 | head -50

Repository: TanStack/router

Length of output: 1351


🏁 Script executed:

# Check if there are any comments or documentation about cookie behavior
rg "cookie" packages/start-server-core/src/request-response.ts -i -B 2 -A 2

Repository: TanStack/router

Length of output: 3291


🏁 Script executed:

# Search for tests related to getCookie function
find packages/start-server-core -name "*.test.*" -o -name "*.spec.*" | xargs rg "getCookie|cookie" 2>/dev/null | head -30

Repository: TanStack/router

Length of output: 41


🏁 Script executed:

# Check if there's any TypeScript type definition or JSDoc for parseCookies
rg "parseCookies" --type ts -B 5 -A 10 | head -50

Repository: TanStack/router

Length of output: 3939


🌐 Web query:

h3 parseCookies TypeScript return type empty string values

💡 Result:

In the h3 library (unjs/h3), the parseCookies(event) utility parses the Cookie header from the request and returns a Record<string, string> (object mapping cookie names to their values as strings). Cookie values are always strings, including empty strings ("") if the cookie was set with an empty value (e.g., name=; Path=/). This is standard behavior for Cookie header parsing using libraries like cookie (jshttp/cookie), which h3 relies on internally. TypeScript treats Record<string, string> as all values being non-nullable strings, so empty string values are fully compatible—no type errors occur. If no cookies are present, it returns {} (empty object), which is also valid. Examples from h3 docs and source: - parseCookies(event) → { cookieName: "cookieValue" } or { cookieName: "" } - getCookie(event, name) → string | undefined (wrapper around parseCookies) No issues or bugs reported specifically about empty string values in TypeScript context. If experiencing type mismatches, ensure proper typing: const cookies: Record<string, string> = parseCookies(event);. For source confirmation, early h3 versions used parse(req.headers.cookie || '') from 'cookie', returning Record<string, string>. Current versions maintain this signature per docs and utils pages.

Citations:


Preserve empty cookie values in getCookie().

Line 309 uses || undefined, which converts valid empty cookie values ('') into undefined. This loses information about whether a cookie was explicitly set to an empty value versus not being set at all. Return the indexed value directly to preserve this distinction.

Suggested fix
 export function getCookie(name: string): string | undefined {
   const event = getH3Event()
   const cookies = h3_parseCookies(event)
-  return cookies[name] || undefined
+  return cookies[name]
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const event = getH3Event()
const cookies = h3_parseCookies(event)
return cookies[name] || undefined
export function getCookie(name: string): string | undefined {
const event = getH3Event()
const cookies = h3_parseCookies(event)
return cookies[name]
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/start-server-core/src/request-response.ts` around lines 307 - 309,
The getCookie implementation is converting empty-string cookie values to
undefined by using "cookies[name] || undefined"; update getCookie to return the
indexed value directly (i.e., return cookies[name]) so that explicit empty
values are preserved; locate the getCookie function where getH3Event() and
h3_parseCookies(event) are used and remove the "|| undefined" fallback.

@codspeed-hq
Copy link

codspeed-hq bot commented Mar 26, 2026

Merging this PR will not alter performance

✅ 6 untouched benchmarks


Comparing ulrichstark:chore-upgrade-and-unpin-h3 (0713e9b) with main (5016e4e)1

Open in CodSpeed

Footnotes

  1. No successful run was found on main (87a5160) during the generation of this report, so 5016e4e was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

@ulrichstark
Copy link
Contributor Author

ulrichstark commented Mar 26, 2026

The e2e test "un-matched malformed paths should return not found on direct navigation" is failing probably because of how h3 now handles malformed paths. I'm not sure what's the best way to continue. I will let the other more experienced contributors decide on how to continue with this PR.

Also no worries if my approach is incorrect and you want to close the PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

start-server-core depends on vulnerable pinned version of h3

1 participant