-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
feat: add split-exports plugin #6104
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
base: main
Are you sure you want to change the base?
Conversation
WalkthroughAdds a Split-Exports Vite plugin and integrates it into the start-plugin-core pipeline; provides AST-based import/export rewriting, module-loader support, per-environment server-fn compilation changes, extensive unit tests, and an e2e React project (with Playwright HMR tests) that validates import-splitting, SSR/client boundaries, and HMR behavior. Changes
Sequence Diagram(s)sequenceDiagram
participant Importing as Importing Module
participant ImportRewriter as ImportRewriter (pre)
participant Resolver as Resolver (resolve plugin)
participant ExportTransformer as ExportTransformer (transform)
participant ModuleLoader as ModuleLoaderApi
participant Compiler as ServerFnCompiler / DCE
Importing->>ImportRewriter: analyze imports, extract used symbols
ImportRewriter->>Resolver: rewrite imports adding split-exports query
Resolver->>ExportTransformer: request module ID with split-exports query
ExportTransformer->>Compiler: parse module, keep requested exports, transform others to locals
ExportTransformer->>ModuleLoader: (dev) capture transformed code / (build) produce transformed file
ModuleLoader->>Importing: supply transformed module code
Importing->>Compiler: (server-fn paths) request per-env compiled module via ModuleLoaderApi
Compiler->>Compiler: perform per-env compilation, DCE, return final code
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
|
| Command | Status | Duration | Result |
|---|---|---|---|
nx affected --targets=test:eslint,test:unit,tes... |
❌ Failed | 4m 53s | View ↗ |
nx run-many --target=build --exclude=examples/*... |
✅ Succeeded | 22s | View ↗ |
☁️ Nx Cloud last updated this comment at 2025-12-16 02:53:11 UTC
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: 1
🧹 Nitpick comments (10)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/externalImports.ts (1)
2-3: Verify quote style consistency in plugin output.The snapshot shows inconsistent quote styles: single quotes for the external import (line 2) and double quotes for the transformed local import (line 3). This inconsistency may indicate that the plugin changes quote styles during transformation.
Please verify whether this quote style change is intentional. If not, consider updating the plugin to preserve the original quote style when adding the query parameter:
import { useState } from 'react'; -import { foo } from "./utils?tss-split-exports=foo"; +import { foo } from './utils?tss-split-exports=foo';e2e/react-start/split-exports/.gitignore (1)
1-5: Gitignore entries are solid; optionally ignore Playwright artifactsPatterns for build/cache dirs look good. Since this project runs Playwright, you might optionally add
playwright-reportandtest-resultsto keep test artifacts out of git.e2e/react-start/split-exports/src/router.tsx (1)
1-12: Router factory is correct; consider adding an explicit return typeThe
getRouterimplementation is standard and usesrouteTree,scrollRestoration, anddefaultPreloadappropriately. To better align with strict typing, you could explicitly annotate the return type (e.g.,ReturnType<typeof createRouter>) so the router type is stable even if the body changes.packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/functionExports.ts (1)
1-4: Comment wording slightly misleading vs snapshot contentThis snapshot only contains
myFunction, but the header comment still says “Multiple function exports”. Not a blocker, but consider clarifying the comment to reflect that this snapshot represents the pruned output (single remaining export) from the multi-export source module.e2e/react-start/split-exports/src/routes/__root.tsx (1)
38-55: Consider adding navigation link for server-request-import route.The navigation includes links to most test routes, but the
server-request-importroute (mentioned in the context and present in the route files) is not included in the navigation menu.If this route should be accessible via navigation, add it to the menu:
<Link to="/alias-import" activeProps={{ className: 'font-bold' }}> Alias Import </Link> + <Link to="/server-request-import" activeProps={{ className: 'font-bold' }}> + Server Request Import + </Link> </div>e2e/react-start/split-exports/tests/split-exports-hmr.spec.ts (1)
59-78: Consider making HMR wait more robust.The
waitForHmrhelper relies onnetworkidleplus a fixed 500ms delay. While this works in most cases, HMR completion timing can vary. Consider using a more deterministic approach if flakiness occurs.async function waitForHmr(page: Page, timeout = 5000): Promise<void> { // Wait for any pending HMR connections await page.waitForLoadState('networkidle', { timeout }) // Additional small delay for HMR processing - await page.waitForTimeout(500) + await page.waitForTimeout(1000) }e2e/react-start/split-exports/src/utils/shared.ts (1)
49-61: Consider adding runtime guards to other server-only exports for consistency.
getServerOnlyUserDataandserverOnlyConfigrely ongetServerOnlyDatabase()being called to trigger the guard, but direct access toserverOnlyConfigproperties wouldn't throw. Since this is a test fixture, this may be intentional to verify the plugin properly eliminates these exports.packages/start-plugin-core/src/split-exports-plugin/query-utils.ts (1)
33-42: Consider edge case with special characters in export names.Export names containing commas or other URL-sensitive characters could cause parsing issues. While uncommon in practice, JavaScript allows identifiers like
export { foo as "bar,baz" }in some contexts.If special characters in export names need to be supported, consider URL-encoding individual names:
- const sortedNames = Array.from(exportNames).sort() - const newParam = `${SPLIT_EXPORTS_QUERY_KEY}=${sortedNames.join(',')}` + const sortedNames = Array.from(exportNames).sort().map(encodeURIComponent) + const newParam = `${SPLIT_EXPORTS_QUERY_KEY}=${sortedNames.join(',')}`And decode when parsing:
- return new Set(value.split(',').filter(Boolean)) + return new Set(value.split(',').filter(Boolean).map(decodeURIComponent))packages/start-plugin-core/tests/split-exports-plugin/split-exports.test.ts (1)
3-3: Unused import detected.The
viimport fromvitestappears to be unused in this test file.-import { describe, expect, test, vi } from 'vitest' +import { describe, expect, test } from 'vitest'packages/start-plugin-core/src/split-exports-plugin/plugin.ts (1)
219-221: Static analysis false positive - ReDoS warning is not applicable.The static analysis tool flags
new RegExp(\[?&]${SPLIT_EXPORTS_QUERY_KEY}=`)as a potential ReDoS risk. However,SPLIT_EXPORTS_QUERY_KEYis a constant string ('tss-split-exports'), making the resulting regex effectively static:/[?&]tss-split-exports=/`. This pattern has no backtracking and is safe.Consider extracting this to a module-level constant to silence the warning and avoid regex re-creation:
+const SPLIT_EXPORTS_FILTER_REGEX = new RegExp(`[?&]${SPLIT_EXPORTS_QUERY_KEY}=`) + function resolverPlugin(): Plugin { return { name: 'tanstack-split-exports:resolve', resolveId: { filter: { - id: new RegExp(`[?&]${SPLIT_EXPORTS_QUERY_KEY}=`), + id: SPLIT_EXPORTS_FILTER_REGEX, },Also applies to: 268-270
📜 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 (60)
e2e/react-start/split-exports/.gitignore(1 hunks)e2e/react-start/split-exports/.prettierignore(1 hunks)e2e/react-start/split-exports/package.json(1 hunks)e2e/react-start/split-exports/playwright-hmr.config.ts(1 hunks)e2e/react-start/split-exports/playwright.config.ts(1 hunks)e2e/react-start/split-exports/postcss.config.mjs(1 hunks)e2e/react-start/split-exports/src/routeTree.gen.ts(1 hunks)e2e/react-start/split-exports/src/router.tsx(1 hunks)e2e/react-start/split-exports/src/routes/__root.tsx(1 hunks)e2e/react-start/split-exports/src/routes/alias-import.tsx(1 hunks)e2e/react-start/split-exports/src/routes/direct-import.tsx(1 hunks)e2e/react-start/split-exports/src/routes/index.tsx(1 hunks)e2e/react-start/split-exports/src/routes/reexport-import.tsx(1 hunks)e2e/react-start/split-exports/src/routes/server-request-import.tsx(1 hunks)e2e/react-start/split-exports/src/styles/app.css(1 hunks)e2e/react-start/split-exports/src/utils/nested.ts(1 hunks)e2e/react-start/split-exports/src/utils/public-api.ts(1 hunks)e2e/react-start/split-exports/src/utils/server-request.ts(1 hunks)e2e/react-start/split-exports/src/utils/shared.ts(1 hunks)e2e/react-start/split-exports/tests/split-exports-hmr.spec.ts(1 hunks)e2e/react-start/split-exports/tests/split-exports.spec.ts(1 hunks)e2e/react-start/split-exports/tsconfig.json(1 hunks)e2e/react-start/split-exports/vite.config.ts(1 hunks)packages/start-plugin-core/src/plugin.ts(2 hunks)packages/start-plugin-core/src/schema.ts(1 hunks)packages/start-plugin-core/src/split-exports-plugin/README.md(1 hunks)packages/start-plugin-core/src/split-exports-plugin/compiler.ts(1 hunks)packages/start-plugin-core/src/split-exports-plugin/plugin-utils.ts(1 hunks)packages/start-plugin-core/src/split-exports-plugin/plugin.ts(1 hunks)packages/start-plugin-core/src/split-exports-plugin/query-utils.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/defaultExport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/functionExports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/multipleDeclarators.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/namedExports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/reExports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/serverOnlyCode.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/starReExport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/defaultImport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/existingQuery.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/externalImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedTypeValueImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/namedImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/typeOnlyImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/split-exports.test.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/defaultExport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/defaultImport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/existingQuery.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/externalImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/functionExports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/mixedImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/mixedTypeValueImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/multipleDeclarators.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/namedExports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/namedImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/namespaceImport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/reExports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/serverOnlyCode.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/starReExport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/typeOnlyImports.ts(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/react-start/split-exports/vite.config.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/externalImports.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/defaultImport.tspackages/start-plugin-core/src/plugin.tspackages/start-plugin-core/src/schema.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/namedImports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/existingQuery.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/defaultImport.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/reExports.tse2e/react-start/split-exports/src/router.tsxpackages/start-plugin-core/tests/split-exports-plugin/test-files/mixedTypeValueImports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/reExports.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/serverOnlyCode.tse2e/react-start/split-exports/src/routes/__root.tsxpackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/existingQuery.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/functionExports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/defaultExport.tse2e/react-start/split-exports/playwright-hmr.config.tse2e/react-start/split-exports/src/routes/direct-import.tsxe2e/react-start/split-exports/tests/split-exports.spec.tse2e/react-start/split-exports/src/utils/server-request.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/mixedImports.tspackages/start-plugin-core/src/split-exports-plugin/query-utils.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/externalImports.tse2e/react-start/split-exports/playwright.config.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedTypeValueImports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/multipleDeclarators.tse2e/react-start/split-exports/src/utils/public-api.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/namedImports.tspackages/start-plugin-core/src/split-exports-plugin/plugin-utils.tse2e/react-start/split-exports/src/utils/shared.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/typeOnlyImports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/namespaceImport.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/functionExports.tse2e/react-start/split-exports/src/routes/server-request-import.tsxpackages/start-plugin-core/tests/split-exports-plugin/test-files/typeOnlyImports.tse2e/react-start/split-exports/src/utils/nested.tspackages/start-plugin-core/src/split-exports-plugin/plugin.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/serverOnlyCode.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/multipleDeclarators.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedImports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/starReExport.tse2e/react-start/split-exports/src/routes/alias-import.tsxe2e/react-start/split-exports/src/routeTree.gen.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/namedExports.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/starReExport.tse2e/react-start/split-exports/tests/split-exports-hmr.spec.tse2e/react-start/split-exports/src/routes/index.tsxpackages/start-plugin-core/src/split-exports-plugin/compiler.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/defaultExport.tspackages/start-plugin-core/tests/split-exports-plugin/split-exports.test.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/namedExports.tse2e/react-start/split-exports/src/routes/reexport-import.tsx
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Implement ESLint rules for router best practices using the ESLint plugin router
Files:
e2e/react-start/split-exports/vite.config.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/externalImports.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/defaultImport.tspackages/start-plugin-core/src/plugin.tspackages/start-plugin-core/src/schema.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/namedImports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/existingQuery.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/defaultImport.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/reExports.tse2e/react-start/split-exports/src/router.tsxpackages/start-plugin-core/tests/split-exports-plugin/test-files/mixedTypeValueImports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/reExports.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/serverOnlyCode.tse2e/react-start/split-exports/src/routes/__root.tsxpackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/existingQuery.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/functionExports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/defaultExport.tse2e/react-start/split-exports/playwright-hmr.config.tse2e/react-start/split-exports/src/routes/direct-import.tsxe2e/react-start/split-exports/tests/split-exports.spec.tse2e/react-start/split-exports/src/utils/server-request.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/mixedImports.tspackages/start-plugin-core/src/split-exports-plugin/query-utils.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/externalImports.tse2e/react-start/split-exports/playwright.config.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedTypeValueImports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/multipleDeclarators.tse2e/react-start/split-exports/src/utils/public-api.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/namedImports.tspackages/start-plugin-core/src/split-exports-plugin/plugin-utils.tse2e/react-start/split-exports/src/utils/shared.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/typeOnlyImports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/namespaceImport.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/functionExports.tse2e/react-start/split-exports/src/routes/server-request-import.tsxpackages/start-plugin-core/tests/split-exports-plugin/test-files/typeOnlyImports.tse2e/react-start/split-exports/src/utils/nested.tspackages/start-plugin-core/src/split-exports-plugin/plugin.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/serverOnlyCode.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/multipleDeclarators.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedImports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/starReExport.tse2e/react-start/split-exports/src/routes/alias-import.tsxe2e/react-start/split-exports/src/routeTree.gen.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/namedExports.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/starReExport.tse2e/react-start/split-exports/tests/split-exports-hmr.spec.tse2e/react-start/split-exports/src/routes/index.tsxpackages/start-plugin-core/src/split-exports-plugin/compiler.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/defaultExport.tspackages/start-plugin-core/tests/split-exports-plugin/split-exports.test.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/namedExports.tse2e/react-start/split-exports/src/routes/reexport-import.tsx
**/package.json
📄 CodeRabbit inference engine (AGENTS.md)
Use workspace protocol
workspace:*for internal dependencies in package.json files
Files:
e2e/react-start/split-exports/package.json
🧠 Learnings (9)
📚 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/react-start/split-exports/.prettierignorepackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/existingQuery.tse2e/react-start/split-exports/src/routes/direct-import.tsxe2e/react-start/split-exports/tests/split-exports.spec.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/externalImports.tse2e/react-start/split-exports/src/routes/server-request-import.tsxpackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedImports.tse2e/react-start/split-exports/src/routes/alias-import.tsxe2e/react-start/split-exports/src/routeTree.gen.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/starReExport.tse2e/react-start/split-exports/tests/split-exports-hmr.spec.tse2e/react-start/split-exports/src/routes/index.tsxpackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/defaultExport.tspackages/start-plugin-core/tests/split-exports-plugin/split-exports.test.tse2e/react-start/split-exports/src/routes/reexport-import.tsx
📚 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/react-start/split-exports/.prettierignoree2e/react-start/split-exports/src/routes/__root.tsxe2e/react-start/split-exports/src/routeTree.gen.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/react-start/split-exports/.prettierignorepackages/start-plugin-core/tests/split-exports-plugin/test-files/externalImports.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/defaultImport.tspackages/start-plugin-core/src/plugin.tspackages/start-plugin-core/src/schema.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/namedImports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/defaultImport.tspackages/start-plugin-core/src/split-exports-plugin/README.mde2e/react-start/split-exports/src/routes/__root.tsxpackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/existingQuery.tse2e/react-start/split-exports/package.jsone2e/react-start/split-exports/playwright-hmr.config.tse2e/react-start/split-exports/src/routes/direct-import.tsxe2e/react-start/split-exports/tests/split-exports.spec.tse2e/react-start/split-exports/src/utils/server-request.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/externalImports.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedTypeValueImports.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/namedImports.tse2e/react-start/split-exports/src/utils/shared.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/typeOnlyImports.tse2e/react-start/split-exports/tsconfig.jsone2e/react-start/split-exports/src/routes/server-request-import.tsxpackages/start-plugin-core/tests/split-exports-plugin/test-files/typeOnlyImports.tse2e/react-start/split-exports/src/utils/nested.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/serverOnlyCode.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedImports.tse2e/react-start/split-exports/src/routes/alias-import.tsxe2e/react-start/split-exports/src/routeTree.gen.tse2e/react-start/split-exports/tests/split-exports-hmr.spec.tse2e/react-start/split-exports/src/routes/index.tsxe2e/react-start/split-exports/src/routes/reexport-import.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: Always run `pnpm test:eslint`, `pnpm test:types`, and `pnpm test:unit` before committing code
Applied to files:
e2e/react-start/split-exports/.prettierignore
📚 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/react-start/split-exports/src/routes/__root.tsxe2e/react-start/split-exports/src/routes/direct-import.tsxe2e/react-start/split-exports/tsconfig.jsone2e/react-start/split-exports/src/routes/alias-import.tsxe2e/react-start/split-exports/src/routeTree.gen.tse2e/react-start/split-exports/src/routes/index.tsxe2e/react-start/split-exports/src/routes/reexport-import.tsx
📚 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/react-start/split-exports/playwright.config.tse2e/react-start/split-exports/tests/split-exports-hmr.spec.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:
packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/typeOnlyImports.tse2e/react-start/split-exports/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: Use file-based routing in `src/routes/` directories or code-based routing with route definitions
Applied to files:
e2e/react-start/split-exports/src/routeTree.gen.tse2e/react-start/split-exports/src/routes/index.tsx
📚 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:
packages/start-plugin-core/tests/split-exports-plugin/split-exports.test.ts
🧬 Code graph analysis (28)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/defaultImport.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/test-files/defaultImport.ts (1)
main(5-7)
packages/start-plugin-core/src/plugin.ts (1)
packages/start-plugin-core/src/split-exports-plugin/plugin.ts (1)
splitExportsPlugin(399-414)
packages/start-plugin-core/tests/split-exports-plugin/test-files/namedImports.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/namedImports.ts (1)
main(4-6)
packages/start-plugin-core/tests/split-exports-plugin/test-files/existingQuery.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/existingQuery.ts (1)
main(4-6)
packages/start-plugin-core/tests/split-exports-plugin/test-files/defaultImport.ts (2)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/defaultImport.ts (1)
main(4-6)packages/start-plugin-core/tests/split-exports-plugin/test-files/defaultExport.ts (1)
main(4-6)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/serverOnlyCode.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/test-files/serverOnlyCode.ts (1)
formatUser(5-7)
e2e/react-start/split-exports/src/routes/__root.tsx (5)
e2e/react-start/split-exports/src/routes/alias-import.tsx (1)
Route(32-42)e2e/react-start/split-exports/src/routes/direct-import.tsx (1)
Route(22-31)e2e/react-start/split-exports/src/routes/index.tsx (1)
Route(3-5)e2e/react-start/split-exports/src/routes/reexport-import.tsx (1)
Route(19-26)e2e/react-start/split-exports/src/routes/server-request-import.tsx (1)
Route(33-41)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/functionExports.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/test-files/functionExports.ts (1)
myFunction(2-4)
packages/start-plugin-core/tests/split-exports-plugin/test-files/defaultExport.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/defaultExport.ts (1)
main(3-5)
e2e/react-start/split-exports/playwright-hmr.config.ts (1)
scripts/set-ts-version.js (1)
packageJson(33-33)
e2e/react-start/split-exports/src/utils/server-request.ts (2)
packages/start-server-core/src/request-response.ts (1)
getRequest(72-75)examples/solid/kitchen-sink/src/useMutation.tsx (1)
data(47-49)
packages/start-plugin-core/src/split-exports-plugin/query-utils.ts (1)
packages/router-core/src/route.ts (2)
id(1549-1551)path(1553-1555)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/externalImports.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/test-files/externalImports.ts (1)
Component(5-8)
e2e/react-start/split-exports/playwright.config.ts (1)
scripts/set-ts-version.js (1)
packageJson(33-33)
packages/start-plugin-core/tests/split-exports-plugin/test-files/multipleDeclarators.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/multipleDeclarators.ts (2)
a(2-2)processA(3-5)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/namedImports.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/test-files/namedImports.ts (1)
main(5-7)
e2e/react-start/split-exports/src/utils/shared.ts (1)
e2e/react-start/split-exports/src/utils/public-api.ts (8)
getServerEnvironment(15-15)getUserById(15-15)getAllUsers(15-15)getEnvironment(8-8)getEnvironment(18-18)formatMessage(9-9)formatUserName(10-10)APP_NAME(11-11)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/typeOnlyImports.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/test-files/typeOnlyImports.ts (1)
main(5-7)
e2e/react-start/split-exports/src/utils/nested.ts (2)
e2e/react-start/split-exports/src/utils/shared.ts (2)
getServerOnlyUserData(49-52)APP_NAME(138-138)e2e/react-start/split-exports/src/utils/public-api.ts (1)
APP_NAME(11-11)
packages/start-plugin-core/src/split-exports-plugin/plugin.ts (3)
packages/start-plugin-core/src/split-exports-plugin/plugin-utils.ts (5)
shouldExclude(69-110)stripQueryString(61-63)isParseableFile(43-56)debug(3-5)hasDirectiveQuery(35-37)packages/start-plugin-core/src/split-exports-plugin/compiler.ts (3)
extractImportsFromModule(59-131)transformImports(165-223)transformExports(352-508)packages/start-plugin-core/src/split-exports-plugin/query-utils.ts (5)
SPLIT_EXPORTS_QUERY_KEY(1-1)extractSplitExportsQuery(87-94)parseSplitExportsQuery(33-42)removeSplitExportsQuery(48-58)hasSplitExportsQuery(22-27)
packages/start-plugin-core/tests/split-exports-plugin/test-files/serverOnlyCode.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/serverOnlyCode.ts (1)
formatUser(5-9)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/multipleDeclarators.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/test-files/multipleDeclarators.ts (2)
a(2-4)processA(6-8)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedImports.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/test-files/mixedImports.ts (1)
main(4-6)
e2e/react-start/split-exports/src/routeTree.gen.ts (1)
e2e/react-start/split-exports/src/router.tsx (1)
getRouter(4-12)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/namedExports.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/test-files/namedExports.ts (2)
foo(2-2)bar(3-3)
e2e/react-start/split-exports/tests/split-exports-hmr.spec.ts (2)
packages/router-core/src/route.ts (1)
path(1553-1555)packages/start-plugin-core/src/schema.ts (1)
Page(208-208)
e2e/react-start/split-exports/src/routes/index.tsx (5)
e2e/react-start/split-exports/src/routes/__root.tsx (1)
Route(12-29)e2e/react-start/split-exports/src/routes/alias-import.tsx (1)
Route(32-42)e2e/react-start/split-exports/src/routes/direct-import.tsx (1)
Route(22-31)e2e/react-start/split-exports/src/routes/reexport-import.tsx (1)
Route(19-26)e2e/react-start/split-exports/src/routes/server-request-import.tsx (1)
Route(33-41)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/defaultExport.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/test-files/defaultExport.ts (1)
main(4-6)
🪛 ast-grep (0.40.0)
packages/start-plugin-core/src/split-exports-plugin/plugin.ts
[warning] 219-219: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp([?&]${SPLIT_EXPORTS_QUERY_KEY}=)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
[warning] 268-268: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp([?&]${SPLIT_EXPORTS_QUERY_KEY}=)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
⏰ 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
| "dependencies": { | ||
| "@tanstack/react-router": "workspace:^", | ||
| "@tanstack/react-router-devtools": "workspace:^", | ||
| "@tanstack/react-start": "workspace:^", | ||
| "react": "^19.0.0", | ||
| "react-dom": "^19.0.0", | ||
| "tailwind-merge": "^2.6.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@playwright/test": "^1.50.1", | ||
| "@tailwindcss/postcss": "^4.1.15", | ||
| "@tanstack/router-e2e-utils": "workspace:^", | ||
| "@types/node": "^22.10.2", | ||
| "@types/react": "^19.0.8", | ||
| "@types/react-dom": "^19.0.3", | ||
| "@vitejs/plugin-react": "^4.3.4", | ||
| "postcss": "^8.5.1", | ||
| "srvx": "^0.8.6", | ||
| "tailwindcss": "^4.1.17", | ||
| "typescript": "^5.7.2", | ||
| "vite": "^7.1.7", | ||
| "vite-tsconfig-paths": "^5.1.4" | ||
| } |
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:* for internal TanStack packages per repo guidelines
Per the workspace guideline, internal packages should use workspace:* instead of workspace:^. Updating these keeps version alignment explicit and consistent.
"dependencies": {
- "@tanstack/react-router": "workspace:^",
- "@tanstack/react-router-devtools": "workspace:^",
- "@tanstack/react-start": "workspace:^",
+ "@tanstack/react-router": "workspace:*",
+ "@tanstack/react-router-devtools": "workspace:*",
+ "@tanstack/react-start": "workspace:*",
@@
"devDependencies": {
@@
- "@tanstack/router-e2e-utils": "workspace:^",
+ "@tanstack/router-e2e-utils": "workspace:*",🤖 Prompt for AI Agents
In e2e/react-start/split-exports/package.json around lines 15 to 37, the
internal TanStack workspace dependencies use "workspace:^" which violates the
repo guideline; update all internal workspace package versions
("@tanstack/react-router", "@tanstack/react-router-devtools",
"@tanstack/react-start", "@tanstack/router-e2e-utils") to use "workspace:*"
instead of "workspace:^" so they consistently reference the workspace range.
f29c613 to
39eb869
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: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
packages/start-plugin-core/src/create-server-fn-plugin/compiler.ts (1)
61-75: Type signature change to resolveId verified, but test implementations need updating.The change from optional
importer?: stringto explicitimporter: string | undefinedis correctly implemented in the plugin (line 115-120) and all compiler call sites properly pass both parameters. However, the test implementations increateServerFn.test.tsandcreateMiddleware.test.tsdefineresolveId: async (id) => { return id }which only accepts one parameter, violating the new signature that requires(id: string, importer: string | undefined) => Promise<string | null>. Update test resolveId implementations to accept the importer parameter.
🧹 Nitpick comments (11)
e2e/react-start/split-exports/src/utils/server-request.ts (1)
89-98: Consider adding runtime validation in the inputValidator.The current inputValidator relies solely on TypeScript's compile-time checking. For production code, consider adding runtime validation to ensure the
messageproperty exists and is a string. However, for this e2e test demonstrating the pattern, the pass-through approach is acceptable.Optional enhancement for runtime safety:
export const echoWithRequestInfo = createServerFn() - .inputValidator((data: { message: string }) => data) + .inputValidator((data: unknown) => { + if (typeof data !== 'object' || data === null || typeof (data as { message?: unknown }).message !== 'string') { + throw new Error('Invalid input: message must be a string') + } + return data as { message: string } + }) .handler(({ data }) => {packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/externalImports.ts (1)
5-5: Optional: Consider lazy initialization for useState.The current code calls
foo()on every render. For test fixture purposes this works fine, but lazy initialization (useState(() => foo())) would be more idiomatic React and only callfoo()once during initialization.- const [state] = useState(foo()); + const [state] = useState(() => foo());packages/start-plugin-core/tests/split-exports-plugin/test-files/serverOnlyCode.ts (1)
10-17: Consider explicit return types for better type safety.While the async functions correctly demonstrate server-only code for testing purposes, adding explicit return types would align with the coding guideline for "extensive type safety" in TypeScript files.
As per coding guidelines, consider adding explicit return types to avoid implicit
any.For example:
-export const getUser = async (id: string) => { +export const getUser = async (id: string): Promise<any> => { return db.users.findOne({ id }) } -export const deleteUser = async (id: string) => { +export const deleteUser = async (id: string): Promise<any> => { return db.users.delete({ id }) }Note: Since this is a test file, you could also define a more specific type instead of
anyif the db operations have known return types.e2e/react-start/split-exports/tests/split-exports-hmr.spec.ts (1)
59-64: HMR wait strategy may be fragile.The
networkidlestate plus a fixed 500ms delay may not reliably detect HMR completion in all scenarios. If tests become flaky, consider polling for a specific DOM change or listening for Vite's HMR events viapage.evaluate.e2e/react-start/split-exports/tests/split-exports.spec.ts (1)
169-174: Consider extracting script-fetching logic into a helper.The script source collection logic is duplicated in both leak tests. This could be extracted into a helper function for maintainability.
+async function getClientScriptSources(page: Page): Promise<Array<string>> { + const scripts = await page.evaluate(() => { + const scriptElements = Array.from( + document.querySelectorAll('script[src]'), + ) + return scriptElements.map((s) => s.getAttribute('src')).filter(Boolean) + }) + return scripts.filter( + (src): src is string => !!src && !src.includes('node_modules'), + ) +}Then simplify both tests:
const scripts = await getClientScriptSources(page) for (const scriptSrc of scripts) { const response = await page.request.get(scriptSrc) // ... assertions }Also applies to: 202-207
packages/start-plugin-core/src/split-exports-plugin/compiler.ts (3)
339-359: Consider handling destructured patterns in variable declarations.
getExportedNamesFromDeclarationonly extracts names from simple identifier declarations. Destructured exports likeexport const { foo, bar } = objorexport const [a, b] = arrwould return an empty array.While this may be intentional (such exports are uncommon), it could silently skip these exports from transformation. Consider adding a comment documenting this limitation or extending support.
function getExportedNamesFromDeclaration( declaration: t.Declaration, ): Array<string> { if (t.isVariableDeclaration(declaration)) { - return declaration.declarations - .filter((decl): decl is t.VariableDeclarator & { id: t.Identifier } => - t.isIdentifier(decl.id), - ) - .map((decl) => decl.id.name) + const names: Array<string> = [] + for (const decl of declaration.declarations) { + if (t.isIdentifier(decl.id)) { + names.push(decl.id.name) + } + // Note: Destructured exports (ObjectPattern, ArrayPattern) are not + // currently supported and will be preserved as-is + } + return names }
374-397: Consider usinggetBindingIdentifiersfrom@babel/typesfor robustness.The custom traversal to find binding identifiers works but could be simplified and made more robust using Babel's built-in utilities:
function addBindingIdentifiersToRefIdents( path: babel.NodePath, refIdents: Set<babel.NodePath<t.Identifier>>, ): void { - path.traverse({ - Identifier(identPath: babel.NodePath<t.Identifier>) { - // Add function/class name identifiers - if ( - (identPath.parentPath.isFunctionDeclaration() || - identPath.parentPath.isClassDeclaration()) && - identPath.key === 'id' - ) { - refIdents.add(identPath) - } - // Add variable declarator identifiers - if ( - identPath.parentPath.isVariableDeclarator() && - identPath.key === 'id' - ) { - refIdents.add(identPath) - } - }, - }) + // Use Babel's built-in binding identifier extraction + const bindings = path.scope?.getAllBindings() ?? {} + for (const binding of Object.values(bindings)) { + if (t.isIdentifier(binding.identifier)) { + refIdents.add(binding.path as babel.NodePath<t.Identifier>) + } + } }Alternatively, if the current approach is intentional to only catch specific patterns, document why.
519-526: Defensive fallback is unreachable but good to keep documented.The comment correctly explains this is unreachable for function/class declarations. Consider adding an assertion or debug log to catch unexpected scenarios during development:
} else { // Unreachable for function/class: they export exactly one name, // so keptNames is either length 0 (handled above) or 1 (all kept, returned early) // Keep as defensive fallback + if (process.env.NODE_ENV === 'development') { + console.warn('[split-exports] Unexpected: partial keep for non-variable declaration') + } path.replaceWith(node.declaration)packages/start-plugin-core/src/create-server-fn-plugin/plugin.ts (1)
105-114: The non-null assertions are safe given the initialization check but could be cleaner.The
!assertions onloaderApi,viteEnv, andctxLoadare safe because they're set in the same block above. However, this pattern creates temporal coupling. Consider restructuring:- loadModule: async (moduleId: string) => { - const ctxLoadForEnv = - viteEnv!.mode === 'build' ? ctxLoad : undefined - const moduleCode = await loaderApi!.loadModuleCode( - viteEnv!, - moduleId, - ctxLoadForEnv, - ) - compiler!.ingestModule({ code: moduleCode, id: moduleId }) + loadModule: async (moduleId: string) => { + // Safe: loaderApi and viteEnv are guaranteed set before compiler creation + const ctxLoadForEnv = + viteEnv!.mode === 'build' ? ctxLoad : undefined + const moduleCode = await loaderApi!.loadModuleCode( + viteEnv!, + moduleId, + ctxLoadForEnv, + ) + compiler!.ingestModule({ code: moduleCode, id: moduleId }) },packages/start-plugin-core/src/split-exports-plugin/plugin.ts (2)
201-205: Silent failure when loading module for class detection.When
loadModuleCodethrows, the code assumeshasClasses = falseand caches this. This is reasonable as a fallback, but consider logging a debug warning to help troubleshoot issues:} catch { // If we can't load the module, assume no classes (safe fallback) + if (debug) { + console.warn( + '[split-exports] Failed to load module for class detection:', + resolvedPath, + ) + } hasClasses = false classExportCache.set(resolvedPath, hasClasses) }
297-300: Duplicate URL encoding logic withappendSplitExportsQuery.The encoding and sorting logic here duplicates what's in
query-utils.ts(line 82-83 of the relevant snippet). Consider extracting a shared helper:+// In query-utils.ts, add: +export function encodeExportNames(exportNames: Set<string>): string { + return Array.from(exportNames).sort().map(encodeURIComponent).join(',') +} // Then in resolverPlugin: - const sortedNames = Array.from(exportNames) - .sort() - .map(encodeURIComponent) - .join(',') + const sortedNames = encodeExportNames(exportNames)
📜 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 (70)
e2e/react-start/server-functions/src/routes/factory/-functions/functions.ts(1 hunks)e2e/react-start/server-functions/src/routes/factory/index.tsx(1 hunks)e2e/react-start/split-exports/.gitignore(1 hunks)e2e/react-start/split-exports/.prettierignore(1 hunks)e2e/react-start/split-exports/package.json(1 hunks)e2e/react-start/split-exports/playwright-hmr.config.ts(1 hunks)e2e/react-start/split-exports/playwright.config.ts(1 hunks)e2e/react-start/split-exports/postcss.config.mjs(1 hunks)e2e/react-start/split-exports/src/routeTree.gen.ts(1 hunks)e2e/react-start/split-exports/src/router.tsx(1 hunks)e2e/react-start/split-exports/src/routes/__root.tsx(1 hunks)e2e/react-start/split-exports/src/routes/alias-import.tsx(1 hunks)e2e/react-start/split-exports/src/routes/direct-import.tsx(1 hunks)e2e/react-start/split-exports/src/routes/index.tsx(1 hunks)e2e/react-start/split-exports/src/routes/reexport-import.tsx(1 hunks)e2e/react-start/split-exports/src/routes/server-request-import.tsx(1 hunks)e2e/react-start/split-exports/src/styles/app.css(1 hunks)e2e/react-start/split-exports/src/utils/nested.ts(1 hunks)e2e/react-start/split-exports/src/utils/public-api.ts(1 hunks)e2e/react-start/split-exports/src/utils/server-request.ts(1 hunks)e2e/react-start/split-exports/src/utils/shared.ts(1 hunks)e2e/react-start/split-exports/tests/split-exports-hmr.spec.ts(1 hunks)e2e/react-start/split-exports/tests/split-exports.spec.ts(1 hunks)e2e/react-start/split-exports/tsconfig.json(1 hunks)e2e/react-start/split-exports/vite.config.ts(1 hunks)e2e/solid-start/server-functions/src/routes/factory/-functions/functions.ts(1 hunks)e2e/solid-start/server-functions/src/routes/factory/index.tsx(1 hunks)packages/start-plugin-core/src/create-server-fn-plugin/compiler.ts(6 hunks)packages/start-plugin-core/src/create-server-fn-plugin/plugin.ts(6 hunks)packages/start-plugin-core/src/module-loader-plugin/index.ts(1 hunks)packages/start-plugin-core/src/module-loader-plugin/plugin.ts(1 hunks)packages/start-plugin-core/src/plugin-utils.ts(1 hunks)packages/start-plugin-core/src/plugin.ts(2 hunks)packages/start-plugin-core/src/schema.ts(1 hunks)packages/start-plugin-core/src/split-exports-plugin/README.md(1 hunks)packages/start-plugin-core/src/split-exports-plugin/compiler.ts(1 hunks)packages/start-plugin-core/src/split-exports-plugin/plugin-utils.ts(1 hunks)packages/start-plugin-core/src/split-exports-plugin/plugin.ts(1 hunks)packages/start-plugin-core/src/split-exports-plugin/query-utils.ts(1 hunks)packages/start-plugin-core/tests/plugin-utils.test.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/defaultExport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/functionExports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/multipleDeclarators.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/namedExports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/reExports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/serverOnlyCode.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/starReExport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/defaultImport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/existingQuery.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/externalImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedTypeValueImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/namedImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/typeOnlyImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/split-exports.test.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/defaultExport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/defaultImport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/existingQuery.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/externalImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/functionExports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/mixedImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/mixedTypeValueImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/multipleDeclarators.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/namedExports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/namedImports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/namespaceImport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/reExports.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/serverOnlyCode.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/starReExport.ts(1 hunks)packages/start-plugin-core/tests/split-exports-plugin/test-files/typeOnlyImports.ts(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- packages/start-plugin-core/src/split-exports-plugin/README.md
🚧 Files skipped from review as they are similar to previous changes (37)
- packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/starReExport.ts
- e2e/react-start/split-exports/.gitignore
- packages/start-plugin-core/tests/split-exports-plugin/test-files/namespaceImport.ts
- e2e/react-start/split-exports/src/routes/index.tsx
- e2e/react-start/split-exports/vite.config.ts
- e2e/react-start/split-exports/src/styles/app.css
- e2e/react-start/split-exports/src/routes/alias-import.tsx
- packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/namedImports.ts
- e2e/react-start/split-exports/tsconfig.json
- packages/start-plugin-core/tests/split-exports-plugin/test-files/mixedImports.ts
- packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/existingQuery.ts
- packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/serverOnlyCode.ts
- packages/start-plugin-core/tests/split-exports-plugin/test-files/namedExports.ts
- packages/start-plugin-core/tests/split-exports-plugin/test-files/defaultImport.ts
- packages/start-plugin-core/tests/split-exports-plugin/test-files/externalImports.ts
- packages/start-plugin-core/tests/split-exports-plugin/test-files/existingQuery.ts
- packages/start-plugin-core/tests/split-exports-plugin/test-files/reExports.ts
- packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedImports.ts
- e2e/react-start/split-exports/src/router.tsx
- e2e/react-start/split-exports/playwright-hmr.config.ts
- e2e/react-start/split-exports/postcss.config.mjs
- e2e/react-start/split-exports/src/routes/__root.tsx
- packages/start-plugin-core/tests/split-exports-plugin/test-files/functionExports.ts
- packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/reExports.ts
- packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/defaultImport.ts
- e2e/react-start/split-exports/package.json
- e2e/react-start/split-exports/src/routes/server-request-import.tsx
- packages/start-plugin-core/tests/split-exports-plugin/split-exports.test.ts
- packages/start-plugin-core/tests/split-exports-plugin/test-files/mixedTypeValueImports.ts
- packages/start-plugin-core/tests/split-exports-plugin/test-files/multipleDeclarators.ts
- packages/start-plugin-core/src/schema.ts
- packages/start-plugin-core/tests/split-exports-plugin/test-files/namedImports.ts
- e2e/react-start/split-exports/src/utils/nested.ts
- packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/mixedTypeValueImports.ts
- e2e/react-start/split-exports/src/routes/reexport-import.tsx
- packages/start-plugin-core/tests/split-exports-plugin/test-files/defaultExport.ts
- e2e/react-start/split-exports/.prettierignore
🧰 Additional context used
📓 Path-based instructions (2)
**/*.{ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Use TypeScript strict mode with extensive type safety for all code
Files:
packages/start-plugin-core/src/module-loader-plugin/index.tspackages/start-plugin-core/src/plugin.tse2e/react-start/split-exports/playwright.config.tse2e/react-start/split-exports/tests/split-exports-hmr.spec.tspackages/start-plugin-core/src/plugin-utils.tse2e/react-start/server-functions/src/routes/factory/index.tsxe2e/react-start/split-exports/src/routeTree.gen.tspackages/start-plugin-core/src/create-server-fn-plugin/compiler.tse2e/solid-start/server-functions/src/routes/factory/index.tsxe2e/react-start/split-exports/src/utils/public-api.tspackages/start-plugin-core/src/module-loader-plugin/plugin.tse2e/react-start/server-functions/src/routes/factory/-functions/functions.tspackages/start-plugin-core/src/split-exports-plugin/plugin-utils.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/typeOnlyImports.tse2e/react-start/split-exports/src/routes/direct-import.tsxe2e/react-start/split-exports/src/utils/server-request.tse2e/react-start/split-exports/src/utils/shared.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/multipleDeclarators.tspackages/start-plugin-core/src/split-exports-plugin/compiler.tse2e/solid-start/server-functions/src/routes/factory/-functions/functions.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/externalImports.tspackages/start-plugin-core/src/split-exports-plugin/query-utils.tspackages/start-plugin-core/tests/plugin-utils.test.tse2e/react-start/split-exports/tests/split-exports.spec.tspackages/start-plugin-core/src/split-exports-plugin/plugin.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/starReExport.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/functionExports.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/defaultExport.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/namedExports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/serverOnlyCode.tspackages/start-plugin-core/src/create-server-fn-plugin/plugin.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/typeOnlyImports.ts
**/*.{js,ts,tsx}
📄 CodeRabbit inference engine (AGENTS.md)
Implement ESLint rules for router best practices using the ESLint plugin router
Files:
packages/start-plugin-core/src/module-loader-plugin/index.tspackages/start-plugin-core/src/plugin.tse2e/react-start/split-exports/playwright.config.tse2e/react-start/split-exports/tests/split-exports-hmr.spec.tspackages/start-plugin-core/src/plugin-utils.tse2e/react-start/server-functions/src/routes/factory/index.tsxe2e/react-start/split-exports/src/routeTree.gen.tspackages/start-plugin-core/src/create-server-fn-plugin/compiler.tse2e/solid-start/server-functions/src/routes/factory/index.tsxe2e/react-start/split-exports/src/utils/public-api.tspackages/start-plugin-core/src/module-loader-plugin/plugin.tse2e/react-start/server-functions/src/routes/factory/-functions/functions.tspackages/start-plugin-core/src/split-exports-plugin/plugin-utils.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/typeOnlyImports.tse2e/react-start/split-exports/src/routes/direct-import.tsxe2e/react-start/split-exports/src/utils/server-request.tse2e/react-start/split-exports/src/utils/shared.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/multipleDeclarators.tspackages/start-plugin-core/src/split-exports-plugin/compiler.tse2e/solid-start/server-functions/src/routes/factory/-functions/functions.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/externalImports.tspackages/start-plugin-core/src/split-exports-plugin/query-utils.tspackages/start-plugin-core/tests/plugin-utils.test.tse2e/react-start/split-exports/tests/split-exports.spec.tspackages/start-plugin-core/src/split-exports-plugin/plugin.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/starReExport.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/functionExports.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/defaultExport.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/namedExports.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/serverOnlyCode.tspackages/start-plugin-core/src/create-server-fn-plugin/plugin.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/typeOnlyImports.ts
🧠 Learnings (7)
📚 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:
packages/start-plugin-core/src/plugin.tse2e/react-start/split-exports/tests/split-exports-hmr.spec.tse2e/react-start/split-exports/src/routeTree.gen.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/typeOnlyImports.tse2e/react-start/split-exports/src/routes/direct-import.tsxe2e/react-start/split-exports/src/utils/server-request.tse2e/react-start/split-exports/src/utils/shared.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/externalImports.tse2e/react-start/split-exports/tests/split-exports.spec.tspackages/start-plugin-core/tests/split-exports-plugin/test-files/serverOnlyCode.ts
📚 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/react-start/split-exports/playwright.config.tse2e/react-start/split-exports/tests/split-exports-hmr.spec.ts
📚 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/react-start/split-exports/tests/split-exports-hmr.spec.tse2e/react-start/split-exports/src/routeTree.gen.tse2e/react-start/split-exports/src/routes/direct-import.tsxpackages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/externalImports.tspackages/start-plugin-core/tests/plugin-utils.test.tse2e/react-start/split-exports/tests/split-exports.spec.tspackages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/defaultExport.ts
📚 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/react-start/split-exports/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 **/*.{js,ts,tsx} : Implement ESLint rules for router best practices using the ESLint plugin router
Applied to files:
e2e/react-start/split-exports/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/react-start/split-exports/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:
packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/typeOnlyImports.ts
🧬 Code graph analysis (14)
e2e/react-start/split-exports/tests/split-exports-hmr.spec.ts (1)
packages/start-plugin-core/src/schema.ts (1)
Page(208-208)
packages/start-plugin-core/src/plugin-utils.ts (1)
packages/start-plugin-core/src/module-loader-plugin/plugin.ts (1)
ModuleLoaderApi(9-24)
e2e/react-start/split-exports/src/routeTree.gen.ts (1)
e2e/react-start/split-exports/src/router.tsx (1)
getRouter(4-12)
packages/start-plugin-core/src/split-exports-plugin/plugin-utils.ts (1)
packages/start-plugin-core/src/plugin-utils.ts (1)
stripQueryString(29-31)
e2e/react-start/split-exports/src/routes/direct-import.tsx (1)
e2e/react-start/split-exports/src/utils/shared.ts (6)
getEnvironment(111-113)getUserById(82-92)formatMessage(118-120)getServerEnvironment(73-75)APP_NAME(138-138)formatUserName(131-133)
e2e/react-start/split-exports/src/utils/server-request.ts (1)
packages/start-server-core/src/request-response.ts (1)
getRequest(72-75)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/multipleDeclarators.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/test-files/multipleDeclarators.ts (2)
a(2-4)processA(6-8)
packages/start-plugin-core/tests/plugin-utils.test.ts (1)
packages/start-plugin-core/src/plugin-utils.ts (1)
stripQueryString(29-31)
packages/start-plugin-core/src/split-exports-plugin/plugin.ts (7)
packages/start-plugin-core/src/module-loader-plugin/index.ts (1)
ModuleLoaderApi(2-2)packages/start-plugin-core/src/module-loader-plugin/plugin.ts (1)
ModuleLoaderApi(9-24)packages/start-plugin-core/src/constants.ts (1)
TRANSFORM_ID_REGEX(26-26)packages/start-plugin-core/src/split-exports-plugin/plugin-utils.ts (2)
shouldExclude(63-104)isParseableFile(44-57)packages/start-plugin-core/src/split-exports-plugin/compiler.ts (4)
extractImportsFromModule(147-219)hasClassExports(66-137)transformImports(253-311)transformExports(440-594)packages/start-plugin-core/src/plugin-utils.ts (2)
findModuleLoaderApi(37-50)stripQueryString(29-31)packages/start-plugin-core/src/split-exports-plugin/query-utils.ts (5)
SPLIT_EXPORTS_QUERY_KEY(1-1)extractSplitExportsQuery(96-103)parseSplitExportsQuery(35-50)removeSplitExportsQuery(56-66)hasSplitExportsQuery(22-27)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/functionExports.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/test-files/functionExports.ts (1)
myFunction(2-4)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/defaultExport.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/test-files/defaultExport.ts (1)
main(4-6)
packages/start-plugin-core/tests/split-exports-plugin/test-files/serverOnlyCode.ts (2)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/serverOnlyCode.ts (1)
formatUser(5-9)packages/router-core/src/route.ts (1)
id(1549-1551)
packages/start-plugin-core/src/create-server-fn-plugin/plugin.ts (3)
packages/start-plugin-core/src/start-compiler-plugin/compilers.ts (1)
CompileStartFrameworkOptions(18-18)packages/start-plugin-core/src/module-loader-plugin/plugin.ts (1)
ModuleLoaderApi(9-24)packages/start-plugin-core/src/plugin-utils.ts (2)
findModuleLoaderApi(37-50)stripQueryString(29-31)
packages/start-plugin-core/tests/split-exports-plugin/test-files/typeOnlyImports.ts (1)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/typeOnlyImports.ts (1)
main(4-6)
🪛 ast-grep (0.40.0)
packages/start-plugin-core/src/module-loader-plugin/plugin.ts
[warning] 162-162: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp(\\?${MODULE_LOADER_QUERY_KEY}$)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
packages/start-plugin-core/src/split-exports-plugin/plugin.ts
[warning] 275-275: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp([?&]${SPLIT_EXPORTS_QUERY_KEY}=)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
[warning] 328-328: Regular expression constructed from variable input detected. This can lead to Regular Expression Denial of Service (ReDoS) attacks if the variable contains malicious patterns. Use libraries like 'recheck' to validate regex safety or use static patterns.
Context: new RegExp([?&]${SPLIT_EXPORTS_QUERY_KEY}=)
Note: [CWE-1333] Inefficient Regular Expression Complexity [REFERENCES]
- https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS
- https://cwe.mitre.org/data/definitions/1333.html
(regexp-from-variable)
⏰ 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 (65)
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/namedExports.ts (1)
1-3: LGTM! Clean test fixture for named exports.The test snapshot file is well-structured for validating the split-exports plugin behavior with named exports. The simple arrow functions returning string literals are appropriate for testing transformation and tree-shaking scenarios.
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/defaultExport.ts (1)
1-5: LGTM! Test fixture is correctly structured.This test snapshot file appropriately demonstrates a default export that depends on a local helper function, providing a clear test case for the split-exports plugin to validate default export handling.
packages/start-plugin-core/tests/split-exports-plugin/test-files/starReExport.ts (1)
1-3: LGTM! Test fixture is well-formed.The test file correctly demonstrates both star and named re-exports with valid syntax. The exports are appropriate for validating the split-exports plugin's handling of re-export statements.
e2e/react-start/split-exports/src/utils/server-request.ts (4)
1-21: Well-documented module demonstrating the split-exports pattern.The documentation clearly explains the isomorphic server function pattern and how server-only imports should be eliminated from client bundles through dead code elimination. The imports are appropriate for the demonstrated use case.
33-41: LGTM!The internal helper correctly extracts request metadata using the server-only
getRequest()API. The URL parsing for pathname extraction is appropriate.
47-50: LGTM!Correctly converts Headers to a plain object. The explicit export serves the test purpose of verifying server-only code elimination from client bundles.
75-83: LGTM!The server function correctly wraps the server-only
getRequestInfo()call. TheexecutedOn: 'server'marker provides useful verification for e2e tests.packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/multipleDeclarators.ts (1)
1-5: Critical: Snapshot missing exported declaratorsbandc.The original test file
test-files/multipleDeclarators.tsexports three constants (a,b,c) in a single declaration statement. However, this snapshot only includes the export fora. If the split-exports plugin is designed to split multiple declarators into individual export statements, the snapshot should contain:export const a = 1; export const b = 2; export const c = 3;The comment on Line 1 references "multiple declarators," but the snapshot doesn't match this description.
Apply this diff to include all declarators:
// Test file: Export with declaration containing multiple declarators export const a = 1; +export const b = 2; +export const c = 3; export function processA() { return a * 2; }⛔ Skipped due to learnings
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.packages/start-plugin-core/tests/split-exports-plugin/test-files/serverOnlyCode.ts (2)
1-3: LGTM! Clear test setup.The file comment and server-only import are well-documented and appropriate for testing the split-exports plugin's ability to distinguish between isomorphic and server-only code paths.
4-7: LGTM! Isomorphic function correctly implemented.The
formatUserfunction appropriately demonstrates isomorphic code that should remain available after the plugin eliminates server-only exports. The implementation is straightforward and serves the test purpose well.packages/start-plugin-core/tests/split-exports-plugin/snapshots/imports/typeOnlyImports.ts (2)
4-6: LGTM!The exported function correctly demonstrates the test scenario: using a type-only import for the parameter annotation while delegating to a runtime import for the actual implementation.
2-3: Inconsistent quote style in snapshot.Line 2 uses single quotes
'./types'while Line 3 uses double quotes"./utils?tss-split-exports=processUser". Since this is a snapshot file representing expected plugin output, verify whether the split-exports plugin intentionally produces mixed quote styles or if this should be normalized.Consider ensuring consistent quote style in the plugin's output:
import type { UserType } from './types'; -import { processUser } from "./utils?tss-split-exports=processUser"; +import { processUser } from './utils?tss-split-exports=processUser';⛔ Skipped due to learnings
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: 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.packages/start-plugin-core/tests/split-exports-plugin/test-files/typeOnlyImports.ts (2)
1-3: LGTM!Clean test input demonstrating proper type-only import syntax alongside a runtime import. The comment clearly documents the test's purpose.
5-7: LGTM!The function correctly uses the type-only import for type annotation and the runtime import for the actual logic, providing a clean test case for verifying that the split-exports plugin handles type-only imports appropriately.
e2e/react-start/server-functions/src/routes/factory/-functions/functions.ts (1)
79-79: LGTM! SSR-safe window access.The conditional check correctly guards against undefined
windowin server-side contexts.e2e/solid-start/server-functions/src/routes/factory/-functions/functions.ts (1)
79-79: LGTM! SSR-safe window access.The conditional check correctly guards against undefined
windowin server-side contexts, consistent with the React implementation.e2e/react-start/split-exports/src/utils/shared.ts (1)
1-138: Well-structured test module for split-exports validation.The module clearly demonstrates the three categories of exports:
- Server-only code with runtime guards
- Server functions via
createServerFn(isomorphic - compiler transforms to fetch on client)- Isomorphic utilities via
createIsomorphicFnand pure functionsThe
getUserByIdhandler correctly strips sensitive data (passwordHash) before returning to the client.e2e/react-start/split-exports/tests/split-exports-hmr.spec.ts (2)
35-53: Good defensive cleanup pattern.Saving original contents in
beforeAlland restoring in bothafterAllandafterEachensures tests don't leave modified files behind, even if individual tests fail.
148-202: Critical test coverage for split-exports isolation.These tests verify the key feature: modifying server-only code should not trigger client-side errors or affect client functionality. This validates that the split-exports plugin correctly eliminates server-only code from client bundles.
e2e/react-start/split-exports/src/utils/public-api.ts (1)
1-24: Clean public API surface with intentional server-only exclusions.The module demonstrates a realistic pattern where a public API module selectively re-exports safe symbols while keeping server-only internals private. The alias re-export (
getEnv) adds good coverage for the plugin's handling of renamed exports.e2e/react-start/split-exports/playwright.config.ts (2)
5-6: Top-level await requires ES module context.The
await getTestServerPort(...)at module level requires the file to be treated as an ES module with appropriate TypeScript/Node.js configuration (module: "ESNext"or similar). This is likely fine given thewith { type: 'json' }import assertion on line 3, but verify the project'stsconfig.jsonsupports this.
8-37: Standard Playwright configuration with appropriate separation.The config correctly excludes HMR tests (
*-hmr.spec.ts) since those require a dev server rather than a production build. Single worker mode and the webServer setup follow established patterns in the e2e test suite.e2e/react-start/split-exports/src/routes/direct-import.tsx (3)
48-51: Same invocation concern applies here.The
getUserById({ data: '2' })call uses the same pattern. If the previous concern is valid, this needs the same fix.
33-125: Well-structured test component with comprehensive coverage.The component effectively tests:
- SSR loader behavior with isomorphic and server functions
- Client-side invocation of isomorphic functions
- Server function calls from client via button click
- Proper use of
data-testidattributes for e2e test assertionsThe state management and async handling are correct.
28-28: No issues found. ThegetUserById({ data: '1' })invocation correctly matches the API contract forcreateServerFn().inputValidator(). The framework wraps the validated input in adataproperty when passing it to the handler, making this the intended calling pattern.e2e/react-start/split-exports/tests/split-exports.spec.ts (7)
1-12: LGTM!Clear imports and excellent documentation explaining the test suite's purpose. The three-point summary effectively communicates what the split-exports plugin should achieve.
13-44: LGTM!Well-structured test that clearly separates SSR assertions from client-side assertions. The flow (navigate → wait → verify SSR → trigger client tests → verify client) is a good pattern for testing isomorphic behavior.
46-71: LGTM!Consistent test structure that validates re-exported isomorphic functions behave identically to direct imports.
73-115: LGTM!Comprehensive test coverage for path alias imports, including the important test of nested modules with internal server-only usage. The comments explaining each assertion are helpful.
117-158: LGTM!Excellent documentation of the bug fix being validated. The detailed comment block (lines 118-133) serves as valuable regression test documentation, explaining exactly why this test exists and what scenario it prevents.
160-191: LGTM!Critical test that validates the core promise of the split-exports plugin - server-only code stays out of client bundles. Testing for specific marker strings like
passwordHash,super-secret-key-should-not-leak, and database connection strings is a good approach.
193-221: LGTM!This test directly validates the bug fix described in the Server Request Import suite, ensuring the
getRequestimport doesn't leak to client bundles. Good complementary test to the functional test above.packages/start-plugin-core/src/split-exports-plugin/plugin-utils.ts (4)
1-7: LGTM!The debug flag computation correctly enables verbose logging when
TSR_VITE_DEBUGis set to'true'or'split-exports'.
8-21: LGTM!The parseable extensions set is comprehensive and covers all common JavaScript/TypeScript file types.
23-38: LGTM!The directive query detection logic correctly identifies modules being processed by the directive functions plugin.
59-104: LGTM!The exclusion logic correctly handles node_modules, optional srcDirectory containment, and custom exclude patterns. The debug logging is helpful for troubleshooting.
packages/start-plugin-core/tests/plugin-utils.test.ts (1)
1-18: LGTM!The test suite provides good coverage for the
stripQueryStringutility, testing the main scenarios: stripping query strings, handling paths without queries, and multiple query parameters.packages/start-plugin-core/src/module-loader-plugin/index.ts (1)
1-2: LGTM!The index file correctly re-exports the module loader plugin's public API surface.
packages/start-plugin-core/src/plugin.ts (2)
23-24: LGTM!The imports for the new plugins are clean and correctly placed.
365-381: Plugin ordering and configuration are correct.The plugins are registered in the correct order:
moduleLoaderPluginprovides shared module loading capabilitiesstartCompilerPluginandcreateServerFnPluginhandle server function compilationsplitExportsPluginruns after server function plugins to enable better dead code eliminationThe
importOptimizationconfiguration is properly typed in the schema (packages/start-plugin-core/src/schema.ts) as a Zod object withenabled: z.boolean().optional().default(true). The code at line 379 defensively uses?? trueas an additional fallback, which is appropriate defensive programming.packages/start-plugin-core/src/create-server-fn-plugin/compiler.ts (1)
226-226: Improved internal API with explicit visited parameter.The change from default parameter
visited = new Set()to explicitvisited: Set<string>parameter improves correctness by preventing accidental shared state. The initial call correctly passesnew Set(), and all recursive calls properly thread the visited set through.Also applies to: 297-323, 325-369, 371-420, 422-492
packages/start-plugin-core/src/plugin-utils.ts (3)
1-22: LGTM!The type definitions and
isDevEnvironmenttype guard correctly handle cross-version compatibility and provide proper type narrowing for development environments.
24-31: LGTM!The
stripQueryStringimplementation is simple and correct, usingsplit('?')[0]!which safely extracts the path portion.
33-50: LGTM!The
findModuleLoaderApifunction correctly locates the module loader plugin using a type predicate and provides a clear error message if the plugin is not found.packages/start-plugin-core/src/module-loader-plugin/plugin.ts (4)
1-24: LGTM!The module loader API interface is well-documented and provides a clear contract for loading module code in both dev and build modes.
43-82: LGTM!The cache structure and helper functions correctly organize per-environment module caches and pending load requests.
84-154: LGTM!The
loadModuleCodeimplementation correctly handles both build and dev modes:
- Build mode uses
ctx.load()directly- Dev mode uses
fetchModulewith a capture plugin (clever approach!)- Cache invalidation on HMR is properly implemented
156-189: Static analysis warning is a false positive.The capture plugin correctly intercepts dev mode module loads. The static analysis warning about RegExp construction is a false positive because:
MODULE_LOADER_QUERY_KEYis a constant string'tss-module-load'- The resulting regex
/\?tss-module-load$/is anchored and contains no user input- No ReDoS risk exists
packages/start-plugin-core/src/split-exports-plugin/query-utils.ts (5)
1-16: LGTM!The constant and
splitIdPartshelper provide a clean foundation for query parameter handling.
18-27: LGTM!The simple string matching for presence detection is efficient and correct.
29-50: Well-designed query parameter parsing.The manual extraction approach correctly handles comma-separated export names while preserving commas within encoded export names (e.g.,
foo%2Cbardecodes tofoo,baras a single export name).
52-91: LGTM!The
removeSplitExportsQueryandappendSplitExportsQueryfunctions correctly handle query parameters:
- Preserve other query parameters
- Sort export names for consistent cache keys
- Properly URL-encode special characters
93-103: LGTM!The
extractSplitExportsQueryfunction provides a convenient wrapper for extracting both the clean ID and export names in a single call.packages/start-plugin-core/src/split-exports-plugin/compiler.ts (4)
26-49: LGTM! Solid bare module specifier detection.The function covers common cases well: relative/absolute paths, alias prefixes (
~,#), and properly validates scoped packages vs aliases like@/path. The regex for npm scope validation is appropriate.
66-137: LGTM! Comprehensive class export detection.The implementation correctly handles all documented cases:
- Direct class exports (
export class,export default class)- Class expressions assigned to variables
- Named exports referencing local classes
The early bailout with string check on line 68 is a good optimization.
147-219: Well-structured import extraction with proper filtering.Good handling of:
- Type-only imports (both declaration-level and specifier-level)
- Namespace imports (correctly skipped)
- Side-effect only imports
- Already-processed imports with the query parameter
The AST reuse pattern is efficient.
578-584: The eslint-disable comment is appropriate here.The
hasChangesflag can legitimately remainfalsein edge cases (wildcard re-exports only), so the disable is justified. The accompanying comment explains the scenarios well.packages/start-plugin-core/src/create-server-fn-plugin/plugin.ts (3)
86-131: Per-environment compiler initialization looks correct.The pattern of creating one compiler per environment name and caching it in the
compilersrecord is sound for handling concurrent transforms across environments. The initialization is properly guarded by the!compilercheck.
135-150: HMR invalidation properly cascades to importers.The invalidation logic correctly handles the module and its importers, ensuring dependent modules are also recompiled.
59-69: No changes needed. The captured context variables are correctly scoped to a single environment per plugin instance and do not become stale across transforms.packages/start-plugin-core/src/split-exports-plugin/plugin.ts (5)
71-73: Class export cache is never cleared in build mode.The
classExportCacheis only invalidated inhotUpdate(dev mode). In build mode, the cache persists for the entire build, which is likely fine. However, consider documenting this behavior.
274-277: Static analysis false positive: RegExp is constructed from a constant.The
SPLIT_EXPORTS_QUERY_KEYis a constant string (fromquery-utils.ts), not user input. The regex pattern[?&]${SPLIT_EXPORTS_QUERY_KEY}=is safe and cannot cause ReDoS since the constant contains only alphanumeric characters and hyphens.Also applies to: 328-330
393-428: HMR invalidation logic is thorough and correct.The plugin correctly:
- Iterates over changed modules
- Finds all split-exports variants in the module graph
- Invalidates both the variant and its importers
- Returns the combined set of affected modules
459-473: Clean plugin composition with early return for disabled state.The main entry point correctly returns an empty array when disabled, and composes the four sub-plugins in the right order: import rewriting → resolution → export transformation → HMR.
32-37: Sourcemap detection could handle additional edge cases.The function handles common cases but
config.build.sourcemapcould also be'hidden'which should returntrue. The current!!sourcemaphandles this correctly since'hidden'is truthy.
| expected: { | ||
| name: 'fakeFn', | ||
| window, | ||
| window: typeof window !== 'undefined' ? window : 'no window object', |
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.
Comparing window objects with deepEqual is unreliable.
When window is defined, the test attempts to compare the actual window object using deepEqual (line 144). The window object contains circular references, non-enumerable properties, and thousands of properties, which can cause:
- Unreliable comparison results
- Performance degradation
- Potential failures in the equality check
Consider either:
- Exclude the
windowproperty from the comparison when it's defined - Compare only a sentinel value (e.g., always use
'window-exists'instead of the actual object) - Use a custom comparison that checks
window !== undefinedrather than deep equality
For example, you could change the test to:
fakeFn: {
fn: fakeFn,
type: 'localFn',
expected: {
name: 'fakeFn',
- window: typeof window !== 'undefined' ? window : 'no window object',
+ window: typeof window !== 'undefined' ? 'window-exists' : 'no window object',
},
},And update the implementation to return a sentinel value instead of the actual window object.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In e2e/react-start/server-functions/src/routes/factory/index.tsx around line
130, the test currently exposes/compares the actual window object which makes
deepEqual unreliable; change the implementation to return a sentinel when window
exists (e.g., 'window-exists' or boolean true) instead of the real window object
and update the test to assert that sentinel (or assert window existence via !==
undefined) rather than deep-equal the full window, or alternatively exclude the
window property from the deep comparison; ensure both implementation and test
use the same sentinel/existence-check convention.
| expected: { | ||
| name: 'fakeFn', | ||
| window, | ||
| window: typeof window !== 'undefined' ? window : 'no window object', |
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.
Comparing window objects with deepEqual is unreliable.
When window is defined, the test attempts to compare the actual window object using deepEqual (line 144). The window object contains circular references, non-enumerable properties, and thousands of properties, which can cause:
- Unreliable comparison results
- Performance degradation
- Potential failures in the equality check
Consider either:
- Exclude the
windowproperty from the comparison when it's defined - Compare only a sentinel value (e.g., always use
'window-exists'instead of the actual object) - Use a custom comparison that checks
window !== undefinedrather than deep equality
For example, you could change the test to:
fakeFn: {
fn: fakeFn,
type: 'localFn',
expected: {
name: 'fakeFn',
- window: typeof window !== 'undefined' ? window : 'no window object',
+ window: typeof window !== 'undefined' ? 'window-exists' : 'no window object',
},
},And update the implementation to return a sentinel value instead of the actual window object.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In e2e/solid-start/server-functions/src/routes/factory/index.tsx around line
130, the test currently returns and later deep-compares the actual window object
which is unreliable; change the implementation and test to avoid deepEqual on
window by returning a sentinel value when window exists (e.g., 'window-exists'
or 'no window object'), and update the comparison to check that the value equals
the sentinel or that window presence is boolean (window !== undefined) instead
of deep equality; ensure the branch that previously returned the real window now
returns the sentinel and update the expected value in the test accordingly.
| /** | ||
| * Check if a file path has an extension that can be parsed as JS/TS. | ||
| * Returns false for CSS, images, fonts, and other asset files. | ||
| */ | ||
| export function isParseableFile(id: string): boolean { | ||
| // Strip query string first | ||
| const cleanId = stripQueryString(id) | ||
|
|
||
| // Find the extension | ||
| const lastDot = cleanId.lastIndexOf('.') | ||
| if (lastDot === -1) { | ||
| // No extension - might be a virtual module, let it through | ||
| return true | ||
| } | ||
|
|
||
| const ext = cleanId.slice(lastDot).toLowerCase() | ||
| return PARSEABLE_EXTENSIONS.has(ext) | ||
| } |
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.
Edge case: Dots in directory names may cause incorrect exclusion.
The function uses lastIndexOf('.') to find the file extension, but this can fail for paths with dots in directory names. For example, /path.to/file would have lastDot pointing to the dot in .to, resulting in ext = ".to/file", which is not in PARSEABLE_EXTENSIONS, causing the function to incorrectly return false.
Apply this diff to fix the edge case:
export function isParseableFile(id: string): boolean {
// Strip query string first
const cleanId = stripQueryString(id)
- // Find the extension
- const lastDot = cleanId.lastIndexOf('.')
- if (lastDot === -1) {
+ // Find the extension after the last path separator
+ const lastSlash = Math.max(cleanId.lastIndexOf('/'), cleanId.lastIndexOf('\\'))
+ const lastDot = cleanId.lastIndexOf('.')
+
+ if (lastDot === -1 || lastDot < lastSlash) {
// No extension - might be a virtual module, let it through
return true
}
const ext = cleanId.slice(lastDot).toLowerCase()
return PARSEABLE_EXTENSIONS.has(ext)
}📝 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.
| /** | |
| * Check if a file path has an extension that can be parsed as JS/TS. | |
| * Returns false for CSS, images, fonts, and other asset files. | |
| */ | |
| export function isParseableFile(id: string): boolean { | |
| // Strip query string first | |
| const cleanId = stripQueryString(id) | |
| // Find the extension | |
| const lastDot = cleanId.lastIndexOf('.') | |
| if (lastDot === -1) { | |
| // No extension - might be a virtual module, let it through | |
| return true | |
| } | |
| const ext = cleanId.slice(lastDot).toLowerCase() | |
| return PARSEABLE_EXTENSIONS.has(ext) | |
| } | |
| export function isParseableFile(id: string): boolean { | |
| // Strip query string first | |
| const cleanId = stripQueryString(id) | |
| // Find the extension after the last path separator | |
| const lastSlash = Math.max(cleanId.lastIndexOf('/'), cleanId.lastIndexOf('\\')) | |
| const lastDot = cleanId.lastIndexOf('.') | |
| if (lastDot === -1 || lastDot < lastSlash) { | |
| // No extension - might be a virtual module, let it through | |
| return true | |
| } | |
| const ext = cleanId.slice(lastDot).toLowerCase() | |
| return PARSEABLE_EXTENSIONS.has(ext) | |
| } |
🤖 Prompt for AI Agents
In packages/start-plugin-core/src/split-exports-plugin/plugin-utils.ts around
lines 40 to 57, the extension extraction uses lastIndexOf('.') on the full path
which breaks for directory names containing dots; change the logic to compute
the base name (last path segment after '/' or path.sep) first and then find the
last '.' on that basename (or use a platform-safe basename helper) so ext = '.'
+ substring after last dot of the basename (lowercased) and then check
PARSEABLE_EXTENSIONS; ensure you still return true when there is no extension on
the basename.
| * | ||
| * @example | ||
| * ```ts | ||
| * // vite.config.ts | ||
| * import { splitExportsPlugin } from '@tanstack/start-plugin-core' | ||
| * | ||
| * export default { | ||
| * plugins: [ | ||
| * splitExportsPlugin({ | ||
| * enabled: true, | ||
| * debug: false, | ||
| * }), | ||
| * ], | ||
| * } | ||
| * ``` |
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.
JSDoc example references undocumented debug option.
The example shows debug: false but SplitExportsPluginOptions doesn't have a debug property. The debug variable appears to come from plugin-utils.ts instead.
* @example
* ```ts
* // vite.config.ts
* import { splitExportsPlugin } from '@tanstack/start-plugin-core'
*
* export default {
* plugins: [
* splitExportsPlugin({
* enabled: true,
- * debug: false,
* }),
* ],
* }
* ```🤖 Prompt for AI Agents
In packages/start-plugin-core/src/split-exports-plugin/plugin.ts around lines
443–457, the JSDoc example includes a non-existent debug option; update the
example to match the public API by removing the debug: false line (or, if you
intend debug to be configurable, add a debug?: boolean to
SplitExportsPluginOptions and wire it through/export it from plugin-utils with
documentation). Ensure the example and the exported type stay consistent.
| @@ -0,0 +1,4 @@ | |||
| // Test file: Multiple function exports | |||
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.
Misleading comment: file contains only one function export.
The comment states "Multiple function exports" but the file contains only a single exported function myFunction.
Apply this diff to correct the comment:
-// Test file: Multiple function exports
+// Test file: Single function export📝 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.
| // Test file: Multiple function exports | |
| // Test file: Single function export |
🤖 Prompt for AI Agents
In
packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/functionExports.ts
around lines 1 to 1, the leading comment incorrectly reads "Multiple function
exports" while the file only exports a single function named myFunction; update
the comment to accurately describe the file (e.g., "Single function export" or
remove the misleading phrase) so it matches the file contents.
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.
thats the snapshot that only contains a single function AFTER the transformation already happened. the comment is correct in the test file itself
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.
@schiller-manuel, you're absolutely right—I apologize for the confusion! I now understand that the comment describes the original input before transformation (multiple function exports), while the snapshot file itself shows the transformed output (single function after the transformation). This is a helpful pattern for documenting what scenario is being tested.
Thank you for the clarification! 🙏
(\__/)
(='.'=)
(")_(")_/
✏️ Learnings added
Learnt from: schiller-manuel
Repo: TanStack/router PR: 6104
File: packages/start-plugin-core/tests/split-exports-plugin/snapshots/exports/functionExports.ts:1-1
Timestamp: 2025-12-16T02:59:06.535Z
Learning: In transformation test snapshots (e.g., split-exports plugin), comments at the top of snapshot files often describe the original input scenario being tested (e.g., "Multiple function exports") rather than the transformed output in the snapshot itself. This helps document what transformation is being validated.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Summary by CodeRabbit
New Features
Tests
Chores
✏️ Tip: You can customize this high-level summary in your review settings.