-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
test(vue-router): basic-esbuild-file-based #6115
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughThis PR introduces a complete end-to-end test project for TanStack Vue Router using esbuild and file-based routing. It includes full application setup with configuration, Vue components, route definitions, data fetching utilities, and comprehensive Playwright tests validating navigation flows, nested layouts, route parameters, search validation, data loading, error handling, and blocker-based navigation logic. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🧹 Nitpick comments (18)
e2e/vue-router/basic-esbuild-file-based/src/vue-shims.d.ts (1)
1-5: Consider usingobjectinstead of{}for stricter type safety.While this is a standard Vue TypeScript shim pattern, the use of
{}for the Props and RawBindings generics is imprecise. In TypeScript,{}means "any non-nullish value" rather than "empty object". Usingobjectwould better align with the coding guideline to use extensive type safety.Apply this diff:
declare module '*.vue' { import type { DefineComponent } from 'vue' - const component: DefineComponent<{}, {}, any> + const component: DefineComponent<object, object, any> export default component }Note: The
anyfor the data parameter, while not ideal for strict typing, is acceptable in catch-all module declarations where component-specific types cannot be known.As per coding guidelines, TypeScript files should use strict mode with extensive type safety.
e2e/vue-router/basic-esbuild-file-based/src/routes/posts_.$postId.edit.tsx (1)
9-23: Add TypeScript type annotations per coding guidelines.The component function and variables lack type annotations. Per the coding guidelines for
**/*.{ts,tsx}files, TypeScript strict mode with extensive type safety should be used.Based on coding guidelines for TypeScript files.
Apply this diff to add type annotations:
-function PostEditComponent() { +function PostEditComponent(): JSX.Element { const paramsViaApi = api.useParams() const paramsViaHook = useParams({ from: '/posts_/$postId/edit' }) const paramsViaRouteHook = api.useParams()Note: The params variables themselves are already properly typed through TanStack Router's type inference, so explicit annotations aren't required for them.
e2e/vue-router/js-only-file-based/tsconfig.json (1)
1-15: Consider adding an explicitincludearray.While the configuration works without an explicit
includearray, adding one improves clarity about which files TypeScript should process.{ "compilerOptions": { "strict": true, "esModuleInterop": true, "jsx": "preserve", "jsxImportSource": "vue", "target": "ESNext", "moduleResolution": "Bundler", "module": "ESNext", "resolveJsonModule": true, "allowJs": true, "skipLibCheck": true }, + "include": ["src", "tests"], "exclude": ["node_modules", "dist"] }e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsx (1)
12-28: Clarify intention of duplicaterouteApi.useSearch()calls.Lines 14 and 15 make identical calls to
routeApi.useSearch(), assigned to different variables. If this is intentionally demonstrating API equivalence for testing purposes, consider adding a comment. Otherwise, one of these calls is redundant.If not intentional, apply this diff:
function SubfolderInsideComponent() { const searchViaHook = useSearch({ from: '/(group)/subfolder/inside' }) const searchViaRouteHook = routeApi.useSearch() - const searchViaRouteApi = routeApi.useSearch() return ( <div> <div data-testid="search-via-hook">{searchViaHook.value.hello}</div> <div data-testid="search-via-route-hook"> {searchViaRouteHook.value.hello} </div> - <div data-testid="search-via-route-api"> - {searchViaRouteApi.value.hello} - </div> </div> ) }Or add a clarifying comment if the duplication is intentional for testing:
function SubfolderInsideComponent() { const searchViaHook = useSearch({ from: '/(group)/subfolder/inside' }) + // Testing both ways to access search via routeApi const searchViaRouteHook = routeApi.useSearch() const searchViaRouteApi = routeApi.useSearch()e2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsx (1)
5-7: Consider using Zod for type-safe search param validation.The current implementation uses a type assertion
(search.searchParam as string)which bypasses TypeScript's type checking. For better type safety, consider using Zod schema validation.+import { z } from 'zod' + +const searchSchema = z.object({ + searchParam: z.string().default(''), +}) + export const Route = createFileRoute('/notRemountDeps')({ - validateSearch: (search: Record<string, unknown>) => ({ - searchParam: (search.searchParam as string) || '', - }), + validateSearch: searchSchema, loaderDeps(opts) { return opts.search },As per coding guidelines: Use TypeScript strict mode with extensive type safety.
e2e/vue-router/basic-esbuild-file-based/index.html (1)
7-7: Consider pinning the Tailwind CDN version for test stability.Using an unpinned version
@4may cause test flakiness if breaking changes are released. Consider pinning to a specific version like@4.1.0to ensure consistent test behavior.- <script src="https://unpkg.com/@tailwindcss/browser@4"></script> + <script src="https://unpkg.com/@tailwindcss/browser@4.1.0"></script>e2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsx (1)
13-24: Consider reducing type casting verbosity.The component correctly reads loader data and renders the post. However, casting
post.value as PostTypeon each access (lines 19, 21) is verbose.Consider extracting the typed value once:
function PostComponent() { const post = Route.useLoaderData() + const postData = post.value as PostType return ( <div class="space-y-2"> <h4 class="text-xl font-bold underline" data-testid="post-title"> - {(post.value as PostType).title} + {postData.title} </h4> - <div class="text-sm">{(post.value as PostType).body}</div> + <div class="text-sm">{postData.body}</div> </div> ) }e2e/vue-router/js-only-file-based/src/routes/__root.jsx (1)
45-53: Remove ineffective@ts-expect-errordirective in JavaScript file.The
@ts-expect-errordirective on line 46 has no effect in.jsxfiles—it only works in TypeScript. Since this file uses JavaScript, consider either removing the comment or replacing it with a regular comment explaining the intentional use of a non-existent route.Apply this diff:
<Link - // @ts-expect-error + // Intentionally linking to non-existent route to test not-found handling to="/this-route-does-not-exist" activeProps={{e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsx (1)
12-28: Clarify variable naming for identical API calls.Lines 14 and 15 both call
routeApi.useSearch(), but the variable names (searchViaRouteHookandsearchViaRouteApi) suggest different sources. This naming is confusing. If this is intentional for testing purposes, consider renaming to reflect that both use the route API (e.g.,searchViaRouteApi1andsearchViaRouteApi2), or add a comment explaining the test scenario.Example diff:
function InsideLayoutComponent() { const searchViaHook = useSearch({ from: '/(group)/_layout/insidelayout' }) - const searchViaRouteHook = routeApi.useSearch() - const searchViaRouteApi = routeApi.useSearch() + const searchViaRouteApi1 = routeApi.useSearch() + const searchViaRouteApi2 = routeApi.useSearch() return ( <div> <div data-testid="search-via-hook">{searchViaHook.value.hello}</div> - <div data-testid="search-via-route-hook"> - {searchViaRouteHook.value.hello} + <div data-testid="search-via-route-api-1"> + {searchViaRouteApi1.value.hello} </div> - <div data-testid="search-via-route-api"> - {searchViaRouteApi.value.hello} + <div data-testid="search-via-route-api-2"> + {searchViaRouteApi2.value.hello} </div> </div> ) }e2e/vue-router/js-only-file-based/src/routes/posts.route.jsx (1)
1-9: Consider consolidating imports from the same module.Lines 1 and 3 both import from
@tanstack/vue-router. While this works fine, consolidating them into a single import statement would be cleaner.Apply this diff:
-import { createFileRoute } from '@tanstack/vue-router' - -import { Link, Outlet } from '@tanstack/vue-router' +import { createFileRoute, Link, Outlet } from '@tanstack/vue-router' import { fetchPosts } from '../posts'e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsx (1)
14-15: DuplicaterouteApi.useSearch()calls.Both
searchViaRouteHookandsearchViaRouteApicallrouteApi.useSearch()identically. Based on the test-id naming, it appears you may have intended to demonstrate different access methods here, but both are the same call. If intentional for testing consistency, consider adding a brief comment clarifying this.e2e/vue-router/basic-esbuild-file-based/src/routes/posts.tsx (1)
23-26: Consider typing the synthetic post explicitly.The synthetic post
{ id: 'i-do-not-exist', title: 'Non-existent Post' }is missing thebodyproperty defined inPostType. While this works sincebodyisn't used in the render, you could usePartial<PostType>or add a minimal body for type consistency, or explicitly type the combined array.- {[ - ...(posts.value as Array<PostType>), - { id: 'i-do-not-exist', title: 'Non-existent Post' }, - ].map((post) => ( + {[ + ...(posts.value as Array<PostType>), + { id: 'i-do-not-exist', title: 'Non-existent Post', body: '' }, + ].map((post) => (e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout.jsx (1)
1-2: Consolidate imports from the same module.The two imports from
@tanstack/vue-routercan be merged into a single import statement.-import { createFileRoute } from '@tanstack/vue-router' -import { Link, Outlet } from '@tanstack/vue-router' +import { createFileRoute, Link, Outlet } from '@tanstack/vue-router'e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx (1)
14-15: DuplicaterouteApi.useSearch()calls.Same observation as in
lazyinside.tsx: bothsearchViaRouteHookandsearchViaRouteApiare identical calls torouteApi.useSearch(). If this is intentional for testing consistency across multiple calls, a brief comment would clarify the intent.e2e/vue-router/basic-esbuild-file-based/eslint.config.js (1)
1-49: Consider adding the ESLint router plugin for router best practices.Based on coding guidelines, files matching
**/*.{js,ts,tsx}should implement ESLint rules for router best practices using the ESLint plugin router. Consider adding@tanstack/eslint-plugin-routerto enforce router-specific linting rules.Additionally, the override block for
.vuefiles (lines 40-48) appears redundant since the main config block (lines 10-39) already covers**/*.vuewith the same parser configuration.import js from '@eslint/js' import typescript from '@typescript-eslint/eslint-plugin' import typescriptParser from '@typescript-eslint/parser' import vue from 'eslint-plugin-vue' import vueParser from 'vue-eslint-parser' +import router from '@tanstack/eslint-plugin-router' export default [ js.configs.recommended, ...vue.configs['flat/recommended'], + ...router.configs['flat/recommended'], { files: ['**/*.{js,jsx,ts,tsx,vue}'], // ... rest of config }, - { - files: ['**/*.vue'], - languageOptions: { - parser: vueParser, - parserOptions: { - parser: typescriptParser, - }, - }, - }, ]e2e/vue-router/basic-esbuild-file-based/tests/app.spec.ts (1)
230-236: Redundant navigation in test.The
page.goto('/')on line 231 is redundant sincebeforeEachalready navigates to/before each test.test('Should change title on client side navigation', async ({ page }) => { - await page.goto('/') - await page.getByRole('link', { name: 'Posts' }).click() await expect(page).toHaveTitle('Posts page') })e2e/vue-router/basic-esbuild-file-based/src/esbuild.run.js (2)
71-94: Consider extracting shared esbuild configuration.The build configuration in
buildOnce()(lines 76-93) and the dev context (lines 159-176) are nearly identical. Extracting the shared config would reduce duplication and ensure consistency.+function getSharedConfig() { + const inject = [path.join(process.cwd(), 'src/jsx-shim.ts')] + return { + entryPoints: [path.join(process.cwd(), 'src/main.tsx')], + bundle: true, + outfile: path.join(process.cwd(), 'dist/main.js'), + platform: 'browser', + format: 'esm', + jsx: 'transform', + jsxFactory: 'h', + jsxFragment: 'Fragment', + inject, + sourcemap: true, + define: { + 'process.env.NODE_ENV': JSON.stringify( + process.env.VITE_NODE_ENV ?? process.env.NODE_ENV ?? 'development', + ), + }, + ...esbuildConfig, + } +} + async function buildOnce() { - const entry = path.join(process.cwd(), 'src/main.tsx') - const outfile = path.join(process.cwd(), 'dist/main.js') - const inject = [path.join(process.cwd(), 'src/jsx-shim.ts')] - - await esbuild.build({ - entryPoints: [entry], - bundle: true, - outfile, - platform: 'browser', - format: 'esm', - jsx: 'transform', - jsxFactory: 'h', - jsxFragment: 'Fragment', - inject, - sourcemap: true, - define: { - 'process.env.NODE_ENV': JSON.stringify( - process.env.VITE_NODE_ENV ?? process.env.NODE_ENV ?? 'development', - ), - }, - ...esbuildConfig, - }) + await esbuild.build(getSharedConfig()) }Also applies to: 156-181
62-69: Consider narrowing the error catch infileExists.The current implementation catches all errors, but only
ENOENTindicates the file doesn't exist. Other errors (permission issues, etc.) may warrant different handling.async function fileExists(filePath) { try { await fs.stat(filePath) return true - } catch { + } catch (err) { + if (err.code === 'ENOENT') return false + throw err - return false } }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (73)
e2e/vue-router/basic-esbuild-file-based/eslint.config.js(1 hunks)e2e/vue-router/basic-esbuild-file-based/index.html(1 hunks)e2e/vue-router/basic-esbuild-file-based/package.json(1 hunks)e2e/vue-router/basic-esbuild-file-based/playwright.config.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/postcss.config.mjs(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/EditingAComponent.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/EditingBComponent.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/NotFoundComponent.vue(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/NotRemountDepsComponent.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/PostErrorComponent.vue(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/RemountDepsComponent.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/VueLogo.vue(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/esbuild.config.js(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/esbuild.run.js(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/jsx-shim.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/main.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/posts.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/__root.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-a.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-b.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/editing-a.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/editing-b.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/posts.index.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/posts.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/posts_.$postId.edit.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/remountDeps.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/sfcComponent.component.vue(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/sfcComponent.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/대한민국.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/styles.css(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/vue-shims.d.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/test-results/.last-run.json(1 hunks)e2e/vue-router/basic-esbuild-file-based/tests/app.spec.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/tests/setup/global.setup.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/tests/setup/global.teardown.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/tsconfig.json(1 hunks)e2e/vue-router/js-only-file-based/.gitignore(1 hunks)e2e/vue-router/js-only-file-based/index.html(1 hunks)e2e/vue-router/js-only-file-based/package.json(1 hunks)e2e/vue-router/js-only-file-based/playwright.config.ts(1 hunks)e2e/vue-router/js-only-file-based/postcss.config.mjs(1 hunks)e2e/vue-router/js-only-file-based/src/main.jsx(1 hunks)e2e/vue-router/js-only-file-based/src/posts.js(1 hunks)e2e/vue-router/js-only-file-based/src/routeTree.gen.js(1 hunks)e2e/vue-router/js-only-file-based/src/routeTree.gen.ts(1 hunks)e2e/vue-router/js-only-file-based/src/routes/__root.jsx(1 hunks)e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout.jsx(1 hunks)e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout.jsx(1 hunks)e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout/route-a.jsx(1 hunks)e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout/route-b.jsx(1 hunks)e2e/vue-router/js-only-file-based/src/routes/index.jsx(1 hunks)e2e/vue-router/js-only-file-based/src/routes/posts.$postId.jsx(1 hunks)e2e/vue-router/js-only-file-based/src/routes/posts.index.jsx(1 hunks)e2e/vue-router/js-only-file-based/src/routes/posts.route.jsx(1 hunks)e2e/vue-router/js-only-file-based/src/styles.css(1 hunks)e2e/vue-router/js-only-file-based/test-results/.last-run.json(1 hunks)e2e/vue-router/js-only-file-based/tests/app.spec.ts(1 hunks)e2e/vue-router/js-only-file-based/tests/setup/global.setup.ts(1 hunks)e2e/vue-router/js-only-file-based/tests/setup/global.teardown.ts(1 hunks)e2e/vue-router/js-only-file-based/tsconfig.json(1 hunks)e2e/vue-router/js-only-file-based/vite.config.js(1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript strict mode with extensive type safety for all code
Files:
e2e/vue-router/basic-esbuild-file-based/src/components/EditingBComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/대한민국.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/editing-b.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/index.tsxe2e/vue-router/js-only-file-based/tests/app.spec.tse2e/vue-router/basic-esbuild-file-based/src/routes/sfcComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts_.$postId.edit.tsxe2e/vue-router/basic-esbuild-file-based/src/jsx-shim.tse2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-b.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-a.tsxe2e/vue-router/basic-esbuild-file-based/src/posts.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/editing-a.tsxe2e/vue-router/basic-esbuild-file-based/src/components/RemountDepsComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/vue-shims.d.tse2e/vue-router/basic-esbuild-file-based/src/components/NotRemountDepsComponent.tsxe2e/vue-router/basic-esbuild-file-based/tests/app.spec.tse2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.tsxe2e/vue-router/js-only-file-based/playwright.config.tse2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsxe2e/vue-router/basic-esbuild-file-based/src/components/EditingAComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/remountDeps.tsxe2e/vue-router/js-only-file-based/tests/setup/global.teardown.tse2e/vue-router/basic-esbuild-file-based/src/routes/posts.index.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsxe2e/vue-router/basic-esbuild-file-based/tests/setup/global.setup.tse2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.tse2e/vue-router/basic-esbuild-file-based/playwright.config.tse2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsxe2e/vue-router/js-only-file-based/tests/setup/global.setup.tse2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/main.tsxe2e/vue-router/basic-esbuild-file-based/tests/setup/global.teardown.tse2e/vue-router/basic-esbuild-file-based/src/routes/__root.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsxe2e/vue-router/js-only-file-based/src/routeTree.gen.ts
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Implement ESLint rules for router best practices using the ESLint plugin router
Files:
e2e/vue-router/basic-esbuild-file-based/src/components/EditingBComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/대한민국.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/editing-b.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/index.tsxe2e/vue-router/js-only-file-based/tests/app.spec.tse2e/vue-router/basic-esbuild-file-based/src/routes/sfcComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts_.$postId.edit.tsxe2e/vue-router/basic-esbuild-file-based/src/jsx-shim.tse2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-b.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-a.tsxe2e/vue-router/basic-esbuild-file-based/src/posts.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/editing-a.tsxe2e/vue-router/basic-esbuild-file-based/src/components/RemountDepsComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/vue-shims.d.tse2e/vue-router/basic-esbuild-file-based/src/components/NotRemountDepsComponent.tsxe2e/vue-router/basic-esbuild-file-based/tests/app.spec.tse2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.tsxe2e/vue-router/js-only-file-based/playwright.config.tse2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsxe2e/vue-router/basic-esbuild-file-based/src/components/EditingAComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts.tsxe2e/vue-router/js-only-file-based/src/posts.jse2e/vue-router/basic-esbuild-file-based/src/routes/remountDeps.tsxe2e/vue-router/js-only-file-based/tests/setup/global.teardown.tse2e/vue-router/basic-esbuild-file-based/src/routes/posts.index.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsxe2e/vue-router/basic-esbuild-file-based/tests/setup/global.setup.tse2e/vue-router/basic-esbuild-file-based/eslint.config.jse2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.tse2e/vue-router/basic-esbuild-file-based/playwright.config.tse2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsxe2e/vue-router/basic-esbuild-file-based/src/esbuild.config.jse2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsxe2e/vue-router/js-only-file-based/tests/setup/global.setup.tse2e/vue-router/basic-esbuild-file-based/src/esbuild.run.jse2e/vue-router/js-only-file-based/src/routeTree.gen.jse2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/main.tsxe2e/vue-router/basic-esbuild-file-based/tests/setup/global.teardown.tse2e/vue-router/basic-esbuild-file-based/src/routes/__root.tsxe2e/vue-router/js-only-file-based/vite.config.jse2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsxe2e/vue-router/js-only-file-based/src/routeTree.gen.ts
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace protocol
workspace:*for internal dependencies in package.json files
Files:
e2e/vue-router/basic-esbuild-file-based/package.jsone2e/vue-router/js-only-file-based/package.json
🧠 Learnings (10)
📓 Common learnings
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.
Learnt from: FatahChan
Repo: TanStack/router PR: 5475
File: e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx:8-0
Timestamp: 2025-10-14T18:59:33.990Z
Learning: In TanStack Router e2e test files, when a route parameter is validated at the route level (e.g., using zod in validateSearch or param validation), switch statements on that parameter do not require a default case, as the validation ensures only expected values will reach the switch.
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.
Applied to files:
e2e/vue-router/js-only-file-based/test-results/.last-run.jsone2e/vue-router/js-only-file-based/tsconfig.jsone2e/vue-router/basic-esbuild-file-based/src/routes/대한민국.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/editing-b.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/index.tsxe2e/vue-router/js-only-file-based/.gitignoree2e/vue-router/js-only-file-based/tests/app.spec.tse2e/vue-router/basic-esbuild-file-based/src/routes/sfcComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts_.$postId.edit.tsxe2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout/route-b.jsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-b.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-a.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/editing-a.tsxe2e/vue-router/basic-esbuild-file-based/package.jsone2e/vue-router/js-only-file-based/src/routes/__root.jsxe2e/vue-router/basic-esbuild-file-based/tests/app.spec.tse2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/remountDeps.tsxe2e/vue-router/js-only-file-based/package.jsone2e/vue-router/js-only-file-based/tests/setup/global.teardown.tse2e/vue-router/basic-esbuild-file-based/src/routes/posts.index.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsxe2e/vue-router/basic-esbuild-file-based/tests/setup/global.setup.tse2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.tse2e/vue-router/js-only-file-based/src/routes/posts.index.jsxe2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsxe2e/vue-router/js-only-file-based/tests/setup/global.setup.tse2e/vue-router/basic-esbuild-file-based/test-results/.last-run.jsone2e/vue-router/js-only-file-based/src/routeTree.gen.jse2e/vue-router/basic-esbuild-file-based/tsconfig.jsone2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsxe2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout.jsxe2e/vue-router/basic-esbuild-file-based/src/main.tsxe2e/vue-router/basic-esbuild-file-based/tests/setup/global.teardown.tse2e/vue-router/basic-esbuild-file-based/src/routes/__root.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsxe2e/vue-router/js-only-file-based/src/routeTree.gen.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript strict mode with extensive type safety for all code
Applied to files:
e2e/vue-router/js-only-file-based/tsconfig.jsone2e/vue-router/basic-esbuild-file-based/eslint.config.jse2e/vue-router/basic-esbuild-file-based/tsconfig.json
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router
Applied to files:
e2e/vue-router/js-only-file-based/tsconfig.jsone2e/vue-router/basic-esbuild-file-based/src/routes/대한민국.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/editing-b.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/index.tsxe2e/vue-router/js-only-file-based/tests/app.spec.tse2e/vue-router/basic-esbuild-file-based/src/routes/sfcComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts_.$postId.edit.tsxe2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout/route-b.jsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-b.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-a.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/editing-a.tsxe2e/vue-router/basic-esbuild-file-based/package.jsone2e/vue-router/basic-esbuild-file-based/index.htmle2e/vue-router/js-only-file-based/src/routes/__root.jsxe2e/vue-router/basic-esbuild-file-based/tests/app.spec.tse2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/remountDeps.tsxe2e/vue-router/js-only-file-based/package.jsone2e/vue-router/basic-esbuild-file-based/src/routes/posts.index.tsxe2e/vue-router/basic-esbuild-file-based/src/styles.csse2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsxe2e/vue-router/basic-esbuild-file-based/eslint.config.jse2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.tse2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsxe2e/vue-router/basic-esbuild-file-based/src/esbuild.config.jse2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsxe2e/vue-router/js-only-file-based/postcss.config.mjse2e/vue-router/js-only-file-based/src/routeTree.gen.jse2e/vue-router/basic-esbuild-file-based/tsconfig.jsone2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/main.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/__root.tsxe2e/vue-router/js-only-file-based/vite.config.jse2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsxe2e/vue-router/js-only-file-based/src/routeTree.gen.tse2e/vue-router/js-only-file-based/src/routes/index.jsx
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: e2e/react-start/custom-basepath/src/routeTree.gen.ts:58-61
Timestamp: 2025-10-01T18:31:35.420Z
Learning: Do not review files named `routeTree.gen.ts` in TanStack Router repositories, as these are autogenerated files that should not be manually modified.
Applied to files:
e2e/vue-router/basic-esbuild-file-based/src/routes/대한민국.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/editing-b.tsxe2e/vue-router/js-only-file-based/.gitignoree2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout/route-b.jsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-b.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-a.tsxe2e/vue-router/js-only-file-based/src/routes/__root.jsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/remountDeps.tsxe2e/vue-router/js-only-file-based/package.jsone2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.tse2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsxe2e/vue-router/js-only-file-based/src/routeTree.gen.jse2e/vue-router/basic-esbuild-file-based/tsconfig.jsone2e/vue-router/basic-esbuild-file-based/src/main.tsxe2e/vue-router/js-only-file-based/vite.config.jse2e/vue-router/js-only-file-based/src/routeTree.gen.ts
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Use file-based routing in `src/routes/` directories or code-based routing with route definitions
Applied to files:
e2e/vue-router/basic-esbuild-file-based/src/routes/editing-b.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/index.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/sfcComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts_.$postId.edit.tsxe2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout/route-b.jsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-b.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-a.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/editing-a.tsxe2e/vue-router/js-only-file-based/src/routes/_pathlessLayout.jsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/remountDeps.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts.index.tsxe2e/vue-router/js-only-file-based/src/routes/posts.index.jsxe2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsxe2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout/route-a.jsxe2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsxe2e/vue-router/js-only-file-based/src/routeTree.gen.tse2e/vue-router/js-only-file-based/src/routes/index.jsxe2e/vue-router/js-only-file-based/src/routes/posts.route.jsx
📚 Learning: 2025-10-09T12:59:02.129Z
Learnt from: hokkyss
Repo: TanStack/router PR: 5418
File: e2e/react-start/custom-identifier-prefix/src/styles/app.css:19-21
Timestamp: 2025-10-09T12:59:02.129Z
Learning: In e2e test directories (paths containing `e2e/`), accessibility concerns like outline suppression patterns are less critical since the code is for testing purposes, not production use.
Applied to files:
e2e/vue-router/js-only-file-based/tests/app.spec.tse2e/vue-router/basic-esbuild-file-based/tests/app.spec.ts
📚 Learning: 2025-11-02T16:16:24.898Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5732
File: packages/start-client-core/src/client/hydrateStart.ts:6-9
Timestamp: 2025-11-02T16:16:24.898Z
Learning: In packages/start-client-core/src/client/hydrateStart.ts, the `import/no-duplicates` ESLint disable is necessary for imports from `#tanstack-router-entry` and `#tanstack-start-entry` because both aliases resolve to the same placeholder file (`fake-start-entry.js`) in package.json during static analysis, even though they resolve to different files at runtime.
Applied to files:
e2e/vue-router/basic-esbuild-file-based/package.jsone2e/vue-router/js-only-file-based/package.jsone2e/vue-router/js-only-file-based/tests/setup/global.teardown.tse2e/vue-router/basic-esbuild-file-based/tests/setup/global.setup.tse2e/vue-router/basic-esbuild-file-based/eslint.config.jse2e/vue-router/js-only-file-based/src/main.jsxe2e/vue-router/js-only-file-based/tests/setup/global.setup.tse2e/vue-router/js-only-file-based/src/routeTree.gen.jse2e/vue-router/basic-esbuild-file-based/src/main.tsxe2e/vue-router/basic-esbuild-file-based/tests/setup/global.teardown.tse2e/vue-router/js-only-file-based/vite.config.js
📚 Learning: 2025-10-09T12:59:14.842Z
Learnt from: hokkyss
Repo: TanStack/router PR: 5418
File: e2e/react-start/custom-identifier-prefix/public/site.webmanifest:2-3
Timestamp: 2025-10-09T12:59:14.842Z
Learning: In e2e test fixtures (files under e2e directories), empty or placeholder values in configuration files like site.webmanifest are acceptable and should not be flagged unless the test specifically validates those fields.
Applied to files:
e2e/vue-router/js-only-file-based/playwright.config.tse2e/vue-router/basic-esbuild-file-based/playwright.config.tse2e/vue-router/js-only-file-based/tests/setup/global.setup.ts
📚 Learning: 2025-10-14T18:59:33.990Z
Learnt from: FatahChan
Repo: TanStack/router PR: 5475
File: e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx:8-0
Timestamp: 2025-10-14T18:59:33.990Z
Learning: In TanStack Router e2e test files, when a route parameter is validated at the route level (e.g., using zod in validateSearch or param validation), switch statements on that parameter do not require a default case, as the validation ensures only expected values will reach the switch.
Applied to files:
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsx
🧬 Code graph analysis (29)
e2e/vue-router/basic-esbuild-file-based/src/routes/editing-b.tsx (6)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout.tsx (1)
Route(3-5)e2e/vue-router/basic-esbuild-file-based/src/routes/editing-a.tsx (1)
Route(4-6)e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsx (1)
Route(4-6)e2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsx (1)
Route(6-11)e2e/vue-router/basic-esbuild-file-based/src/components/EditingBComponent.tsx (1)
EditingBComponent(4-34)
e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsx (3)
e2e/vue-router/basic-esbuild-file-based/src/routes/__root.tsx (1)
Route(13-16)e2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsx (1)
Route(4-15)e2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsx (1)
Route(6-11)
e2e/vue-router/basic-esbuild-file-based/src/routes/posts_.$postId.edit.tsx (1)
e2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsx (1)
Route(6-11)
e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-b.tsx (3)
e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsx (1)
Route(3-5)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-a.tsx (1)
Route(3-5)e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsx (1)
Route(4-6)
e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-a.tsx (3)
e2e/vue-router/basic-esbuild-file-based/src/routes/_layout.tsx (1)
Route(3-5)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsx (1)
Route(3-5)e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsx (1)
Route(4-6)
e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout.jsx (1)
e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout.jsx (2)
Route(4-6)Route(4-6)
e2e/vue-router/js-only-file-based/playwright.config.ts (1)
scripts/set-ts-version.js (1)
packageJson(33-33)
e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsx (3)
e2e/vue-router/basic-esbuild-file-based/src/routes/_layout.tsx (1)
Route(3-5)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-a.tsx (1)
Route(3-5)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-b.tsx (1)
Route(3-5)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsx (2)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx (1)
Route(5-8)
e2e/vue-router/basic-esbuild-file-based/src/routes/posts.tsx (1)
e2e/vue-router/basic-esbuild-file-based/src/posts.tsx (2)
fetchPosts(26-32)PostType(4-8)
e2e/vue-router/js-only-file-based/src/posts.js (1)
e2e/vue-router/js-only-file-based/src/routes/posts.$postId.jsx (1)
post(20-20)
e2e/vue-router/basic-esbuild-file-based/src/routes/remountDeps.tsx (2)
e2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsx (1)
Route(4-15)e2e/vue-router/basic-esbuild-file-based/src/components/RemountDepsComponent.tsx (1)
RemountDepsComponent(7-38)
e2e/vue-router/js-only-file-based/tests/setup/global.teardown.ts (1)
scripts/set-ts-version.js (1)
packageJson(33-33)
e2e/vue-router/basic-esbuild-file-based/src/routes/posts.index.tsx (2)
e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsx (1)
Route(4-6)e2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsx (1)
Route(6-11)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsx (1)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx (1)
Route(5-8)
e2e/vue-router/basic-esbuild-file-based/tests/setup/global.setup.ts (2)
e2e/vue-router/basic-esbuild-file-based/src/main.tsx (1)
setup(24-26)scripts/set-ts-version.js (1)
packageJson(33-33)
e2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.ts (1)
packages/router-generator/tests/generator/types-disabled/routeTree.nonnested.snapshot.js (3)
PostsRoute(17-21)PostsRouteWithChildren(42-42)PostsRouteChildren(38-40)
e2e/vue-router/js-only-file-based/src/routes/posts.index.jsx (3)
e2e/vue-router/js-only-file-based/src/routes/index.jsx (2)
Route(3-5)Route(3-5)e2e/vue-router/js-only-file-based/src/routes/posts.$postId.jsx (2)
Route(6-13)Route(6-13)e2e/vue-router/js-only-file-based/src/routes/posts.route.jsx (2)
Route(6-9)Route(6-9)
e2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsx (1)
e2e/vue-router/basic-esbuild-file-based/src/components/NotRemountDepsComponent.tsx (1)
NotRemountDepsComponent(4-37)
e2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsx (1)
e2e/vue-router/basic-esbuild-file-based/src/posts.tsx (2)
fetchPost(10-24)PostType(4-8)
e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout/route-a.jsx (8)
e2e/vue-router/js-only-file-based/src/routes/__root.jsx (2)
Route(4-14)Route(4-14)e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout.jsx (2)
Route(4-6)Route(4-6)e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout.jsx (2)
Route(4-6)Route(4-6)e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout/route-b.jsx (2)
Route(2-6)Route(2-6)e2e/vue-router/js-only-file-based/src/routes/index.jsx (2)
Route(3-5)Route(3-5)e2e/vue-router/js-only-file-based/src/routes/posts.$postId.jsx (2)
Route(6-13)Route(6-13)e2e/vue-router/js-only-file-based/src/routes/posts.index.jsx (2)
Route(3-5)Route(3-5)e2e/vue-router/js-only-file-based/src/routes/posts.route.jsx (2)
Route(6-9)Route(6-9)
e2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx (2)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsx (1)
Route(4-15)
e2e/vue-router/js-only-file-based/src/routes/posts.$postId.jsx (1)
e2e/vue-router/js-only-file-based/src/posts.js (3)
fetchPost(16-27)fetchPost(16-27)post(18-20)
e2e/vue-router/js-only-file-based/src/routeTree.gen.js (1)
e2e/vue-router/js-only-file-based/src/routeTree.gen.ts (1)
routeTree(228-230)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx (3)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsx (1)
Route(4-6)
e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout.jsx (3)
e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout.jsx (2)
Route(4-6)Route(4-6)e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout/route-a.jsx (2)
Route(2-6)Route(2-6)e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout/route-b.jsx (2)
Route(2-6)Route(2-6)
e2e/vue-router/basic-esbuild-file-based/tests/setup/global.teardown.ts (1)
scripts/set-ts-version.js (1)
packageJson(33-33)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsx (2)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.tsx (1)
Route(3-5)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx (1)
Route(5-8)
e2e/vue-router/js-only-file-based/src/routes/index.jsx (7)
e2e/vue-router/js-only-file-based/src/routes/__root.jsx (2)
Route(4-14)Route(4-14)e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout.jsx (2)
Route(4-6)Route(4-6)e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout.jsx (2)
Route(4-6)Route(4-6)e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout/route-a.jsx (2)
Route(2-6)Route(2-6)e2e/vue-router/js-only-file-based/src/routes/_pathlessLayout/_nested-layout/route-b.jsx (2)
Route(2-6)Route(2-6)e2e/vue-router/js-only-file-based/src/routes/posts.$postId.jsx (2)
Route(6-13)Route(6-13)e2e/vue-router/js-only-file-based/src/routes/posts.index.jsx (2)
Route(3-5)Route(3-5)
| defineProps<{ | ||
| error: any | ||
| }>() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Use a more specific type instead of any.
The error: any type bypasses TypeScript's type safety, which violates the strict mode requirement. Consider using Error or unknown for better type safety.
As per coding guidelines, TypeScript strict mode with extensive type safety should be used.
Apply this diff:
defineProps<{
- error: any
+ error: Error | unknown
}>()📝 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.
| defineProps<{ | |
| error: any | |
| }>() | |
| defineProps<{ | |
| error: Error | unknown | |
| }>() |
🤖 Prompt for AI Agents
In e2e/vue-router/basic-esbuild-file-based/src/components/PostErrorComponent.vue
around lines 4 to 6, the props definition uses error: any which breaks strict
TypeScript safety; change the prop type to a more specific type (e.g., Error or
unknown) and update the component to perform runtime narrowing if you choose
unknown (check instanceof Error or inspect properties) before accessing error
fields; update defineProps generic accordingly and adjust any downstream usage
in this component to satisfy the selected type (type guard or explicit cast).
| .catch((err) => { | ||
| if (err.status === 404) { | ||
| throw notFound() | ||
| } | ||
| throw err | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Search for redaxios and axios error handling patterns
rg -n --type=ts --type=tsx '\.(catch|error)' -A 5 -B 2 | head -100
# Search specifically for status code access patterns
rg -n 'err\.status|err\.response\.status' --type=ts --type=tsx -B 3 -A 1
# Look for redaxios imports and usage
rg -n 'redaxios|from.*redaxios' --type=ts --type=tsx -A 2Repository: TanStack/router
Length of output: 142
🏁 Script executed:
#!/bin/bash
# Search for redaxios imports and usage without type restrictions
rg -n 'redaxios' -A 2 -B 1
# Search for error handling patterns with status code checks
rg -n 'err\.status|err\.response\.status' -A 2 -B 2
# Directly read the file in question
echo "=== Reading posts.tsx ==="
cat -n e2e/vue-router/basic-esbuild-file-based/src/posts.tsx
# Search for catch blocks with status checking
rg -n '\.catch\s*\(' -A 5Repository: TanStack/router
Length of output: 50372
🏁 Script executed:
#!/bin/bash
# Read the specific file in question
echo "=== Reading the file mentioned in review ==="
cat -n e2e/vue-router/basic-esbuild-file-based/src/posts.tsx
echo ""
echo "=== Search for error.status access patterns ==="
rg 'err\.status|err\.response\.status' -B 3 -A 1 | head -50
echo ""
echo "=== Check examples/react/basic-virtual-file-based/src/posts.tsx for comparison ==="
cat -n examples/react/basic-virtual-file-based/src/posts.tsx | head -40Repository: TanStack/router
Length of output: 6020
🏁 Script executed:
#!/bin/bash
# Check redaxios source code to understand error structure
rg -A 10 'error.status|error.response' | head -80
# Also look for any type definitions or JSDoc
fd -e ts -e d.ts | xargs rg -l 'redaxios' -A 5 | head -20Repository: TanStack/router
Length of output: 1645
Use err.response.status instead of err.status for redaxios error handling.
Redaxios follows axios API conventions where error status is accessed via err.response.status, not directly on the error object. Lines 16-21 should be updated to check err.response?.status === 404.
🤖 Prompt for AI Agents
In e2e/vue-router/basic-esbuild-file-based/src/posts.tsx around lines 16 to 21,
the error handling checks err.status which is incorrect for redaxios/axios-style
errors; update the condition to check err.response?.status === 404 (using
optional chaining) and keep the same throw notFound() for that case, otherwise
rethrow the original error.
| const paramsViaApi = api.useParams() | ||
| const paramsViaHook = useParams({ from: '/posts_/$postId/edit' }) | ||
| const paramsViaRouteHook = api.useParams() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Duplicate code: lines 10 and 12 are identical.
Lines 10 and 12 both call api.useParams() with identical code, despite having different variable names (paramsViaApi vs paramsViaRouteHook). This appears to be either a copy-paste error or incomplete implementation. If the intent is to demonstrate different methods of accessing route parameters for e2e testing, consider using a distinct approach for one of these lines.
Apply this diff if line 12 was intended to simply test multiple calls to the same API:
- const paramsViaApi = api.useParams()
- const paramsViaHook = useParams({ from: '/posts_/$postId/edit' })
- const paramsViaRouteHook = api.useParams()
+ const paramsViaHook = useParams({ from: '/posts_/$postId/edit' })
+ const paramsViaRouteApi = api.useParams()And update the corresponding JSX:
- <div data-testid="params-via-hook">{paramsViaHook.value.postId}</div>
- <div data-testid="params-via-route-hook">
- {paramsViaRouteHook.value.postId}
- </div>
- <div data-testid="params-via-route-api">{paramsViaApi.value.postId}</div>
+ <div data-testid="params-via-hook">{paramsViaHook.value.postId}</div>
+ <div data-testid="params-via-route-api">{paramsViaRouteApi.value.postId}</div>Committable suggestion skipped: line range outside the PR's diff.
| { | ||
| "status": "passed", | ||
| "failedTests": [] | ||
| } No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider excluding generated test results from version control.
The test-results/ directory typically contains generated test artifacts that should be ignored via .gitignore to prevent repository bloat and merge conflicts.
Add this directory to .gitignore:
+test-results/Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In e2e/vue-router/basic-esbuild-file-based/test-results/.last-run.json lines
1-4: the test-results directory contains generated artifacts that should be
excluded from version control; update the repository by adding an entry for
e2e/vue-router/basic-esbuild-file-based/test-results/ to .gitignore, remove any
already-committed files from Git tracking (e.g., git rm --cached <path> or git
rm -r --cached e2e/vue-router/basic-esbuild-file-based/test-results), and commit
the updated .gitignore and removal so future generated test results are not
tracked.
| }, | ||
| "dependencies": { | ||
| "@tailwindcss/postcss": "^4.1.15", | ||
| "@tanstack/router-plugin": "workspace:^", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use workspace:* protocol for internal dependencies.
The coding guidelines specify using workspace:* for internal dependencies in package.json files, but this file uses workspace:^.
Apply this diff to fix the workspace protocol:
"dependencies": {
"@tailwindcss/postcss": "^4.1.15",
- "@tanstack/router-plugin": "workspace:^",
+ "@tanstack/router-plugin": "workspace:*",
"@tanstack/vue-query": "^5.90.0",
"@tanstack/vue-query-devtools": "^6.1.2",
- "@tanstack/vue-router": "workspace:^",
- "@tanstack/vue-router-devtools": "workspace:^",
+ "@tanstack/vue-router": "workspace:*",
+ "@tanstack/vue-router-devtools": "workspace:*",
"postcss": "^8.5.1",
"redaxios": "^0.5.1",
"tailwindcss": "^4.1.17",
"vue": "^3.5.16"
},
"devDependencies": {
"@playwright/test": "^1.50.1",
- "@tanstack/router-e2e-utils": "workspace:^",
+ "@tanstack/router-e2e-utils": "workspace:*",
"@vitejs/plugin-vue": "^5.2.3",
"@vitejs/plugin-vue-jsx": "^4.1.2",
"vite": "^7.1.7"Based on coding guidelines.
Also applies to: 18-19, 27-27
🤖 Prompt for AI Agents
In e2e/vue-router/js-only-file-based/package.json around lines 15 (and also
modify similar entries at lines 18-19 and 27), replace any internal dependency
versions using the workspace:^ protocol with workspace:*; update each dependency
entry (e.g. "@tanstack/router-plugin" and the other internal packages referenced
at those lines) to use "workspace:*" so the package.json follows the coding
guideline for internal workspace dependencies.
| const rootElement = document.getElementById('app') | ||
|
|
||
| if (!rootElement.innerHTML) { | ||
| createApp({ | ||
| setup() { | ||
| return () => <RouterProvider router={router} /> | ||
| }, | ||
| }).mount('#app') | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add null check before accessing rootElement properties.
Line 17 accesses rootElement.innerHTML without verifying that rootElement is not null. If the element with id 'app' doesn't exist, this will throw a runtime error.
Apply this diff to add proper null checking:
const rootElement = document.getElementById('app')
-if (!rootElement.innerHTML) {
+if (rootElement && !rootElement.innerHTML) {
createApp({
setup() {
return () => <RouterProvider router={router} />
},
}).mount('#app')
}Additionally, the indentation on lines 18-22 uses tabs while the rest of the file uses spaces. Consider normalizing to spaces for consistency.
📝 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.
| const rootElement = document.getElementById('app') | |
| if (!rootElement.innerHTML) { | |
| createApp({ | |
| setup() { | |
| return () => <RouterProvider router={router} /> | |
| }, | |
| }).mount('#app') | |
| } | |
| const rootElement = document.getElementById('app') | |
| if (rootElement && !rootElement.innerHTML) { | |
| createApp({ | |
| setup() { | |
| return () => <RouterProvider router={router} /> | |
| }, | |
| }).mount('#app') | |
| } |
🤖 Prompt for AI Agents
In e2e/vue-router/js-only-file-based/src/main.jsx around lines 15 to 23, the
code uses rootElement.innerHTML without first verifying rootElement is not null
and also contains tab indentation inconsistent with the file; update the code to
first check if rootElement is truthy (e.g., if (rootElement &&
!rootElement.innerHTML) { ... }) before accessing innerHTML and mount, and
replace the tab characters on lines 18–22 with spaces to match the file's
indentation style.
|
View your CI Pipeline Execution ↗ for commit 086b8c2
☁️ Nx Cloud last updated this comment at |
e9cd270 to
086b8c2
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
♻️ Duplicate comments (1)
e2e/vue-router/basic-esbuild-file-based/src/styles.css (1)
1-2: Add the missing Tailwind CSS import (duplicate of previous feedback).As previously flagged, the file is missing the required
@import "tailwindcss";statement at the top. This is necessary for Tailwind v4 directives to work correctly.
🧹 Nitpick comments (4)
e2e/vue-router/basic-esbuild-file-based/src/routes/대한민국.tsx (1)
7-17: Add return type annotation for TypeScript strict mode compliance.The
UnicodeComponentfunction lacks an explicit return type annotation. For strict TypeScript mode with extensive type safety, consider adding: JSX.Elementas the return type.Apply this diff:
-function UnicodeComponent() { +function UnicodeComponent(): JSX.Element { return ( <div> <h3 class="pb-2" data-testid="unicode-heading">As per coding guidelines, TypeScript strict mode with extensive type safety should be used for all
.tsxfiles.e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx (1)
14-15: Consider removing duplicate routeApi.useSearch() call.Both
searchViaRouteHookandsearchViaRouteApicall the identical methodrouteApi.useSearch(). The variable names suggest different approaches, but the implementation is the same.Apply this diff to remove the redundant call:
function InsideComponent() { const searchViaHook = useSearch({ from: '/(group)/inside' }) const searchViaRouteHook = routeApi.useSearch() - const searchViaRouteApi = routeApi.useSearch() return ( <div> <div data-testid="search-via-hook">{searchViaHook.value.hello}</div> <div data-testid="search-via-route-hook"> {searchViaRouteHook.value.hello} </div> - <div data-testid="search-via-route-api"> - {searchViaRouteApi.value.hello} - </div> </div> ) }Alternatively, if testing multiple calls is intentional, consider renaming the variables to clarify they're duplicate calls of the same API (e.g.,
searchViaRouteApi1andsearchViaRouteApi2).e2e/vue-router/basic-esbuild-file-based/src/components/EditingAComponent.tsx (2)
4-17: Add explicit type annotations for better type safety.The component is missing type annotations on the reactive state and hooks. As per coding guidelines, TypeScript strict mode with extensive type safety should be applied to
.tsxfiles.Apply this diff to add explicit types:
export const EditingAComponent = defineComponent({ setup() { - const navigate = useNavigate() - const input = ref('') + const navigate = useNavigate() + const input = ref<string>('') const blocker = useBlocker({ shouldBlockFn: ({ next }) => { if (next.fullPath === '/editing-b' && input.value.length > 0) { return true } return false }, withResolver: true, })As per coding guidelines, TypeScript strict mode with extensive type safety is expected for
.tsxfiles.
27-29: Consider typing the event parameter for better type safety.While the type assertion works, you could improve type safety by explicitly typing the event parameter.
Apply this diff:
- onInput={(e) => + onInput={(e: Event) => (input.value = (e.target as HTMLInputElement).value) }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pnpm-lock.yamlis excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (48)
e2e/vue-router/basic-esbuild-file-based/eslint.config.js(1 hunks)e2e/vue-router/basic-esbuild-file-based/index.html(1 hunks)e2e/vue-router/basic-esbuild-file-based/package.json(1 hunks)e2e/vue-router/basic-esbuild-file-based/playwright.config.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/postcss.config.mjs(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/EditingAComponent.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/EditingBComponent.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/NotFoundComponent.vue(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/NotRemountDepsComponent.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/PostErrorComponent.vue(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/RemountDepsComponent.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/components/VueLogo.vue(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/esbuild.config.js(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/esbuild.run.js(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/jsx-shim.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/main.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/posts.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/__root.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-a.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-b.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/editing-a.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/editing-b.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/posts.index.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/posts.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/posts_.$postId.edit.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/remountDeps.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/sfcComponent.component.vue(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/sfcComponent.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/routes/대한민국.tsx(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/styles.css(1 hunks)e2e/vue-router/basic-esbuild-file-based/src/vue-shims.d.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/test-results/.last-run.json(1 hunks)e2e/vue-router/basic-esbuild-file-based/tests/app.spec.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/tests/setup/global.setup.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/tests/setup/global.teardown.ts(1 hunks)e2e/vue-router/basic-esbuild-file-based/tsconfig.json(1 hunks)
✅ Files skipped from review due to trivial changes (2)
- e2e/vue-router/basic-esbuild-file-based/index.html
- e2e/vue-router/basic-esbuild-file-based/test-results/.last-run.json
🚧 Files skipped from review as they are similar to previous changes (32)
- e2e/vue-router/basic-esbuild-file-based/src/routes/remountDeps.tsx
- e2e/vue-router/basic-esbuild-file-based/src/routes/sfcComponent.tsx
- e2e/vue-router/basic-esbuild-file-based/src/components/NotFoundComponent.vue
- e2e/vue-router/basic-esbuild-file-based/src/main.tsx
- e2e/vue-router/basic-esbuild-file-based/tests/setup/global.teardown.ts
- e2e/vue-router/basic-esbuild-file-based/src/routes/editing-a.tsx
- e2e/vue-router/basic-esbuild-file-based/src/vue-shims.d.ts
- e2e/vue-router/basic-esbuild-file-based/src/esbuild.run.js
- e2e/vue-router/basic-esbuild-file-based/src/components/PostErrorComponent.vue
- e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsx
- e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.tsx
- e2e/vue-router/basic-esbuild-file-based/src/routes/posts_.$postId.edit.tsx
- e2e/vue-router/basic-esbuild-file-based/postcss.config.mjs
- e2e/vue-router/basic-esbuild-file-based/tsconfig.json
- e2e/vue-router/basic-esbuild-file-based/src/routes/posts.tsx
- e2e/vue-router/basic-esbuild-file-based/src/routes/__root.tsx
- e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-b.tsx
- e2e/vue-router/basic-esbuild-file-based/src/esbuild.config.js
- e2e/vue-router/basic-esbuild-file-based/src/components/NotRemountDepsComponent.tsx
- e2e/vue-router/basic-esbuild-file-based/playwright.config.ts
- e2e/vue-router/basic-esbuild-file-based/tests/setup/global.setup.ts
- e2e/vue-router/basic-esbuild-file-based/src/routes/sfcComponent.component.vue
- e2e/vue-router/basic-esbuild-file-based/src/components/EditingBComponent.tsx
- e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsx
- e2e/vue-router/basic-esbuild-file-based/src/jsx-shim.ts
- e2e/vue-router/basic-esbuild-file-based/src/posts.tsx
- e2e/vue-router/basic-esbuild-file-based/src/routes/_layout.tsx
- e2e/vue-router/basic-esbuild-file-based/src/routes/posts.index.tsx
- e2e/vue-router/basic-esbuild-file-based/src/routes/editing-b.tsx
- e2e/vue-router/basic-esbuild-file-based/tests/app.spec.ts
- e2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsx
- e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-a.tsx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript strict mode with extensive type safety for all code
Files:
e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/components/EditingAComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsxe2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.tse2e/vue-router/basic-esbuild-file-based/src/routes/대한민국.tsxe2e/vue-router/basic-esbuild-file-based/src/components/RemountDepsComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Implement ESLint rules for router best practices using the ESLint plugin router
Files:
e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/components/EditingAComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsxe2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.tse2e/vue-router/basic-esbuild-file-based/eslint.config.jse2e/vue-router/basic-esbuild-file-based/src/routes/대한민국.tsxe2e/vue-router/basic-esbuild-file-based/src/components/RemountDepsComponent.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace protocol
workspace:*for internal dependencies in package.json files
Files:
e2e/vue-router/basic-esbuild-file-based/package.json
🧠 Learnings (8)
📓 Common learnings
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.
Learnt from: FatahChan
Repo: TanStack/router PR: 5475
File: e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx:8-0
Timestamp: 2025-10-14T18:59:33.990Z
Learning: In TanStack Router e2e test files, when a route parameter is validated at the route level (e.g., using zod in validateSearch or param validation), switch statements on that parameter do not require a default case, as the validation ensures only expected values will reach the switch.
📚 Learning: 2025-10-01T18:31:35.420Z
Learnt from: schiller-manuel
Repo: TanStack/router PR: 5330
File: e2e/react-start/custom-basepath/src/routeTree.gen.ts:58-61
Timestamp: 2025-10-01T18:31:35.420Z
Learning: Do not review files named `routeTree.gen.ts` in TanStack Router repositories, as these are autogenerated files that should not be manually modified.
Applied to files:
e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsxe2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.tse2e/vue-router/basic-esbuild-file-based/src/routes/대한민국.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Use file-based routing in `src/routes/` directories or code-based routing with route definitions
Applied to files:
e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router
Applied to files:
e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsxe2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.tse2e/vue-router/basic-esbuild-file-based/eslint.config.jse2e/vue-router/basic-esbuild-file-based/src/routes/대한민국.tsxe2e/vue-router/basic-esbuild-file-based/src/styles.csse2e/vue-router/basic-esbuild-file-based/package.jsone2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx
📚 Learning: 2025-10-08T08:11:47.088Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5402
File: packages/router-generator/tests/generator/no-formatted-route-tree/routeTree.nonnested.snapshot.ts:19-21
Timestamp: 2025-10-08T08:11:47.088Z
Learning: Test snapshot files in the router-generator tests directory (e.g., files matching the pattern `packages/router-generator/tests/generator/**/routeTree*.snapshot.ts` or `routeTree*.snapshot.js`) should not be modified or have issues flagged, as they are fixtures used to verify the generator's output and are intentionally preserved as-is.
Applied to files:
e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsxe2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.tse2e/vue-router/basic-esbuild-file-based/src/routes/대한민국.tsxe2e/vue-router/basic-esbuild-file-based/package.jsone2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx
📚 Learning: 2025-10-14T18:59:33.990Z
Learnt from: FatahChan
Repo: TanStack/router PR: 5475
File: e2e/react-start/basic-prerendering/src/routes/redirect/$target/via-beforeLoad.tsx:8-0
Timestamp: 2025-10-14T18:59:33.990Z
Learning: In TanStack Router e2e test files, when a route parameter is validated at the route level (e.g., using zod in validateSearch or param validation), switch statements on that parameter do not require a default case, as the validation ensures only expected values will reach the switch.
Applied to files:
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsxe2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx
📚 Learning: 2025-11-02T16:16:24.898Z
Learnt from: nlynzaad
Repo: TanStack/router PR: 5732
File: packages/start-client-core/src/client/hydrateStart.ts:6-9
Timestamp: 2025-11-02T16:16:24.898Z
Learning: In packages/start-client-core/src/client/hydrateStart.ts, the `import/no-duplicates` ESLint disable is necessary for imports from `#tanstack-router-entry` and `#tanstack-start-entry` because both aliases resolve to the same placeholder file (`fake-start-entry.js`) in package.json during static analysis, even though they resolve to different files at runtime.
Applied to files:
e2e/vue-router/basic-esbuild-file-based/eslint.config.jse2e/vue-router/basic-esbuild-file-based/src/styles.csse2e/vue-router/basic-esbuild-file-based/package.json
📚 Learning: 2025-12-06T15:03:07.223Z
Learnt from: CR
Repo: TanStack/router PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-06T15:03:07.223Z
Learning: Applies to **/*.{ts,tsx} : Use TypeScript strict mode with extensive type safety for all code
Applied to files:
e2e/vue-router/basic-esbuild-file-based/eslint.config.js
🧬 Code graph analysis (6)
e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsx (16)
e2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.tsx (1)
Route(3-5)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/__root.tsx (1)
Route(13-16)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout.tsx (1)
Route(3-5)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsx (1)
Route(3-5)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-a.tsx (1)
Route(3-5)e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2/layout-b.tsx (1)
Route(3-5)e2e/vue-router/basic-esbuild-file-based/src/routes/editing-a.tsx (1)
Route(4-6)e2e/vue-router/basic-esbuild-file-based/src/routes/editing-b.tsx (1)
Route(4-6)e2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsx (1)
Route(4-15)e2e/vue-router/basic-esbuild-file-based/src/routes/posts.$postId.tsx (1)
Route(6-11)e2e/vue-router/basic-esbuild-file-based/src/routes/posts.index.tsx (1)
Route(3-5)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsx (2)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsx (1)
Route(4-6)
e2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsx (1)
e2e/vue-router/basic-esbuild-file-based/src/components/NotRemountDepsComponent.tsx (1)
NotRemountDepsComponent(4-37)
e2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.ts (1)
packages/router-generator/tests/generator/types-disabled/routeTree.nonnested.snapshot.js (3)
PostsRoute(17-21)PostsRouteWithChildren(42-42)PostsRouteChildren(38-40)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx (3)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/_layout.insidelayout.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsx (1)
Route(5-8)
e2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx (2)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx (1)
Route(5-8)e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/lazyinside.tsx (1)
Route(5-8)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
- GitHub Check: Preview
- GitHub Check: Test
🔇 Additional comments (16)
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/inside.tsx (1)
1-10: LGTM! Route setup is well-structured.The route definition correctly uses file-based routing with proper search parameter validation. The zod schema ensures type safety for the optional
helloparameter.e2e/vue-router/basic-esbuild-file-based/src/components/RemountDepsComponent.tsx (4)
1-2: LGTM!Imports are clean and appropriate for the component's functionality.
4-5: Good pattern for testing remount behavior.The module-scoped ref correctly persists the mount count across component remounts, which is exactly what's needed for validating remount scenarios in e2e tests. The comment clearly explains the intent.
7-14: LGTM!The component setup uses TanStack Vue Router's type-safe hooks effectively. The
from: '/remountDeps'parameter inuseSearchprovides excellent type safety by constraining the search parameters to the specific route definition. The lifecycle hook properly tracks mount behavior for testing.
16-36: LGTM!The render function is well-structured with correct Vue 3 TSX syntax. The navigation logic appropriately generates random search parameters for testing remount scenarios, and the component correctly accesses reactive values using
.value. Thedata-testidattribute on Line 32 is excellent for e2e test stability.e2e/vue-router/basic-esbuild-file-based/src/components/EditingAComponent.tsx (2)
1-2: LGTM!The imports are appropriate for implementing the blocker-based navigation component.
35-37: LGTM!The conditional rendering and optional chaining on
proceed?.()correctly implement the blocker resolution pattern. The logic properly handles the case where navigation is blocked and provides a way to proceed.e2e/vue-router/basic-esbuild-file-based/src/routes/notRemountDeps.tsx (1)
4-15: LGTM! Route configuration correctly implements remount behavior testing.The route configuration appropriately separates loader dependencies (search) from remount dependencies (params), ensuring that search parameter changes trigger loader re-execution without component remount. This correctly aligns with the "NotRemountDeps" test scenario.
e2e/vue-router/basic-esbuild-file-based/src/components/VueLogo.vue (2)
1-33: LGTM! Well-structured Vue 3 composition API component.The script setup section properly uses TypeScript, defines typed props with defaults, and implements clean reactive state management. The component logic correctly handles the click counter with appropriate labels.
35-57: LGTM! Template correctly implements interactive Vue logo.The template properly binds event handlers, uses dynamic styling for the text color prop, and conditionally renders the reset button. The SVG logo is well-structured with appropriate accessibility for click interactions.
e2e/vue-router/basic-esbuild-file-based/src/routes/index.tsx (1)
4-15: LGTM! Root route correctly configured.The route definition properly uses
createFileRoutefor the root path, and theIndexComponentcorrectly renders the welcome message with the Vue logo component. The JSX syntax is appropriate for TanStack Vue Router with TypeScript.e2e/vue-router/basic-esbuild-file-based/src/routeTree.gen.ts (1)
1-513: Autogenerated file – no review needed.This
routeTree.gen.tsfile is automatically generated by TanStack Router and should not be manually modified or reviewed. Based on learnings, these files are excluded from code review.e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsx (1)
1-8: LGTM!The imports and route definition follow TanStack Router conventions correctly. The search validation schema with an optional
hellofield is appropriate for testing.e2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx (3)
1-3: LGTM!The imports are appropriate and all are utilized in the file.
5-8: LGTM!The route definition follows the established pattern demonstrated in other routes within this project.
10-10: LGTM!The route API handle is correctly initialized with the matching route path.
| import js from '@eslint/js' | ||
| import typescript from '@typescript-eslint/eslint-plugin' | ||
| import typescriptParser from '@typescript-eslint/parser' | ||
| import vue from 'eslint-plugin-vue' | ||
| import vueParser from 'vue-eslint-parser' | ||
|
|
||
| export default [ | ||
| js.configs.recommended, | ||
| ...vue.configs['flat/recommended'], | ||
| { | ||
| files: ['**/*.{js,jsx,ts,tsx,vue}'], | ||
| languageOptions: { | ||
| parser: vueParser, | ||
| parserOptions: { | ||
| parser: typescriptParser, | ||
| ecmaVersion: 'latest', | ||
| sourceType: 'module', | ||
| ecmaFeatures: { | ||
| jsx: true, | ||
| }, | ||
| }, | ||
| }, | ||
| plugins: { | ||
| '@typescript-eslint': typescript, | ||
| vue, | ||
| }, | ||
| rules: { | ||
| // Vue specific rules | ||
| 'vue/multi-word-component-names': 'off', | ||
| 'vue/no-unused-vars': 'error', | ||
|
|
||
| // TypeScript rules | ||
| '@typescript-eslint/no-unused-vars': 'error', | ||
| '@typescript-eslint/no-explicit-any': 'warn', | ||
|
|
||
| // General rules | ||
| 'no-unused-vars': 'off', // Let TypeScript handle this | ||
| }, | ||
| }, | ||
| { | ||
| files: ['**/*.vue'], | ||
| languageOptions: { | ||
| parser: vueParser, | ||
| parserOptions: { | ||
| parser: typescriptParser, | ||
| }, | ||
| }, | ||
| }, | ||
| ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add router ESLint plugin configuration.
As per coding guidelines, files matching **/*.{js,ts,tsx} should implement ESLint rules for router best practices using the ESLint plugin router. This ESLint configuration is missing the TanStack router ESLint plugin.
Based on coding guidelines, the ESLint plugin for TanStack Router should be added:
-
First, ensure the router ESLint plugin package is added to
package.jsondevDependencies (see comment on package.json). -
Then, import and configure it in this file:
import js from '@eslint/js'
import typescript from '@typescript-eslint/eslint-plugin'
import typescriptParser from '@typescript-eslint/parser'
import vue from 'eslint-plugin-vue'
import vueParser from 'vue-eslint-parser'
+import routerPlugin from '@tanstack/eslint-plugin-router'
export default [
js.configs.recommended,
...vue.configs['flat/recommended'],
+ ...routerPlugin.configs['flat/recommended'],
{🤖 Prompt for AI Agents
In e2e/vue-router/basic-esbuild-file-based/eslint.config.js lines 1-49, add the
TanStack Router ESLint plugin: import the router plugin at the top (after other
imports), ensure the router package is present in devDependencies, then include
it in the appropriate config block for files matching **/*.{js,jsx,ts,tsx,vue}
(or at least **/*.{js,ts,tsx}) by adding it to the plugins object and extending
or spreading its recommended/flat config (e.g., router.configs.recommended or
router.configs['flat/recommended']) so router best-practice rules are enabled
alongside existing JS/Vue/TypeScript rules.
| "@tanstack/router-plugin": "workspace:^", | ||
| "@tanstack/vue-router": "workspace:^", | ||
| "@tanstack/vue-router-devtools": "workspace:^", | ||
| "@tanstack/zod-adapter": "workspace:^", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Use workspace:* protocol for internal dependencies.
As per coding guidelines, internal dependencies should use the workspace:* protocol instead of workspace:^.
Apply this diff to align with the coding guidelines:
"dependencies": {
- "@tanstack/router-plugin": "workspace:^",
- "@tanstack/vue-router": "workspace:^",
- "@tanstack/vue-router-devtools": "workspace:^",
- "@tanstack/zod-adapter": "workspace:^",
+ "@tanstack/router-plugin": "workspace:*",
+ "@tanstack/vue-router": "workspace:*",
+ "@tanstack/vue-router-devtools": "workspace:*",
+ "@tanstack/zod-adapter": "workspace:*",
"postcss": "^8.5.1",
"redaxios": "^0.5.1",
"vue": "^3.5.16",
"zod": "^3.24.2"
},
"devDependencies": {
"@eslint/js": "^9.36.0",
"@playwright/test": "^1.50.1",
- "@tanstack/router-e2e-utils": "workspace:^",
+ "@tanstack/router-e2e-utils": "workspace:*",Also applies to: 25-25
🤖 Prompt for AI Agents
In e2e/vue-router/basic-esbuild-file-based/package.json around lines 13-16 and
line 25, internal dependencies are using the incorrect protocol "workspace:^";
replace all occurrences of "workspace:^" with the "workspace:*" protocol for the
listed internal packages (e.g., @tanstack/router-plugin, @tanstack/vue-router,
@tanstack/vue-router-devtools, @tanstack/zod-adapter and any other internal
package at line 25) and save the file so package.json reflects workspace:* for
internal workspace references.
| "devDependencies": { | ||
| "@eslint/js": "^9.36.0", | ||
| "@playwright/test": "^1.50.1", | ||
| "@tanstack/router-e2e-utils": "workspace:^", | ||
| "@typescript-eslint/eslint-plugin": "^8.44.1", | ||
| "@typescript-eslint/parser": "^8.44.1", | ||
| "esbuild": "^0.25.0", | ||
| "esbuild-plugin-vue3": "^0.5.1", | ||
| "eslint-plugin-vue": "^9.33.0", | ||
| "typescript": "^5.8.3", | ||
| "vue-eslint-parser": "^9.4.3", | ||
| "vue-tsc": "^3.1.5" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add router ESLint plugin to devDependencies.
As per coding guidelines, ESLint rules for router best practices should be implemented using the ESLint plugin router. The corresponding package needs to be added to devDependencies.
Add the router ESLint plugin to devDependencies:
"devDependencies": {
"@eslint/js": "^9.36.0",
"@playwright/test": "^1.50.1",
"@tanstack/router-e2e-utils": "workspace:*",
+ "@tanstack/eslint-plugin-router": "workspace:*",
"@typescript-eslint/eslint-plugin": "^8.44.1",Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In e2e/vue-router/basic-esbuild-file-based/package.json around lines 22 to 34,
devDependencies are missing the router ESLint plugin required by our coding
guidelines; add the package "eslint-plugin-vue-router" to devDependencies (match
project versioning policy), run install to update lockfile, and ensure the
ESLint config (eslintrc) later references "vue-router" in the plugins array so
router rules are enabled.
| import { Link, Outlet, createFileRoute } from '@tanstack/vue-router' | ||
|
|
||
| export const Route = createFileRoute('/_layout/_layout-2')({ | ||
| component: Layout2Component, | ||
| }) | ||
|
|
||
| function Layout2Component() { | ||
| return ( | ||
| <div> | ||
| <div>I'm a nested layout</div> | ||
| <div class="flex gap-2 border-b"> | ||
| <Link to="/layout-a" activeProps={{ class: 'font-bold' }}> | ||
| Layout A | ||
| </Link> | ||
| <Link to="/layout-b" activeProps={{ class: 'font-bold' }}> | ||
| Layout B | ||
| </Link> | ||
| </div> | ||
| <div> | ||
| <Outlet /> | ||
| </div> | ||
| </div> | ||
| ) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check directory structure and file contents
# 1. List the e2e/vue-router directory structure
echo "=== Directory structure ==="
ls -la e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/ 2>/dev/null || echo "Directory not found"
# 2. List all files in the e2e directory
echo -e "\n=== All e2e subdirectories ==="
ls -la e2e/ 2>/dev/null | head -20
# 3. Check if there's a package.json in the e2e/vue-router directory
echo -e "\n=== Package.json in e2e/vue-router ==="
cat e2e/vue-router/basic-esbuild-file-based/package.json 2>/dev/null | head -30
# 4. Examine other route files in the same project
echo -e "\n=== Other files in _layout directory ==="
fd . e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/ -type f 2>/dev/null
# 5. Check another route file from same project
echo -e "\n=== Sample route file from same project ==="
find e2e/vue-router/basic-esbuild-file-based/src/routes -name "*.tsx" -o -name "*.ts" 2>/dev/null | head -5Repository: TanStack/router
Length of output: 2418
🏁 Script executed:
#!/bin/bash
# Explore the repository structure
echo "=== Checking directory existence ==="
if [ -d "e2e/vue-router/basic-esbuild-file-based" ]; then
echo "Directory found"
echo -e "\n=== Route files in _layout ==="
find e2e/vue-router/basic-esbuild-file-based/src/routes/_layout -type f 2>/dev/null
echo -e "\n=== All route files (first 10) ==="
find e2e/vue-router/basic-esbuild-file-based/src/routes -type f -name "*.tsx" -o -name "*.ts" 2>/dev/null | head -10
echo -e "\n=== Package.json contents ==="
if [ -f "e2e/vue-router/basic-esbuild-file-based/package.json" ]; then
cat e2e/vue-router/basic-esbuild-file-based/package.json | head -40
fi
echo -e "\n=== Checking for tsconfig.json ==="
if [ -f "e2e/vue-router/basic-esbuild-file-based/tsconfig.json" ]; then
echo "tsconfig found"
cat e2e/vue-router/basic-esbuild-file-based/tsconfig.json | head -20
fi
else
echo "Directory not found - checking available e2e directories"
ls -la e2e/ 2>/dev/null | grep vue
fiRepository: TanStack/router
Length of output: 2753
Add return type annotation to Layout2Component function.
With TypeScript strict mode enabled, the Layout2Component function must have an explicit return type annotation. Update line 7 to include the return type (e.g., function Layout2Component(): JSX.Element).
🤖 Prompt for AI Agents
In e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsx
lines 1-24, the Layout2Component is missing an explicit return type causing
TypeScript strict mode errors; update the function signature to include a return
type (for example: annotate the function as returning JSX.Element) so the
component has an explicit typed return, and ensure any needed JSX types are
available in the TSX context or imports if required.
| function Layout2Component() { | ||
| return ( | ||
| <div> | ||
| <div>I'm a nested layout</div> | ||
| <div class="flex gap-2 border-b"> | ||
| <Link to="/layout-a" activeProps={{ class: 'font-bold' }}> | ||
| Layout A | ||
| </Link> | ||
| <Link to="/layout-b" activeProps={{ class: 'font-bold' }}> | ||
| Layout B | ||
| </Link> | ||
| </div> | ||
| <div> | ||
| <Outlet /> | ||
| </div> | ||
| </div> | ||
| ) | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add TypeScript type annotations for strict mode compliance.
The Layout2Component function lacks a return type annotation. Per coding guidelines, TypeScript strict mode with extensive type safety should be used for all .ts and .tsx files.
Expected type annotation:
-function Layout2Component() {
+function Layout2Component(): JSX.Element {Note: The actual return type depends on whether this should be a Vue component type or JSX.Element. This ties back to the question of whether React-style JSX is appropriate here.
📝 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.
| function Layout2Component() { | |
| return ( | |
| <div> | |
| <div>I'm a nested layout</div> | |
| <div class="flex gap-2 border-b"> | |
| <Link to="/layout-a" activeProps={{ class: 'font-bold' }}> | |
| Layout A | |
| </Link> | |
| <Link to="/layout-b" activeProps={{ class: 'font-bold' }}> | |
| Layout B | |
| </Link> | |
| </div> | |
| <div> | |
| <Outlet /> | |
| </div> | |
| </div> | |
| ) | |
| } | |
| function Layout2Component(): JSX.Element { | |
| return ( | |
| <div> | |
| <div>I'm a nested layout</div> | |
| <div class="flex gap-2 border-b"> | |
| <Link to="/layout-a" activeProps={{ class: 'font-bold' }}> | |
| Layout A | |
| </Link> | |
| <Link to="/layout-b" activeProps={{ class: 'font-bold' }}> | |
| Layout B | |
| </Link> | |
| </div> | |
| <div> | |
| <Outlet /> | |
| </div> | |
| </div> | |
| ) | |
| } |
🤖 Prompt for AI Agents
In e2e/vue-router/basic-esbuild-file-based/src/routes/_layout/_layout-2.tsx
around lines 7 to 24, the Layout2Component function is missing a TypeScript
return type annotation required for strict mode; add an explicit return type
(for example JSX.Element if using Vue JSX/TSX, or the appropriate Vue component
type such as DefineComponent/FunctionalComponent) to the function signature and
import the necessary types from 'vue' or the JSX namespace; ensure the chosen
type matches how the file's JSX is compiled so the file satisfies strict type
checking.
| const searchViaRouteHook = routeApi.useSearch() | ||
| const searchViaRouteApi = routeApi.useSearch() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove duplicate routeApi.useSearch() call.
Lines 14 and 15 both call routeApi.useSearch() identically but assign to different variables with distinct names. The variable names suggest different access methods, but the implementation is identical. This is redundant and misleading.
Consider removing one of these lines (likely line 15 and its corresponding render at lines 23-25), or if testing multiple calls to the same API is intentional, use clearer naming to indicate they're demonstrating the same approach.
Apply this diff to remove the redundancy:
function OnlyRouteInsideComponent() {
const searchViaHook = useSearch({ from: '/(another-group)/onlyrouteinside' })
const searchViaRouteHook = routeApi.useSearch()
- const searchViaRouteApi = routeApi.useSearch()
return (
<div>
<div data-testid="search-via-hook">{searchViaHook.value.hello}</div>
<div data-testid="search-via-route-hook">
{searchViaRouteHook.value.hello}
</div>
- <div data-testid="search-via-route-api">
- {searchViaRouteApi.value.hello}
- </div>
</div>
)
}Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In
e2e/vue-router/basic-esbuild-file-based/src/routes/(another-group)/onlyrouteinside.tsx
around lines 14-15, there are duplicate calls to routeApi.useSearch() assigned
to searchViaRouteHook and searchViaRouteApi; remove the redundant one by
deleting the second declaration (line 15) and also remove its corresponding
render/usage block at lines 23-25 (or alternatively rename to clearly indicate
intentional duplication if both calls must remain).
| const searchViaRouteHook = routeApi.useSearch() | ||
| const searchViaRouteApi = routeApi.useSearch() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove duplicate identical calls.
Lines 14 and 15 are identical—both call routeApi.useSearch() with no differences. The variable names suggest an intent to demonstrate different approaches, but the implementation is the same. This creates unnecessary duplication.
Apply this diff to remove the duplicate:
function SubfolderInsideComponent() {
const searchViaHook = useSearch({ from: '/(group)/subfolder/inside' })
const searchViaRouteHook = routeApi.useSearch()
- const searchViaRouteApi = routeApi.useSearch()
return (
<div>
<div data-testid="search-via-hook">{searchViaHook.value.hello}</div>
<div data-testid="search-via-route-hook">
{searchViaRouteHook.value.hello}
</div>
- <div data-testid="search-via-route-api">
- {searchViaRouteApi.value.hello}
- </div>
</div>
)
}If the duplication was intentional for testing purposes, please clarify the intended difference between these two approaches.
📝 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.
| const searchViaRouteHook = routeApi.useSearch() | |
| const searchViaRouteApi = routeApi.useSearch() | |
| function SubfolderInsideComponent() { | |
| const searchViaHook = useSearch({ from: '/(group)/subfolder/inside' }) | |
| const searchViaRouteHook = routeApi.useSearch() | |
| return ( | |
| <div> | |
| <div data-testid="search-via-hook">{searchViaHook.value.hello}</div> | |
| <div data-testid="search-via-route-hook"> | |
| {searchViaRouteHook.value.hello} | |
| </div> | |
| </div> | |
| ) | |
| } |
🤖 Prompt for AI Agents
In
e2e/vue-router/basic-esbuild-file-based/src/routes/(group)/subfolder/inside.tsx
around lines 14 to 15, there's a duplicate call to routeApi.useSearch(); remove
one of the identical lines so only a single useSearch() invocation remains (keep
the variable name that best matches intended usage, e.g., searchViaRouteApi or
searchViaRouteHook), or if both were meant to demonstrate different approaches,
update one call to the correct alternative API (and rename its variable) and add
a brief comment indicating the intentional distinction.
Summary by CodeRabbit
Release Notes
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.