Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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