fix(router-generator): harden route file transform rewrites#7167
Conversation
📝 WalkthroughWalkthroughRemoves verboseFileRoutes and auto-import plugin, switches generated and example route files to curried form (e.g., createFileRoute('/path')({...})), rewrites transform to synchronous Babel + MagicString edits preserving quotes and safer import handling, updates generator templates, deps, tests, and e2e/example files accordingly. Changes
Sequence Diagram(s)mermaid Editor->>Generator: save route tree / run generator Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested reviewers
Poem
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
|
|
View your CI Pipeline Execution ↗ for commit 1e68341
☁️ Nx Cloud last updated this comment at |
🚀 Changeset Version Preview4 package(s) bumped directly, 14 bumped as dependents. 🟩 Patch bumps
|
Bundle Size Benchmarks
Trend sparkline is historical gzip bytes ending with this PR measurement; lower is better. |
There was a problem hiding this comment.
Actionable comments posted: 4
Note
Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.
🧹 Nitpick comments (1)
e2e/vue-router/basic-virtual-file-based/src/routes/home.tsx (1)
1-2: Add the required blank line after the import.Line 1 violates
import/newline-after-import, which will fail lint checks.Proposed fix
import { createFileRoute } from '@tanstack/vue-router' + export const Route = createFileRoute('/')({ component: Home, })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@e2e/vue-router/basic-virtual-file-based/src/routes/home.tsx` around lines 1 - 2, Add a blank line after the import statement to satisfy the import/newline-after-import rule: insert an empty line between the import { createFileRoute }... statement and the export const Route = createFileRoute('/') { ... } declaration so the import is followed by a single newline.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@e2e/vue-start/basic-vue-query/src/routes/posts`.$postId.tsx:
- Line 6: The import for ErrorComponentProps is being brought in as a value
import but it's only used as a type (e.g., in the error component signature in
posts.$postId.tsx); change the import to a type-only import (use the TS `type {
ErrorComponentProps }` form) so the compiler and linters treat it as a type
import and the import-order rule is satisfied; update the import statement that
currently includes ErrorComponentProps to `type { ErrorComponentProps }` while
leaving other imports unchanged.
In `@packages/router-generator/src/index.ts`:
- Line 48: The package root removed the TransformImportsConfig type export which
can break downstream TypeScript imports; restore a compatibility export for
TransformImportsConfig by re-exporting it from the original module (export type
{ TransformImportsConfig } from './transform/types') alongside the existing
export of TransformContext and TransformOptions in index.ts, and add a JSDoc
`@deprecated` comment to the TransformImportsConfig export to mark it as
compatibility-only if you intend to keep it for a patch release (or
alternatively prepare to bump the package major/minor and document the breaking
change if you do not re-export).
In `@packages/router-generator/src/template.ts`:
- Around line 79-82: The template currently interpolates routePath raw into
generated code (e.g., tsrExportStart uses `createFileRoute('${routePath}')(`),
which breaks when route ids contain quotes; update all occurrences
(tsrExportStart, the corresponding createLazyFileRoute branch(s), and equivalent
Solid and Vue template functions) to serialize routePath with
JSON.stringify(routePath) when embedding into the generated string so the value
is properly escaped; ensure every template that currently does `'${routePath}'`
uses the JSON.stringify approach to produce a valid JS/TS literal.
In `@packages/router-generator/src/transform/transform.ts`:
- Around line 10-13: The normalization currently loses
ImportSpecifier.importKind because the NamedImport type only has imported/local;
update the NamedImport shape to include importKind (e.g., "type" | "value" |
undefined) and propagate that field through the router import normalization code
(the normalization pass that transforms import specifiers) so that imports
declared as type-only remain type-only; also update any equality/dedup helper
functions that compare NamedImport entries (used in deduping/merging imports) to
include importKind in their comparison logic so type vs value imports are not
collapsed into each other.
---
Minor comments:
In
`@e2e/react-router/basic-file-based-code-splitting/src/routes/_layout/_layout-2/layout-a.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy the
import/newline-after-import lint rule: in the file where createFileRoute is
imported and Route is exported, insert one empty line between the import line
(import { createFileRoute } from '@tanstack/react-router') and the export
declaration (export const Route = createFileRoute(...)) so the import is
separated from the code that follows.
In
`@e2e/react-router/basic-file-based-code-splitting/src/routes/_layout/_layout-2/layout-b.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy the
import/newline-after-import lint rule: insert a single empty line between the
import { createFileRoute } from '@tanstack/react-router' line and the export
const Route = createFileRoute('/_layout/_layout-2/layout-b')({ declaration so
the import and the Route/createFileRoute usage are separated.
In
`@e2e/react-router/basic-file-based-code-splitting/src/routes/viewport-test.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy the
import/newline-after-import rule: insert an empty line between the "import {
createFileRoute } from '@tanstack/react-router'" line and the "export const
Route = createFileRoute('/viewport-test')({" declaration so the
createFileRoute/Route block starts on its own paragraph.
In
`@e2e/react-router/basic-file-based-code-splitting/src/routes/without-loader.tsx`:
- Around line 1-2: Add a blank line after the import statement in
without-loader.tsx so the file conforms to the import/newline-after-import rule;
specifically, place a single empty line between the import of createFileRoute
and the export of Route (the createFileRoute('/without-loader') call) to satisfy
linting.
In `@e2e/react-router/basic-virtual-file-based/src/routes/a.tsx`:
- Around line 1-2: The import statement and the subsequent export currently lack
a blank line; add a single empty line after the import { createFileRoute } from
'@tanstack/react-router' so the export const Route =
createFileRoute('/_first/_second/layout-a')({ ... }) starts on a new paragraph,
resolving the import/newline-after-import lint rule and keeping createFileRoute
and Route unchanged.
In `@e2e/react-router/basic-virtual-file-based/src/routes/b.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy
ESLint's import/newline-after-import rule; specifically, in the file where you
call createFileRoute (the import line and the export const Route =
createFileRoute('/_first/_second/layout-b')({...}) block), insert one empty line
between the import { createFileRoute } ... line and the export const Route ...
line.
In
`@e2e/react-router/basic-virtual-file-based/src/routes/file-based-subtree/hello/index.tsx`:
- Around line 1-2: The import statement at the top lacks the required blank
line; add a single empty line after "import { createFileRoute } from
'@tanstack/react-router'" so the file conforms to the
import/newline-after-import rule and before the createFileRoute call that
defines the exported Route constant.
In
`@e2e/react-router/basic-virtual-file-based/src/routes/file-based-subtree/hello/universe.tsx`:
- Around line 1-2: Add a single blank line between the import statement and the
export declaration to satisfy ESLint spacing rules: leave the import of
createFileRoute as-is and insert one empty line before the export const Route =
createFileRoute('/classic/hello/universe')({ ... so the file has an empty line
separating the import and the Route export.
In
`@e2e/react-router/basic-virtual-file-based/src/routes/file-based-subtree/hello/world.tsx`:
- Around line 1-2: The file is missing a blank line after the import which trips
the import/newline-after-import ESLint rule; update the top of the file by
inserting a single empty line between the import statement and the subsequent
code so the import line "import { createFileRoute } from
'@tanstack/react-router'" is followed by a blank line before the "export const
Route = createFileRoute('/classic/hello/world')({" declaration.
In
`@e2e/react-router/basic-virtual-named-export-config-file-based/src/routes/a.tsx`:
- Around line 1-2: Add a blank line after the import statement so the import and
the Route declaration are separated (fixes import/newline-after-import); locate
the import of createFileRoute and the exported Route constant
(createFileRoute('/_first/_second/layout-a') assigned to Route) and insert a
single empty line between them.
In
`@e2e/react-router/basic-virtual-named-export-config-file-based/src/routes/b.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy lint
spacing: in b.tsx, leave the existing import of createFileRoute but insert an
empty line before the export of Route (the
createFileRoute('/_first/_second/layout-b') call) so the import and the exported
Route are separated by one blank line.
In
`@e2e/react-router/basic-virtual-named-export-config-file-based/src/routes/file-based-subtree/hello/index.tsx`:
- Around line 1-2: Add a single blank line after the import statement so the
export sits separated per ESLint rule import/newline-after-import; specifically,
insert an empty line between the "import { createFileRoute } from
'@tanstack/react-router'" line and the "export const Route =
createFileRoute('/classic/hello/')({" declaration (symbols: createFileRoute,
Route).
In
`@e2e/react-router/basic-virtual-named-export-config-file-based/src/routes/file-based-subtree/hello/universe.tsx`:
- Around line 1-2: Add a blank line after the import statement so the file
satisfies the import/newline-after-import rule: insert an empty line between the
import line (import { createFileRoute } from '@tanstack/react-router') and the
export definition for Route (export const Route =
createFileRoute('/classic/hello/universe')({...})).
In
`@e2e/react-router/basic-virtual-named-export-config-file-based/src/routes/file-based-subtree/hello/world.tsx`:
- Around line 1-2: The file's import line and the export declaration for Route
violate the import/newline-after-import rule; insert a single blank line after
the import statement "import { createFileRoute } from '@tanstack/react-router'"
so that the export const Route = createFileRoute('/classic/hello/world')({ ...
}) declaration is separated by one empty line.
In
`@e2e/solid-router/basic-file-based-code-splitting/src/routes/_layout/_layout-2/layout-a.tsx`:
- Around line 1-2: Add a newline after the import statement so the import and
export are on separate lines: separate the "import { createFileRoute } from
'@tanstack/solid-router'" and the "export const Route =
createFileRoute('/_layout/_layout-2/layout-a')({" by inserting one blank line
between them to satisfy lint rules and keep the import for createFileRoute and
the Route export distinct.
In
`@e2e/solid-router/basic-file-based-code-splitting/src/routes/_layout/_layout-2/layout-b.tsx`:
- Around line 1-2: Add a blank line after the top import statement to satisfy
the import/newline-after-import rule; open the file where you call
createFileRoute and export Route (the export const Route =
createFileRoute('/_layout/_layout-2/layout-b') line) and insert a single empty
line between the import { createFileRoute } ... line and the export declaration.
In `@e2e/solid-router/basic-file-based-code-splitting/src/routes/index.tsx`:
- Around line 1-2: There is an ESLint import/newline-after-import violation: add
a single blank line after the import statement so the export declaration for
Route (created via createFileRoute) is separated from the import; update the top
of the file where createFileRoute is imported and the export const Route =
createFileRoute('/')({ ... }) appears to insert one empty line between them.
In `@e2e/solid-router/basic-file-based-code-splitting/src/routes/posts.index.tsx`:
- Around line 1-2: Add a single blank line between the import and the exported
Route declaration to satisfy ESLint: leave the existing import of
createFileRoute from '@tanstack/solid-router' as-is and insert one empty line
before the "export const Route = createFileRoute('/posts/')({" declaration so
there is a blank line separating the import and the exported Route.
In
`@e2e/solid-router/basic-file-based-code-splitting/src/routes/viewport-test.tsx`:
- Around line 1-2: Add a blank line after the import statement so the
import/newline-after-import lint rule is satisfied; specifically, in the file
where you call createFileRoute (the import line "import { createFileRoute } from
'@tanstack/solid-router'"), insert a single empty line before the declaration of
Route (the createFileRoute('/viewport-test') call).
In
`@e2e/solid-router/basic-file-based-code-splitting/src/routes/without-loader.tsx`:
- Around line 1-2: The import statement and the Route declaration need a blank
line between them to satisfy the import/newline-after-import rule; update the
file so there is an empty line after the import of createFileRoute from
'@tanstack/solid-router' before the export const Route =
createFileRoute('/without-loader')({ ... }) declaration.
In `@e2e/solid-router/basic-virtual-file-based/src/routes/a.tsx`:
- Around line 1-2: Add a single blank line after the import statement so there
is an empty line between "import { createFileRoute } from
'@tanstack/solid-router'" and the "export const Route =
createFileRoute('/_first/_second/layout-a')({" declaration; this satisfies the
import/newline-after-import rule and keeps the import and the Route export
visually separated.
In `@e2e/solid-router/basic-virtual-file-based/src/routes/b.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy the
import/newline-after-import rule: insert a single empty line between the import
{ createFileRoute } from '@tanstack/solid-router' statement and the export const
Route = createFileRoute('/_first/_second/layout-b')({ declaration so the import
and the export (Route / createFileRoute) are separated by a newline.
In
`@e2e/solid-router/basic-virtual-file-based/src/routes/file-based-subtree/hello/index.tsx`:
- Around line 1-2: The file is missing a blank line after the import which
triggers the import/newline-after-import lint rule; update the top of the file
by adding a single empty line immediately after the import statement (the line
with "import { createFileRoute } from '@tanstack/solid-router'") so the export
line that defines Route via createFileRoute('/classic/hello/') is separated by
one blank line.
In
`@e2e/solid-router/basic-virtual-file-based/src/routes/file-based-subtree/hello/universe.tsx`:
- Around line 1-2: The file is missing a blank line after the import which
violates the import/newline-after-import lint rule; update the top of the module
so there is one empty line between the import statement for createFileRoute and
the exported Route declaration (the createFileRoute('/classic/hello/universe')
call) to satisfy the rule.
In
`@e2e/solid-router/basic-virtual-file-based/src/routes/file-based-subtree/hello/world.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy the
import/newline-after-import lint rule; in this file, insert an empty line
between the import { createFileRoute } from '@tanstack/solid-router' and the
export const Route = createFileRoute('/classic/hello/world')({ so the import and
the Route definition are separated.
In `@e2e/solid-router/basic-virtual-file-based/src/routes/home.tsx`:
- Around line 1-2: The file imports createFileRoute then immediately exports
Route without a separating blank line; update the top of the file so there is
one empty line after the import statement (the line containing "import {
createFileRoute } from '@tanstack/solid-router'") before the export of Route
(the createFileRoute('/') call) to satisfy linting/spacing rules.
In
`@e2e/solid-router/basic-virtual-named-export-config-file-based/src/routes/a.tsx`:
- Around line 1-2: Add a blank line after the import statement so the export
isn't directly adjacent to the import: insert an empty line between the "import
{ createFileRoute } from '@tanstack/solid-router'" line and the "export const
Route = createFileRoute('/_first/_second/layout-a')({" declaration to satisfy
the import/newline-after-import ESLint rule.
In
`@e2e/solid-router/basic-virtual-named-export-config-file-based/src/routes/b.tsx`:
- Around line 1-2: The import statement and export are missing the required
blank line; add a single empty line after the import of createFileRoute so the
file reads the import, a blank line, then the export declaration (i.e., the
createFileRoute(...) call for the exported Route) to satisfy lint rules.
In
`@e2e/solid-router/basic-virtual-named-export-config-file-based/src/routes/file-based-subtree/hello/index.tsx`:
- Around line 1-2: Add a blank line after the import statement so the file
satisfies ESLint's import/newline-after-import rule; specifically, after the
line importing createFileRoute from '@tanstack/solid-router' (the import that
precedes the exported Route created by createFileRoute('/classic/hello/') and
assigned to Route), insert a single empty line before the export to separate
imports from module code.
In
`@e2e/solid-router/basic-virtual-named-export-config-file-based/src/routes/file-based-subtree/hello/universe.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy the
import/newline-after-import rule: open the file containing the import of
createFileRoute and the exported Route (the import line and the export const
Route = createFileRoute('/classic/hello/universe')({...})), insert a single
empty line immediately after the import line so the import is separated from the
subsequent code.
In
`@e2e/solid-router/basic-virtual-named-export-config-file-based/src/routes/file-based-subtree/hello/world.tsx`:
- Around line 1-2: Add a single blank line after the import statement so the
file satisfies the import/newline-after-import lint rule; specifically insert an
empty line between the "import { createFileRoute } from
'@tanstack/solid-router'" line and the declaration of Route created with
createFileRoute('/classic/hello/world') to separate imports from the Route
definition.
In
`@e2e/solid-router/basic-virtual-named-export-config-file-based/src/routes/home.tsx`:
- Around line 1-2: The file violates the import/newline-after-import rule: add a
single blank line immediately after the import statement so the import line
"import { createFileRoute } from '@tanstack/solid-router'" is followed by an
empty line before the "export const Route = createFileRoute('/')({" declaration;
this will satisfy ESLint without changing the createFileRoute or Route
identifiers.
In
`@e2e/solid-router/basic-virtual-named-export-config-file-based/src/routes/posts/posts-home.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy the
import/newline-after-import rule: place an empty line between the "import {
createFileRoute } from '@tanstack/solid-router'" statement and the export of
Route (the createFileRoute('/posts/') call) so the import is separated from the
subsequent "export const Route" declaration.
In `@e2e/vue-router/basic-virtual-file-based/src/routes/a.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy the
import/newline-after-import rule: locate the import of createFileRoute and the
subsequent export const Route = createFileRoute(...) and insert a single empty
line between them so the file has a newline separating imports from the rest of
the code.
In `@e2e/vue-router/basic-virtual-file-based/src/routes/b.tsx`:
- Around line 1-2: The file breaks the import/newline-after-import rule because
there is no blank line after the import; add a single blank line between the
import statement and the export declaration so the import (createFileRoute) is
followed by an empty line before the export const Route =
createFileRoute('/_first/_second/layout-b')({ ... }) line.
In
`@e2e/vue-router/basic-virtual-file-based/src/routes/file-based-subtree/hello/index.tsx`:
- Around line 1-2: Add a blank line after the import statement at the top of the
file to satisfy the import/newline-after-import rule; specifically, insert one
empty line between the import { createFileRoute } from '@tanstack/vue-router'
line and the export const Route = createFileRoute('/classic/hello/')({
declaration so the import and the Route/createFileRoute block are separated by a
single newline.
In
`@e2e/vue-router/basic-virtual-file-based/src/routes/file-based-subtree/hello/universe.tsx`:
- Around line 1-2: The file is missing a blank line after the import which
violates the import/newline-after-import rule; add a single empty line
immediately after the import statement that references createFileRoute (the line
that defines Route = createFileRoute(...)) so there is one blank line between
the import and the export/Route declaration.
In
`@e2e/vue-router/basic-virtual-file-based/src/routes/file-based-subtree/hello/world.tsx`:
- Around line 1-2: Add a single blank line after the import statement to satisfy
the import/newline-after-import lint rule: in world.tsx, after "import {
createFileRoute } from '@tanstack/vue-router'" insert one empty line before the
export declaration ("export const Route =
createFileRoute('/classic/hello/world')({") so the import and the following
export are separated by a blank line.
In `@e2e/vue-router/basic-virtual-file-based/src/routes/posts/posts-home.tsx`:
- Around line 1-2: The file violates the import/newline-after-import rule
because the import statement is immediately followed by code; add a single blank
line after the import of createFileRoute so the top of file reads the import,
one empty line, then the export of Route (the createFileRoute('/posts/') call)
to satisfy ESLint.
In
`@e2e/vue-router/basic-virtual-named-export-config-file-based/src/routes/a.tsx`:
- Around line 1-2: The import statement for createFileRoute lacks a trailing
blank line which violates the import/newline-after-import rule; add a single
empty line immediately after the import line (the one importing createFileRoute)
before the export const Route = createFileRoute(...) declaration to separate
imports from the module code.
In
`@e2e/vue-router/basic-virtual-named-export-config-file-based/src/routes/b.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy
import/newline-after-import: locate the import of createFileRoute (import {
createFileRoute } from '@tanstack/vue-router') and insert one empty line before
the export const Route = createFileRoute(... ) declaration so the import and the
Route declaration are separated by a blank line.
In
`@e2e/vue-router/basic-virtual-named-export-config-file-based/src/routes/file-based-subtree/hello/index.tsx`:
- Around line 1-2: The import and export are on adjacent lines violating ESLint
spacing rules; add a single blank line after the import statement so the import
line (import { createFileRoute } from '@tanstack/vue-router') is separated from
the export declaration (export const Route =
createFileRoute('/classic/hello/')({) to satisfy ESLint formatting.
In
`@e2e/vue-router/basic-virtual-named-export-config-file-based/src/routes/file-based-subtree/hello/universe.tsx`:
- Around line 1-2: Insert a blank line immediately after the import statement in
file-based-subtree/hello/universe.tsx so the import statement "import {
createFileRoute } from '@tanstack/vue-router'" is followed by an empty line
before the export/Route definition (the
createFileRoute('/classic/hello/universe') call), addressing the
import/newline-after-import rule.
In
`@e2e/vue-router/basic-virtual-named-export-config-file-based/src/routes/file-based-subtree/hello/world.tsx`:
- Around line 1-2: Add a single blank line after the import statement to satisfy
the import/newline-after-import rule: ensure the file has a blank line between
the "import { createFileRoute } from '@tanstack/vue-router'" line and the
"export const Route = createFileRoute('/classic/hello/world')({" declaration so
that the import is separated from the export/Route definition.
In
`@e2e/vue-router/basic-virtual-named-export-config-file-based/src/routes/home.tsx`:
- Around line 1-2: The import line importing createFileRoute should be followed
by a blank line to satisfy the import/newline-after-import rule; open the module
containing the top-level import and the export const Route =
createFileRoute('/')({...}) declaration and insert a single empty line
immediately after the import statement so there is a blank line between the
import and the export.
In
`@e2e/vue-router/basic-virtual-named-export-config-file-based/src/routes/posts/posts-detail.tsx`:
- Around line 9-12: Remove the unnecessary type cast on the route's error
component: in the Route created by createFileRoute('/posts/$postId') change the
errorComponent assignment so it uses the strongly-typed PostErrorComponent
directly (remove "as any"); ensure PostErrorComponent conforms to
ErrorComponentProps and assign it to the errorComponent property without casting
so type safety is preserved.
In
`@e2e/vue-router/basic-virtual-named-export-config-file-based/src/routes/posts/posts-home.tsx`:
- Around line 1-2: The file is missing a required blank line after the import
which breaks the import/newline-after-import lint rule; add a single empty line
immediately after the import statement "import { createFileRoute } from
'@tanstack/vue-router'" so the exported constant "export const Route =
createFileRoute('/posts/')({" is separated by one blank line from the import.
In `@examples/react/basic-virtual-file-based/src/routes/a.tsx`:
- Around line 1-2: The linter rule import/newline-after-import is failing
because there's no blank line after the import; update the top of the module
containing the import statement for createFileRoute and the export const Route =
createFileRoute(...) by inserting a single empty line immediately after the
import block (i.e., after the line "import { createFileRoute } from
'@tanstack/react-router'") so there is one blank line before the next statement.
In `@examples/react/basic-virtual-file-based/src/routes/b.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy the
import/newline-after-import ESLint rule: insert one empty line between the
"import { createFileRoute } from '@tanstack/react-router'" line and the
subsequent "export const Route = createFileRoute(" line so the import is
separated from the Route declaration.
In
`@examples/react/basic-virtual-file-based/src/routes/file-based-subtree/hello/index.tsx`:
- Around line 1-2: Add a blank line after the import statement so the file
follows the import/newline-after-import rule; specifically insert an empty line
between the import of createFileRoute and the export of Route (the
createFileRoute('/classic/hello/') call) to separate imports from code.
In
`@examples/react/basic-virtual-file-based/src/routes/file-based-subtree/hello/universe.tsx`:
- Around line 1-2: The file violates the import/newline-after-import rule; add a
single blank line after the import statement so the import of createFileRoute is
separated from the export declaration for Route (the
createFileRoute('/classic/hello/universe') call), i.e., insert one empty line
between the import line and the export const Route line.
In
`@examples/react/basic-virtual-file-based/src/routes/file-based-subtree/hello/world.tsx`:
- Around line 1-2: The import statement and the export need a separating blank
line to satisfy the import/newline-after-import rule; update the file that
defines Route (the createFileRoute('/classic/hello/world') export) by inserting
a single empty line between the import line "import { createFileRoute } from
'@tanstack/react-router'" and the "export const Route = createFileRoute(...)"
declaration so the import is followed by one blank line.
In
`@examples/react/basic-virtual-inside-file-based/src/routes/_layout/_layout-2/layout-a.tsx`:
- Around line 1-2: The import spacing violates ESLint rule
import/newline-after-import; in the module that defines Route using
createFileRoute (the export const Route =
createFileRoute('/_layout/_layout-2/layout-a')({...}) block), add a single blank
line immediately after the import statement (after "import { createFileRoute }
from '@tanstack/react-router'") so there's one empty line between the import and
the Route declaration.
In
`@examples/react/basic-virtual-inside-file-based/src/routes/_layout/_layout-2/layout-b.tsx`:
- Around line 1-2: Add a blank line after the top import to satisfy the
import/newline-after-import ESLint rule: insert one empty line between the
import statement for createFileRoute and the export const Route =
createFileRoute('/_layout/_layout-2/layout-b')({ line so that the import is
separated from the route declaration.
In
`@examples/react/basic-virtual-inside-file-based/src/routes/posts/lets-go/deeper/home.tsx`:
- Around line 1-2: The linter complains about a missing blank line after the
import; update the top of the module so there is exactly one empty line between
the import statement and the route declaration: add a blank line after the
"import { createFileRoute } from '@tanstack/react-router'" line before the
"export const Route = createFileRoute('/posts/inception/deeper/')({" declaration
to satisfy import/newline-after-import.
In
`@examples/react/basic-virtual-inside-file-based/src/routes/posts/lets-go/index.tsx`:
- Around line 1-2: The import/newline-after-import lint rule is violated because
there is no blank line after the import; insert a single blank line after the
import statement "import { createFileRoute } from '@tanstack/react-router'" so
that the export declaration "export const Route =
createFileRoute('/posts/inception/')({" is separated by one empty line.
In `@examples/react/search-validator-adapters/src/routes/users/arktype.index.tsx`:
- Line 2: The import named specifiers are out of alphabetical order causing the
sort-imports lint rule to fail; reorder the named imports in the import
statement so they are alphabetized (swap useNavigate and createFileRoute) in the
line that imports useNavigate and createFileRoute to satisfy ESLint.
In `@examples/react/search-validator-adapters/src/routes/users/valibot.index.tsx`:
- Line 2: The named imports from '@tanstack/react-router' are not alphabetically
ordered; change the import specifiers in the statement that currently lists
"useNavigate, createFileRoute" so the members are sorted alphabetically (i.e.,
"createFileRoute, useNavigate") to satisfy the sort-imports rule and avoid lint
failures.
In `@examples/react/search-validator-adapters/src/routes/users/zod.index.tsx`:
- Line 2: The named imports from '@tanstack/react-router' are not alphabetized;
reorder the import specifiers so they follow alphabetical order (place
createFileRoute before useNavigate) in the import statement that currently lists
useNavigate and createFileRoute to satisfy the sort-imports rule.
In `@examples/solid/basic-virtual-file-based/src/routes/a.tsx`:
- Around line 1-2: Add a blank line after the import statement so ESLint's
import/newline-after-import rule is satisfied: insert an empty line between the
"import { createFileRoute } from '@tanstack/solid-router'" line and the "export
const Route = createFileRoute(" line (i.e., ensure a blank line separates the
import from the export creating Route).
In `@examples/solid/basic-virtual-file-based/src/routes/b.tsx`:
- Line 1: The file's first line imports createFileRoute but lacks the required
blank line after imports (violates import/newline-after-import); add a single
empty line immediately after the import statement for createFileRoute so there
is one blank line between the import and the following export/JSX code or export
of the route component.
In
`@examples/solid/basic-virtual-file-based/src/routes/file-based-subtree/hello/index.tsx`:
- Around line 1-2: The import statement at the top is missing a trailing blank
line which breaks the import/newline-after-import rule; add a single blank line
immediately after the import line so the file starts with the import followed by
a blank line and then the export definition (the export const Route =
createFileRoute(...) block) to satisfy the linter.
In
`@examples/solid/basic-virtual-file-based/src/routes/file-based-subtree/hello/universe.tsx`:
- Around line 1-2: The file is missing a blank line after the import statement
which triggers the import/newline-after-import lint rule; add a single newline
immediately after the "import { createFileRoute } from '@tanstack/solid-router'"
line so the subsequent export const Route =
createFileRoute('/classic/hello/universe')({ ... }) statement is separated.
Ensure the blank line stays between the import and the Route declaration
(referencing createFileRoute and Route) and commit the change.
In
`@examples/solid/basic-virtual-file-based/src/routes/file-based-subtree/hello/world.tsx`:
- Around line 1-2: Add a blank line immediately after the import statement to
satisfy the import/newline-after-import rule; locate the top-level import
"import { createFileRoute } from '@tanstack/solid-router'" and insert one empty
line before the subsequent declaration of "export const Route =
createFileRoute('/classic/hello/world')({".
In `@examples/solid/basic-virtual-file-based/src/routes/home.tsx`:
- Line 1: Add a single blank line immediately after the import of
createFileRoute to separate imports from the Route export; locate the import
statement "import { createFileRoute } from '@tanstack/solid-router'" and ensure
there's an empty line before the subsequent Route export (the code that uses
createFileRoute or exports Route) to satisfy the import/newline-after-import
rule.
In `@examples/solid/basic-virtual-file-based/src/routes/posts/posts-home.tsx`:
- Line 1: The file has an import statement "import { createFileRoute } from
'@tanstack/solid-router'" that is immediately followed by an export which
violates the import/newline-after-import rule; open posts-home.tsx and insert a
single blank line after the import statement (the line importing
createFileRoute) so there is a clear newline between imports and the following
export/other top-level code.
In
`@examples/solid/basic-virtual-inside-file-based/src/routes/_layout/_layout-2/layout-a.tsx`:
- Around line 1-2: There is no blank line after the import which triggers the
import/newline-after-import lint rule; add a single empty line between the
import statement and the Route export (the
createFileRoute('/_layout/_layout-2/layout-a') export) so the import and the
export are separated by one blank line.
In
`@examples/solid/basic-virtual-inside-file-based/src/routes/_layout/_layout-2/layout-b.tsx`:
- Around line 1-2: The import statement and the subsequent export are on
consecutive lines; insert a single blank line after the import of
createFileRoute so the statement "import { createFileRoute } from
'@tanstack/solid-router'" is followed by an empty line before the "export const
Route = createFileRoute('/_layout/_layout-2/layout-b')({" line to satisfy the
import/newline-after-import rule and keep the createFileRoute/Route declaration
separated from imports.
In `@examples/solid/basic-virtual-inside-file-based/src/routes/index.tsx`:
- Around line 1-2: Insert a blank line after the import statement so the import
and export are separated (add an empty line after "import { createFileRoute }
from '@tanstack/solid-router'"); this will satisfy the
import/newline-after-import rule and keep the export const Route =
createFileRoute('/')({ ... }) block on a new line.
In `@examples/solid/basic-virtual-inside-file-based/src/routes/posts/home.tsx`:
- Around line 1-2: Add a blank line after the import statement so the import is
separated from executable code; in this file move or insert a single empty line
between the import of createFileRoute and the Route declaration (the
createFileRoute('/posts/') call) to satisfy import/newline-after-import linting.
In
`@examples/solid/basic-virtual-inside-file-based/src/routes/posts/lets-go/deeper/home.tsx`:
- Around line 1-2: Add a single blank line after the import statement so the
import and the export are separated; specifically, in the file where
createFileRoute is imported and Route is declared (the
createFileRoute('/posts/inception/deeper/') export named Route), insert one
empty line between the import { createFileRoute } from '@tanstack/solid-router'
and the export const Route = ... line to satisfy the import/newline-after-import
rule.
In
`@examples/solid/basic-virtual-inside-file-based/src/routes/posts/lets-go/index.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy the
import/newline-after-import rule: insert one empty line between the import {
createFileRoute } from '@tanstack/solid-router' line and the subsequent export
const Route = createFileRoute('/posts/inception/')({ declaration so the import
is separated from the executable code.
In `@examples/solid/search-validator-adapters/src/routes/users/arktype.index.tsx`:
- Line 1: The named imports are out of order for the lint rule: in the import
from '@tanstack/solid-router' place createFileRoute before useNavigate; update
the import specifier list to read createFileRoute, useNavigate (i.e., change
"import { useNavigate, createFileRoute } ..." to list createFileRoute first) so
the named-member order for createFileRoute and useNavigate is correct.
In `@examples/solid/search-validator-adapters/src/routes/users/valibot.index.tsx`:
- Line 1: Sort the named imports on the top import line alphabetically to
satisfy linting: swap the order so createFileRoute appears before useNavigate in
the import statement that currently imports "useNavigate, createFileRoute" (look
for the import from '@tanstack/solid-router'); update that line to import
"createFileRoute, useNavigate".
In `@examples/solid/search-validator-adapters/src/routes/users/zod.index.tsx`:
- Line 1: The import's named members are not alphabetically ordered causing an
ESLint `sort-imports` violation; update the import statement that currently
imports "useNavigate" and "createFileRoute" from '@tanstack/solid-router' so the
named members are sorted alphabetically (i.e., "createFileRoute" before
"useNavigate") to satisfy the linter.
---
Nitpick comments:
In `@e2e/vue-router/basic-virtual-file-based/src/routes/home.tsx`:
- Around line 1-2: Add a blank line after the import statement to satisfy the
import/newline-after-import rule: insert an empty line between the import {
createFileRoute }... statement and the export const Route = createFileRoute('/')
{ ... } declaration so the import is followed by a single newline.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
| Link, | ||
| createFileRoute, | ||
| type ErrorComponentProps, | ||
| ErrorComponentProps, |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Verify TS emit-related compiler options that affect import handling
fd -i 'tsconfig*.json' | while read -r f; do
echo "### $f"
jq '.compilerOptions | {verbatimModuleSyntax, importsNotUsedAsValues, preserveValueImports}' "$f"
done
# Verify how ErrorComponentProps is declared/exported across the repo
rg -n --type=ts -C2 '\bErrorComponentProps\b'Repository: TanStack/router
Length of output: 51023
🏁 Script executed:
cat -n e2e/vue-start/basic-vue-query/src/routes/posts.$postId.tsx | head -20Repository: TanStack/router
Length of output: 142
🏁 Script executed:
fd -t f "posts" e2e/vue-start/basic-vue-query/src/routes/Repository: TanStack/router
Length of output: 290
🏁 Script executed:
cat -n "e2e/vue-start/basic-vue-query/src/routes/posts.\$postId.tsx" | head -20Repository: TanStack/router
Length of output: 775
Use a type-only import for ErrorComponentProps on Line 6.
ErrorComponentProps is only used as a type (Line 10). The current value import violates consistency with the codebase (all similar files use type { ErrorComponentProps }) and the strict type safety guideline. It also triggered the import-order lint error.
Proposed fix
import { useQuery } from '@tanstack/vue-query'
import {
ErrorComponent,
+ type ErrorComponentProps,
Link,
createFileRoute,
- ErrorComponentProps,
} from '@tanstack/vue-router'📝 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.
| ErrorComponentProps, | |
| import { useQuery } from '@tanstack/vue-query' | |
| import { | |
| ErrorComponent, | |
| type ErrorComponentProps, | |
| Link, | |
| createFileRoute, | |
| } from '@tanstack/vue-router' |
🧰 Tools
🪛 ESLint
[error] 6-6: Member 'ErrorComponentProps' of the import declaration should be sorted alphabetically.
(sort-imports)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@e2e/vue-start/basic-vue-query/src/routes/posts`.$postId.tsx at line 6, The
import for ErrorComponentProps is being brought in as a value import but it's
only used as a type (e.g., in the error component signature in
posts.$postId.tsx); change the import to a type-only import (use the TS `type {
ErrorComponentProps }` form) so the compiler and linters treat it as a type
import and the import-order rule is satisfied; update the import statement that
currently includes ErrorComponentProps to `type { ErrorComponentProps }` while
leaving other imports unchanged.
| TransformContext, | ||
| TransformOptions, | ||
| } from './transform/types' | ||
| export type { TransformContext, TransformOptions } from './transform/types' |
There was a problem hiding this comment.
Potential patch-level breaking API change at package root.
If TransformImportsConfig was previously exported here, removing it will break downstream TypeScript imports. With a patch release, keep a deprecated compatibility export (or bump release level and document migration).
Compatibility-oriented option
export type { TransformContext, TransformOptions } from './transform/types'
+// Back-compat for existing consumers importing from package root
+// (adjust alias shape to match current transform types)
+export type { TransformImportsConfig } from './transform/types'🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/router-generator/src/index.ts` at line 48, The package root removed
the TransformImportsConfig type export which can break downstream TypeScript
imports; restore a compatibility export for TransformImportsConfig by
re-exporting it from the original module (export type { TransformImportsConfig }
from './transform/types') alongside the existing export of TransformContext and
TransformOptions in index.ts, and add a JSDoc `@deprecated` comment to the
TransformImportsConfig export to mark it as compatibility-only if you intend to
keep it for a patch release (or alternatively prepare to bump the package
major/minor and document the breaking change if you do not re-export).
There was a problem hiding this comment.
Actionable comments posted: 2
♻️ Duplicate comments (1)
packages/router-generator/src/transform/transform.ts (1)
10-23:⚠️ Potential issue | 🟠 MajorPreserve per-specifier
typemodifiers during import normalization.
NamedImportstill dropsImportSpecifier.importKind, so a file likeimport { type createFileRoute } ...is treated as if the runtime constructor is already imported. That can leave the transformed file with only a type import for the symbol it calls at runtime, and mixedtypespecifiers will also be re-rendered as value imports.Representative fix
type NamedImport = { imported: string local: string + importKind: 'type' | 'value' } named: statement.specifiers .filter((specifier): specifier is t.ImportSpecifier => t.isImportSpecifier(specifier), ) .map((specifier) => ({ imported: t.isIdentifier(specifier.imported) ? specifier.imported.name : specifier.imported.value, local: specifier.local.name, + importKind: specifier.importKind ?? 'value', })), - if (!isRouteConstructorName(imported.name)) { + if (specifier.importKind === 'type' || !isRouteConstructorName(imported.name)) { continue } - const key = `${specifier.imported}:${specifier.local}` + const key = `${specifier.importKind}:${specifier.imported}:${specifier.local}` .map((specifier) => - specifier.imported === specifier.local - ? specifier.imported - : `${specifier.imported} as ${specifier.local}`, + `${specifier.importKind === 'type' ? 'type ' : ''}${ + specifier.imported === specifier.local + ? specifier.imported + : `${specifier.imported} as ${specifier.local}` + }`, )Also applies to: 379-388, 461-466, 566-679
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/router-generator/src/transform/transform.ts` around lines 10 - 23, The NamedImport shape currently omits per-specifier importKind so import statements like `import { type foo }` are normalized as value imports; update the NamedImport type to include an importKind?: "type" | "value", ensure ParsedImportDeclaration.named preserves ImportSpecifier.importKind when building the named array, and update any normalization/printing logic that consumes ParsedImportDeclaration (e.g., import parsing code and re-rendering code in transform.ts) to respect and emit ImportSpecifier.importKind so mixed type/value specifiers are preserved. Use the symbols NamedImport, ParsedImportDeclaration, and ImportSpecifier.importKind to locate the points to change.
🤖 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/router-generator/src/transform/transform.ts`:
- Around line 681-695: The getLineEnding function incorrectly uses includes to
detect any presence of CRLF/LF/CR; change it to find the first line break in the
source by using indexOf (or similar) to get the earliest non-negative index
among '\r\n', '\n', and '\r' and return the line ending corresponding to that
earliest match (defaulting to '\n' if none found). Update the logic in
getLineEnding to compute positions for '\r\n', '\n', and '\r', pick the smallest
index > -1, and map that to the correct return value so the function reflects
the file's first line ending rather than any later occurrences.
- Around line 322-347: getCreateFileRouteProps currently only collects keys from
ObjectProperty nodes and skips object-literal method shorthand (e.g., loader()
{}), causing missing entries; update getCreateFileRouteProps to also handle
ObjectMethod nodes (skip computed ones) and add their keys to the props Set the
same way as for ObjectProperty: for ObjectMethod check
t.isIdentifier(property.key) and t.isStringLiteral(property.key) and add
property.key.name or property.key.value respectively so method shorthand names
like "loader" and "beforeLoad" are included in node.createFileRouteProps.
---
Duplicate comments:
In `@packages/router-generator/src/transform/transform.ts`:
- Around line 10-23: The NamedImport shape currently omits per-specifier
importKind so import statements like `import { type foo }` are normalized as
value imports; update the NamedImport type to include an importKind?: "type" |
"value", ensure ParsedImportDeclaration.named preserves
ImportSpecifier.importKind when building the named array, and update any
normalization/printing logic that consumes ParsedImportDeclaration (e.g., import
parsing code and re-rendering code in transform.ts) to respect and emit
ImportSpecifier.importKind so mixed type/value specifiers are preserved. Use the
symbols NamedImport, ParsedImportDeclaration, and ImportSpecifier.importKind to
locate the points to change.
🪄 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: 84361bbd-aced-46fa-8392-9b4a38d4e556
📒 Files selected for processing (8)
packages/router-generator/src/generator.tspackages/router-generator/src/transform/transform.tspackages/router-generator/src/utils.tspackages/router-generator/tests/generator/root-export-specifier/routeTree.snapshot.tspackages/router-generator/tests/generator/root-export-specifier/routes/__root.tsxpackages/router-generator/tests/generator/root-export-specifier/routes/about.tsxpackages/router-generator/tests/generator/root-export-specifier/routes/index.tsxpackages/router-generator/tests/transform.test.ts
💤 Files with no reviewable changes (1)
- packages/router-generator/src/generator.ts
✅ Files skipped from review due to trivial changes (3)
- packages/router-generator/tests/generator/root-export-specifier/routes/__root.tsx
- packages/router-generator/tests/generator/root-export-specifier/routeTree.snapshot.ts
- packages/router-generator/tests/transform.test.ts
| function getCreateFileRouteProps( | ||
| arg: t.CallExpression['arguments'][number] | undefined, | ||
| ) { | ||
| if (!arg || !t.isObjectExpression(arg)) { | ||
| return undefined | ||
| } | ||
|
|
||
| const props = new Set<string>() | ||
|
|
||
| for (const property of arg.properties) { | ||
| if (!t.isObjectProperty(property) || property.computed) { | ||
| continue | ||
| } | ||
|
|
||
| if (t.isIdentifier(property.key)) { | ||
| props.add(property.key.name) | ||
| continue | ||
| } | ||
|
|
||
| if (t.isStringLiteral(property.key)) { | ||
| props.add(property.key.value) | ||
| } | ||
| } | ||
|
|
||
| return props | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's examine the file and the function in context
head -n 360 packages/router-generator/src/transform/transform.ts | tail -n 60Repository: TanStack/router
Length of output: 1397
🏁 Script executed:
# Search for how getCreateFileRouteProps is used
rg "getCreateFileRouteProps" packages/router-generator/Repository: TanStack/router
Length of output: 275
🏁 Script executed:
# Search for createFileRoute usage patterns in the codebase to see if method shorthand is used
rg "createFileRoute\(" packages/router-generator/ -A 5 -B 2Repository: TanStack/router
Length of output: 50372
🏁 Script executed:
# Check test files for examples of createFileRoute configurations
fd "\.test\.(ts|tsx)$|\.spec\.(ts|tsx)$" packages/router-generator/tests/ | head -20Repository: TanStack/router
Length of output: 377
🏁 Script executed:
# Look at how createFileRouteProps is used in the transform.ts file
grep -n "createFileRouteProps" packages/router-generator/src/transform/transform.ts -A 3 -B 3Repository: TanStack/router
Length of output: 427
🏁 Script executed:
# Check the transform.test.ts to see what properties are expected
head -n 100 packages/router-generator/tests/transform.test.tsRepository: TanStack/router
Length of output: 2800
🏁 Script executed:
# Search for test examples that use createFileRoute with different property styles
fd "\.tsx?$" packages/router-generator/tests/generator/ -x grep -l "loader\|beforeLoad" {} \; | head -5Repository: TanStack/router
Length of output: 447
🏁 Script executed:
# Look at a specific test route file to see actual configuration patterns
cat packages/router-generator/tests/generator/virtual/routes/index.tsxRepository: TanStack/router
Length of output: 201
🏁 Script executed:
# Search for all properties used in createFileRoute configs across test files
rg "createFileRoute\(" packages/router-generator/tests/generator/ -A 5 | grep -E "^\s+(component|loader|beforeLoad|action|shouldReload|errorComponent|pendingComponent|notFoundComponent|layout|defaults|gcMaxAge)\s*[(:=]" | head -20Repository: TanStack/router
Length of output: 41
🏁 Script executed:
# Check the route type definitions to see what properties are valid
fd "types\\.ts|index\\.ts" packages/router/src/ | xargs grep -l "createFileRoute" | head -3Repository: TanStack/router
Length of output: 166
🏁 Script executed:
# Look for method shorthand usage pattern in entire router-generator
rg "loader\s*\(\s*\)\s*\{|beforeLoad\s*\(\s*\)\s*\{|action\s*\(\s*\)\s*\{" packages/router-generator/Repository: TanStack/router
Length of output: 41
🏁 Script executed:
# Check what createFileRouteProps is specifically used for - search for its usage context
grep -n "createFileRouteProps" packages/router-generator/src/transform/transform.ts -B 10 -A 10 | head -40Repository: TanStack/router
Length of output: 953
🏁 Script executed:
# Check how node.createFileRouteProps is used after being set
rg "createFileRouteProps" packages/router-generator/src/ -B 2 -A 2Repository: TanStack/router
Length of output: 1039
🏁 Script executed:
# Look at the RouteNode type to understand what createFileRouteProps is for
rg "createFileRouteProps" packages/router-generator/src/types.ts -B 5 -A 5Repository: TanStack/router
Length of output: 559
🏁 Script executed:
# Search in the generator.ts to see how createFileRouteProps is used when generating code
rg "\.createFileRouteProps" packages/router-generator/src/generator.ts -B 3 -A 3Repository: TanStack/router
Length of output: 41
🏁 Script executed:
# Search more broadly for how createFileRouteProps is used in generator
rg "createFileRouteProps" packages/router-generator/src/generator.tsRepository: TanStack/router
Length of output: 41
🏁 Script executed:
# Check the entire codebase for where createFileRouteProps is used
rg "createFileRouteProps" packages/router-generator/src/ --type tsRepository: TanStack/router
Length of output: 453
🏁 Script executed:
# Look at the actual Babel AST types to understand ObjectMethod better
# Search for documentation or comments about property extraction
rg "ObjectProperty|ObjectMethod" packages/router-generator/src/transform/transform.ts -B 2 -A 2Repository: TanStack/router
Length of output: 185
🏁 Script executed:
# Check if there are any tests that specifically test the getCreateFileRouteProps function
rg "getCreateFileRouteProps" packages/router-generator/tests/Repository: TanStack/router
Length of output: 41
🏁 Script executed:
# Check if createFileRouteProps is actually used anywhere - search all packages
rg "\.createFileRouteProps" packages/ --type tsRepository: TanStack/router
Length of output: 1021
🏁 Script executed:
# Search with different patterns
rg "createFileRouteProps\s*\?" packages/router-generator/ -B 2 -A 2Repository: TanStack/router
Length of output: 430
🏁 Script executed:
# Let me check what the actual purpose is by looking at git history or comments
cat packages/router-generator/src/types.ts | head -80Repository: TanStack/router
Length of output: 2016
🏁 Script executed:
# Look at the broader context in generator.ts to see if createFileRouteProps affects route generation
grep -n "createFileRoute" packages/router-generator/src/generator.ts | head -20Repository: TanStack/router
Length of output: 213
🏁 Script executed:
# Check the transform test to see what's expected for getCreateFileRouteProps
rg "createFileRouteProps" packages/router-generator/tests/transform.test.ts -B 10 -A 10Repository: TanStack/router
Length of output: 764
🏁 Script executed:
# Search for actual route config examples with loader or other properties to see the pattern
fd "\.tsx$" packages/router-generator/tests/generator/ -x grep -A 10 "createFileRoute" {} \; | grep -E "(loader|beforeLoad|action|errorComponent)" | head -20Repository: TanStack/router
Length of output: 680
🏁 Script executed:
# Check if ObjectMethod is even imported or used elsewhere in the codebase
rg "ObjectMethod" packages/router-generator/ packages/start-plugin-core/Repository: TanStack/router
Length of output: 215
🏁 Script executed:
# Look at what Babel types are imported in transform.ts
head -50 packages/router-generator/src/transform/transform.ts | grep importRepository: TanStack/router
Length of output: 294
🏁 Script executed:
# Check the actual route config type definition to see what syntax is accepted
fd "route\." packages/router/src/core/ --type ts | head -5Repository: TanStack/router
Length of output: 228
🏁 Script executed:
# Search in router package for the type signature of createFileRoute
rg "createFileRoute" packages/router/src/ -A 5 | head -50Repository: TanStack/router
Length of output: 119
🏁 Script executed:
# Look at actual usage patterns - are there ANY examples with method shorthand in ANY router files?
rg "loader\s*\(" packages/ | grep -v "loaderDeps\|loader:" | head -20Repository: TanStack/router
Length of output: 1484
🏁 Script executed:
# More specifically, check if method shorthand appears anywhere in route definitions
rg "beforeLoad\s*\(\s*\)" packages/ --type ts --type tsxRepository: TanStack/router
Length of output: 86
🏁 Script executed:
# Let me examine that file that had the method shorthand loader
cat packages/start-plugin-core/tests/createServerFn/test-files/isomorphic-fns.tsxRepository: TanStack/router
Length of output: 2386
🏁 Script executed:
# Check if this is in a createFileRoute context
grep -B 10 -A 10 "loader()" packages/start-plugin-core/tests/createServerFn/test-files/isomorphic-fns.tsx | head -30Repository: TanStack/router
Length of output: 664
🏁 Script executed:
# Search specifically in router test fixtures for method shorthand in route configs
rg "loader\s*\(\s*\)\s*\{" packages/ -B 2 -A 2 | head -40Repository: TanStack/router
Length of output: 1747
🏁 Script executed:
# Check packages/router to understand the structure
ls -la packages/ | grep routerRepository: TanStack/router
Length of output: 1323
🏁 Script executed:
# Create a simple test to verify the current function misses method shorthand
cat > /tmp/test-objectmethod.js << 'EOF'
const t = require('@babel/types');
// Simulate what getCreateFileRouteProps does
function getCreateFileRouteProps_Current(arg) {
if (!arg || !t.isObjectExpression(arg)) {
return undefined
}
const props = new Set<string>()
for (const property of arg.properties) {
if (!t.isObjectProperty(property) || property.computed) {
continue
}
if (t.isIdentifier(property.key)) {
props.add(property.key.name)
continue
}
if (t.isStringLiteral(property.key)) {
props.add(property.key.value)
}
}
return props
}
// Simulate what the fixed version would do
function getCreateFileRouteProps_Fixed(arg) {
if (!arg || !t.isObjectExpression(arg)) {
return undefined
}
const props = new Set<string>()
for (const property of arg.properties) {
if (property.computed) {
continue
}
if (t.isObjectProperty(property) || t.isObjectMethod(property)) {
if (t.isIdentifier(property.key)) {
props.add(property.key.name)
continue
}
if (t.isStringLiteral(property.key)) {
props.add(property.key.value)
}
}
}
return props
}
console.log('ObjectProperty type:', t.OBJECT_PROPERTY)
console.log('ObjectMethod type:', t.OBJECT_METHOD)
EOF
node /tmp/test-objectmethod.jsRepository: TanStack/router
Length of output: 783
🏁 Script executed:
# Verify the method shorthand is in the actual test file we found
cat packages/start-plugin-core/tests/createServerFn/test-files/isomorphic-fns.tsx | grep -A 5 "loader()"Repository: TanStack/router
Length of output: 125
🏁 Script executed:
# Check how many other route files use method shorthand
rg "createFileRoute\(" packages/start-plugin-core/ -A 10 | grep -E "^\s+(loader|beforeLoad|action|errorComponent)\s*\(\s*\)" | wc -lRepository: TanStack/router
Length of output: 60
🏁 Script executed:
# Search router-core to see if method shorthand is documented as valid syntax
rg "loader\s*\(\s*\)\s*\{|beforeLoad\s*\(\s*\)\s*\{" packages/router-core/ packages/react-router/ | head -10Repository: TanStack/router
Length of output: 41
🏁 Script executed:
# Check that the test expects 'component' to be captured
rg "createFileRouteProps.*component" packages/router-generator/tests/transform.test.tsRepository: TanStack/router
Length of output: 128
🏁 Script executed:
# Look at the actual usage to confirm method shorthand properties matter
cat packages/start-plugin-core/src/start-router-plugin/pruneServerOnlySubtrees.ts | head -60Repository: TanStack/router
Length of output: 1293
🏁 Script executed:
# Verify how createFileRouteProps is checked in start-plugin-core
grep -B 3 -A 3 "createFileRouteProps.has" packages/start-plugin-core/src/start-router-plugin/pruneServerOnlySubtrees.tsRepository: TanStack/router
Length of output: 41
Include object-literal method shorthand in createFileRoute prop extraction.
The getCreateFileRouteProps function only records ObjectProperty nodes, which misses valid method shorthand syntax like loader() {} or beforeLoad() {}. This causes node.createFileRouteProps to be incomplete, affecting downstream route analysis in packages that rely on this data (e.g., tree pruning logic in start-plugin-core).
Representative fix
for (const property of arg.properties) {
- if (!t.isObjectProperty(property) || property.computed) {
+ if (property.computed) {
continue
}
- if (t.isIdentifier(property.key)) {
+ if (t.isObjectProperty(property) || t.isObjectMethod(property)) {
+ if (t.isIdentifier(property.key)) {
+ props.add(property.key.name)
+ continue
+ }
+
+ if (t.isStringLiteral(property.key)) {
+ props.add(property.key.value)
+ }
+ }
- props.add(property.key.name)
- continue
- }
-
- if (t.isStringLiteral(property.key)) {
- props.add(property.key.value)
- }
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/router-generator/src/transform/transform.ts` around lines 322 - 347,
getCreateFileRouteProps currently only collects keys from ObjectProperty nodes
and skips object-literal method shorthand (e.g., loader() {}), causing missing
entries; update getCreateFileRouteProps to also handle ObjectMethod nodes (skip
computed ones) and add their keys to the props Set the same way as for
ObjectProperty: for ObjectMethod check t.isIdentifier(property.key) and
t.isStringLiteral(property.key) and add property.key.name or property.key.value
respectively so method shorthand names like "loader" and "beforeLoad" are
included in node.createFileRouteProps.
| function getLineEnding(source: string): '\r\n' | '\n' | '\r' { | ||
| if (source.includes('\r\n')) { | ||
| return '\r\n' | ||
| } | ||
|
|
||
| visit(ast, { | ||
| visitStringLiteral(path) { | ||
| if (path.parent.node.type !== 'JSXAttribute') { | ||
| const raw = path.node.extra?.raw | ||
| if (raw?.startsWith("'")) single++ | ||
| else if (raw?.startsWith('"')) double++ | ||
| } | ||
| return false | ||
| }, | ||
| }) | ||
| if (source.includes('\n')) { | ||
| return '\n' | ||
| } | ||
|
|
||
| if (single >= double) { | ||
| return "'" | ||
| if (source.includes('\r')) { | ||
| return '\r' | ||
| } | ||
| return '"' | ||
|
|
||
| return '\n' | ||
| } |
There was a problem hiding this comment.
Detect the first line ending, not just whether CRLF exists anywhere.
source.includes('\r\n') will pick CRLF even when the file’s first line break is LF and a later line happens to contain CRLF. That reintroduces the exact mixed-ending rewrite this PR is trying to avoid.
Representative fix
function getLineEnding(source: string): '\r\n' | '\n' | '\r' {
- if (source.includes('\r\n')) {
- return '\r\n'
- }
-
- if (source.includes('\n')) {
- return '\n'
- }
-
- if (source.includes('\r')) {
- return '\r'
- }
-
- return '\n'
+ const match = /\r\n|\n|\r/.exec(source)
+ return (match?.[0] as '\r\n' | '\n' | '\r' | undefined) ?? '\n'
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@packages/router-generator/src/transform/transform.ts` around lines 681 - 695,
The getLineEnding function incorrectly uses includes to detect any presence of
CRLF/LF/CR; change it to find the first line break in the source by using
indexOf (or similar) to get the earliest non-negative index among '\r\n', '\n',
and '\r' and return the line ending corresponding to that earliest match
(defaulting to '\n' if none found). Update the logic in getLineEnding to compute
positions for '\r\n', '\n', and '\r', pick the smallest index > -1, and map that
to the correct return value so the function reflects the file's first line
ending rather than any later occurrences.
There was a problem hiding this comment.
♻️ Duplicate comments (3)
packages/router-generator/src/transform/transform.ts (3)
323-347:⚠️ Potential issue | 🟡 MinorInclude object-literal method shorthand in
createFileRouteprop extraction.
loader() {}/beforeLoad() {}parse asObjectMethod, so this Set currently misses them. That leavesnode.createFileRoutePropsincomplete for valid route configs.Representative fix
for (const property of arg.properties) { - if (!t.isObjectProperty(property) || property.computed) { + if ( + property.computed || + (!t.isObjectProperty(property) && !t.isObjectMethod(property)) + ) { continue } if (t.isIdentifier(property.key)) { props.add(property.key.name)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/router-generator/src/transform/transform.ts` around lines 323 - 347, getCreateFileRouteProps currently only collects keys from ObjectProperty and misses method shorthand entries parsed as ObjectMethod (e.g., loader() {}), causing incomplete node.createFileRouteProps; update the loop over arg.properties to also handle t.isObjectMethod(property) (skip computed keys like existing checks) and extract the method name exactly like for ObjectProperty (use property.key.name when t.isIdentifier and property.key.value when t.isStringLiteral) so method shorthand keys are added to the props Set.
115-137:⚠️ Potential issue | 🟠 MajorEscape rewritten route IDs before splicing them back in.
expectedRouteIdis built by raw concatenation. Ifctx.routeIdcontains the active quote, a backtick, or${, this rewrite can emit invalid TS/JS even though the template side now serializes those values safely. Please render the replacement with quote-aware escaping befores.update(...), and add a regression case for ids like/can't,/a"b, and/a\${b}.Representative fix
- const expectedRouteId = `${routeIdQuote}${ctx.routeId}${routeIdQuote}` + const expectedRouteId = renderRouteId(ctx.routeId, routeIdQuote)function renderRouteId(routeId: string, quote: '"' | "'" | '`') { if (quote === "'") { return `'${routeId.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'` } if (quote === '"') { return `"${routeId.replace(/\\/g, '\\\\').replace(/"/g, '\\"')}"` } return `\`${routeId .replace(/\\/g, '\\\\') .replace(/`/g, '\\`') .replace(/\$\{/g, '\\${')}\`` }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/router-generator/src/transform/transform.ts` around lines 115 - 137, The replacement for route IDs currently injects expectedRouteId (built from ctx.routeId) raw, which can produce invalid JS/TS when the id contains the active quote, backtick, backslash, or ${}; before calling s.update for routeCall.routeIdArg replace expectedRouteId with a quote-aware escaped rendering (use the same quote character as routeIdQuote) that escapes backslashes and the quote char, and for backticks also escape backticks and any "${" sequences; update the call site where expectedRouteId is computed (and used in s.update) to use this renderer and add regression tests for ids like /can't, /a"b, and /a\${b} to ensure correct escaping.
685-698:⚠️ Potential issue | 🟠 MajorDetect the first line ending, not just any CRLF occurrence.
source.includes('\r\n')returns CRLF even when the file starts with LF and only later contains CRLF. That still violates the “first detected line break” behavior from#4367and can reintroduce mixed-ending rewrites when a missing import is prepended.Representative fix
function getLineEnding(source: string): '\r\n' | '\n' | '\r' { - if (source.includes('\r\n')) { - return '\r\n' - } - - if (source.includes('\n')) { - return '\n' - } - - if (source.includes('\r')) { - return '\r' - } - - return '\n' + const match = /\r\n|\n|\r/.exec(source) + return (match?.[0] as '\r\n' | '\n' | '\r' | undefined) ?? '\n' }🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@packages/router-generator/src/transform/transform.ts` around lines 685 - 698, getLineEnding currently uses source.includes and can return CRLF based on a later occurrence; change it to detect the first line break by finding the earliest index of '\r\n', '\n', and '\r' in source (using indexOf or similar) and return the line ending corresponding to the smallest non-negative index, defaulting to '\n' if none found; update the getLineEnding function to compare indices for '\r\n', '\n', and '\r' so the very first line ending in the file is returned.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@packages/router-generator/src/transform/transform.ts`:
- Around line 323-347: getCreateFileRouteProps currently only collects keys from
ObjectProperty and misses method shorthand entries parsed as ObjectMethod (e.g.,
loader() {}), causing incomplete node.createFileRouteProps; update the loop over
arg.properties to also handle t.isObjectMethod(property) (skip computed keys
like existing checks) and extract the method name exactly like for
ObjectProperty (use property.key.name when t.isIdentifier and property.key.value
when t.isStringLiteral) so method shorthand keys are added to the props Set.
- Around line 115-137: The replacement for route IDs currently injects
expectedRouteId (built from ctx.routeId) raw, which can produce invalid JS/TS
when the id contains the active quote, backtick, backslash, or ${}; before
calling s.update for routeCall.routeIdArg replace expectedRouteId with a
quote-aware escaped rendering (use the same quote character as routeIdQuote)
that escapes backslashes and the quote char, and for backticks also escape
backticks and any "${" sequences; update the call site where expectedRouteId is
computed (and used in s.update) to use this renderer and add regression tests
for ids like /can't, /a"b, and /a\${b} to ensure correct escaping.
- Around line 685-698: getLineEnding currently uses source.includes and can
return CRLF based on a later occurrence; change it to detect the first line
break by finding the earliest index of '\r\n', '\n', and '\r' in source (using
indexOf or similar) and return the line ending corresponding to the smallest
non-negative index, defaulting to '\n' if none found; update the getLineEnding
function to compare indices for '\r\n', '\n', and '\r' so the very first line
ending in the file is returned.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: f08d62f8-528a-43c8-a722-922217623ac2
📒 Files selected for processing (4)
packages/router-generator/src/template.tspackages/router-generator/src/transform/transform.tspackages/router-generator/tests/template.test.tspackages/router-generator/tests/transform.test.ts
✅ Files skipped from review due to trivial changes (1)
- packages/router-generator/tests/template.test.ts
There was a problem hiding this comment.
Nx Cloud has identified a possible root cause for your failed CI:
We identified this failure as an environment issue rather than a code regression. The Chromium browser crashed with signal 11 (SIGSEGV / General Protection Fault) during launch before any test logic ran, and 9 of the 10 tests passed successfully. Our PR's changes are scoped to router-generator transform logic and are unrelated to the scroll-restoration e2e app.
No code changes were suggested for this issue.
Trigger a rerun:
🎓 Learn more about Self-Healing CI on nx.dev
* fix: republish react-start-rsc dependency chain * ci: changeset release * chore: sync published start package versions * ci: changeset release * fix publishing * ci: changeset release * fix * ci: apply automated fixes * ci: changeset release * refactor: switch router stores to atom get/set API (#7150) * ci: changeset release * refactor: shorten internal router store names (#7152) * ci: changeset release * chore(types): re-export SearchMiddleware type from react-router (#7087) * fix(start-plugin-core): reuse deduped server function ids across compilers (#7153) * ci: changeset release * fix(router-core): avoid false notFound matches for proxied loader data (#7156) * fix(router-core): avoid false notFound matches for proxied loader data * test(react-start): cover proxied loader data notFound regression * test(react-start): move notFound regression to rsc direct loader * chore: add changeset * ci: changeset release * fix: reduce start SSR manifest asset duplication (#7157) Co-authored-by: schiller-manuel <schiller-manuel@users.noreply.github.com> Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> * ci: changeset release * docs: fix file extension syntax for prefix/suffix routing examples (#7149) docs: fix file-based routing examples with literal dots * chore: bump to h3 v2 rc.20 (#7140) * ci: changeset release * chore: stabilize tests (#7159) * chore: add vite 8 to peer deps (#7160) Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * ci: changeset release * chore(start-server-core): remove unnecessary `any` in `getRequestHeaders` (#7164) * fix(router-generator): harden route file transform rewrites (#7167) * fix docs (#7168) * ci: changeset release * fix(router-plugin): update vite-plugin-solid peer dependency to support version 3.0.0-0 (#7170) * ci: changeset release * fix(router-generator): normalize virtual physical subtree paths (#7169) Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> * ci: changeset release * fix: unify virtual module handling for Start Vite plugins (#7178) Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: CodeRabbit <noreply@coderabbit.ai> Co-authored-by: schiller-manuel <schiller-manuel@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> * ci: changeset release * fix: add react-server server export for react-start (#7180) * ci: changeset release * fix(docs): correct server function name in example (#7173) * fix react server exports for start and react-router (#7183) Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> * chore: stabilize tests (#7185) * ci: changeset release * fix(router-core): avoid intermediate success state for async notFound (#7184) * ci: changeset release * Add a React Start server-components skill (#7181) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * chore: add sharding for playwright tests (#7187) * add sharding * fix dependnancy * fix playwright shard port reuse * full bust * throw more runners into this run * try to throw money at it and see the effect * tune * fix react-router shared route css persistence on nav (#7186) Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * ci: changeset release * chore: stabilize test (#7192) * fix(start): include Vite style.css when cssCodeSplit is disabled (#7191) Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * ci: changeset release * chore: bump solid-js override 1.9.12 (#7202) * chore: bump query override to 5.99.0 (#7203) * fix(solid-router): use keyed Show in Outlet to fix child route rendering with useQuery (#7204) * ci: changeset release * docs(start): fix authenticated routes doc URL (#7214) * chore(deps): vitest 4.1.4 (#7212) * stabilize rsc tests (#7217) * fix(react-router): prevent webpack static analysis of React.use with let binding (#7182) * ci: changeset release * stabilize test (#7220) * chore: unify react-start basic e2e mode projects (#7206) * feat(nx): support rsbuild in Playwright inference (#7221) * test(e2e-rsc): migrate to playwrightModes and dynamic inferred dist (#7222) * fix(nx): align playwright mode build target naming (#7223) * docs(start): add missing space after comma in 'Handling requests with a body' (#7234) * update intent workflow (#7243) * rsbuild plugin (#7228) Co-authored-by: neverland <chenjiahan.jait@bytedance.com> Co-authored-by: Keven Arroyo <dake.3601@gmail.com> * ci: changeset release * fix: Split Start plugin core (#7249) * ci: changeset release * update intent workflow (#7244) * fix: asset sorting (#7251) * ci: changeset release * chore(deps): update Rsbuild related deps to v2.0.1 (#7245) * fix actions again? (#7252) * inline css (#7253) * ci: changeset release * fix: do not import 'react-refresh/runtime' (#7255) Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> * ci: changeset release * chore(examples): checkin git outdated route-tree files for react and solid examples (#7257) * add new bundlesize measurements for rsbuild (#7256) Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> * refactor(router-plugin): upgrade unplugin to `v3` (#7258) * refactor(router-plugin): upgrade unplugin to `v3` * refactor(start-client-core): use a more explicit typing to `CustomFetch` type * chore(examples): runtime enforce for needing the `VITE_CONVEX_URL` * ci: changeset release * fix: issue 7240 causing fouc (#7250) * fix: server middleware type in solid-router (#7260) * replace tsx by jiti (#7261) Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> * ci: changeset release * docs: Fix server function middleware prop (#7262) * feat(query): add support for custom dehydrate and hydrate options in SSR integration (#7246) Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * ci: changeset release * fix: use loader data goes undefined (#7265) * fix: streaming when using Await component (#7264) * ci: changeset release * fix(solid-start): bundle solid-query packages during SSR to fix duplicate QueryClientContext (#6151) (#7267) * ci: changeset release * fix(solid-router): hydration mismatch for ssr='data-only' with pendingComponent (#7266) * docs(router): fix typo in doc (#7268) * ci: changeset release * fix(router-core): wildcard nodes respect DFS priority like other nodes in route matching (#7273) * ci: changeset release * fix(solid-router): enable route component HMR for Solid * ci: apply automated fixes * Revert "ci: apply automated fixes" This reverts commit 7122f28. * Revert "fix(solid-router): enable route component HMR for Solid" This reverts commit b86b061. * fix(react-start-rsc): re-export renderable types from public entries (#7278) * fix(react-start-rsc): re-export renderable types from public entries * changeset - patch * ci: changeset release * fix: disabled topLevelVar (#7293) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * ci: changeset release * fix: fix exports for react-start so useServerFn is available with RSC (#7292) Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> * feat: match params (#7263) * ci: changeset release * fix(start-plugin-core): sort server fn manifest entries for deterministic build output (#7287) Co-authored-by: Dor Alagem <doralagem@MacBook-Pro-sl-Dor.local> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Manuel Schiller <meisterpink@gmail.com> * docs: remove redundant code example from query integration doc (#7298) * ci: changeset release * fix: Ignore fully type-only imports and re-exports when collecting im… (#7305) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * ci: changeset release * feat: `strict: false` for server functions (#7277) * feat: `strict: false` for server functions Add a `strict` option to `createServerFn` for type-level server function serialization checks * feat: `strict: false` for server functions [Self-Healing CI Rerun] --------- Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> * ci: changeset release * fix: parse params union inference (#7306) * ci: changeset release * feat: rsc css (#7310) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * ci: changeset release * fix(router-plugin): isolate route metadata per plugin instance (#7313) * ci: changeset release * docs: Improve key differences b/w Start Server Functions and Next.js Server Actions (#7312) * fix(deps): move fetchdts from devDependencies to dependencies (#7317) * Revise bug report template for clarity and requirements Updated the bug report template to clarify the requirements for a reproducer project and modified some labels and descriptions for better clarity. * ci: changeset release * chore: fix duplicate "the" typo across router packages (#7323) * feat: early hints (#7324) * ci: changeset release * feat: Link header (#7327) Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> * ci: changeset release * docs(skills): address 8 agent failure modes from user feedback (#7314) * docs(skills): address 8 agent failure modes from external feedback Adds new start-core/auth-server-primitives skill (sessions, cookies, OAuth+PKCE, password-reset enumeration defense, CSRF, rate limiting, session rotation) and updates 8 existing skills + matching docs to fix patterns where agents produce insecure or wrong-framework output. Skill changes: - new: start-core/auth-server-primitives (server half of auth) - router-core/auth-and-guards: route guard != RPC guard - start-core/server-functions: wrong import path, RPC auth required, Cache-Control public is a cross-tenant leak, wrong-framework patterns - start-core/middleware: wrong import path, sendContext shape vs access (3-layer wrong/still-wrong/correct), authMiddleware framing - start-core/execution-model: file markers (server-only/client-only), module-level process.env is undefined under Worker SSR - start-core/deployment: cloudflare env-at-request-time - router-core/ssr: wrong file structures (next.js, react-router-dom) - router-core/type-safety: wrong-framework imports + structures Docs updated to mirror each skill change so source-of-truth and the intent-indexed skill stay in sync. New authentication-server-primitives guide is the long-form companion to the new skill. intent validate: 30 skill files pass (was 29). * ci: apply automated fixes * docs(skills): address coderabbit review feedback - Fix internal docs links to use correct relative paths instead of an absolute /start/latest/... URL and missing one ../ segment - Remove blank line inside auth-and-guards blockquote (markdownlint MD028) - Restore overload pattern in type-safety ValidateNavigateOptions and ValidateRedirectOptions examples; the casts I had introduced stripped generic context and contradicted the skill's own no-cast rule - Add db.sessions.revokeAllForUser before create in login rotation snippets so the example matches the prose - Soften useServerFn guidance: it's required only when the server function throws redirect/notFound; plain-data calls work directly and via useMutation/useQuery * ci: apply automated fixes * docs(skills): compress type-safety to stay under 500-line cap Prettier's autofix expanded my single-line overload signatures across multiple lines, pushing the file over the 500-line limit. Drop the redundant fetchOrRedirect example (same pattern as useDelayedNavigate) and describe ValidateRedirectOptions usage in prose instead. * docs(skills): CSRF origin check should compare full origin, not host alone Comparing only new URL(origin).host against APP_HOST silently accepts a mismatched scheme — http://example.com would pass a check meant for https://example.com. Compare the full origin (scheme + host + port) against APP_ORIGIN instead. Same fix in skill and docs. * docs(skills): make useDelayedNavigate callback truly return void The callback returned the result of setTimeout (a timer handle), not void as the public overload's return type implied. Wrap in a block so the example matches the declared return type. Skipped the related nitpick to add a separate redirect example — the existing prose already describes the same overload pattern, and a duplicate example would push the file close to the 500-line cap that prettier autofix has been bumping us against. * docs(skills): fix two real bugs in auth-server-primitives examples 1. Cookie parser truncated values containing '='. Signed cookies, JWTs, and base64-padded values all use '='. Use indexOf to split on the FIRST '=' only. 2. Login example short-circuited verifyPasswordHash on user-not-found, contradicting the prose's "same time, same error" claim — the no-user branch returned instantly while wrong-password spent ~100ms hashing, leaking account existence over the wire. Always verify against a hash; use a precomputed DUMMY_PASSWORD_HASH when the user is missing, then combine with the user-exists bit for the final ok. Same fixes in the SKILL.md and the docs companion. * docs(skills): address manuel's review on react-specific guides - middleware.md, server-functions.md: drop cross-framework <framework> placeholders; this is the React-specific guide, just say @tanstack/react-start - execution-model.md: drop the same trailing line about solid-start / vue-start paths - hosting.md: remove the Cloudflare env-handling subsection — the general per-request rule lives in environment-variables.md and doesn't need to be repeated under a specific host - environment-variables.md: mention the cloudflare:workers env binding as the canonical Cloudflare way to read env (including module scope), per Manuel's link to the Cloudflare docs - deployment skill: same upgrade — show the cloudflare:workers env pattern alongside the per-request handler approach * docs(skills): drop redundant server-only marker in session example The file already imports from @tanstack/react-start/server, which is on import protection's default client-deny specifier list. The side-effect marker is redundant — drop it. Same fix in skill and docs. * docs(skills): drop wrong-import-path mistakes — TS already catches them Manuel pointed out that TypeScript catches both common wrong paths: '@tanstack/react-router' has no exported member createServerFn / createMiddleware, and '@tanstack/start' is "Cannot find module". Skill space is precious; the items don't earn their slot if tsc handles them. Removed: - Common Mistake "Wrong import path" from server-functions and middleware skills (renumbered the remaining mistakes) - The matching top-of-file CRITICAL line in both skills - The "Import path" callouts in the middleware and server-functions docs --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * remove old intent artifacts (#7333) * fix(start-server-core): fall back to GET handler for HEAD requests (RFC 9110 §9.3.2) (#7325) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * ci: changeset release * test: add reproducer for #2514 (#7336) * test: reproducer for #2547 (#7337) * fix: fix plain TypeScript parser handling (#7342) * ci: changeset release * fix: disable rsbuild server compression (#7348) * fix: update deps (#7340) * ci: changeset release * update bundlesize benchmark (#7356) * fix: Bump jiti to 2.7.0 (#7355) Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> * ci: apply automated fixes * ci: changeset release * Document server function strict serialization options (#7358) * Document server function strict option Agent-Logs-Url: https://github.com/TanStack/router/sessions/8deabe7a-7412-455e-9111-97a13cb4582e Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> * Refine strict docs wording Agent-Logs-Url: https://github.com/TanStack/router/sessions/e2857d6e-314e-496c-b99b-78c207c28c77 Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> * feat(start): CSRF middleware (#7373) * fix(router-core): fix missing closing paren in CSS.supports check for view transition types (#7369) * fix: fix jiti usage for tsconfig paths (#7382) * Enable jiti tsconfig path aliases Agent-Logs-Url: https://github.com/TanStack/router/sessions/0a481c9b-eb97-4543-acc5-71d43b97d386 Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> * Use fixture for jiti tsconfig aliases Agent-Logs-Url: https://github.com/TanStack/router/sessions/182b9baa-9e54-4813-a322-c33a1da5417d Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> * Track fixture path alias helper Agent-Logs-Url: https://github.com/TanStack/router/sessions/182b9baa-9e54-4813-a322-c33a1da5417d Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> * Add router-generator changeset Agent-Logs-Url: https://github.com/TanStack/router/sessions/ab1a42cc-7326-4e36-a656-f01179221cee Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> * Format virtual config fixture Agent-Logs-Url: https://github.com/TanStack/router/sessions/22194166-b3a7-431e-b723-ad594d4b0405 Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> * Update bundle-size.yml * Update labeler.yml * Update bundle-size.yml * ci: add pinGitHubActionDigests (#7387) * chore(deps): pin dependencies (#7388) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> * minor semver bump to all packages (#7395) * ci: zizmor (#7389) * chore(pnpm): update pnpm to v11 (#7392) * chore: add CODEOWNERS file (#7394) * chore: add CODEOWNERS file * chore: add Nx and NPMRC * Update .github/CODEOWNERS --------- Co-authored-by: Nicolas Beaussart <nic.beaussart@gmail.com> * fix: revert plugin changes, createCsrfMiddleware compilation, fix HMR tests (#7400) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Manuel Schiller <manuel.schiller@caligano.de> * ci: align release workflow to query (#7404) * ci: Version Packages (#7405) ci: changeset release Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * feat(start): add inline CSS runtime controls and asset URL templates (#7380) * ci: Version Packages (#7407) * fix: Fix literal underscore paths under pathless layouts (#7408) * ci: Version Packages (#7409) ci: changeset release Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * feat(router-core): params.priority route option as tie breaker in matching algorithm (#7411) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * ci: Version Packages (#7413) * fix(router-core): hydrate before initial client route match (#7416) * ci: Version Packages (#7417) * fix(router-plugin): detect typed root route context for HMR (#7420) * ci: Version Packages (#7421) * fix: fix route mismatch warnings and HMR route indexes (#7422) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * ci: Version Packages (#7423) * security: stricter pnpm config blockExoticSubdeps & trustPolicy (#7425) * docs(start): use router package for module declaration to type the request context (#7427) * feat: deferred hydration (#7362) * feat: deferred hydration * fix * tests * solid tests * Changes before error encountered Agent-Logs-Url: https://github.com/TanStack/router/sessions/5263c469-75c2-4470-bd4c-86f9b43964f4 Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> * chore: address hydration review follow-ups Agent-Logs-Url: https://github.com/TanStack/router/sessions/16e27113-ff01-4de8-aded-b9be9f6dd4ff Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> * fix(start-client-core): correct import order in hydrateStart.ts Co-authored-by: schiller-manuel <schiller-manuel@users.noreply.github.com> * chore: remove tracked nx self-healing artifacts Agent-Logs-Url: https://github.com/TanStack/router/sessions/95750760-1348-437c-8f73-cc45e899003a Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> Co-authored-by: schiller-manuel <schiller-manuel@users.noreply.github.com> * chore: update @swc/core in example/react/quickstart-webpack-file-based (#7434) * chore: update @swc/core in example/react/quickstart-webpack-file-based * chore: update @swc/core in example/react/quickstart-webpack-file-based [Self-Healing CI Rerun] --------- Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> * docs(start): compare deferred hydration to Astro islands (#7438) Adds a short mental-model section answering the common question about how TanStack Start's deferred hydration relates to Astro islands. * docs(start): compare deferred hydration to React selective hydration (#7442) Adds a short comparison section answering the common question about how TanStack Start's deferred hydration relates to React 18's selective hydration. The framing: selective hydration controls the order of inevitable hydration work; deferred hydration controls whether and when that work happens at all. * chore: update chokidar to v5 (#7439) * chore: update @rolldown/pluginutils to 1.0.1 (#7440) * chore: update zod to v4.4.3 (#7441) * chore: update zod to v4.4.3 * fix(start): preserve route path defaults * fix(examples): resolve zod 4 build failures * chore: update express and webpack-dev-server (#7443) * chore: update express to v5.2.1 * chore: update webpack-dev-server to v5.2.4 * ci: Version Packages (#7435) ci: changeset release Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * chore: ignore nx generated folders (#7451) * perf: optimize and test rewrite (#7448) optimize and test rewrite * fix: fix scroll restoration issues (#7447) Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> * ci: Version Packages (#7452) * fix: Fix escaped underscore index route generation (#7453) * ci: Version Packages (#7454) * ci: fix release notes diff range after Release PR flow (#7456) * fix(start): explicitly re-export public API to survive SSR cold-start cycle (#7466) * fix: Fix hash scrolling with `resetScroll={false}` (#7464) Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * chore: enforce pnpm 11 (#7465) * ci: Version Packages (#7467) * chore: only run autofix on PRs (#7469) * feat(start): support rsbuild iife client output (#7477) * ci: Version Packages (#7478) * fix: bundled dev support for vite (#7482) * ci: Version Packages (#7483) * fix(start): avoid encoded virtual adapter ids in vite dev (#7484) * fix release (#7487) * ci: Version Packages (#7485) * chore: migrate changesets changelog generator (#7490) * fix: Fix Hydrate re-exports to avoid circular HMR updates (#7492) * ci: Version Packages (#7493) * fix(start): emit boot-sibling chunks as scripts for IIFE entries (#7501) Co-authored-by: Keven Arroyo <kevenarroyo@microsoft.com> * ci: Version Packages (#7502) * chore: stabilize tests (#7503) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: fix streaming (#7497) * ci: Version Packages (#7504) ci: changeset release Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * ci: update all actions (#7506) * ci: update all actions * disable package manager cache * fix: fix primitive beforeLoad errors (#7505) * fix: fix primitive beforeLoad errors * ci: apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * ci: Version Packages (#7508) * feat(rsbuild): add RSC support (#7509) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * ci: Version Packages (#7513) * fix(solid): resolve Solid 2 merge issues * ci: apply automated fixes * use v2 query * fix solid v2 imports * solid v2 port of new e2e * solid v2 * nxignore solid v1 peer deps * use "@rsbuild/plugin-solid": "^2.0.0-beta.0", * fix hydrationscript * add nohydration * remove early return * fix: solid-start hydration * fix: update createEffect to return true for hydration signals * remove nxignore * add back nxignore for 3rdparty deps * $_TSR stub to fix serialization tests * Revert "$_TSR stub to fix serialization tests" This reverts commit ef802e9. * fix: update solid selective ssr links * fix: stream solid Await fallback * align solid-start basic by removing test:e2e * remove unusese build:prerender build:spa * fix: clean up solid hydrate fallback dom * fix: resolve solid wrapper children * fix: stabilize serialization stream e2e test * fix: keep SSR globals through document parse * html standard mode * clean * fix: pass solid ssr manifest * use await fallback --------- Co-authored-by: Tanner Linsley <tannerlinsley@gmail.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Manuel Schiller <manuel.schiller@caligano.de> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Flo <fpellet@ensc.fr> Co-authored-by: James Howard <james@reetgood.co.uk> Co-authored-by: schiller-manuel <schiller-manuel@users.noreply.github.com> Co-authored-by: nx-cloud[bot] <71083854+nx-cloud[bot]@users.noreply.github.com> Co-authored-by: Mohamed Khaled <mohamedkhaled012@yahoo.com> Co-authored-by: Birk Skyum <74932975+birkskyum@users.noreply.github.com> Co-authored-by: schiller-manuel <6340397+schiller-manuel@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: Ulrich Stark <github@ustark.de> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: CodeRabbit <noreply@coderabbit.ai> Co-authored-by: MoonBrillante <32852571+MoonBrillante@users.noreply.github.com> Co-authored-by: Coding Cossack <108333654+CodingCossack@users.noreply.github.com> Co-authored-by: Nicolas Beaussart <nic.beaussart@gmail.com> Co-authored-by: Pavan Shinde <pavann97@gmail.com> Co-authored-by: mixelburg <52622705+mixelburg@users.noreply.github.com> Co-authored-by: Mukunda Rao Katta <mukunda.vjcs6@gmail.com> Co-authored-by: Sarah Gerrard <gerrardsarah@gmail.com> Co-authored-by: neverland <chenjiahan.jait@bytedance.com> Co-authored-by: Keven Arroyo <dake.3601@gmail.com> Co-authored-by: Sean Cassiere <33615041+SeanCassiere@users.noreply.github.com> Co-authored-by: Abhishek Raj <abhi@raj.me> Co-authored-by: Dominik Dorfmeister 🔮 <office@dorfmeister.cc> Co-authored-by: Birk Skyum <birk.skyum@pm.me> Co-authored-by: Keven Arroyo <kevenarroyo@microsoft.com> Co-authored-by: Dor Alagem <dor3382@gmail.com> Co-authored-by: Dor Alagem <doralagem@MacBook-Pro-sl-Dor.local> Co-authored-by: Manuel Schiller <meisterpink@gmail.com> Co-authored-by: Franklin Shera <fshera96@gmail.com> Co-authored-by: Tom Smithhisler <tomsmithhisler@gmail.com> Co-authored-by: dfedoryshchev <64079946+dfedoryshchev@users.noreply.github.com> Co-authored-by: Sarah Gerrard <hello@sarahgerrard.me> Co-authored-by: Zelys <zelys@dfkhelper.com> Co-authored-by: Shkumbin Hasani <34962865+shkumbinhasani@users.noreply.github.com> Co-authored-by: Lachlan Collins <1667261+lachlancollins@users.noreply.github.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Harry Whorlow <79278353+harry-whorlow@users.noreply.github.com> Co-authored-by: Corbin Crutchley <git@crutchcorn.dev> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
fixes #7163
fixes #4367
fixes #4366
fixes #4487
Summary by CodeRabbit
New Features
Bug Fixes
Refactor
Tests / Chores