Skip to content

Conversation

@Sheraff
Copy link
Contributor

@Sheraff Sheraff commented Jan 23, 2026

Problem

We used to extract all route params with regular expressions. This would intrinsically enforce a very strict format for the parameter names: [a-zA-Z$][a-zA-Z0-9$]*, i.e. a valid javascript variable name.

When we rewrote the matcher (#5722), regular params were not matched by a regex anymore ($param) but more complex param syntaxes were still (e.g. prefix{-$optional}suffix). So we were only half enforcing the parameter name, which is not ideal.

Now we would like to move completely off of regexes (#6470) and we should probably enforce some limitations on parameter names, or we risk preventing future evolutions of the syntax if parameter names are too lax, and users start using characters we would eventually like to assign special meaning to.

Solution

This PR proposes we simply add a warning in the console during router generation.

Summary by CodeRabbit

  • New Features

    • Route parameter validation now detects and warns about invalid parameter names during generation, including file and route context to help locate issues.
  • Tests

    • Added tests covering invalid and valid parameter scenarios to ensure warnings are emitted correctly and valid params are ignored.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 23, 2026

📝 Walkthrough

Walkthrough

Adds runtime route-parameter validation to the router generator: a new validator module extracts and checks param names, logs warnings for invalid names, and is invoked during route-node processing. Tests, fixtures, and snapshots for invalid/valid param scenarios were added.

Changes

Cohort / File(s) Summary
Validator module
packages/router-generator/src/validate-route-params.ts
New module extracting params from route segments, validating JS-identifier-like names via regex, skipping wildcards, and emitting warnings via provided logger for invalid names.
Generator integration
packages/router-generator/src/generator.ts
Imported and invoked validateRouteParams(routePath, filePath, logger) when processing RouteNode instances with routePath, placed after file-existence check and before updating route cache.
Unit tests
packages/router-generator/tests/validate-route-params.test.ts
New test that spies on warnings: asserts invalid param names emit warnings and valid names do not.
Test fixtures / snapshots
packages/router-generator/tests/generator/invalid-param-names/*
.../routes/$123.tsx, .../routes/$user-name.tsx, .../routes/$validParam.tsx, .../routes/__root.tsx, .../routeTree.snapshot.ts
Added test route files and generated routeTree snapshot to exercise invalid/valid param name scenarios in generator tests.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Generator as Generator (route-node processor)
  participant FS as FileSystem (exists check)
  participant Validator as validateRouteParams
  participant Logger as Logger

  Generator->>FS: check file exists for node
  alt file exists
    Generator->>Validator: validateRouteParams(routePath, filePath, logger)
    Validator-->>Logger: warn(...) for each invalid param (if any)
    Generator->>Generator: update route cache entry
  else file missing
    Generator-->>Logger: warn about missing file / skip
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • schiller-manuel
  • nlynzaad

Poem

🐰✨ I hopped through files both near and far,
Found names that tripped—numbers and a hyphen star.
I poked and warned with a tiny, polite nudge,
Kept the valid ones cozy, nudged the bad to judge.
🥕

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(router-generator): param name syntax check and warn' directly and accurately summarizes the main change—adding validation and warnings for route parameter names in the router generator.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing touches
  • 📝 Generate docstrings

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

@nx-cloud
Copy link

nx-cloud bot commented Jan 23, 2026

View your CI Pipeline Execution ↗ for commit a517ae5

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

☁️ Nx Cloud last updated this comment at 2026-01-23 22:24:28 UTC

@pkg-pr-new
Copy link

pkg-pr-new bot commented Jan 23, 2026

More templates

@tanstack/arktype-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/arktype-adapter@6472

@tanstack/eslint-plugin-router

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

@tanstack/history

npm i https://pkg.pr.new/TanStack/router/@tanstack/history@6472

@tanstack/nitro-v2-vite-plugin

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

@tanstack/react-router

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

@tanstack/react-router-devtools

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

@tanstack/react-router-ssr-query

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

@tanstack/react-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start@6472

@tanstack/react-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-client@6472

@tanstack/react-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/react-start-server@6472

@tanstack/router-cli

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

@tanstack/router-core

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

@tanstack/router-devtools

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

@tanstack/router-devtools-core

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

@tanstack/router-generator

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

@tanstack/router-plugin

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

@tanstack/router-ssr-query-core

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

@tanstack/router-utils

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

@tanstack/router-vite-plugin

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

@tanstack/solid-router

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

@tanstack/solid-router-devtools

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

@tanstack/solid-router-ssr-query

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

@tanstack/solid-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start@6472

@tanstack/solid-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-client@6472

@tanstack/solid-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/solid-start-server@6472

@tanstack/start-client-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-client-core@6472

@tanstack/start-fn-stubs

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-fn-stubs@6472

@tanstack/start-plugin-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-plugin-core@6472

@tanstack/start-server-core

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-server-core@6472

@tanstack/start-static-server-functions

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

@tanstack/start-storage-context

npm i https://pkg.pr.new/TanStack/router/@tanstack/start-storage-context@6472

@tanstack/valibot-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/valibot-adapter@6472

@tanstack/virtual-file-routes

npm i https://pkg.pr.new/TanStack/router/@tanstack/virtual-file-routes@6472

@tanstack/vue-router

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

@tanstack/vue-router-devtools

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

@tanstack/vue-router-ssr-query

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

@tanstack/vue-start

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start@6472

@tanstack/vue-start-client

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-client@6472

@tanstack/vue-start-server

npm i https://pkg.pr.new/TanStack/router/@tanstack/vue-start-server@6472

@tanstack/zod-adapter

npm i https://pkg.pr.new/TanStack/router/@tanstack/zod-adapter@6472

commit: a517ae5

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

🤖 Fix all issues with AI agents
In `@packages/router-generator/src/validate-route-params.ts`:
- Around line 55-58: The variable `match` is implicitly any; explicitly type it
as the return type of RegExp.exec to satisfy strict TypeScript: declare `match`
as `RegExpExecArray | null` (e.g., `let match: RegExpExecArray | null = null`)
before the loop that uses `bracePattern.exec(segment)`, so the while loop `while
((match = bracePattern.exec(segment)) !== null)` remains valid; update the
declaration near `bracePattern` and `segment` in validate-route-params to use
this explicit type.

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

🤖 Fix all issues with AI agents
In `@packages/router-generator/tests/validate-route-params.test.ts`:
- Around line 7-33: The console.warn spy (warnSpy) can leak if generator.run()
throws; wrap the test's async work (creating Generator, awaiting
generator.run(), and assertions) in a try/finally and call warnSpy.mockRestore()
in the finally block so the spy is always restored; locate the warnSpy
declaration and the await generator.run() call in this test and move the
existing assertions into the try, leaving only warnSpy.mockRestore() inside
finally to guarantee restoration even on failure.

@Sheraff Sheraff merged commit 6c1e215 into main Jan 23, 2026
6 checks passed
@Sheraff Sheraff deleted the feat-router-generator-param-name-syntax-checker branch January 23, 2026 22:27
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.

2 participants