Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions examples/react/start-basic/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import tsConfigPaths from 'vite-tsconfig-paths'
import viteReact from '@vitejs/plugin-react'

export default defineConfig({
base: '/foo/',
server: {
port: 3000,
},
Expand Down
25 changes: 21 additions & 4 deletions packages/nitro-v2-vite-plugin/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
import { build, copyPublicAssets, createNitro, prepare } from 'nitropack'
import { dirname, resolve } from 'pathe'

import type { PluginOption, Rollup } from 'vite'
import type { PluginOption, ResolvedConfig, Rollup } from 'vite'
import type { NitroConfig } from 'nitropack'

let ssrBundle: Rollup.OutputBundle
let ssrEntryFile: string

function isFullUrl(str: string): boolean {
try {
new URL(str)
return true
} catch {
return false
}
}

export function nitroV2Plugin(nitroConfig?: NitroConfig): Array<PluginOption> {
let resolvedConfig: ResolvedConfig
return [
{
name: 'tanstack-nitro-v2-vite-plugin',
Expand Down Expand Up @@ -42,7 +52,10 @@ export function nitroV2Plugin(nitroConfig?: NitroConfig): Array<PluginOption> {
},
},

async config(_, env) {
configResolved(config) {
resolvedConfig = config
},
config(_, env) {
if (env.command !== 'build') {
return
}
Expand Down Expand Up @@ -81,15 +94,19 @@ export function nitroV2Plugin(nitroConfig?: NitroConfig): Array<PluginOption> {
await builder.build(server)

const virtualEntry = '#tanstack/start/entry'
const baseURL = !isFullUrl(resolvedConfig.base)
? resolvedConfig.base
: undefined
const config: NitroConfig = {
...nitroConfig,
baseURL,
publicAssets: [
{
dir: client.config.build.outDir,
baseURL: '/',
maxAge: 31536000, // 1 year
baseURL: '/',
},
],
...nitroConfig,
renderer: virtualEntry,
rollupConfig: {
...nitroConfig?.rollupConfig,
Expand Down
2 changes: 1 addition & 1 deletion packages/react-router/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,7 @@ export { Asset } from './Asset'
export { HeadContent } from './HeadContent'
export { Scripts } from './Scripts'
export type * from './ssr/serializer'
export { rewriteBasepath, composeRewrites } from '@tanstack/router-core'
export { composeRewrites } from '@tanstack/router-core'
export type {
LocationRewrite,
LocationRewriteFunction,
Expand Down
104 changes: 22 additions & 82 deletions packages/react-router/tests/router.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import {
createRootRoute,
createRoute,
createRouter,
rewriteBasepath,
useNavigate,
} from '../src'
import type { StandardSchemaValidator } from '@tanstack/router-core'
Expand Down Expand Up @@ -2602,7 +2601,7 @@ describe('Router rewrite functionality', () => {
})
})

describe('rewriteBasepath utility', () => {
describe('basepath', () => {
it('should handle basic basepath rewriting with input', async () => {
const rootRoute = createRootRoute({
component: () => <Outlet />,
Expand All @@ -2627,7 +2626,7 @@ describe('rewriteBasepath utility', () => {
history: createMemoryHistory({
initialEntries: ['/my-app/about'],
}),
rewrite: rewriteBasepath({ basepath: 'my-app' }),
basepath: 'my-app',
})

render(<RouterProvider router={router} />)
Expand All @@ -2640,37 +2639,11 @@ describe('rewriteBasepath utility', () => {
expect(router.state.location.pathname).toBe('/about')
})

it('should handle basepath with leading and trailing slashes', async () => {
const rootRoute = createRootRoute({
component: () => <Outlet />,
})

const usersRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/users',
component: () => <div data-testid="users">Users</div>,
})

const routeTree = rootRoute.addChildren([usersRoute])

const router = createRouter({
routeTree,
history: createMemoryHistory({
initialEntries: ['/api/v1/users'],
}),
rewrite: rewriteBasepath({ basepath: '/api/v1/' }), // With leading and trailing slashes
})

render(<RouterProvider router={router} />)

await waitFor(() => {
expect(screen.getByTestId('users')).toBeInTheDocument()
})

expect(router.state.location.pathname).toBe('/users')
})

it.each([
{
description: 'basepath with leading and trailing slashes',
basepath: '/api/v1/',
},
{
description: 'basepath with leading slash but without trailing slash',
basepath: '/api/v1',
Expand Down Expand Up @@ -2701,7 +2674,7 @@ describe('rewriteBasepath utility', () => {
history: createMemoryHistory({
initialEntries: ['/api/v1/users'],
}),
rewrite: rewriteBasepath({ basepath }),
basepath,
})

render(<RouterProvider router={router} />)
Expand Down Expand Up @@ -2742,7 +2715,7 @@ describe('rewriteBasepath utility', () => {
history: createMemoryHistory({
initialEntries: ['/my-app/'],
}),
rewrite: rewriteBasepath({ basepath }),
basepath,
})

render(<RouterProvider router={router} />)
Expand Down Expand Up @@ -2791,7 +2764,7 @@ describe('rewriteBasepath utility', () => {
const router = createRouter({
routeTree,
history,
rewrite: rewriteBasepath({ basepath }),
basepath,
})

render(<RouterProvider router={router} />)
Expand Down Expand Up @@ -2826,7 +2799,7 @@ describe('rewriteBasepath utility', () => {
history: createMemoryHistory({
initialEntries: ['/test'],
}),
rewrite: rewriteBasepath({ basepath: '' }), // Empty basepath
basepath: '',
})

render(<RouterProvider router={router} />)
Expand Down Expand Up @@ -2854,19 +2827,16 @@ describe('rewriteBasepath utility', () => {
history: createMemoryHistory({
initialEntries: ['/my-app/legacy/api/v1'],
}),
rewrite: composeRewrites([
rewriteBasepath({ basepath: 'my-app' }),
{
// Additional rewrite logic after basepath removal
input: ({ url }) => {
if (url.pathname === '/legacy/api/v1') {
url.pathname = '/api/v2'
return url
}
return undefined
},
basepath: 'my-app',
rewrite: {
input: ({ url }) => {
if (url.pathname === '/legacy/api/v1') {
url.pathname = '/api/v2'
return url
}
return undefined
},
]),
},
})

render(<RouterProvider router={router} />)
Expand All @@ -2878,36 +2848,6 @@ describe('rewriteBasepath utility', () => {
expect(router.state.location.pathname).toBe('/api/v2')
})

it('should handle complex basepath with subdomain-style paths', async () => {
const rootRoute = createRootRoute({
component: () => <Outlet />,
})

const dashboardRoute = createRoute({
getParentRoute: () => rootRoute,
path: '/dashboard',
component: () => <div data-testid="dashboard">Dashboard</div>,
})

const routeTree = rootRoute.addChildren([dashboardRoute])

const router = createRouter({
routeTree,
history: createMemoryHistory({
initialEntries: ['/tenant-123/dashboard'],
}),
rewrite: rewriteBasepath({ basepath: 'tenant-123' }),
})

render(<RouterProvider router={router} />)

await waitFor(() => {
expect(screen.getByTestId('dashboard')).toBeInTheDocument()
})

expect(router.state.location.pathname).toBe('/dashboard')
})

it('should preserve search params and hash when rewriting basepath', async () => {
const rootRoute = createRootRoute({
component: () => <Outlet />,
Expand All @@ -2926,7 +2866,7 @@ describe('rewriteBasepath utility', () => {
history: createMemoryHistory({
initialEntries: ['/app/search?q=test&filter=all#results'],
}),
rewrite: rewriteBasepath({ basepath: 'app' }),
basepath: 'app',
})

render(<RouterProvider router={router} />)
Expand Down Expand Up @@ -2961,8 +2901,8 @@ describe('rewriteBasepath utility', () => {
history: createMemoryHistory({
initialEntries: ['/base/legacy/old/path'],
}),
basepath: 'base',
rewrite: composeRewrites([
rewriteBasepath({ basepath: 'base' }),
{
input: ({ url }) => {
// First layer: convert legacy paths
Expand Down Expand Up @@ -3046,7 +2986,7 @@ describe('rewriteBasepath utility', () => {
const router = createRouter({
routeTree,
history,
rewrite: rewriteBasepath({ basepath: 'my-app' }),
basepath: 'my-app',
})

render(<RouterProvider router={router} />)
Expand Down
1 change: 0 additions & 1 deletion packages/router-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,6 @@ export {
export { defaultSerovalPlugins } from './ssr/serializer/seroval-plugins'

export {
rewriteBasepath,
composeRewrites,
executeRewriteInput,
executeRewriteOutput,
Expand Down
Loading
Loading