diff --git a/benchmarks/bundle-size/package.json b/benchmarks/bundle-size/package.json index 6426e78d96f..8344aabafda 100644 --- a/benchmarks/bundle-size/package.json +++ b/benchmarks/bundle-size/package.json @@ -24,7 +24,7 @@ "@vitejs/plugin-react": "^6.0.1", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4" } diff --git a/benchmarks/client-nav/jsdom.ts b/benchmarks/client-nav/jsdom.ts index d2183decee3..05535e693db 100644 --- a/benchmarks/client-nav/jsdom.ts +++ b/benchmarks/client-nav/jsdom.ts @@ -25,6 +25,7 @@ setGlobal('Element', window.Element) setGlobal('SVGElement', window.SVGElement) setGlobal('DocumentFragment', window.DocumentFragment) setGlobal('Node', window.Node) +setGlobal('MouseEvent', window.MouseEvent) setGlobal('MutationObserver', window.MutationObserver) setGlobal('sessionStorage', window.sessionStorage) setGlobal('localStorage', window.localStorage) diff --git a/benchmarks/client-nav/package.json b/benchmarks/client-nav/package.json index 7e377bac911..4c9da5352a9 100644 --- a/benchmarks/client-nav/package.json +++ b/benchmarks/client-nav/package.json @@ -37,7 +37,7 @@ "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5", "@types/jsdom": "28.0.0", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vitest": "^4.0.17" diff --git a/benchmarks/client-nav/react/app.tsx b/benchmarks/client-nav/react/app.tsx index d26aba6e91b..cad766e26ce 100644 --- a/benchmarks/client-nav/react/app.tsx +++ b/benchmarks/client-nav/react/app.tsx @@ -14,53 +14,130 @@ import { createRoot } from 'react-dom/client' function runPerfSelectorComputation(seed: number) { let value = Math.trunc(seed) | 0 - for (let index = 0; index < 100; index++) { + for (let index = 0; index < 40; index++) { value = (value * 1664525 + 1013904223 + index) >>> 0 } return value } -const selectors = Array.from({ length: 20 }, (_, index) => index) +function normalizePage(value: unknown) { + const page = Number(value) + return Number.isFinite(page) && page > 0 ? Math.trunc(page) : 1 +} + +function normalizeFilter(value: unknown) { + return typeof value === 'string' && value.length > 0 ? value : 'all' +} -function Params() { +const noop = () => {} +const rootSelectors = Array.from({ length: 10 }, (_, index) => index) +const routeSelectors = Array.from({ length: 6 }, (_, index) => index) +const linkGroups = Array.from({ length: 4 }, (_, index) => index) + +function RootParamsSubscriber() { const params = useParams({ strict: false, select: (params) => runPerfSelectorComputation(Number(params.id ?? 0)), }) - void params + + void runPerfSelectorComputation(params) return null } -function Search() { +function RootSearchSubscriber() { const search = useSearch({ strict: false, - select: (search) => runPerfSelectorComputation(Number(search.id ?? 0)), + select: (search) => runPerfSelectorComputation(Number(search.page ?? 0)), }) - void search + + void runPerfSelectorComputation(search) return null } -function Links() { +function LinkPanel() { return ( - - Link - + <> + {linkGroups.map((groupIndex) => { + const itemsId = groupIndex === 0 ? 1 : groupIndex + 2 + const ctxId = groupIndex + 1 + + return ( +
+ + {`Items ${itemsId}`} + + + {`Items 2 alt ${groupIndex}`} + + + {`Search ${groupIndex}`} + + + {`Context ${ctxId}`} + + ({ + page: prev.page + groupIndex + 1, + filter: prev.filter, + junk: `updater-${groupIndex}`, + })} + activeOptions={{ includeSearch: true }} + > + {({ isActive }) => + isActive + ? `Search updater active ${groupIndex}` + : `Search updater inactive ${groupIndex}` + } + +
+ ) + })} + ) } function Root() { return ( <> - {selectors.map((selector) => ( - + {rootSelectors.map((selector) => ( + ))} - {selectors.map((selector) => ( - - ))} - {selectors.map((selector) => ( - + {rootSelectors.map((selector) => ( + ))} + ) @@ -70,19 +147,230 @@ const rootRoute = createRootRoute({ component: Root, }) -const route = createRoute({ +const itemsRoute = createRoute({ getParentRoute: () => rootRoute, - path: '/$id', - component: () =>
, + path: '/items/$id', + params: { + parse: (params) => ({ + ...params, + id: normalizePage(params.id), + }), + stringify: (params) => ({ + ...params, + id: `${params.id}`, + }), + }, + onEnter: noop, + onStay: noop, + onLeave: noop, + component: ItemsPage, +}) + +const itemDetailsRoute = createRoute({ + getParentRoute: () => itemsRoute, + path: 'details', + component: ItemDetailsPage, +}) + +const searchRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/search', + validateSearch: (search: Record) => ({ + page: normalizePage(search.page), + filter: normalizeFilter(search.filter), + }), + search: { + middlewares: [ + ({ search, next }) => { + const result = next(search) + return { + page: result.page, + filter: result.filter, + } + }, + ], + }, + loaderDeps: ({ search }) => ({ + page: search.page, + filter: search.filter, + }), + loader: ({ deps }) => ({ + seed: deps.page * 31 + deps.filter.length, + checksum: deps.page * 17 + deps.filter.length, + }), + staleTime: 60_000, + gcTime: 60_000, + component: SearchPage, }) +const contextRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/ctx/$id', + beforeLoad: ({ params }) => ({ + sectionSeed: Number(params.id) * 13 + 1, + }), + component: ContextPage, +}) + +function ItemParamsSubscriber() { + const params = itemsRoute.useParams({ + select: (params) => runPerfSelectorComputation(params.id), + }) + + void runPerfSelectorComputation(params) + return null +} + +function SearchStateSubscriber() { + const search = searchRoute.useSearch({ + select: (search) => + runPerfSelectorComputation(search.page + search.filter.length), + }) + + void runPerfSelectorComputation(search) + return null +} + +function SearchLoaderDepsSubscriber() { + const loaderDeps = searchRoute.useLoaderDeps({ + select: (loaderDeps) => + runPerfSelectorComputation(loaderDeps.page + loaderDeps.filter.length), + }) + + void runPerfSelectorComputation(loaderDeps) + return null +} + +function SearchLoaderDataSubscriber() { + const loaderData = searchRoute.useLoaderData({ + select: (loaderData) => + runPerfSelectorComputation(loaderData.seed + loaderData.checksum), + }) + + void runPerfSelectorComputation(loaderData) + return null +} + +function ContextParamsSubscriber() { + const params = contextRoute.useParams({ + select: (params) => runPerfSelectorComputation(Number(params.id)), + }) + + void runPerfSelectorComputation(params) + return null +} + +function ContextRouteSubscriber() { + const context = contextRoute.useRouteContext({ + select: (context) => runPerfSelectorComputation(context.sectionSeed), + }) + + void runPerfSelectorComputation(context) + return null +} + +function ItemsPage() { + return ( + <> + {routeSelectors.map((selector) => ( + + ))} + + Details + + + Preserve search on item + + + + ) +} + +function ItemDetailsPage() { + return ( + <> + {routeSelectors.map((selector) => ( + + ))} + + Back to item + + + ) +} + +function SearchPage() { + return ( + <> + {routeSelectors.map((selector) => ( + + ))} + {routeSelectors.map((selector) => ( + + ))} + {routeSelectors.map((selector) => ( + + ))} + ({ + page: prev.page + 1, + filter: prev.filter, + junk: 'local-updater', + })} + activeOptions={{ includeSearch: true }} + activeProps={{ className: 'active-link' }} + inactiveProps={{ className: 'inactive-link' }} + > + Next page + + + ) +} + +function ContextPage() { + return ( + <> + {routeSelectors.map((selector) => ( + + ))} + {routeSelectors.map((selector) => ( + + ))} + + ) +} + export function mountTestApp(container: Element) { const router = createRouter({ history: createMemoryHistory({ - initialEntries: ['/0'], + initialEntries: ['/items/0'], }), scrollRestoration: true, - routeTree: rootRoute.addChildren([route]), + routeTree: rootRoute.addChildren([ + itemsRoute.addChildren([itemDetailsRoute]), + searchRoute, + contextRoute, + ]), }) const reactRoot = createRoot(container) diff --git a/benchmarks/client-nav/react/setup.ts b/benchmarks/client-nav/react/setup.ts index bc51cdb53bb..c637baf5701 100644 --- a/benchmarks/client-nav/react/setup.ts +++ b/benchmarks/client-nav/react/setup.ts @@ -1,5 +1,6 @@ import type { NavigateOptions } from '@tanstack/router-core' import type * as App from './app' +import { getRequiredLink, waitForRequiredLink } from '../setup-helpers' const appModulePath = './dist/app.js' const { mountTestApp } = (await import(appModulePath)) as typeof App @@ -10,40 +11,85 @@ export function setup() { 'client-nav benchmark is running without NODE_ENV=production; React dev overhead will dominate results.', ) } - let id = 0 - let unmount: (() => void) | undefined = undefined + let container: HTMLDivElement | undefined = undefined + let unmount: (() => void) | undefined = undefined let unsub = () => {} + let stepIndex = 0 let next: () => Promise = () => Promise.reject('Test not initialized') async function before() { - id = 0 + stepIndex = 0 container = document.createElement('div') document.body.append(container) const { router, unmount: dispose } = mountTestApp(container) unmount = dispose - let resolve: () => void = () => {} - unsub = router.subscribe('onRendered', () => resolve()) + + let resolveRendered: () => void = () => {} + unsub = router.subscribe('onRendered', () => { + resolveRendered() + }) const navigate = (opts: NavigateOptions) => new Promise((resolveNext) => { - resolve = resolveNext + resolveRendered = resolveNext router.navigate(opts) }) - next = () => { - const nextId = id++ - - return navigate({ - to: '/$id', - params: { id: nextId }, - // update search every 2 navigations, to still test them, but also measure the impact of granular re-rendering - search: { id: Math.floor(nextId / 2) }, - replace: true, + const click = (testId: string, cache?: Map) => + new Promise((resolveNext) => { + resolveRendered = resolveNext + + getRequiredLink(container!, testId, cache).dispatchEvent( + new MouseEvent('click', { + bubbles: true, + cancelable: true, + button: 0, + }), + ) }) - } + await router.load() + + const cachedLinks = new Map() + for (const testId of ['go-items-1', 'go-items-2', 'go-search', 'go-ctx']) { + await waitForRequiredLink(container, testId, cachedLinks) + } + + const steps = [ + () => click('go-items-1', cachedLinks), + () => click('items-details'), + () => + navigate({ + to: '/items/$id/details', + params: { id: 2 }, + replace: true, + }), + () => click('items-parent'), + () => click('go-search', cachedLinks), + () => click('search-next-page'), + () => + navigate({ + to: '/search', + search: { page: 1, filter: 'all' }, + replace: true, + }), + () => click('go-ctx', cachedLinks), + () => + navigate({ + to: '/ctx/$id', + params: { id: 2 }, + replace: true, + }), + () => click('go-items-2', cachedLinks), + ] as const + + next = () => { + const step = steps[stepIndex % steps.length]! + stepIndex += 1 + return step() + } } function after() { diff --git a/benchmarks/client-nav/setup-helpers.ts b/benchmarks/client-nav/setup-helpers.ts new file mode 100644 index 00000000000..c0700187436 --- /dev/null +++ b/benchmarks/client-nav/setup-helpers.ts @@ -0,0 +1,43 @@ +export function getRequiredLink( + container: ParentNode, + testId: string, + cache?: Map, +) { + const cachedLink = cache?.get(testId) + if (cachedLink) { + return cachedLink + } + + const link = container.querySelector( + `[data-testid="${testId}"]`, + ) + if (!link) { + throw new Error(`Unable to find benchmark link: ${testId}`) + } + + cache?.set(testId, link) + return link +} + +export async function waitForRequiredLink( + container: ParentNode, + testId: string, + cache?: Map, +) { + for (let attempt = 0; attempt < 10; attempt++) { + const link = container.querySelector( + `[data-testid="${testId}"]`, + ) + + if (link) { + cache?.set(testId, link) + return link + } + + await new Promise((resolve) => { + requestAnimationFrame(() => resolve()) + }) + } + + return getRequiredLink(container, testId, cache) +} diff --git a/benchmarks/client-nav/solid/app.tsx b/benchmarks/client-nav/solid/app.tsx index 42bc383d468..5c73ffce0c0 100644 --- a/benchmarks/client-nav/solid/app.tsx +++ b/benchmarks/client-nav/solid/app.tsx @@ -1,4 +1,4 @@ -import { For, createEffect } from 'solid-js' +import { For, createRenderEffect } from 'solid-js' import { render } from '@solidjs/web' import { Link, @@ -15,84 +15,355 @@ import { function runPerfSelectorComputation(seed: number) { let value = Math.trunc(seed) | 0 - for (let index = 0; index < 100; index++) { + for (let index = 0; index < 40; index++) { value = (value * 1664525 + 1013904223 + index) >>> 0 } return value } -const selectors = Array.from({ length: 20 }, (_, index) => index) +function normalizePage(value: unknown) { + const page = Number(value) + return Number.isFinite(page) && page > 0 ? Math.trunc(page) : 1 +} -function Params() { - const params = useParams({ - strict: false, - select: (params) => runPerfSelectorComputation(Number(params.id ?? 0)), - }) +function normalizeFilter(value: unknown) { + return typeof value === 'string' && value.length > 0 ? value : 'all' +} + +const noop = () => {} +const rootSelectors = Array.from({ length: 10 }, (_, index) => index) +const routeSelectors = Array.from({ length: 6 }, (_, index) => index) +const linkGroups = Array.from({ length: 4 }, (_, index) => index) - createEffect( - () => params(), +function PerfValue(props: { value: () => number }) { + createRenderEffect( + () => props.value(), () => {}, ) return null } -function Search() { - const search = useSearch({ +function RootParamsSubscriber() { + const params = useParams({ strict: false, - select: (search) => runPerfSelectorComputation(Number(search.id ?? 0)), + select: (params) => runPerfSelectorComputation(Number(params.id ?? 0)), }) - createEffect( - () => search(), - () => {}, - ) + return runPerfSelectorComputation(params())} /> +} - return null +function RootSearchSubscriber() { + const search = useSearch({ + strict: false, + select: (search) => runPerfSelectorComputation(Number(search.page ?? 0)), + }) + + return runPerfSelectorComputation(search())} /> } -function Links() { +function LinkPanel() { return ( - - Link - + <> + + {(groupIndexAccessor) => { + const groupIndex = groupIndexAccessor() + const itemsId = groupIndex === 0 ? 1 : groupIndex + 2 + const ctxId = groupIndex + 1 + + return ( +
+ + {`Items ${itemsId}`} + + + {`Items 2 alt ${groupIndex}`} + + + {`Search ${groupIndex}`} + + + {`Context ${ctxId}`} + + ({ + page: prev.page + groupIndex + 1, + filter: prev.filter, + junk: `updater-${groupIndex}`, + })} + activeOptions={{ includeSearch: true }} + > + {({ isActive }) => + isActive + ? `Search updater active ${groupIndex}` + : `Search updater inactive ${groupIndex}` + } + +
+ ) + }} +
+ ) } function Root() { return ( <> - {() => } - {() => } - {() => } + {() => } + {() => } + ) } -const root = createRootRoute({ +const rootRoute = createRootRoute({ component: Root, }) -const route = createRoute({ - getParentRoute: () => root, - path: '/$id', - component: () => { - return
+const itemsRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/items/$id', + params: { + parse: (params) => ({ + ...params, + id: normalizePage(params.id), + }), + stringify: (params) => ({ + ...params, + id: `${params.id}`, + }), + }, + onEnter: noop, + onStay: noop, + onLeave: noop, + component: ItemsPage, +}) + +const itemDetailsRoute = createRoute({ + getParentRoute: () => itemsRoute, + path: 'details', + component: ItemDetailsPage, +}) + +const searchRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/search', + validateSearch: (search: Record) => ({ + page: normalizePage(search.page), + filter: normalizeFilter(search.filter), + }), + search: { + middlewares: [ + ({ search, next }) => { + const result = next(search) + return { + page: result.page, + filter: result.filter, + } + }, + ], }, + loaderDeps: ({ search }) => ({ + page: search.page, + filter: search.filter, + }), + loader: ({ deps }) => ({ + seed: deps.page * 31 + deps.filter.length, + checksum: deps.page * 17 + deps.filter.length, + }), + staleTime: 60_000, + gcTime: 60_000, + component: SearchPage, +}) + +const contextRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/ctx/$id', + beforeLoad: ({ params }) => ({ + sectionSeed: Number(params.id) * 13 + 1, + }), + component: ContextPage, }) +function ItemParamsSubscriber() { + const params = itemsRoute.useParams({ + select: (params) => runPerfSelectorComputation(params.id), + }) + + return runPerfSelectorComputation(params())} /> +} + +function SearchStateSubscriber() { + const search = searchRoute.useSearch({ + select: (search) => + runPerfSelectorComputation(search.page + search.filter.length), + }) + + return runPerfSelectorComputation(search())} /> +} + +function SearchLoaderDepsSubscriber() { + const loaderDeps = searchRoute.useLoaderDeps({ + select: (loaderDeps) => + runPerfSelectorComputation(loaderDeps.page + loaderDeps.filter.length), + }) + + return runPerfSelectorComputation(loaderDeps())} /> +} + +function SearchLoaderDataSubscriber() { + const loaderData = searchRoute.useLoaderData({ + select: (loaderData) => + runPerfSelectorComputation(loaderData.seed + loaderData.checksum), + }) + + return runPerfSelectorComputation(loaderData())} /> +} + +function ContextParamsSubscriber() { + const params = contextRoute.useParams({ + select: (params) => runPerfSelectorComputation(Number(params.id)), + }) + + return runPerfSelectorComputation(params())} /> +} + +function ContextRouteSubscriber() { + const context = contextRoute.useRouteContext({ + select: (context) => runPerfSelectorComputation(context.sectionSeed), + }) + + return runPerfSelectorComputation(context())} /> +} + +function ItemsPage() { + return ( + <> + {() => } + + Details + + + Preserve search on item + + + + ) +} + +function ItemDetailsPage() { + return ( + <> + {() => } + + Back to item + + + ) +} + +function SearchPage() { + return ( + <> + {() => } + {() => } + {() => } + ({ + page: prev.page + 1, + filter: prev.filter, + junk: 'local-updater', + })} + activeOptions={{ includeSearch: true }} + activeProps={{ class: 'active-link' }} + inactiveProps={{ class: 'inactive-link' }} + > + Next page + + + ) +} + +function ContextPage() { + return ( + <> + {() => } + {() => } + + ) +} + export function mountTestApp(container: Element) { const router = createRouter({ history: createMemoryHistory({ - initialEntries: ['/0'], + initialEntries: ['/items/0'], }), scrollRestoration: true, - routeTree: root.addChildren([route]), + routeTree: rootRoute.addChildren([ + itemsRoute.addChildren([itemDetailsRoute]), + searchRoute, + contextRoute, + ]), }) const unmount = render(() => , container) - return { router, unmount } + return { + router, + unmount, + } } diff --git a/benchmarks/client-nav/solid/setup.ts b/benchmarks/client-nav/solid/setup.ts index 6c73350cf1a..ea138001f48 100644 --- a/benchmarks/client-nav/solid/setup.ts +++ b/benchmarks/client-nav/solid/setup.ts @@ -1,5 +1,6 @@ import type { NavigateOptions } from '@tanstack/router-core' import type * as App from './app' +import { getRequiredLink, waitForRequiredLink } from '../setup-helpers' const appModulePath = './dist/app.js' const { mountTestApp } = (await import(appModulePath)) as typeof App @@ -11,19 +12,20 @@ export function setup() { ) } - let id = 0 - let dispose: (() => void) | undefined = undefined let container: HTMLDivElement | undefined = undefined + let unmount: (() => void) | undefined = undefined let unsub = () => {} + let stepIndex = 0 let next: () => Promise = () => Promise.reject('Test not initialized') async function before() { - id = 0 + stepIndex = 0 container = document.createElement('div') document.body.append(container) - const { router, unmount } = mountTestApp(container) - dispose = unmount + const { router, unmount: dispose } = mountTestApp(container) + unmount = dispose + let resolveRendered: () => void = () => {} unsub = router.subscribe('onRendered', () => { resolveRendered() @@ -35,22 +37,63 @@ export function setup() { router.navigate(opts) }) - next = () => { - const nextId = id++ - - return navigate({ - to: '/$id', - params: { id: nextId }, - // update search every 2 navigations, to still test them, but also measure the impact of granular re-rendering - search: { id: Math.floor(nextId / 2) }, - replace: true, + const click = (testId: string, cache?: Map) => + new Promise((resolveNext) => { + resolveRendered = resolveNext + + getRequiredLink(container!, testId, cache).dispatchEvent( + new MouseEvent('click', { + bubbles: true, + cancelable: true, + button: 0, + }), + ) }) - } + await router.load() + + const cachedLinks = new Map() + for (const testId of ['go-items-1', 'go-items-2', 'go-search', 'go-ctx']) { + await waitForRequiredLink(container, testId, cachedLinks) + } + + const steps = [ + () => click('go-items-1', cachedLinks), + () => click('items-details'), + () => + navigate({ + to: '/items/$id/details', + params: { id: 2 }, + replace: true, + }), + () => click('items-parent'), + () => click('go-search', cachedLinks), + () => click('search-next-page'), + () => + navigate({ + to: '/search', + search: { page: 1, filter: 'all' }, + replace: true, + }), + () => click('go-ctx', cachedLinks), + () => + navigate({ + to: '/ctx/$id', + params: { id: 2 }, + replace: true, + }), + () => click('go-items-2', cachedLinks), + ] as const + + next = () => { + const step = steps[stepIndex % steps.length]! + stepIndex += 1 + return step() + } } function after() { - dispose?.() + unmount?.() container?.remove() unsub() } diff --git a/benchmarks/client-nav/vue/app.tsx b/benchmarks/client-nav/vue/app.tsx index cf6c8643800..f88eee81298 100644 --- a/benchmarks/client-nav/vue/app.tsx +++ b/benchmarks/client-nav/vue/app.tsx @@ -14,16 +14,28 @@ import { function runPerfSelectorComputation(seed: number) { let value = Math.trunc(seed) | 0 - for (let index = 0; index < 100; index++) { + for (let index = 0; index < 40; index++) { value = (value * 1664525 + 1013904223 + index) >>> 0 } return value } -const selectors = Array.from({ length: 20 }, (_, index) => index) +function normalizePage(value: unknown) { + const page = Number(value) + return Number.isFinite(page) && page > 0 ? Math.trunc(page) : 1 +} + +function normalizeFilter(value: unknown) { + return typeof value === 'string' && value.length > 0 ? value : 'all' +} + +const noop = () => {} +const rootSelectors = Array.from({ length: 10 }, (_, index) => index) +const routeSelectors = Array.from({ length: 6 }, (_, index) => index) +const linkGroups = Array.from({ length: 4 }, (_, index) => index) -const Params = Vue.defineComponent({ +const RootParamsSubscriber = Vue.defineComponent({ setup() { const params = useParams({ strict: false, @@ -31,32 +43,97 @@ const Params = Vue.defineComponent({ }) return () => { - void params.value + void runPerfSelectorComputation(params.value) return null } }, }) -const Search = Vue.defineComponent({ +const RootSearchSubscriber = Vue.defineComponent({ setup() { const search = useSearch({ strict: false, - select: (search) => runPerfSelectorComputation(Number(search.id ?? 0)), + select: (search) => runPerfSelectorComputation(Number(search.page ?? 0)), }) return () => { - void search.value + void runPerfSelectorComputation(search.value) return null } }, }) -const Links = Vue.defineComponent({ +const LinkPanel = Vue.defineComponent({ setup() { return () => ( - - Link - + <> + {linkGroups.map((groupIndex) => { + const itemsId = groupIndex === 0 ? 1 : groupIndex + 2 + const ctxId = groupIndex + 1 + + return ( +
+ + {`Items ${itemsId}`} + + + {`Items 2 alt ${groupIndex}`} + + + {`Search ${groupIndex}`} + + + {`Context ${ctxId}`} + + ({ + page: prev.page + groupIndex + 1, + filter: prev.filter, + junk: `updater-${groupIndex}`, + })} + activeOptions={{ includeSearch: true }} + > + {({ isActive }: { isActive: boolean }) => + isActive + ? `Search updater active ${groupIndex}` + : `Search updater inactive ${groupIndex}` + } + +
+ ) + })} + ) }, }) @@ -65,38 +142,279 @@ const Root = Vue.defineComponent({ setup() { return () => ( <> - {selectors.map((selector) => ( - + {rootSelectors.map((selector) => ( + ))} - {selectors.map((selector) => ( - - ))} - {selectors.map((selector) => ( - + {rootSelectors.map((selector) => ( + ))} + ) }, }) -const root = createRootRoute({ +const rootRoute = createRootRoute({ component: Root, }) -const route = createRoute({ - getParentRoute: () => root, - path: '/$id', - component: () =>
, +const ItemParamsSubscriber = Vue.defineComponent({ + setup() { + const params = itemsRoute.useParams({ + select: (params) => runPerfSelectorComputation(params.id), + }) + + return () => { + void runPerfSelectorComputation(params.value) + return null + } + }, +}) + +const SearchStateSubscriber = Vue.defineComponent({ + setup() { + const search = searchRoute.useSearch({ + select: (search) => + runPerfSelectorComputation(search.page + search.filter.length), + }) + + return () => { + void runPerfSelectorComputation(search.value) + return null + } + }, +}) + +const SearchLoaderDepsSubscriber = Vue.defineComponent({ + setup() { + const loaderDeps = searchRoute.useLoaderDeps({ + select: (loaderDeps) => + runPerfSelectorComputation(loaderDeps.page + loaderDeps.filter.length), + }) + + return () => { + void runPerfSelectorComputation(loaderDeps.value) + return null + } + }, +}) + +const SearchLoaderDataSubscriber = Vue.defineComponent({ + setup() { + const loaderData = searchRoute.useLoaderData({ + select: (loaderData) => + runPerfSelectorComputation(loaderData.seed + loaderData.checksum), + }) + + return () => { + void runPerfSelectorComputation(loaderData.value) + return null + } + }, +}) + +const ContextParamsSubscriber = Vue.defineComponent({ + setup() { + const params = contextRoute.useParams({ + select: (params) => runPerfSelectorComputation(Number(params.id)), + }) + + return () => { + void runPerfSelectorComputation(params.value) + return null + } + }, +}) + +const ContextRouteSubscriber = Vue.defineComponent({ + setup() { + const context = contextRoute.useRouteContext({ + select: (context) => runPerfSelectorComputation(context.sectionSeed), + }) + + return () => { + void runPerfSelectorComputation(context.value) + return null + } + }, +}) + +const ItemsPage = Vue.defineComponent({ + setup() { + return () => ( + <> + {routeSelectors.map((selector) => ( + + ))} + + Details + + + Preserve search on item + + + + ) + }, +}) + +const ItemDetailsPage = Vue.defineComponent({ + setup() { + return () => ( + <> + {routeSelectors.map((selector) => ( + + ))} + + Back to item + + + ) + }, +}) + +const SearchPage = Vue.defineComponent({ + setup() { + return () => ( + <> + {routeSelectors.map((selector) => ( + + ))} + {routeSelectors.map((selector) => ( + + ))} + {routeSelectors.map((selector) => ( + + ))} + ({ + page: prev.page + 1, + filter: prev.filter, + junk: 'local-updater', + })} + activeOptions={{ includeSearch: true }} + activeProps={{ class: 'active-link' }} + inactiveProps={{ class: 'inactive-link' }} + > + Next page + + + ) + }, +}) + +const ContextPage = Vue.defineComponent({ + setup() { + return () => ( + <> + {routeSelectors.map((selector) => ( + + ))} + {routeSelectors.map((selector) => ( + + ))} + + ) + }, +}) + +const itemsRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/items/$id', + params: { + parse: (params) => ({ + ...params, + id: normalizePage(params.id), + }), + stringify: (params) => ({ + ...params, + id: `${params.id}`, + }), + }, + onEnter: noop, + onStay: noop, + onLeave: noop, + component: ItemsPage, +}) + +const itemDetailsRoute = createRoute({ + getParentRoute: () => itemsRoute, + path: 'details', + component: ItemDetailsPage, +}) + +const searchRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/search', + validateSearch: (search: Record) => ({ + page: normalizePage(search.page), + filter: normalizeFilter(search.filter), + }), + search: { + middlewares: [ + ({ search, next }) => { + const result = next(search) + return { + page: result.page, + filter: result.filter, + } + }, + ], + }, + loaderDeps: ({ search }) => ({ + page: search.page, + filter: search.filter, + }), + loader: ({ deps }) => ({ + seed: deps.page * 31 + deps.filter.length, + checksum: deps.page * 17 + deps.filter.length, + }), + staleTime: 60_000, + gcTime: 60_000, + component: SearchPage, +}) + +const contextRoute = createRoute({ + getParentRoute: () => rootRoute, + path: '/ctx/$id', + beforeLoad: ({ params }) => ({ + sectionSeed: Number(params.id) * 13 + 1, + }), + component: ContextPage, }) export function mountTestApp(container: Element) { const router = createRouter({ history: createMemoryHistory({ - initialEntries: ['/0'], + initialEntries: ['/items/0'], }), scrollRestoration: true, - routeTree: root.addChildren([route]), + routeTree: rootRoute.addChildren([ + itemsRoute.addChildren([itemDetailsRoute]), + searchRoute, + contextRoute, + ]), }) const component = diff --git a/benchmarks/client-nav/vue/setup.ts b/benchmarks/client-nav/vue/setup.ts index 5b4a91cb059..a7450203029 100644 --- a/benchmarks/client-nav/vue/setup.ts +++ b/benchmarks/client-nav/vue/setup.ts @@ -1,5 +1,6 @@ import type { NavigateOptions } from '@tanstack/router-core' import type * as App from './app' +import { getRequiredLink, waitForRequiredLink } from '../setup-helpers' const appModulePath = './dist/app.js' const { mountTestApp } = (await import(appModulePath)) as typeof App @@ -11,19 +12,20 @@ export function setup() { ) } - let id = 0 - let unmount: (() => void) | undefined = undefined let container: HTMLDivElement | undefined = undefined + let unmount: (() => void) | undefined = undefined let unsub = () => {} + let stepIndex = 0 let next: () => Promise = () => Promise.reject('Test not initialized') async function before() { - id = 0 + stepIndex = 0 container = document.createElement('div') document.body.append(container) const { router, unmount: dispose } = mountTestApp(container) unmount = dispose + let resolveRendered: () => void = () => {} unsub = router.subscribe('onRendered', () => { resolveRendered() @@ -35,18 +37,59 @@ export function setup() { router.navigate(opts) }) - next = () => { - const nextId = id++ - - return navigate({ - to: '/$id', - params: { id: nextId }, - // update search every 2 navigations, to still test them, but also measure the impact of granular re-rendering - search: { id: Math.floor(nextId / 2) }, - replace: true, + const click = (testId: string, cache?: Map) => + new Promise((resolveNext) => { + resolveRendered = resolveNext + + getRequiredLink(container!, testId, cache).dispatchEvent( + new MouseEvent('click', { + bubbles: true, + cancelable: true, + button: 0, + }), + ) }) - } + await router.load() + + const cachedLinks = new Map() + for (const testId of ['go-items-1', 'go-items-2', 'go-search', 'go-ctx']) { + await waitForRequiredLink(container, testId, cachedLinks) + } + + const steps = [ + () => click('go-items-1', cachedLinks), + () => click('items-details'), + () => + navigate({ + to: '/items/$id/details', + params: { id: 2 }, + replace: true, + }), + () => click('items-parent'), + () => click('go-search', cachedLinks), + () => click('search-next-page'), + () => + navigate({ + to: '/search', + search: { page: 1, filter: 'all' }, + replace: true, + }), + () => click('go-ctx', cachedLinks), + () => + navigate({ + to: '/ctx/$id', + params: { id: 2 }, + replace: true, + }), + () => click('go-items-2', cachedLinks), + ] as const + + next = () => { + const step = steps[stepIndex % steps.length]! + stepIndex += 1 + return step() + } } function after() { diff --git a/benchmarks/ssr/package.json b/benchmarks/ssr/package.json index 0c5bd1ad211..c1c15a1a27d 100644 --- a/benchmarks/ssr/package.json +++ b/benchmarks/ssr/package.json @@ -32,7 +32,7 @@ "@codspeed/vitest-plugin": "^5.0.1", "@vitejs/plugin-react": "^6.0.1", "@vitejs/plugin-vue-jsx": "^5.1.5", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vitest": "^4.0.17" diff --git a/docs/router/api/router/RouterEventsType.md b/docs/router/api/router/RouterEventsType.md index 45d6431cdfd..c79bb47f817 100644 --- a/docs/router/api/router/RouterEventsType.md +++ b/docs/router/api/router/RouterEventsType.md @@ -13,6 +13,7 @@ type RouterEvents = { toLocation: ParsedLocation pathChanged: boolean hrefChanged: boolean + hashChanged: boolean } onBeforeLoad: { type: 'onBeforeLoad' @@ -20,6 +21,7 @@ type RouterEvents = { toLocation: ParsedLocation pathChanged: boolean hrefChanged: boolean + hashChanged: boolean } onLoad: { type: 'onLoad' @@ -27,6 +29,7 @@ type RouterEvents = { toLocation: ParsedLocation pathChanged: boolean hrefChanged: boolean + hashChanged: boolean } onResolved: { type: 'onResolved' @@ -34,6 +37,7 @@ type RouterEvents = { toLocation: ParsedLocation pathChanged: boolean hrefChanged: boolean + hashChanged: boolean } onBeforeRouteMount: { type: 'onBeforeRouteMount' @@ -41,6 +45,7 @@ type RouterEvents = { toLocation: ParsedLocation pathChanged: boolean hrefChanged: boolean + hashChanged: boolean } onInjectedHtml: { type: 'onInjectedHtml' @@ -49,6 +54,9 @@ type RouterEvents = { type: 'onRendered' fromLocation?: ParsedLocation toLocation: ParsedLocation + pathChanged: boolean + hrefChanged: boolean + hashChanged: boolean } } ``` @@ -59,7 +67,7 @@ Once an event is emitted, the following properties will be present on the event ### `type` property -- Type: `onBeforeNavigate | onBeforeLoad | onLoad | onBeforeRouteMount | onResolved` +- Type: `onBeforeNavigate | onBeforeLoad | onLoad | onBeforeRouteMount | onResolved | onRendered | onInjectedHtml` - The type of the event - This is useful for discriminating between events in a listener function. @@ -83,6 +91,11 @@ Once an event is emitted, the following properties will be present on the event - Type: `boolean` - `true` if the href has changed between the `fromLocation` and `toLocation`. +### `hashChanged` property + +- Type: `boolean` +- `true` if the hash has changed between the `fromLocation` and `toLocation`. + ## Example ```tsx diff --git a/docs/router/api/router/RouterType.md b/docs/router/api/router/RouterType.md index 0b829b85e0a..757a6098ca4 100644 --- a/docs/router/api/router/RouterType.md +++ b/docs/router/api/router/RouterType.md @@ -23,10 +23,11 @@ An instance of the `Router` has the following properties and methods: ### `.subscribe` method -- Type: `(eventType: TType, fn: ListenerFn) => (event: RouterEvent) => void` +- Type: `(eventType: TType, fn: ListenerFn) => () => void` - Subscribes to a [`RouterEvent`](./RouterEventsType.md). - Returns a function that can be used to unsubscribe from the event. -- The callback provided to the returned function will be called with the event that was emitted. +- The listener will be called with the event payload whenever that event is emitted. +- See the [Router Events guide](../../guide/router-events.md) for lifecycle ordering and usage patterns. ### `.matchRoutes` method diff --git a/docs/router/api/router/useBlockerHook.md b/docs/router/api/router/useBlockerHook.md index 98d4a06c3b2..3d9c00d6022 100644 --- a/docs/router/api/router/useBlockerHook.md +++ b/docs/router/api/router/useBlockerHook.md @@ -20,7 +20,7 @@ The `useBlocker` hook accepts a single _required_ argument, an option object: - Think of this function as telling the router if it should block the navigation, so returning `true` mean that it should block the navigation and `false` meaning that it should be allowed ```ts -interface ShouldBlockFnLocation<...> { +type ShouldBlockFnLocation<...> = { routeId: TRouteId fullPath: TFullPath pathname: string diff --git a/docs/router/config.json b/docs/router/config.json index e13b8e403f5..fd564ceb286 100644 --- a/docs/router/config.json +++ b/docs/router/config.json @@ -163,6 +163,10 @@ "label": "Navigation", "to": "guide/navigation" }, + { + "label": "Router Events", + "to": "guide/router-events" + }, { "label": "Path Params", "to": "guide/path-params" diff --git a/docs/router/guide/data-mutations.md b/docs/router/guide/data-mutations.md index 53899f51d4a..7ffb403bfb1 100644 --- a/docs/router/guide/data-mutations.md +++ b/docs/router/guide/data-mutations.md @@ -123,6 +123,8 @@ function ChatRoom() { ## Using the `router.subscribe` method +See the [Router Events guide](./router-events.md) for a more complete walkthrough of the available events and when to use them. + For libraries that don't have a keying mechanism, we'll likely need to manually reset the mutation state when the user navigates away from the screen. To solve this, we can use TanStack Router's `invalidate` and `subscribe` method to clear mutation states when the user is no longer in need of them. The `router.subscribe` method is a function that subscribes a callback to various router events. The event in particular that we'll use here is the `onResolved` event. It's important to understand that this event is fired when the location path is _changed (not just reloaded) and has finally resolved_. diff --git a/docs/router/guide/document-head-management.md b/docs/router/guide/document-head-management.md index cf66544a4af..381462e20a5 100644 --- a/docs/router/guide/document-head-management.md +++ b/docs/router/guide/document-head-management.md @@ -68,6 +68,24 @@ The `` component is **required** to render the head, title, meta, It should be **rendered either in the `` tag of your root layout or as high up in the component tree as possible** if your application doesn't or can't manage the `` tag. +For manifest-managed assets, you can also set `crossorigin` values on emitted +`modulepreload` and stylesheet links: + +```tsx + + + +``` + +`assetCrossOrigin` only applies to manifest-managed asset links emitted by Start. +If you also set `crossOrigin` via `transformAssets` (either the object shorthand +or a callback return value), `assetCrossOrigin` wins. + ### Start/Full-Stack Applications diff --git a/docs/router/guide/router-events.md b/docs/router/guide/router-events.md new file mode 100644 index 00000000000..ca798a96768 --- /dev/null +++ b/docs/router/guide/router-events.md @@ -0,0 +1,129 @@ +--- +title: Router Events +--- + +TanStack Router exposes router lifecycle events through `router.subscribe`. This is useful for imperative side effects like analytics, resetting external state, or running DOM-dependent logic after navigation. + +## Basic usage + +`router.subscribe` takes an event name and a listener, then returns an unsubscribe function: + +```tsx +const unsubscribe = router.subscribe('onResolved', (event) => { + console.info('Navigation finished:', event.toLocation.href) +}) + +// Later, clean up the listener +unsubscribe() +``` + +## When to use it + +`router.subscribe` is best for imperative integrations that need to observe navigation without driving rendering: + +- Analytics and pageview tracking +- Resetting external caches or mutation state +- Logging navigation timing and transitions +- Running DOM-dependent logic after routes render + +If you need reactive UI updates, prefer framework hooks like `useRouterState`, `useSearch`, and `useParams` instead of subscribing manually. + +## Available events + +TanStack Router emits these lifecycle events: + +- `onBeforeNavigate` - right before a navigation begins +- `onBeforeLoad` - before route loading starts +- `onLoad` - after the next location has committed and route matches have loaded +- `onBeforeRouteMount` - after loading finishes, just before route components mount +- `onResolved` - after the navigation has fully resolved +- `onRendered` - after the route has rendered + +For the full event payload types, see the [`RouterEvents` type](../api/router/RouterEventsType.md). + +## Typical event flow + +For a normal navigation, the events usually flow like this: + +1. `onBeforeNavigate` +2. `onBeforeLoad` +3. `onLoad` +4. `onBeforeRouteMount` +5. `onResolved` +6. `onRendered` + +You usually do not need every event. A good rule of thumb is: + +- Use `onBeforeNavigate` or `onBeforeLoad` to observe navigation start +- Use `onResolved` for analytics and cleanup after navigation finishes +- Use `onRendered` for DOM-dependent work + +## Event payload + +Navigation events receive location change metadata describing what changed: + +```tsx +const unsubscribe = router.subscribe('onBeforeNavigate', (event) => { + console.info({ + from: event.fromLocation?.href, + to: event.toLocation.href, + pathChanged: event.pathChanged, + hrefChanged: event.hrefChanged, + hashChanged: event.hashChanged, + }) +}) +``` + +A few useful details: + +- `fromLocation` can be `undefined` on the initial load +- `pathChanged` tells you whether the pathname changed +- `hrefChanged` includes pathname, search, and hash changes +- `hashChanged` is useful for distinguishing hash-only navigations + +## Common patterns + +### Track pageviews + +`onResolved` is a good default for analytics because it fires after navigation finishes: + +```tsx +const unsubscribe = router.subscribe('onResolved', ({ toLocation }) => { + analytics.track('page_view', { + path: toLocation.pathname, + href: toLocation.href, + }) +}) +``` + +### Clear external mutation state + +If you use a mutation library without keyed mutation state, clear it after navigation: + +```tsx +const unsubscribe = router.subscribe('onResolved', ({ pathChanged }) => { + if (pathChanged) { + mutationCache.clear() + } +}) +``` + +### Run DOM-dependent logic + +Use `onRendered` when your side effect depends on the new route content already being in the DOM: + +```tsx +const unsubscribe = router.subscribe('onRendered', ({ toLocation }) => { + focusPageHeading(toLocation.pathname) +}) +``` + +## Unsubscribing in components + +If you subscribe from a component or framework effect, always return the unsubscribe function from your cleanup so the listener is removed when the component unmounts. + +## Related APIs + +- [`Router` type](../api/router/RouterType.md) +- [`RouterEvents` type](../api/router/RouterEventsType.md) +- [Data Mutations](./data-mutations.md) diff --git a/docs/router/quick-start.md b/docs/router/quick-start.md index 69ec50c5381..a3571756df2 100644 --- a/docs/router/quick-start.md +++ b/docs/router/quick-start.md @@ -9,8 +9,8 @@ The fastest way to get started with TanStack Router is to scaffold a new project -react: create-tsrouter-app@latest -solid: create-tsrouter-app@latest --framework solid +react: @tanstack/cli create --router-only +solid: @tanstack/cli create --router-only --framework solid @@ -25,7 +25,7 @@ The CLI will guide you through a short series of prompts to customize your setup Once complete, a new project will be generated with TanStack Router installed and ready to use. > [!TIP] -> For full details on available options and templates, visit the [`create-tsrouter-app` documentation](https://github.com/TanStack/create-tsrouter-app/tree/main/cli/create-tsrouter-app). +> For full details on available options and templates, visit the [`@tanstack/cli` documentation](https://github.com/TanStack/cli). ## Routing Options @@ -35,23 +35,37 @@ TanStack Router supports both file-based and code-based route configurations. Yo The file-based approach is the recommended option for most projects. It automatically creates routes based on your file structure, giving you the best mix of performance, simplicity, and developer experience. - +For more details, see the [file-based routing documentation](./routing/file-based-routing.md) or -react: create-tsrouter-app@latest my-app --template file-router -solid: create-tsrouter-app@latest my-app --framework solid --template file-router + - +# React + +[explore the live example](https://tanstack.com/router/latest/docs/framework/react/examples/basic-file-based) + +# Solid + +[explore the live example](https://tanstack.com/router/latest/docs/framework/solid/examples/basic-file-based) + + ### Code-Based Route Configuration If you prefer to define routes programmatically, you can use the code-based route configuration. This approach gives you full control over routing logic. - +For more details, see the [code-based routing documentation](./routing/code-based-routing.md) or -react: create-tsrouter-app@latest my-app -solid: create-tsrouter-app@latest my-app --framework solid + - +# React + +[explore the live example](https://tanstack.com/router/latest/docs/framework/react/examples/basic) + +# Solid + +[explore the live example](https://tanstack.com/router/latest/docs/framework/solid/examples/basic) + + With either approach, navigate to your project directory and start the development server. diff --git a/docs/start/framework/react/guide/cdn-asset-urls.md b/docs/start/framework/react/guide/cdn-asset-urls.md index 977c030c685..745250b8216 100644 --- a/docs/start/framework/react/guide/cdn-asset-urls.md +++ b/docs/start/framework/react/guide/cdn-asset-urls.md @@ -5,13 +5,15 @@ title: CDN Asset URLs # CDN Asset URLs -> **Experimental:** `transformAssetUrls` is experimental and subject to change. +> **Experimental:** `transformAssets` is experimental and subject to change. -When deploying to production, you may want to serve your static assets (JavaScript, CSS) from a CDN. The `transformAssetUrls` option on `createStartHandler` lets you rewrite asset URLs at runtime — for example, prepending a CDN origin that is only known when the server starts. +When deploying to production, you may want to serve your static assets (JavaScript, CSS) from a CDN. The `transformAssets` option on `createStartHandler` lets you rewrite asset URLs at runtime - for example, prepending a CDN origin that is only known when the server starts. + +`transformAssetUrls` still works, but it is deprecated and now delegates to `transformAssets` with a development warning. ## Why Runtime URL Rewriting? -Vite's `base` config is evaluated at build time. If your CDN URL is determined at deploy time (via environment variables, dynamic configuration, etc.), you need a way to rewrite URLs at runtime. `transformAssetUrls` solves this for the URLs that TanStack Start manages in its manifest: +Vite's `base` config is evaluated at build time. If your CDN URL is determined at deploy time (via environment variables, dynamic configuration, etc.), you need a way to rewrite URLs at runtime. `transformAssets` solves this for the URLs that TanStack Start manages in its manifest: - `` tags (JS preloads) - `` tags (CSS) @@ -33,7 +35,7 @@ import { createServerEntry } from '@tanstack/react-start/server-entry' const handler = createStartHandler({ handler: defaultStreamHandler, - transformAssetUrls: process.env.CDN_ORIGIN || '', + transformAssets: process.env.CDN_ORIGIN || '', }) export default createServerEntry({ fetch: handler }) @@ -43,9 +45,46 @@ If `CDN_ORIGIN` is `https://cdn.example.com` and an asset URL is `/assets/index- When the string is empty (or not set), the URLs are left unchanged. +### Object Shorthand (Prefix + CrossOrigin) + +If you also need to set `crossOrigin` on manifest-managed `` tags, use the object shorthand with `prefix` and `crossOrigin`: + +```tsx +// src/server.ts +import { + createStartHandler, + defaultStreamHandler, +} from '@tanstack/react-start/server' +import { createServerEntry } from '@tanstack/react-start/server-entry' + +const handler = createStartHandler({ + handler: defaultStreamHandler, + transformAssets: { + prefix: process.env.CDN_ORIGIN || '', + crossOrigin: 'anonymous', + }, +}) + +export default createServerEntry({ fetch: handler }) +``` + +`crossOrigin` accepts either a single value applied to all asset kinds, or a per-kind record (matching the `HeadContent assetCrossOrigin` shape): + +```tsx +transformAssets: { + prefix: 'https://cdn.example.com', + crossOrigin: { + modulepreload: 'anonymous', + stylesheet: 'use-credentials', + }, +} +``` + +Kinds not listed in the per-kind record receive no `crossOrigin` attribute. Like the string shorthand, the object shorthand is always cached (`cache: true`). + ### Callback -For more control, pass a callback that receives `{ url, type }` and returns a new URL (or a `Promise` of one). By default, the transformed manifest is cached after the first request (`cache: true`), so the callback only runs once in production: +For more control, pass a callback that receives `{ kind, url }` and returns a string, or `{ href, crossOrigin? }` (or a `Promise` of either). By default, the transformed manifest is cached after the first request (`cache: true`), so the callback only runs once in production: ```tsx // src/server.ts @@ -57,10 +96,17 @@ import { createServerEntry } from '@tanstack/react-start/server-entry' const handler = createStartHandler({ handler: defaultStreamHandler, - transformAssetUrls: ({ url, type }) => { - // Only rewrite JS and CSS, leave client entry unchanged - if (type === 'clientEntry') return url - return `https://cdn.example.com${url}` + transformAssets: ({ kind, url }) => { + const href = `https://cdn.example.com${url}` + + if (kind === 'modulepreload') { + return { + href, + crossOrigin: 'anonymous', + } + } + + return { href } }, }) @@ -69,17 +115,19 @@ export default createServerEntry({ fetch: handler }) If you need per-request behavior (for example, choosing a CDN based on a header), use the object form with `cache: false`. -The `type` parameter tells you what kind of asset URL is being transformed: +The `kind` parameter tells you what kind of asset URL is being transformed: -| `type` | Description | +| `kind` | Description | | ----------------- | ---------------------------------------------------- | | `'modulepreload'` | JS module preload URL (``) | | `'stylesheet'` | CSS stylesheet URL (``) | | `'clientEntry'` | Client entry module URL (used in `import('...')`) | +`crossOrigin` applies to manifest-managed link tags. For the client entry, returning `{ href }` is equivalent to returning a string. + ### Object Form (Explicit Cache Control) -For per-request transforms — where the CDN URL depends on request-specific data like headers — use the object form with `cache: false`: +For per-request transforms - where the CDN URL depends on request-specific data like headers - use the object form with `cache: false`: ```tsx // src/server.ts @@ -92,14 +140,22 @@ import { getRequest } from '@tanstack/react-start/server' const handler = createStartHandler({ handler: defaultStreamHandler, - transformAssetUrls: { - transform: ({ url, type }) => { + transformAssets: { + transform: ({ kind, url }) => { const region = getRequest().headers.get('x-region') || 'us' const cdnBase = region === 'eu' ? 'https://cdn-eu.example.com' : 'https://cdn-us.example.com' - return `${cdnBase}${url}` + + if (kind === 'modulepreload') { + return { + href: `${cdnBase}${url}`, + crossOrigin: 'anonymous', + } + } + + return { href: `${cdnBase}${url}` } }, cache: false, }, @@ -110,34 +166,43 @@ export default createServerEntry({ fetch: handler }) The object form accepts: -| Property | Type | Description | -| ----------------- | -------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | -| `transform` | `string \| (asset) => string \| Promise` | A string prefix or callback, same as the shorthand forms above. | -| `createTransform` | `(ctx: { warmup: true } \| { warmup: false; request: Request }) => (asset) => string \| Promise` | Async factory that runs once per manifest computation and returns a per-asset transform. Mutually exclusive with `transform`. | -| `cache` | `boolean` | Whether to cache the transformed manifest. Defaults to `true`. | -| `warmup` | `boolean` | When `true`, warms up the cached manifest on server startup (prod only). Defaults to `false`. | +| Property | Type | Description | +| ----------------- | ------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | +| `transform` | `string \| (asset) => string \| { href, crossOrigin? } \| Promise<...>` | A string prefix or callback, same as the shorthand forms above. | +| `createTransform` | `(ctx: { warmup: true } \| { warmup: false; request: Request }) => (asset) => string \| { href, crossOrigin? } \| Promise<...>` | Async factory that runs once per manifest computation and returns a per-asset transform. Mutually exclusive with `transform`. | +| `cache` | `boolean` | Whether to cache the transformed manifest. Defaults to `true`. | +| `warmup` | `boolean` | When `true`, warms up the cached manifest on server startup (prod only). Defaults to `false`. | If you need to do async work once per manifest computation (e.g. fetch a CDN origin from a service) and then transform many URLs, prefer `createTransform`: ```ts -transformAssetUrls: { +transformAssets: { cache: false, async createTransform(ctx) { if (ctx.warmup) { - // optional: return a default transform during warmup - return ({ url }) => url + return ({ url }) => ({ href: url }) } const region = ctx.request.headers.get('x-region') || 'us' const cdnBase = await fetchCdnBaseForRegion(region) - return ({ url }) => `${cdnBase}${url}` + + return ({ kind, url }) => { + if (kind === 'modulepreload') { + return { + href: `${cdnBase}${url}`, + crossOrigin: 'anonymous', + } + } + + return { href: `${cdnBase}${url}` } + } }, } ``` ## Caching Behavior -By default, **all forms** of `transformAssetUrls` cache the transformed manifest after the first request (`cache: true`). This means the transform function runs once on the first request, and the result is reused for every subsequent request in production. +By default, all forms of `transformAssets` cache the transformed manifest after the first request (`cache: true`). This means the transform function runs once on the first request, and the result is reused for every subsequent request in production. | Form | Default cache | Behavior | | -------------------------------------- | ------------- | ---------------------------------------------------------- | @@ -154,7 +219,7 @@ If you're using the object form with `cache: true`, you can set `warmup: true` to compute the transformed manifest in the background at server startup. ```ts -transformAssetUrls: { +transformAssets: { transform: process.env.CDN_ORIGIN || '', cache: true, warmup: true, @@ -165,11 +230,34 @@ This has no effect in development mode, or when `cache: false`. > **Note:** In development mode (`TSS_DEV_SERVER`), caching is always skipped regardless of the `cache` setting, so you always get fresh manifests. +## With `HeadContent assetCrossOrigin` + +If you want to set cross-origin behavior from the app shell instead of the server entry, `HeadContent` also accepts `assetCrossOrigin`: + +```tsx + +``` + +or: + +```tsx + +``` + +If both `transformAssets` and `assetCrossOrigin` set a cross-origin value, `assetCrossOrigin` overrides the value from `transformAssets`. + +`assetCrossOrigin` only applies to manifest-managed `modulepreload` and stylesheet links, not arbitrary links you return from route `head()` functions. + ## Recommended: Set `base: ''` for Client-Side Navigation -`transformAssetUrls` rewrites the URLs in the SSR HTML — modulepreload hints, stylesheets, and the client entry script. This means the browser's initial page load fetches all assets from the CDN. +`transformAssets` rewrites the URLs in the SSR HTML - modulepreload hints, stylesheets, and the client entry script. This means the browser's initial page load fetches all assets from the CDN. -However, when users navigate client-side (e.g., clicking a ``), TanStack Router lazy-loads route chunks using `import()` calls with paths that were baked in at **build time** by Vite. By default, Vite uses `base: '/'`, which produces absolute paths like `/assets/about-abc123.js`. These resolve against the **app server's origin**, not the CDN — even though the entry module was loaded from the CDN. +However, when users navigate client-side (e.g., clicking a ``), TanStack Router lazy-loads route chunks using `import()` calls with paths that were baked in at build time by Vite. By default, Vite uses `base: '/'`, which produces absolute paths like `/assets/about-abc123.js`. These resolve against the app server's origin, not the CDN - even though the entry module was loaded from the CDN. To fix this, set `base: ''` in your Vite config: @@ -181,29 +269,29 @@ export default defineConfig({ }) ``` -With `base: ''`, Vite generates **relative** import paths for client-side chunks. Since the client entry module was loaded from the CDN (thanks to `transformAssetUrls`), all relative `import()` calls resolve against the CDN origin. This ensures that lazy-loaded route chunks during client-side navigation are also served from the CDN. +With `base: ''`, Vite generates relative import paths for client-side chunks. Since the client entry module was loaded from the CDN (thanks to `transformAssets`), all relative `import()` calls resolve against the CDN origin. This ensures that lazy-loaded route chunks during client-side navigation are also served from the CDN. -Using an empty string rather than `'./'` is important — both produce relative client-side imports, but `base: ''` preserves the correct root-relative paths (`/assets/...`) in the SSR manifest so that `transformAssetUrls` can properly prepend the CDN origin. +Using an empty string rather than `'./'` is important - both produce relative client-side imports, but `base: ''` preserves the correct root-relative paths (`/assets/...`) in the SSR manifest so that `transformAssets` can properly prepend the CDN origin. -| `base` setting | SSR assets (initial load) | Client-side navigation chunks | -| --------------- | ------------------------------ | ------------------------------ | -| `'/'` (default) | CDN (via `transformAssetUrls`) | App server | -| `''` | CDN (via `transformAssetUrls`) | CDN (relative to entry module) | +| `base` setting | SSR assets (initial load) | Client-side navigation chunks | +| --------------- | --------------------------- | ------------------------------ | +| `'/'` (default) | CDN (via `transformAssets`) | App server | +| `''` | CDN (via `transformAssets`) | CDN (relative to entry module) | -> **Tip:** `base: ''` is recommended whenever you use `transformAssetUrls` so that all assets — both on initial load and during client-side navigation — are consistently served from the CDN. +> **Tip:** `base: ''` is recommended whenever you use `transformAssets` so that all assets - both on initial load and during client-side navigation - are consistently served from the CDN. -## What This Does NOT Cover +## What This Does Not Cover -`transformAssetUrls` only rewrites URLs in the TanStack Start manifest — the tags emitted during SSR for preloading and bootstrapping the application. +`transformAssets` only rewrites URLs in the TanStack Start manifest - the tags emitted during SSR for preloading and bootstrapping the application. -It does **not** rewrite asset URLs that are imported directly in your components: +It does not rewrite asset URLs imported directly in your components: ```tsx // This import resolves to a URL at build time by Vite import logo from './logo.svg' function Header() { - return // This URL is NOT affected by transformAssetUrls + return // This URL is NOT affected by transformAssets } ``` diff --git a/docs/start/framework/react/guide/hosting.md b/docs/start/framework/react/guide/hosting.md index e66a430f355..26e2e0db663 100644 --- a/docs/start/framework/react/guide/hosting.md +++ b/docs/start/framework/react/guide/hosting.md @@ -190,8 +190,8 @@ tool](https://docs.netlify.com/start/quickstarts/deploy-from-ai-code-generation- - - + + Railway logo diff --git a/docs/start/framework/react/migrate-from-next-js.md b/docs/start/framework/react/migrate-from-next-js.md index ea82a4e8503..35173607431 100644 --- a/docs/start/framework/react/migrate-from-next-js.md +++ b/docs/start/framework/react/migrate-from-next-js.md @@ -52,16 +52,16 @@ rm postcss.config.* next.config.* ### 2. Install Required Dependencies -TanStack Start leverages [Vite](https://vite.dev) and TanStack Router: +TanStack Start leverages Tanstack Router, [Vite](https://vite.dev), and a vite deployment plugin e.g. [nitro](https://nitro.build/). ```sh -npm i @tanstack/react-router @tanstack/react-start +npm i @tanstack/react-router @tanstack/react-start nitro vite @vitejs/plugin-react ``` -For Tailwind CSS and resolving imports using path aliases: +For Tailwind CSS: ```sh -npm i -D vite @vitejs/plugin-react @tailwindcss/vite tailwindcss vite-tsconfig-paths +npm i -D @tailwindcss/vite tailwindcss ``` ### 3. Update Project Configuration @@ -88,17 +88,19 @@ Now that you've installed the necessary dependencies, update your project config import { defineConfig } from 'vite' import { tanstackStart } from '@tanstack/react-start/plugin/vite' import viteReact from '@vitejs/plugin-react' -import tsconfigPaths from 'vite-tsconfig-paths' import tailwindcss from '@tailwindcss/vite' +import { nitro } from 'nitro/vite' export default defineConfig({ server: { port: 3000, }, + resolve: { + // Enables Vite to resolve imports using path aliases. + tsconfigPaths: true, + }, plugins: [ tailwindcss(), - // Enables Vite to resolve imports using path aliases. - tsconfigPaths(), tanstackStart({ srcDirectory: 'src', // This is the default router: { @@ -107,6 +109,7 @@ export default defineConfig({ }, }), viteReact(), + nitro(), ], }) ``` diff --git a/e2e/react-router/basepath-file-based/tests/scroll-restoration-session-storage-error.test.ts b/e2e/react-router/basepath-file-based/tests/scroll-restoration-session-storage-error.test.ts index ab0bb4bc993..06b90f6528f 100644 --- a/e2e/react-router/basepath-file-based/tests/scroll-restoration-session-storage-error.test.ts +++ b/e2e/react-router/basepath-file-based/tests/scroll-restoration-session-storage-error.test.ts @@ -1,25 +1,10 @@ /* eslint-disable */ import { expect, test } from '@playwright/test' -import type { Page } from '@playwright/test' - -const trackConsole = (page: Page) => { - const consoleWarnings: Array = [] - - page.on('console', (msg) => { - if (msg.type() === 'warning') { - consoleWarnings.push(msg.text()) - } - }) - - return consoleWarnings -} test.describe('Scroll Restoration with Session Storage Error', () => { test('should not crash when sessionStorage.setItem throws an error', async ({ page, }) => { - const consoleWarnings = trackConsole(page) - await page.goto('/app/scroll-error') await page.waitForLoadState('networkidle') @@ -32,20 +17,9 @@ test.describe('Scroll Restoration with Session Storage Error', () => { await page.evaluate(() => window.scrollTo(0, 200)) await page.waitForTimeout(150) - await page.click('a[href="/app/about"]') - await page.waitForLoadState('networkidle') - - await page.goBack() + await page.reload() await page.waitForLoadState('networkidle') - expect( - consoleWarnings.some((warning) => - warning.includes( - '[ts-router] Could not persist scroll restoration state to sessionStorage.', - ), - ), - ).toBeTruthy() - const heading = page.locator('h1:has-text("Scroll Error Test")') await expect(heading).toBeVisible() @@ -53,11 +27,9 @@ test.describe('Scroll Restoration with Session Storage Error', () => { expect(scrollPosition).not.toBe(200) }) - test('should surface warning when sessionStorage quota is exceeded', async ({ + test('should not crash when sessionStorage quota is exceeded', async ({ page, }) => { - const consoleWarnings = trackConsole(page) - await page.goto('/app/scroll-error') await page.waitForLoadState('networkidle') @@ -78,20 +50,9 @@ test.describe('Scroll Restoration with Session Storage Error', () => { await page.evaluate(() => window.scrollTo(0, 200)) await page.waitForTimeout(150) - await page.click('a[href="/app/about"]') + await page.reload() await page.waitForLoadState('networkidle') - await page.goBack() - await page.waitForLoadState('networkidle') - - expect( - consoleWarnings.some((warning) => - warning.includes( - '[ts-router] Could not persist scroll restoration state to sessionStorage.', - ), - ), - ).toBeTruthy() - const heading = page.locator('h1:has-text("Scroll Error Test")') await expect(heading).toBeVisible() diff --git a/e2e/react-router/basic-file-based-code-splitting/src/vite-env.d.ts b/e2e/react-router/basic-file-based-code-splitting/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/basic-file-based-code-splitting/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/basic-file-based/src/vite-env.d.ts b/e2e/react-router/basic-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/basic-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/basic-react-query-file-based/src/vite-env.d.ts b/e2e/react-router/basic-react-query-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/basic-react-query-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/basic-react-query/src/vite-env.d.ts b/e2e/react-router/basic-react-query/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/basic-react-query/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/basic-scroll-restoration/package.json b/e2e/react-router/basic-scroll-restoration/package.json index 2d6ab9dd36a..d9a76d8f030 100644 --- a/e2e/react-router/basic-scroll-restoration/package.json +++ b/e2e/react-router/basic-scroll-restoration/package.json @@ -26,6 +26,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "vite": "^8.0.0" + "vite": "^8.0.0", + "typescript": "~5.9.0" } } diff --git a/e2e/react-router/basic-scroll-restoration/src/vite-env.d.ts b/e2e/react-router/basic-scroll-restoration/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/basic-scroll-restoration/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/basic-virtual-file-based/src/vite-env.d.ts b/e2e/react-router/basic-virtual-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/basic-virtual-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/basic-virtual-named-export-config-file-based/src/vite-env.d.ts b/e2e/react-router/basic-virtual-named-export-config-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/basic-virtual-named-export-config-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/basic/src/vite-env.d.ts b/e2e/react-router/basic/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/basic/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/generator-cli-only/src/vite-env.d.ts b/e2e/react-router/generator-cli-only/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/generator-cli-only/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/i18n-paraglide/package.json b/e2e/react-router/i18n-paraglide/package.json index 1d4f8d0b4c8..0316269242c 100644 --- a/e2e/react-router/i18n-paraglide/package.json +++ b/e2e/react-router/i18n-paraglide/package.json @@ -26,7 +26,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/e2e/react-router/i18n-paraglide/src/vite-env.d.ts b/e2e/react-router/i18n-paraglide/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/i18n-paraglide/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/js-only-file-based/src/vite-env.d.ts b/e2e/react-router/js-only-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/js-only-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/rspack-basic-file-based/package.json b/e2e/react-router/rspack-basic-file-based/package.json index e276a82cf1d..743a3042f62 100644 --- a/e2e/react-router/rspack-basic-file-based/package.json +++ b/e2e/react-router/rspack-basic-file-based/package.json @@ -27,6 +27,6 @@ "@types/react-dom": "^19.0.3", "postcss": "^8.5.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-router/rspack-basic-file-based/src/vite-env.d.ts b/e2e/react-router/rspack-basic-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/rspack-basic-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/rspack-basic-file-based/tsconfig.json b/e2e/react-router/rspack-basic-file-based/tsconfig.json index 76f578eb540..2f5f67eac71 100644 --- a/e2e/react-router/rspack-basic-file-based/tsconfig.json +++ b/e2e/react-router/rspack-basic-file-based/tsconfig.json @@ -12,6 +12,6 @@ "useDefineForClassFields": true, "allowJs": true }, - "include": ["src", "playwright.config.ts", "tests"], + "include": ["src", "tests"], "exclude": ["node_modules", "dist"] } diff --git a/e2e/react-router/rspack-basic-virtual-named-export-config-file-based/package.json b/e2e/react-router/rspack-basic-virtual-named-export-config-file-based/package.json index d4ca0606f1c..ad6d498d6a0 100644 --- a/e2e/react-router/rspack-basic-virtual-named-export-config-file-based/package.json +++ b/e2e/react-router/rspack-basic-virtual-named-export-config-file-based/package.json @@ -28,6 +28,6 @@ "@types/react-dom": "^19.0.3", "postcss": "^8.5.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-router/rspack-basic-virtual-named-export-config-file-based/src/vite-env.d.ts b/e2e/react-router/rspack-basic-virtual-named-export-config-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/rspack-basic-virtual-named-export-config-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/rspack-basic-virtual-named-export-config-file-based/tsconfig.json b/e2e/react-router/rspack-basic-virtual-named-export-config-file-based/tsconfig.json index 7dc6d51cf90..a32f07a8efd 100644 --- a/e2e/react-router/rspack-basic-virtual-named-export-config-file-based/tsconfig.json +++ b/e2e/react-router/rspack-basic-virtual-named-export-config-file-based/tsconfig.json @@ -12,6 +12,6 @@ "useDefineForClassFields": true, "allowJs": true }, - "include": ["src", "playwright.config.ts", "tests", "./routes.ts"], + "include": ["src", "tests", "./routes.ts"], "exclude": ["node_modules", "dist"] } diff --git a/e2e/react-router/scroll-restoration-sandbox-vite/src/routeTree.gen.ts b/e2e/react-router/scroll-restoration-sandbox-vite/src/routeTree.gen.ts index 6664a9ddf75..a4dc8750b34 100644 --- a/e2e/react-router/scroll-restoration-sandbox-vite/src/routeTree.gen.ts +++ b/e2e/react-router/scroll-restoration-sandbox-vite/src/routeTree.gen.ts @@ -16,6 +16,8 @@ import { Route as testsPageWithSearchRouteImport } from './routes/(tests)/page-w import { Route as testsNormalPageRouteImport } from './routes/(tests)/normal-page' import { Route as testsLazyWithLoaderPageRouteImport } from './routes/(tests)/lazy-with-loader-page' import { Route as testsLazyPageRouteImport } from './routes/(tests)/lazy-page' +import { Route as testsIssue7040TargetRouteImport } from './routes/(tests)/issue-7040-target' +import { Route as testsIssue7040SourceRouteImport } from './routes/(tests)/issue-7040-source' const testsVirtualPageLazyRouteImport = createFileRoute( '/(tests)/virtual-page', @@ -59,9 +61,21 @@ const testsLazyPageRoute = testsLazyPageRouteImport getParentRoute: () => rootRouteImport, } as any) .lazy(() => import('./routes/(tests)/lazy-page.lazy').then((d) => d.Route)) +const testsIssue7040TargetRoute = testsIssue7040TargetRouteImport.update({ + id: '/(tests)/issue-7040-target', + path: '/issue-7040-target', + getParentRoute: () => rootRouteImport, +} as any) +const testsIssue7040SourceRoute = testsIssue7040SourceRouteImport.update({ + id: '/(tests)/issue-7040-source', + path: '/issue-7040-source', + getParentRoute: () => rootRouteImport, +} as any) export interface FileRoutesByFullPath { '/': typeof IndexRoute + '/issue-7040-source': typeof testsIssue7040SourceRoute + '/issue-7040-target': typeof testsIssue7040TargetRoute '/lazy-page': typeof testsLazyPageRoute '/lazy-with-loader-page': typeof testsLazyWithLoaderPageRoute '/normal-page': typeof testsNormalPageRoute @@ -70,6 +84,8 @@ export interface FileRoutesByFullPath { } export interface FileRoutesByTo { '/': typeof IndexRoute + '/issue-7040-source': typeof testsIssue7040SourceRoute + '/issue-7040-target': typeof testsIssue7040TargetRoute '/lazy-page': typeof testsLazyPageRoute '/lazy-with-loader-page': typeof testsLazyWithLoaderPageRoute '/normal-page': typeof testsNormalPageRoute @@ -79,6 +95,8 @@ export interface FileRoutesByTo { export interface FileRoutesById { __root__: typeof rootRouteImport '/': typeof IndexRoute + '/(tests)/issue-7040-source': typeof testsIssue7040SourceRoute + '/(tests)/issue-7040-target': typeof testsIssue7040TargetRoute '/(tests)/lazy-page': typeof testsLazyPageRoute '/(tests)/lazy-with-loader-page': typeof testsLazyWithLoaderPageRoute '/(tests)/normal-page': typeof testsNormalPageRoute @@ -89,6 +107,8 @@ export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath fullPaths: | '/' + | '/issue-7040-source' + | '/issue-7040-target' | '/lazy-page' | '/lazy-with-loader-page' | '/normal-page' @@ -97,6 +117,8 @@ export interface FileRouteTypes { fileRoutesByTo: FileRoutesByTo to: | '/' + | '/issue-7040-source' + | '/issue-7040-target' | '/lazy-page' | '/lazy-with-loader-page' | '/normal-page' @@ -105,6 +127,8 @@ export interface FileRouteTypes { id: | '__root__' | '/' + | '/(tests)/issue-7040-source' + | '/(tests)/issue-7040-target' | '/(tests)/lazy-page' | '/(tests)/lazy-with-loader-page' | '/(tests)/normal-page' @@ -114,6 +138,8 @@ export interface FileRouteTypes { } export interface RootRouteChildren { IndexRoute: typeof IndexRoute + testsIssue7040SourceRoute: typeof testsIssue7040SourceRoute + testsIssue7040TargetRoute: typeof testsIssue7040TargetRoute testsLazyPageRoute: typeof testsLazyPageRoute testsLazyWithLoaderPageRoute: typeof testsLazyWithLoaderPageRoute testsNormalPageRoute: typeof testsNormalPageRoute @@ -165,11 +191,27 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof testsLazyPageRouteImport parentRoute: typeof rootRouteImport } + '/(tests)/issue-7040-target': { + id: '/(tests)/issue-7040-target' + path: '/issue-7040-target' + fullPath: '/issue-7040-target' + preLoaderRoute: typeof testsIssue7040TargetRouteImport + parentRoute: typeof rootRouteImport + } + '/(tests)/issue-7040-source': { + id: '/(tests)/issue-7040-source' + path: '/issue-7040-source' + fullPath: '/issue-7040-source' + preLoaderRoute: typeof testsIssue7040SourceRouteImport + parentRoute: typeof rootRouteImport + } } } const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, + testsIssue7040SourceRoute: testsIssue7040SourceRoute, + testsIssue7040TargetRoute: testsIssue7040TargetRoute, testsLazyPageRoute: testsLazyPageRoute, testsLazyWithLoaderPageRoute: testsLazyWithLoaderPageRoute, testsNormalPageRoute: testsNormalPageRoute, diff --git a/e2e/react-router/scroll-restoration-sandbox-vite/src/routes/(tests)/issue-7040-source.tsx b/e2e/react-router/scroll-restoration-sandbox-vite/src/routes/(tests)/issue-7040-source.tsx new file mode 100644 index 00000000000..3c1702a942a --- /dev/null +++ b/e2e/react-router/scroll-restoration-sandbox-vite/src/routes/(tests)/issue-7040-source.tsx @@ -0,0 +1,49 @@ +import * as React from 'react' +import { Link, createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/(tests)/issue-7040-source')({ + component: Component, +}) + +const sectionCount = 180 + +function Component() { + return ( +
+
+

issue-7040-source

+

+ Tall page for reproducing the scroll restoration race. +

+
+ + + Go to issue-7040-target + + +
+ {Array.from({ length: sectionCount }).map((_, index) => ( +
+

Section {index + 1}

+

+ This section adds vertical space so the page can be scrolled far + enough to reproduce issue #7040. +

+
+ ))} +
+ +
+ Bottom of issue-7040-source +
+
+ ) +} diff --git a/e2e/react-router/scroll-restoration-sandbox-vite/src/routes/(tests)/issue-7040-target.tsx b/e2e/react-router/scroll-restoration-sandbox-vite/src/routes/(tests)/issue-7040-target.tsx new file mode 100644 index 00000000000..df541c6dbb0 --- /dev/null +++ b/e2e/react-router/scroll-restoration-sandbox-vite/src/routes/(tests)/issue-7040-target.tsx @@ -0,0 +1,40 @@ +import * as React from 'react' +import { createFileRoute } from '@tanstack/react-router' +import { sleep } from '../../posts' + +export const Route = createFileRoute('/(tests)/issue-7040-target')({ + loader: async () => { + await sleep(250) + return null + }, + component: Component, +}) + +function Component() { + return ( +
+
+

issue-7040-target

+

+ Short page that should reset to top on navigation. +

+
+ +
+ {Array.from({ length: 18 }).map((_, index) => ( +
+

Target section {index + 1}

+

This page is intentionally much shorter than the source page.

+
+ ))} +
+ +
+ Bottom of issue-7040-target +
+
+ ) +} diff --git a/e2e/react-router/scroll-restoration-sandbox-vite/src/routes/__root.tsx b/e2e/react-router/scroll-restoration-sandbox-vite/src/routes/__root.tsx index 18726e1168a..ed80300a68b 100644 --- a/e2e/react-router/scroll-restoration-sandbox-vite/src/routes/__root.tsx +++ b/e2e/react-router/scroll-restoration-sandbox-vite/src/routes/__root.tsx @@ -45,6 +45,8 @@ function Nav({ type }: { type: 'header' | 'footer' }) { linkOptions({ to: '/virtual-page' }), linkOptions({ to: '/lazy-with-loader-page' }), linkOptions({ to: '/page-with-search', search: { where: type } }), + linkOptions({ to: '/issue-7040-source' }), + linkOptions({ to: '/issue-7040-target' }), ] as const ).map((options, i) => ( {( [ + linkOptions({ to: '/issue-7040-source' }), + linkOptions({ to: '/issue-7040-target' }), linkOptions({ to: '/normal-page' }), linkOptions({ to: '/lazy-page' }), linkOptions({ to: '/virtual-page' }), diff --git a/e2e/react-router/scroll-restoration-sandbox-vite/src/vite-env.d.ts b/e2e/react-router/scroll-restoration-sandbox-vite/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/scroll-restoration-sandbox-vite/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/scroll-restoration-sandbox-vite/tests/app.spec.ts b/e2e/react-router/scroll-restoration-sandbox-vite/tests/app.spec.ts index 6b598426252..f72d2d06abd 100644 --- a/e2e/react-router/scroll-restoration-sandbox-vite/tests/app.spec.ts +++ b/e2e/react-router/scroll-restoration-sandbox-vite/tests/app.spec.ts @@ -9,6 +9,67 @@ test('Smoke - Renders home', async ({ page }) => { ).toBeVisible() }) +test('restores the prior scroll position after browser back then forward', async ({ + page, +}) => { + await page.goto(toRuntimePath('/')) + await page.getByRole('link', { name: 'Head-/normal-page' }).click() + await page.waitForURL('**/normal-page') + await expect(page.getByTestId('at-the-top')).toBeInViewport() + + const scrollY = await page.evaluate(async () => { + window.scrollTo(0, document.documentElement.scrollHeight) + await new Promise((resolve) => requestAnimationFrame(() => resolve(null))) + return window.scrollY + }) + + expect(scrollY).toBeGreaterThan(0) + await expect(page.getByTestId('at-the-bottom')).toBeInViewport() + + await page.goBack() + await expect( + page.getByRole('heading', { name: 'Welcome Home!' }), + ).toBeVisible() + + await page.goForward() + await page.waitForURL('**/normal-page') + await page.waitForFunction( + (expectedScrollY) => Math.abs(window.scrollY - expectedScrollY) <= 2, + scrollY, + ) + await expect(page.getByTestId('at-the-bottom')).toBeInViewport() +}) + +test('restores the prior scroll position after browser back navigation', async ({ + page, +}) => { + await page.goto(toRuntimePath('/normal-page')) + await expect(page.getByTestId('at-the-top')).toBeInViewport() + + const scrollY = await page.evaluate(async () => { + window.scrollTo(0, document.documentElement.scrollHeight) + await new Promise((resolve) => requestAnimationFrame(() => resolve(null))) + return window.scrollY + }) + + expect(scrollY).toBeGreaterThan(0) + await expect(page.getByTestId('at-the-bottom')).toBeInViewport() + + await page.getByRole('link', { name: 'Foot-/', exact: true }).click() + await page.waitForURL('**/') + await expect( + page.getByRole('heading', { name: 'Welcome Home!' }), + ).toBeVisible() + + await page.goBack() + await page.waitForURL('**/normal-page') + await page.waitForFunction( + (expectedScrollY) => Math.abs(window.scrollY - expectedScrollY) <= 2, + scrollY, + ) + await expect(page.getByTestId('at-the-bottom')).toBeInViewport() +}) + const pages = [ linkOptions({ to: '/normal-page' }), linkOptions({ to: '/lazy-page' }), diff --git a/e2e/react-router/scroll-restoration-sandbox-vite/tests/issue-7040.repro.spec.ts b/e2e/react-router/scroll-restoration-sandbox-vite/tests/issue-7040.repro.spec.ts new file mode 100644 index 00000000000..db335f8e2ea --- /dev/null +++ b/e2e/react-router/scroll-restoration-sandbox-vite/tests/issue-7040.repro.spec.ts @@ -0,0 +1,151 @@ +import { expect, test } from '@playwright/test' +import type { Page } from '@playwright/test' +import { toRuntimePath } from '@tanstack/router-e2e-utils' + +const attemptCount = 3 +const sourceScrollTargetY = 6000 +const fastScrollStepPx = 220 +const fastScrollDelayMs = 3 +const maxFastScrollSteps = 80 +const preClickReverseScrollPx = 60 + +type ReproAttempt = { + attempt: number + before: { + sourceKey: string + sourceScrollY: number + sourceHeight: number + } + after: { + destinationKey: string + destinationScrollY: number + destinationHeight: number + destinationMaxScrollY: number + } +} + +async function openFreshSourcePage(page: Page) { + await page.goto(toRuntimePath('/issue-7040-source')) + await page.waitForLoadState('networkidle') + + await page.evaluate(() => { + sessionStorage.clear() + window.scrollTo(0, 0) + }) + + await page.reload() + await page.waitForLoadState('networkidle') +} + +async function fastScrollSourcePage(page: Page) { + await page.evaluate( + async ({ targetScrollY, stepPx, stepDelayMs, maxSteps }) => { + const sleep = (ms: number) => + new Promise((resolve) => setTimeout(resolve, ms)) + + window.scrollTo(0, 0) + + let steps = 0 + + while (window.scrollY < targetScrollY && steps < maxSteps) { + window.scrollBy(0, stepPx) + steps += 1 + await sleep(stepDelayMs) + } + + if (window.scrollY < targetScrollY) { + throw new Error( + `Could not reach source scroll target ${targetScrollY}; got ${window.scrollY}`, + ) + } + }, + { + targetScrollY: sourceScrollTargetY, + stepPx: fastScrollStepPx, + stepDelayMs: fastScrollDelayMs, + maxSteps: maxFastScrollSteps, + }, + ) +} + +async function clickTargetLinkImmediatelyAfterScroll(page: Page) { + await page.evaluate( + ({ reverseScrollPx }) => { + const link = document.querySelector( + '[data-testid="issue-7040-target-link"]', + ) + + if (!(link instanceof HTMLAnchorElement)) { + throw new Error('issue-7040 target link not found') + } + + // Trigger one more browser scroll update immediately before navigation + // so the test stays focused on the stale-scroll race. + window.scrollBy(0, -reverseScrollPx) + link.dispatchEvent( + new MouseEvent('click', { + bubbles: true, + cancelable: true, + view: window, + }), + ) + }, + { reverseScrollPx: preClickReverseScrollPx }, + ) +} + +async function waitForTargetPageToSettle(page: Page) { + await page.waitForURL('**/issue-7040-target') + await page.waitForLoadState('networkidle') + await page.waitForFunction(() => window.scrollY === 0) +} + +test('Issue #7040 repro: fast scroll then click can restore target below top', async ({ + page, +}) => { + const attempts: Array = [] + + for (let attempt = 0; attempt < attemptCount; attempt++) { + await openFreshSourcePage(page) + await fastScrollSourcePage(page) + + const before = await page.evaluate(() => { + return { + sourceKey: window.history.state.__TSR_key, + sourceScrollY: window.scrollY, + sourceHeight: document.documentElement.scrollHeight, + } + }) + + await clickTargetLinkImmediatelyAfterScroll(page) + await waitForTargetPageToSettle(page) + + const after = await page.evaluate(() => { + return { + destinationKey: window.history.state.__TSR_key, + destinationScrollY: window.scrollY, + destinationHeight: document.documentElement.scrollHeight, + destinationMaxScrollY: + document.documentElement.scrollHeight - window.innerHeight, + } + }) + + attempts.push({ attempt, before, after }) + } + + for (const attempt of attempts) { + expect(attempt.before.sourceHeight).toBeGreaterThan(15000) + expect(attempt.before.sourceScrollY).toBeGreaterThan(sourceScrollTargetY) + expect(attempt.before.sourceKey).not.toBe(attempt.after.destinationKey) + expect(attempt.before.sourceScrollY).toBeGreaterThan( + attempt.after.destinationMaxScrollY, + ) + expect(attempt.after.destinationHeight).toBeLessThan( + attempt.before.sourceHeight, + ) + expect(attempt.after.destinationScrollY).toBe(0) + expect(attempt.after.destinationScrollY).toBeLessThanOrEqual( + attempt.after.destinationMaxScrollY, + ) + } +}) diff --git a/e2e/react-router/sentry-integration/src/vite-env.d.ts b/e2e/react-router/sentry-integration/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/sentry-integration/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-router/view-transitions/package.json b/e2e/react-router/view-transitions/package.json index bfba8a5de74..4fa6a2dde61 100644 --- a/e2e/react-router/view-transitions/package.json +++ b/e2e/react-router/view-transitions/package.json @@ -27,7 +27,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/e2e/react-router/view-transitions/src/vite-env.d.ts b/e2e/react-router/view-transitions/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-router/view-transitions/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-start/basic-auth/package.json b/e2e/react-start/basic-auth/package.json index e00c3fd2a20..0dd1a6a642d 100644 --- a/e2e/react-start/basic-auth/package.json +++ b/e2e/react-start/basic-auth/package.json @@ -36,6 +36,6 @@ "dotenv": "^17.2.3", "prisma": "^7.0.0", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/basic-auth/tsconfig.json b/e2e/react-start/basic-auth/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/basic-auth/tsconfig.json +++ b/e2e/react-start/basic-auth/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/basic-cloudflare/package.json b/e2e/react-start/basic-cloudflare/package.json index d0e0d42d5a0..f7257697811 100644 --- a/e2e/react-start/basic-cloudflare/package.json +++ b/e2e/react-start/basic-cloudflare/package.json @@ -29,7 +29,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "wrangler": "^4.74.0" } diff --git a/e2e/react-start/basic-cloudflare/tsconfig.json b/e2e/react-start/basic-cloudflare/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/basic-cloudflare/tsconfig.json +++ b/e2e/react-start/basic-cloudflare/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/basic-prerender/.gitignore b/e2e/react-start/basic-prerender/.gitignore new file mode 100644 index 00000000000..6381bf3860f --- /dev/null +++ b/e2e/react-start/basic-prerender/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/test-results/ +/playwright-report/ +/blob-report/ diff --git a/e2e/react-start/basic-prerender/package.json b/e2e/react-start/basic-prerender/package.json new file mode 100644 index 00000000000..415e0f47395 --- /dev/null +++ b/e2e/react-start/basic-prerender/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-react-start-e2e-basic-prerender", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "test:e2e:startDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.setup.ts\").then(m => m.default())' & node -e 'import(\"../basic-test-suite/src/setup/waitForDummyServer.ts\").then(m => m.default())'", + "test:e2e:stopDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.teardown.ts\").then(m => m.default())'", + "test:e2e": "rm -rf port*.txt; MODE=prerender playwright test --project=chromium" + }, + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tanstack/router-e2e-utils": "workspace:^", + "tanstack-react-start-e2e-basic": "workspace:*", + "tanstack-react-start-e2e-basic-test-suite": "workspace:*" + }, + "nx": { + "targets": { + "test:e2e": { + "parallelism": false + } + } + } +} diff --git a/e2e/react-start/basic-prerender/playwright.config.ts b/e2e/react-start/basic-prerender/playwright.config.ts new file mode 100644 index 00000000000..cf2cf5d396e --- /dev/null +++ b/e2e/react-start/basic-prerender/playwright.config.ts @@ -0,0 +1,48 @@ +import { defineConfig, devices } from '@playwright/test' +import { + getDummyServerPort, + getTestServerPort, +} from '@tanstack/router-e2e-utils' +import packageJson from './package.json' with { type: 'json' } + +const PORT = await getTestServerPort(packageJson.name) +const START_PORT = await getTestServerPort(`${packageJson.name}_start`) +const EXTERNAL_PORT = await getDummyServerPort(packageJson.name) +const baseURL = `http://localhost:${PORT}` + +export default defineConfig({ + testDir: '../basic-test-suite/src', + workers: 1, + reporter: [['line']], + + globalTeardown: '../basic-test-suite/src/setup/global.teardown.ts', + + use: { + baseURL, + }, + + webServer: { + command: + 'pnpm run test:e2e:startDummyServer && pnpm --dir ../basic build:prerender && pnpm --dir ../basic start', + url: baseURL, + reuseExistingServer: !process.env.CI, + stdout: 'pipe', + env: { + MODE: 'prerender', + VITE_NODE_ENV: 'test', + VITE_EXTERNAL_PORT: String(EXTERNAL_PORT), + VITE_SERVER_PORT: String(PORT), + START_PORT: String(START_PORT), + PORT: String(PORT), + }, + }, + + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + }, + }, + ], +}) diff --git a/e2e/react-start/basic-preview/.gitignore b/e2e/react-start/basic-preview/.gitignore new file mode 100644 index 00000000000..6381bf3860f --- /dev/null +++ b/e2e/react-start/basic-preview/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/test-results/ +/playwright-report/ +/blob-report/ diff --git a/e2e/react-start/basic-preview/package.json b/e2e/react-start/basic-preview/package.json new file mode 100644 index 00000000000..ba24e8a41a8 --- /dev/null +++ b/e2e/react-start/basic-preview/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-react-start-e2e-basic-preview", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "test:e2e:startDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.setup.ts\").then(m => m.default())' & node -e 'import(\"../basic-test-suite/src/setup/waitForDummyServer.ts\").then(m => m.default())'", + "test:e2e:stopDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.teardown.ts\").then(m => m.default())'", + "test:e2e": "rm -rf port*.txt; MODE=preview playwright test --project=chromium" + }, + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tanstack/router-e2e-utils": "workspace:^", + "tanstack-react-start-e2e-basic": "workspace:*", + "tanstack-react-start-e2e-basic-test-suite": "workspace:*" + }, + "nx": { + "targets": { + "test:e2e": { + "parallelism": false + } + } + } +} diff --git a/e2e/react-start/basic-preview/playwright.config.ts b/e2e/react-start/basic-preview/playwright.config.ts new file mode 100644 index 00000000000..071f336f9f1 --- /dev/null +++ b/e2e/react-start/basic-preview/playwright.config.ts @@ -0,0 +1,47 @@ +import { defineConfig, devices } from '@playwright/test' +import { + getDummyServerPort, + getTestServerPort, +} from '@tanstack/router-e2e-utils' +import packageJson from './package.json' with { type: 'json' } + +const PORT = await getTestServerPort(packageJson.name) +const START_PORT = await getTestServerPort(`${packageJson.name}_start`) +const EXTERNAL_PORT = await getDummyServerPort(packageJson.name) +const baseURL = `http://localhost:${PORT}` + +export default defineConfig({ + testDir: '../basic-test-suite/src', + workers: 1, + reporter: [['line']], + + globalTeardown: '../basic-test-suite/src/setup/global.teardown.ts', + + use: { + baseURL, + }, + + webServer: { + command: `pnpm run test:e2e:startDummyServer && pnpm --dir ../basic build && pnpm --dir ../basic preview --port ${PORT}`, + url: baseURL, + reuseExistingServer: !process.env.CI, + stdout: 'pipe', + env: { + MODE: 'preview', + VITE_NODE_ENV: 'test', + VITE_EXTERNAL_PORT: String(EXTERNAL_PORT), + VITE_SERVER_PORT: String(PORT), + START_PORT: String(START_PORT), + PORT: String(PORT), + }, + }, + + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + }, + }, + ], +}) diff --git a/e2e/react-start/basic-react-query/package.json b/e2e/react-start/basic-react-query/package.json index 5335ebcd93b..86a22604d90 100644 --- a/e2e/react-start/basic-react-query/package.json +++ b/e2e/react-start/basic-react-query/package.json @@ -35,6 +35,6 @@ "@vitejs/plugin-react": "^6.0.1", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/basic-react-query/tsconfig.json b/e2e/react-start/basic-react-query/tsconfig.json index a07911fe5f4..c7a0597e4bf 100644 --- a/e2e/react-start/basic-react-query/tsconfig.json +++ b/e2e/react-start/basic-react-query/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/basic-rsc/package.json b/e2e/react-start/basic-rsc/package.json index 1785fe3c84e..7e94fd7b3ad 100644 --- a/e2e/react-start/basic-rsc/package.json +++ b/e2e/react-start/basic-rsc/package.json @@ -25,7 +25,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" }, "overrides": { "react": "0.0.0-experimental-035a41c4e-20230704", diff --git a/e2e/react-start/basic-rsc/src/routeTree.gen.ts b/e2e/react-start/basic-rsc/src/routeTree.gen.ts index 500f71a9f73..9bc5483f542 100644 --- a/e2e/react-start/basic-rsc/src/routeTree.gen.ts +++ b/e2e/react-start/basic-rsc/src/routeTree.gen.ts @@ -142,7 +142,7 @@ declare module '@tanstack/react-router' { '/_layout': { id: '/_layout' path: '' - fullPath: '' + fullPath: '/' preLoaderRoute: typeof LayoutRouteImport parentRoute: typeof rootRouteImport } @@ -170,7 +170,7 @@ declare module '@tanstack/react-router' { '/_layout/_layout-2': { id: '/_layout/_layout-2' path: '' - fullPath: '' + fullPath: '/' preLoaderRoute: typeof LayoutLayout2RouteImport parentRoute: typeof LayoutRoute } @@ -249,6 +249,7 @@ import type { getRouter } from './router.tsx' import type { createStart } from '@tanstack/react-start' declare module '@tanstack/react-start' { interface Register { + ssr: true router: Awaited> } } diff --git a/e2e/react-start/basic-rsc/tsconfig.json b/e2e/react-start/basic-rsc/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/basic-rsc/tsconfig.json +++ b/e2e/react-start/basic-rsc/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/basic-spa/.gitignore b/e2e/react-start/basic-spa/.gitignore new file mode 100644 index 00000000000..6381bf3860f --- /dev/null +++ b/e2e/react-start/basic-spa/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/test-results/ +/playwright-report/ +/blob-report/ diff --git a/e2e/react-start/basic-spa/package.json b/e2e/react-start/basic-spa/package.json new file mode 100644 index 00000000000..709ce8a0d6f --- /dev/null +++ b/e2e/react-start/basic-spa/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-react-start-e2e-basic-spa", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "test:e2e:startDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.setup.ts\").then(m => m.default())' & node -e 'import(\"../basic-test-suite/src/setup/waitForDummyServer.ts\").then(m => m.default())'", + "test:e2e:stopDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.teardown.ts\").then(m => m.default())'", + "test:e2e": "rm -rf port*.txt; MODE=spa playwright test --project=chromium" + }, + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tanstack/router-e2e-utils": "workspace:^", + "tanstack-react-start-e2e-basic": "workspace:*", + "tanstack-react-start-e2e-basic-test-suite": "workspace:*" + }, + "nx": { + "targets": { + "test:e2e": { + "parallelism": false + } + } + } +} diff --git a/e2e/react-start/basic-spa/playwright.config.ts b/e2e/react-start/basic-spa/playwright.config.ts new file mode 100644 index 00000000000..27e85e1f1a4 --- /dev/null +++ b/e2e/react-start/basic-spa/playwright.config.ts @@ -0,0 +1,48 @@ +import { defineConfig, devices } from '@playwright/test' +import { + getDummyServerPort, + getTestServerPort, +} from '@tanstack/router-e2e-utils' +import packageJson from './package.json' with { type: 'json' } + +const PORT = await getTestServerPort(packageJson.name) +const START_PORT = await getTestServerPort(`${packageJson.name}_start`) +const EXTERNAL_PORT = await getDummyServerPort(packageJson.name) +const baseURL = `http://localhost:${PORT}` + +export default defineConfig({ + testDir: '../basic-test-suite/src', + workers: 1, + reporter: [['line']], + + globalTeardown: '../basic-test-suite/src/setup/global.teardown.ts', + + use: { + baseURL, + }, + + webServer: { + command: + 'pnpm run test:e2e:startDummyServer && pnpm --dir ../basic build:spa && pnpm --dir ../basic start', + url: baseURL, + reuseExistingServer: !process.env.CI, + stdout: 'pipe', + env: { + MODE: 'spa', + VITE_NODE_ENV: 'test', + VITE_EXTERNAL_PORT: String(EXTERNAL_PORT), + VITE_SERVER_PORT: String(PORT), + START_PORT: String(START_PORT), + PORT: String(PORT), + }, + }, + + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + }, + }, + ], +}) diff --git a/e2e/react-start/basic-test-suite/.gitignore b/e2e/react-start/basic-test-suite/.gitignore new file mode 100644 index 00000000000..6381bf3860f --- /dev/null +++ b/e2e/react-start/basic-test-suite/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/test-results/ +/playwright-report/ +/blob-report/ diff --git a/e2e/react-start/basic-test-suite/package.json b/e2e/react-start/basic-test-suite/package.json new file mode 100644 index 00000000000..aaf431e09d3 --- /dev/null +++ b/e2e/react-start/basic-test-suite/package.json @@ -0,0 +1,12 @@ +{ + "name": "tanstack-react-start-e2e-basic-test-suite", + "private": true, + "sideEffects": false, + "type": "module", + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tanstack/router-e2e-utils": "workspace:*", + "@types/node": "^22.10.2", + "combinate": "^1.1.11" + } +} diff --git a/e2e/react-start/basic/tests/client-only.spec.ts b/e2e/react-start/basic-test-suite/src/client-only.spec.ts similarity index 100% rename from e2e/react-start/basic/tests/client-only.spec.ts rename to e2e/react-start/basic-test-suite/src/client-only.spec.ts diff --git a/e2e/react-start/basic/tests/navigation.spec.ts b/e2e/react-start/basic-test-suite/src/navigation.spec.ts similarity index 100% rename from e2e/react-start/basic/tests/navigation.spec.ts rename to e2e/react-start/basic-test-suite/src/navigation.spec.ts diff --git a/e2e/react-start/basic/tests/not-found.spec.ts b/e2e/react-start/basic-test-suite/src/not-found.spec.ts similarity index 99% rename from e2e/react-start/basic/tests/not-found.spec.ts rename to e2e/react-start/basic-test-suite/src/not-found.spec.ts index 89f6b6d4e9f..d6e91696e32 100644 --- a/e2e/react-start/basic/tests/not-found.spec.ts +++ b/e2e/react-start/basic-test-suite/src/not-found.spec.ts @@ -1,7 +1,7 @@ import { expect } from '@playwright/test' import combinateImport from 'combinate' import { test } from '@tanstack/router-e2e-utils' -import { isSpaMode } from '../tests/utils/isSpaMode' +import { isSpaMode } from './utils/isSpaMode' // somehow playwright does not correctly import default exports const combinate = (combinateImport as any).default as typeof combinateImport diff --git a/e2e/react-start/basic/tests/open-redirect-prevention.spec.ts b/e2e/react-start/basic-test-suite/src/open-redirect-prevention.spec.ts similarity index 100% rename from e2e/react-start/basic/tests/open-redirect-prevention.spec.ts rename to e2e/react-start/basic-test-suite/src/open-redirect-prevention.spec.ts diff --git a/e2e/vue-start/basic/tests/prerendering.spec.ts b/e2e/react-start/basic-test-suite/src/prerendering.spec.ts similarity index 90% rename from e2e/vue-start/basic/tests/prerendering.spec.ts rename to e2e/react-start/basic-test-suite/src/prerendering.spec.ts index 8506ff9b061..66cc1f68ff2 100644 --- a/e2e/vue-start/basic/tests/prerendering.spec.ts +++ b/e2e/react-start/basic-test-suite/src/prerendering.spec.ts @@ -3,13 +3,14 @@ import { join } from 'node:path' import { expect } from '@playwright/test' import { test } from '@tanstack/router-e2e-utils' import { isPrerender } from './utils/isPrerender' +import { getBasicAppRoot } from './utils/getBasicAppRoot' test.describe('Prerender Static Path Discovery', () => { test.skip(!isPrerender, 'Skipping since not in prerender mode') test.describe('Build Output Verification', () => { test('should automatically discover and prerender static routes', () => { // Check that static routes were automatically discovered and prerendered - const distDir = join(process.cwd(), 'dist', 'client') + const distDir = join(getBasicAppRoot(), 'dist', 'client') // These static routes should be automatically discovered and prerendered expect(existsSync(join(distDir, 'index.html'))).toBe(true) @@ -34,7 +35,7 @@ test.describe('Prerender Static Path Discovery', () => { test.describe('Static Files Verification', () => { test('should contain prerendered content in posts.html', () => { - const distDir = join(process.cwd(), 'dist', 'client') + const distDir = join(getBasicAppRoot(), 'dist', 'client') expect(existsSync(join(distDir, 'posts/index.html'))).toBe(true) // "Select a post." should be in the prerendered HTML diff --git a/e2e/react-start/basic/tests/raw-stream.spec.ts b/e2e/react-start/basic-test-suite/src/raw-stream.spec.ts similarity index 100% rename from e2e/react-start/basic/tests/raw-stream.spec.ts rename to e2e/react-start/basic-test-suite/src/raw-stream.spec.ts diff --git a/e2e/react-start/basic/tests/redirect.spec.ts b/e2e/react-start/basic-test-suite/src/redirect.spec.ts similarity index 95% rename from e2e/react-start/basic/tests/redirect.spec.ts rename to e2e/react-start/basic-test-suite/src/redirect.spec.ts index bc36de96230..0763a901a26 100644 --- a/e2e/react-start/basic/tests/redirect.spec.ts +++ b/e2e/react-start/basic-test-suite/src/redirect.spec.ts @@ -6,18 +6,15 @@ import { getTestServerPort, test, } from '@tanstack/router-e2e-utils' -import { isSpaMode } from '../tests/utils/isSpaMode' -import { isPreview } from '../tests/utils/isPreview' -import packageJson from '../package.json' with { type: 'json' } +import { getPackageName } from './utils/getPackageName.ts' // somehow playwright does not correctly import default exports const combinate = (combinateImport as any).default as typeof combinateImport +const packageName = getPackageName() -const PORT = await getTestServerPort( - `${packageJson.name}${isSpaMode ? '_spa' : ''}${isPreview ? '_preview' : ''}`, -) +const PORT = await getTestServerPort(packageName) -const EXTERNAL_HOST_PORT = await getDummyServerPort(packageJson.name) +const EXTERNAL_HOST_PORT = await getDummyServerPort(packageName) test.describe('redirects', () => { test.describe('internal', () => { diff --git a/e2e/react-start/basic/tests/root-scripts.spec.ts b/e2e/react-start/basic-test-suite/src/root-scripts.spec.ts similarity index 100% rename from e2e/react-start/basic/tests/root-scripts.spec.ts rename to e2e/react-start/basic-test-suite/src/root-scripts.spec.ts diff --git a/e2e/react-start/basic/tests/script-duplication.spec.ts b/e2e/react-start/basic-test-suite/src/script-duplication.spec.ts similarity index 100% rename from e2e/react-start/basic/tests/script-duplication.spec.ts rename to e2e/react-start/basic-test-suite/src/script-duplication.spec.ts diff --git a/e2e/vue-start/basic/tests/search-params.spec.ts b/e2e/react-start/basic-test-suite/src/search-params.spec.ts similarity index 98% rename from e2e/vue-start/basic/tests/search-params.spec.ts rename to e2e/react-start/basic-test-suite/src/search-params.spec.ts index 74c1aa54dc9..cdf5a21b4ae 100644 --- a/e2e/vue-start/basic/tests/search-params.spec.ts +++ b/e2e/react-start/basic-test-suite/src/search-params.spec.ts @@ -1,6 +1,6 @@ import { expect } from '@playwright/test' import { test } from '@tanstack/router-e2e-utils' -import { isSpaMode } from 'tests/utils/isSpaMode' +import { isSpaMode } from './utils/isSpaMode' import { isPrerender } from './utils/isPrerender' import type { Response } from '@playwright/test' diff --git a/e2e/react-start/basic-test-suite/src/setup/global.setup.ts b/e2e/react-start/basic-test-suite/src/setup/global.setup.ts new file mode 100644 index 00000000000..fc06a655910 --- /dev/null +++ b/e2e/react-start/basic-test-suite/src/setup/global.setup.ts @@ -0,0 +1,6 @@ +import { e2eStartDummyServer } from '@tanstack/router-e2e-utils' +import { getPackageName } from '../utils/getPackageName.ts' + +export default async function setup() { + await e2eStartDummyServer(getPackageName()) +} diff --git a/e2e/react-start/basic-test-suite/src/setup/global.teardown.ts b/e2e/react-start/basic-test-suite/src/setup/global.teardown.ts new file mode 100644 index 00000000000..a8a68997009 --- /dev/null +++ b/e2e/react-start/basic-test-suite/src/setup/global.teardown.ts @@ -0,0 +1,8 @@ +import { e2eStopDummyServer } from '@tanstack/router-e2e-utils' +import { getPackageName } from '../utils/getPackageName.ts' + +export default async function teardown() { + try { + await e2eStopDummyServer(getPackageName()) + } catch {} +} diff --git a/e2e/react-start/basic-test-suite/src/setup/waitForDummyServer.ts b/e2e/react-start/basic-test-suite/src/setup/waitForDummyServer.ts new file mode 100644 index 00000000000..f27dc86d5b8 --- /dev/null +++ b/e2e/react-start/basic-test-suite/src/setup/waitForDummyServer.ts @@ -0,0 +1,24 @@ +import { getDummyServerPort } from '@tanstack/router-e2e-utils' +import { getPackageName } from '../utils/getPackageName.ts' + +const timeoutMs = 10_000 +const retryIntervalMs = 100 + +export default async function waitForDummyServer() { + const port = await getDummyServerPort(getPackageName()) + const deadline = Date.now() + timeoutMs + + while (Date.now() < deadline) { + try { + const response = await fetch(`http://localhost:${port}/`) + + if (response.ok) { + return + } + } catch {} + + await new Promise((resolve) => setTimeout(resolve, retryIntervalMs)) + } + + throw new Error(`Timed out waiting for dummy server on port ${port}`) +} diff --git a/e2e/react-start/basic/tests/special-characters.spec.ts b/e2e/react-start/basic-test-suite/src/special-characters.spec.ts similarity index 95% rename from e2e/react-start/basic/tests/special-characters.spec.ts rename to e2e/react-start/basic-test-suite/src/special-characters.spec.ts index ce800a77ef0..8e05ec5e0a2 100644 --- a/e2e/react-start/basic/tests/special-characters.spec.ts +++ b/e2e/react-start/basic-test-suite/src/special-characters.spec.ts @@ -77,11 +77,23 @@ test.describe('Unicode route rendering', () => { `${baseURL}/specialChars/search?searchParam=%EB%8C%80|`, ) + await page.waitForLoadState('networkidle') + const searchParam = await page .getByTestId('special-search-param') .textContent() expect(searchParam).toBe('대|') + + const loadedOn = await page + .getByTestId('special-search-loaded-info') + .textContent() + + if (isSpaMode) { + expect(loadedOn).toBe('Loaded on: client') + } else { + expect(loadedOn).toBe('Loaded on: server') + } }) test('should render route correctly on router navigation', async ({ diff --git a/e2e/react-start/basic/tests/streaming.spec.ts b/e2e/react-start/basic-test-suite/src/streaming.spec.ts similarity index 100% rename from e2e/react-start/basic/tests/streaming.spec.ts rename to e2e/react-start/basic-test-suite/src/streaming.spec.ts diff --git a/e2e/react-start/basic/tests/type-only-reexport.spec.ts b/e2e/react-start/basic-test-suite/src/type-only-reexport.spec.ts similarity index 100% rename from e2e/react-start/basic/tests/type-only-reexport.spec.ts rename to e2e/react-start/basic-test-suite/src/type-only-reexport.spec.ts diff --git a/e2e/react-start/basic-test-suite/src/utils/getBasicAppRoot.ts b/e2e/react-start/basic-test-suite/src/utils/getBasicAppRoot.ts new file mode 100644 index 00000000000..4725f532ed6 --- /dev/null +++ b/e2e/react-start/basic-test-suite/src/utils/getBasicAppRoot.ts @@ -0,0 +1,8 @@ +import { join } from 'node:path' +import { getPackageName } from './getPackageName.ts' + +export function getBasicAppRoot() { + return getPackageName() === 'tanstack-react-start-e2e-basic' + ? process.cwd() + : join(process.cwd(), '../basic') +} diff --git a/e2e/react-start/basic-test-suite/src/utils/getPackageName.ts b/e2e/react-start/basic-test-suite/src/utils/getPackageName.ts new file mode 100644 index 00000000000..6bd2e0499ed --- /dev/null +++ b/e2e/react-start/basic-test-suite/src/utils/getPackageName.ts @@ -0,0 +1,16 @@ +import { readFileSync } from 'node:fs' +import { join } from 'node:path' + +let packageName: string | undefined + +export function getPackageName() { + if (!packageName) { + const packageJson = JSON.parse( + readFileSync(join(process.cwd(), 'package.json'), 'utf-8'), + ) as { name: string } + + packageName = packageJson.name + } + + return packageName +} diff --git a/e2e/react-start/basic-test-suite/src/utils/isPrerender.ts b/e2e/react-start/basic-test-suite/src/utils/isPrerender.ts new file mode 100644 index 00000000000..d5d991d4545 --- /dev/null +++ b/e2e/react-start/basic-test-suite/src/utils/isPrerender.ts @@ -0,0 +1 @@ +export const isPrerender: boolean = process.env.MODE === 'prerender' diff --git a/e2e/react-start/basic-test-suite/src/utils/isPreview.ts b/e2e/react-start/basic-test-suite/src/utils/isPreview.ts new file mode 100644 index 00000000000..7ea362a83ed --- /dev/null +++ b/e2e/react-start/basic-test-suite/src/utils/isPreview.ts @@ -0,0 +1 @@ +export const isPreview: boolean = process.env.MODE === 'preview' diff --git a/e2e/react-start/basic-test-suite/src/utils/isSpaMode.ts b/e2e/react-start/basic-test-suite/src/utils/isSpaMode.ts new file mode 100644 index 00000000000..b4edb829a8f --- /dev/null +++ b/e2e/react-start/basic-test-suite/src/utils/isSpaMode.ts @@ -0,0 +1 @@ +export const isSpaMode: boolean = process.env.MODE === 'spa' diff --git a/e2e/react-start/basic-test-suite/tsconfig.json b/e2e/react-start/basic-test-suite/tsconfig.json new file mode 100644 index 00000000000..3f3dbe6bcd7 --- /dev/null +++ b/e2e/react-start/basic-test-suite/tsconfig.json @@ -0,0 +1,18 @@ +{ + "include": ["src/**/*.ts"], + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "isolatedModules": true, + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "target": "ES2022", + "types": ["node"], + "forceConsistentCasingInFileNames": true, + "noEmit": true + } +} diff --git a/e2e/react-start/basic-tsr-config/package.json b/e2e/react-start/basic-tsr-config/package.json index af90af8060e..725ac3f0bab 100644 --- a/e2e/react-start/basic-tsr-config/package.json +++ b/e2e/react-start/basic-tsr-config/package.json @@ -23,6 +23,6 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "srvx": "^0.11.9", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/basic-tsr-config/tsconfig.json b/e2e/react-start/basic-tsr-config/tsconfig.json index 3558337b0c1..f3895f6eb1d 100644 --- a/e2e/react-start/basic-tsr-config/tsconfig.json +++ b/e2e/react-start/basic-tsr-config/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/app/*"] }, diff --git a/e2e/react-start/basic/package.json b/e2e/react-start/basic/package.json index f85cdae20bf..957372b08ee 100644 --- a/e2e/react-start/basic/package.json +++ b/e2e/react-start/basic/package.json @@ -11,13 +11,9 @@ "build:prerender": "MODE=prerender vite build && tsc --noEmit", "preview": "vite preview", "start": "node server.js", - "test:e2e:startDummyServer": "node -e 'import(\"./tests/setup/global.setup.ts\").then(m => m.default())' &", - "test:e2e:stopDummyServer": "node -e 'import(\"./tests/setup/global.teardown.ts\").then(m => m.default())'", - "test:e2e:spaMode": "rm -rf dist; rm -rf port*.txt; MODE=spa playwright test --project=chromium", - "test:e2e:ssrMode": "rm -rf dist; rm -rf port*.txt; playwright test --project=chromium", - "test:e2e:prerender": "rm -rf dist; rm -rf port*.txt; MODE=prerender playwright test --project=chromium", - "test:e2e:preview": "rm -rf dist; rm -rf port*.txt; MODE=preview playwright test --project=chromium", - "test:e2e": "pnpm run test:e2e:spaMode && pnpm run test:e2e:ssrMode && pnpm run test:e2e:prerender && pnpm run test:e2e:preview" + "test:e2e:startDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.setup.ts\").then(m => m.default())' & node -e 'import(\"../basic-test-suite/src/setup/waitForDummyServer.ts\").then(m => m.default())'", + "test:e2e:stopDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.teardown.ts\").then(m => m.default())'", + "test:e2e": "rm -rf dist; rm -rf port*.txt; playwright test --project=chromium" }, "dependencies": { "@tanstack/react-router": "workspace:^", @@ -35,6 +31,7 @@ "@playwright/test": "^1.50.1", "@tailwindcss/vite": "^4.2.2", "@tanstack/router-e2e-utils": "workspace:^", + "tanstack-react-start-e2e-basic-test-suite": "workspace:*", "@types/js-cookie": "^3.0.6", "@types/node": "^22.10.2", "@types/react": "^19.0.8", @@ -43,8 +40,15 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "zod": "^3.24.2" + }, + "nx": { + "targets": { + "test:e2e": { + "parallelism": false + } + } } } diff --git a/e2e/react-start/basic/playwright.config.ts b/e2e/react-start/basic/playwright.config.ts index 86c58bc1ce3..bf22363c94a 100644 --- a/e2e/react-start/basic/playwright.config.ts +++ b/e2e/react-start/basic/playwright.config.ts @@ -3,43 +3,22 @@ import { getDummyServerPort, getTestServerPort, } from '@tanstack/router-e2e-utils' -import { isSpaMode } from './tests/utils/isSpaMode' -import { isPrerender } from './tests/utils/isPrerender' -import { isPreview } from './tests/utils/isPreview' import packageJson from './package.json' with { type: 'json' } -const PORT = await getTestServerPort( - `${packageJson.name}${isSpaMode ? '_spa' : ''}${isPreview ? '_preview' : ''}`, -) -const START_PORT = await getTestServerPort( - `${packageJson.name}${isSpaMode ? '_spa_start' : ''}`, -) +const PORT = await getTestServerPort(packageJson.name) +const START_PORT = await getTestServerPort(`${packageJson.name}_start`) const EXTERNAL_PORT = await getDummyServerPort(packageJson.name) const baseURL = `http://localhost:${PORT}` -const spaModeCommand = `pnpm build:spa && pnpm start` const ssrModeCommand = `pnpm build && pnpm start` -const prerenderModeCommand = `pnpm run test:e2e:startDummyServer && pnpm build:prerender && pnpm run test:e2e:stopDummyServer && pnpm start` -const previewModeCommand = `pnpm build && pnpm preview --port ${PORT}` - -const getCommand = () => { - if (isSpaMode) return spaModeCommand - if (isPrerender) return prerenderModeCommand - if (isPreview) return previewModeCommand - return ssrModeCommand -} -console.log('running in spa mode: ', isSpaMode.toString()) -console.log('running in prerender mode: ', isPrerender.toString()) -console.log('running in preview mode: ', isPreview.toString()) /** * See https://playwright.dev/docs/test-configuration. */ export default defineConfig({ - testDir: './tests', + testDir: '../basic-test-suite/src', workers: 1, reporter: [['line']], - globalSetup: './tests/setup/global.setup.ts', - globalTeardown: './tests/setup/global.teardown.ts', + globalTeardown: '../basic-test-suite/src/setup/global.teardown.ts', use: { /* Base URL to use in actions like `await page.goto('/')`. */ @@ -47,12 +26,12 @@ export default defineConfig({ }, webServer: { - command: getCommand(), + command: `pnpm run test:e2e:startDummyServer && ${ssrModeCommand}`, url: baseURL, reuseExistingServer: !process.env.CI, stdout: 'pipe', env: { - MODE: process.env.MODE || '', + MODE: '', VITE_NODE_ENV: 'test', VITE_EXTERNAL_PORT: String(EXTERNAL_PORT), VITE_SERVER_PORT: String(PORT), diff --git a/e2e/react-start/basic/src/routes/specialChars/search.tsx b/e2e/react-start/basic/src/routes/specialChars/search.tsx index 152f39f527b..9e4b42e888b 100644 --- a/e2e/react-start/basic/src/routes/specialChars/search.tsx +++ b/e2e/react-start/basic/src/routes/specialChars/search.tsx @@ -1,19 +1,29 @@ import { createFileRoute } from '@tanstack/react-router' import z from 'zod' +const isBrowser = typeof window !== 'undefined' + export const Route = createFileRoute('/specialChars/search')({ validateSearch: z.object({ searchParam: z.string(), }), + loader: async () => { + console.log(`[loader] Running on ${isBrowser ? 'client' : 'server'}`) + return { + loadedOn: isBrowser ? 'client' : 'server', + } + }, component: RouteComponent, }) function RouteComponent() { const search = Route.useSearch() + const { loadedOn } = Route.useLoaderData() return (
Hello "/specialChars/search"! +
Loaded on: {loadedOn}
{search.searchParam}
) diff --git a/e2e/react-start/basic/tests/setup/global.setup.ts b/e2e/react-start/basic/tests/setup/global.setup.ts deleted file mode 100644 index 3593d10ab90..00000000000 --- a/e2e/react-start/basic/tests/setup/global.setup.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { e2eStartDummyServer } from '@tanstack/router-e2e-utils' -import packageJson from '../../package.json' with { type: 'json' } - -export default async function setup() { - await e2eStartDummyServer(packageJson.name) -} diff --git a/e2e/react-start/basic/tests/setup/global.teardown.ts b/e2e/react-start/basic/tests/setup/global.teardown.ts deleted file mode 100644 index 62fd79911cc..00000000000 --- a/e2e/react-start/basic/tests/setup/global.teardown.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { e2eStopDummyServer } from '@tanstack/router-e2e-utils' -import packageJson from '../../package.json' with { type: 'json' } - -export default async function teardown() { - await e2eStopDummyServer(packageJson.name) -} diff --git a/e2e/react-start/basic/tsconfig.json b/e2e/react-start/basic/tsconfig.json index b3a2d67dfa6..af81492efb0 100644 --- a/e2e/react-start/basic/tsconfig.json +++ b/e2e/react-start/basic/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/clerk-basic/package.json b/e2e/react-start/clerk-basic/package.json index 6b127cf195e..dd38f35d24b 100644 --- a/e2e/react-start/clerk-basic/package.json +++ b/e2e/react-start/clerk-basic/package.json @@ -29,7 +29,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "@tailwindcss/vite": "^4.2.2" } } diff --git a/e2e/react-start/clerk-basic/src/routeTree.gen.ts b/e2e/react-start/clerk-basic/src/routeTree.gen.ts index a6767e0efd5..5b9f75e27a9 100644 --- a/e2e/react-start/clerk-basic/src/routeTree.gen.ts +++ b/e2e/react-start/clerk-basic/src/routeTree.gen.ts @@ -93,7 +93,7 @@ declare module '@tanstack/react-router' { '/_authed': { id: '/_authed' path: '' - fullPath: '' + fullPath: '/' preLoaderRoute: typeof AuthedRouteImport parentRoute: typeof rootRouteImport } diff --git a/e2e/react-start/clerk-basic/tsconfig.json b/e2e/react-start/clerk-basic/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/clerk-basic/tsconfig.json +++ b/e2e/react-start/clerk-basic/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/csp/package.json b/e2e/react-start/csp/package.json index e96dbeb836c..e5821a3a81a 100644 --- a/e2e/react-start/csp/package.json +++ b/e2e/react-start/csp/package.json @@ -24,6 +24,6 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "srvx": "^0.11.9", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/csp/src/vite-env.d.ts b/e2e/react-start/csp/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-start/csp/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-start/csp/tsconfig.json b/e2e/react-start/csp/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/csp/tsconfig.json +++ b/e2e/react-start/csp/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/css-modules/package.json b/e2e/react-start/css-modules/package.json index 00cd504b431..6f3615dc574 100644 --- a/e2e/react-start/css-modules/package.json +++ b/e2e/react-start/css-modules/package.json @@ -42,7 +42,7 @@ "nitro": "^3.0.260311-beta", "sass": "^1.97.2", "srvx": "^0.11.9", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "wrangler": "^4.74.0" } diff --git a/e2e/react-start/css-modules/tsconfig.json b/e2e/react-start/css-modules/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/css-modules/tsconfig.json +++ b/e2e/react-start/css-modules/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/custom-basepath/package.json b/e2e/react-start/custom-basepath/package.json index b2295fba6df..0cabf5bff6b 100644 --- a/e2e/react-start/custom-basepath/package.json +++ b/e2e/react-start/custom-basepath/package.json @@ -32,7 +32,7 @@ "srvx": "^0.11.9", "tailwindcss": "^4.2.2", "tsx": "^4.20.3", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/e2e/react-start/custom-basepath/tsconfig.json b/e2e/react-start/custom-basepath/tsconfig.json index d35a4b17f48..3824b148e15 100644 --- a/e2e/react-start/custom-basepath/tsconfig.json +++ b/e2e/react-start/custom-basepath/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/dev-ssr-styles/package.json b/e2e/react-start/dev-ssr-styles/package.json index 4536c502bea..954deffa06e 100644 --- a/e2e/react-start/dev-ssr-styles/package.json +++ b/e2e/react-start/dev-ssr-styles/package.json @@ -37,7 +37,7 @@ "@vitejs/plugin-react": "^6.0.1", "nitro": "^3.0.260311-beta", "srvx": "^0.11.9", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "zod": "^3.24.2" } diff --git a/e2e/react-start/dev-ssr-styles/src/vite-env.d.ts b/e2e/react-start/dev-ssr-styles/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-start/dev-ssr-styles/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-start/dev-ssr-styles/tsconfig.json b/e2e/react-start/dev-ssr-styles/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/dev-ssr-styles/tsconfig.json +++ b/e2e/react-start/dev-ssr-styles/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/flamegraph-bench/package.json b/e2e/react-start/flamegraph-bench/package.json index 7c849cb4e37..36d8393fb3c 100644 --- a/e2e/react-start/flamegraph-bench/package.json +++ b/e2e/react-start/flamegraph-bench/package.json @@ -22,7 +22,7 @@ "nitro": "^3.0.260311-beta", "autocannon": "^8.0.0", "concurrently": "9.2.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/e2e/react-start/hmr/package.json b/e2e/react-start/hmr/package.json index a7c0cb6f55e..8682ec6ff0c 100644 --- a/e2e/react-start/hmr/package.json +++ b/e2e/react-start/hmr/package.json @@ -24,7 +24,7 @@ "@types/react-dom": "^19.0.3", "tailwindcss": "^4.2.2", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/e2e/react-start/hmr/tsconfig.json b/e2e/react-start/hmr/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/hmr/tsconfig.json +++ b/e2e/react-start/hmr/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/i18n-paraglide/package.json b/e2e/react-start/i18n-paraglide/package.json index 6c5fd5801a4..69dd0a0a2f3 100644 --- a/e2e/react-start/i18n-paraglide/package.json +++ b/e2e/react-start/i18n-paraglide/package.json @@ -27,7 +27,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/e2e/react-start/i18n-paraglide/src/vite-env.d.ts b/e2e/react-start/i18n-paraglide/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/react-start/i18n-paraglide/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/react-start/i18n-paraglide/tsconfig.json b/e2e/react-start/i18n-paraglide/tsconfig.json index 3e42c72626a..471d55aed83 100644 --- a/e2e/react-start/i18n-paraglide/tsconfig.json +++ b/e2e/react-start/i18n-paraglide/tsconfig.json @@ -21,7 +21,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true, - "baseUrl": ".", "paths": { "@/*": ["./src/*"] } diff --git a/e2e/react-start/import-protection-custom-config/package.json b/e2e/react-start/import-protection-custom-config/package.json index 4f3da0fcafa..ee633ffe394 100644 --- a/e2e/react-start/import-protection-custom-config/package.json +++ b/e2e/react-start/import-protection-custom-config/package.json @@ -26,6 +26,6 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "srvx": "^0.11.9", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/import-protection-custom-config/tsconfig.json b/e2e/react-start/import-protection-custom-config/tsconfig.json index 8b1cd45e855..2afe40d931c 100644 --- a/e2e/react-start/import-protection-custom-config/tsconfig.json +++ b/e2e/react-start/import-protection-custom-config/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "noEmit": true } } diff --git a/e2e/react-start/import-protection/package.json b/e2e/react-start/import-protection/package.json index a122b8ee473..5464e40b943 100644 --- a/e2e/react-start/import-protection/package.json +++ b/e2e/react-start/import-protection/package.json @@ -27,6 +27,6 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "srvx": "^0.11.9", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/import-protection/tsconfig.json b/e2e/react-start/import-protection/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/import-protection/tsconfig.json +++ b/e2e/react-start/import-protection/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/query-integration/package.json b/e2e/react-start/query-integration/package.json index 6e9b2a6b7f4..bcb51c9d865 100644 --- a/e2e/react-start/query-integration/package.json +++ b/e2e/react-start/query-integration/package.json @@ -33,6 +33,6 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/query-integration/tsconfig.json b/e2e/react-start/query-integration/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/query-integration/tsconfig.json +++ b/e2e/react-start/query-integration/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/scroll-restoration/package.json b/e2e/react-start/scroll-restoration/package.json index 53d9ad37d8c..f9700e4c3d6 100644 --- a/e2e/react-start/scroll-restoration/package.json +++ b/e2e/react-start/scroll-restoration/package.json @@ -34,6 +34,6 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/scroll-restoration/src/routeTree.gen.ts b/e2e/react-start/scroll-restoration/src/routeTree.gen.ts index 5f7f3095403..5194bbc556a 100644 --- a/e2e/react-start/scroll-restoration/src/routeTree.gen.ts +++ b/e2e/react-start/scroll-restoration/src/routeTree.gen.ts @@ -13,6 +13,8 @@ import { Route as IndexRouteImport } from './routes/index' import { Route as testsWithSearchRouteImport } from './routes/(tests)/with-search' import { Route as testsWithLoaderRouteImport } from './routes/(tests)/with-loader' import { Route as testsNormalPageRouteImport } from './routes/(tests)/normal-page' +import { Route as testsHashScrollReproRouteImport } from './routes/(tests)/hash-scroll-repro' +import { Route as testsHashScrollAboutRouteImport } from './routes/(tests)/hash-scroll-about' const IndexRoute = IndexRouteImport.update({ id: '/', @@ -34,15 +36,29 @@ const testsNormalPageRoute = testsNormalPageRouteImport.update({ path: '/normal-page', getParentRoute: () => rootRouteImport, } as any) +const testsHashScrollReproRoute = testsHashScrollReproRouteImport.update({ + id: '/(tests)/hash-scroll-repro', + path: '/hash-scroll-repro', + getParentRoute: () => rootRouteImport, +} as any) +const testsHashScrollAboutRoute = testsHashScrollAboutRouteImport.update({ + id: '/(tests)/hash-scroll-about', + path: '/hash-scroll-about', + getParentRoute: () => rootRouteImport, +} as any) export interface FileRoutesByFullPath { '/': typeof IndexRoute + '/hash-scroll-about': typeof testsHashScrollAboutRoute + '/hash-scroll-repro': typeof testsHashScrollReproRoute '/normal-page': typeof testsNormalPageRoute '/with-loader': typeof testsWithLoaderRoute '/with-search': typeof testsWithSearchRoute } export interface FileRoutesByTo { '/': typeof IndexRoute + '/hash-scroll-about': typeof testsHashScrollAboutRoute + '/hash-scroll-repro': typeof testsHashScrollReproRoute '/normal-page': typeof testsNormalPageRoute '/with-loader': typeof testsWithLoaderRoute '/with-search': typeof testsWithSearchRoute @@ -50,18 +66,34 @@ export interface FileRoutesByTo { export interface FileRoutesById { __root__: typeof rootRouteImport '/': typeof IndexRoute + '/(tests)/hash-scroll-about': typeof testsHashScrollAboutRoute + '/(tests)/hash-scroll-repro': typeof testsHashScrollReproRoute '/(tests)/normal-page': typeof testsNormalPageRoute '/(tests)/with-loader': typeof testsWithLoaderRoute '/(tests)/with-search': typeof testsWithSearchRoute } export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: '/' | '/normal-page' | '/with-loader' | '/with-search' + fullPaths: + | '/' + | '/hash-scroll-about' + | '/hash-scroll-repro' + | '/normal-page' + | '/with-loader' + | '/with-search' fileRoutesByTo: FileRoutesByTo - to: '/' | '/normal-page' | '/with-loader' | '/with-search' + to: + | '/' + | '/hash-scroll-about' + | '/hash-scroll-repro' + | '/normal-page' + | '/with-loader' + | '/with-search' id: | '__root__' | '/' + | '/(tests)/hash-scroll-about' + | '/(tests)/hash-scroll-repro' | '/(tests)/normal-page' | '/(tests)/with-loader' | '/(tests)/with-search' @@ -69,6 +101,8 @@ export interface FileRouteTypes { } export interface RootRouteChildren { IndexRoute: typeof IndexRoute + testsHashScrollAboutRoute: typeof testsHashScrollAboutRoute + testsHashScrollReproRoute: typeof testsHashScrollReproRoute testsNormalPageRoute: typeof testsNormalPageRoute testsWithLoaderRoute: typeof testsWithLoaderRoute testsWithSearchRoute: typeof testsWithSearchRoute @@ -104,11 +138,27 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof testsNormalPageRouteImport parentRoute: typeof rootRouteImport } + '/(tests)/hash-scroll-repro': { + id: '/(tests)/hash-scroll-repro' + path: '/hash-scroll-repro' + fullPath: '/hash-scroll-repro' + preLoaderRoute: typeof testsHashScrollReproRouteImport + parentRoute: typeof rootRouteImport + } + '/(tests)/hash-scroll-about': { + id: '/(tests)/hash-scroll-about' + path: '/hash-scroll-about' + fullPath: '/hash-scroll-about' + preLoaderRoute: typeof testsHashScrollAboutRouteImport + parentRoute: typeof rootRouteImport + } } } const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, + testsHashScrollAboutRoute: testsHashScrollAboutRoute, + testsHashScrollReproRoute: testsHashScrollReproRoute, testsNormalPageRoute: testsNormalPageRoute, testsWithLoaderRoute: testsWithLoaderRoute, testsWithSearchRoute: testsWithSearchRoute, diff --git a/e2e/react-start/scroll-restoration/src/routes/(tests)/hash-scroll-about.tsx b/e2e/react-start/scroll-restoration/src/routes/(tests)/hash-scroll-about.tsx new file mode 100644 index 00000000000..2c2748e6a51 --- /dev/null +++ b/e2e/react-start/scroll-restoration/src/routes/(tests)/hash-scroll-about.tsx @@ -0,0 +1,22 @@ +import * as React from 'react' +import { createFileRoute } from '@tanstack/react-router' +import { sleep } from '~/utils/posts' + +export const Route = createFileRoute('/(tests)/hash-scroll-about')({ + loader: async () => { + await sleep(50) + return null + }, + component: Component, +}) + +function Component() { + return ( +
+

hash-scroll-about

+

+ This route exists so hover preloading can reproduce the hash scroll bug. +

+
+ ) +} diff --git a/e2e/react-start/scroll-restoration/src/routes/(tests)/hash-scroll-repro.tsx b/e2e/react-start/scroll-restoration/src/routes/(tests)/hash-scroll-repro.tsx new file mode 100644 index 00000000000..ff85d140fa6 --- /dev/null +++ b/e2e/react-start/scroll-restoration/src/routes/(tests)/hash-scroll-repro.tsx @@ -0,0 +1,64 @@ +import * as React from 'react' +import { Link, createFileRoute, useRouter } from '@tanstack/react-router' +import { sleep } from '~/utils/posts' + +export const Route = createFileRoute('/(tests)/hash-scroll-repro')({ + loader: async () => { + await sleep(50) + return null + }, + component: Component, +}) + +const sectionIds = ['one', 'two', 'three', 'four', 'five'] as const + +function Component() { + const router = useRouter() + const [invalidateCount, setInvalidateCount] = React.useState(0) + + return ( +
+
+

hash-scroll-repro

+

+ Invalidate count: {invalidateCount} +

+
+ + About + + +
+
+ +
+ {sectionIds.map((sectionId) => ( +
+ {sectionId} +
+ ))} +
+
+ ) +} diff --git a/e2e/react-start/scroll-restoration/src/routes/__root.tsx b/e2e/react-start/scroll-restoration/src/routes/__root.tsx index fb4303fae47..563d9208ec5 100644 --- a/e2e/react-start/scroll-restoration/src/routes/__root.tsx +++ b/e2e/react-start/scroll-restoration/src/routes/__root.tsx @@ -110,6 +110,7 @@ function Nav({ type }: { type: 'header' | 'footer' }) { linkOptions({ to: '/normal-page' }), linkOptions({ to: '/with-loader' }), linkOptions({ to: '/with-search', search: { where: type } }), + linkOptions({ to: '/hash-scroll-repro' }), ] as const ).map((options, i) => ( window.scrollY > 0, null, { timeout: 5000 }) + await expect(page.getByTestId('hash-scroll-section-five')).toBeInViewport() +} + +async function scrollUpFromHashTarget(page: Page) { + const scrollY = await page.evaluate(async () => { + window.scrollBy(0, -500) + await new Promise((resolve) => requestAnimationFrame(() => resolve(null))) + return window.scrollY + }) + + expect(scrollY).toBeGreaterThan(0) + + // Verify #five is no longer centered in the viewport (we scrolled up from it) + await page.waitForFunction(() => { + const section = document.querySelector( + '[data-testid="hash-scroll-section-five"]', + ) + + if (!(section instanceof HTMLElement)) { + return false + } + + return section.getBoundingClientRect().top > window.innerHeight / 2 + }) + + return scrollY +} + +test('hover preloading another route does not scroll back to the current hash', async ({ + page, +}) => { + await goToRepro(page) + const scrollYBeforeHover = await scrollUpFromHashTarget(page) + + const preloadResponse = page.waitForResponse( + (response) => + response.url().includes('/hash-scroll-about') && response.ok(), + ) + + // Hover the About link to trigger preload + await page.getByTestId('hash-scroll-about-link').hover() + await preloadResponse + + // Give any erroneous scroll a chance to happen + await page.waitForTimeout(300) + + const scrollYAfterHover = await page.evaluate(() => window.scrollY) + expect(scrollYAfterHover).toBe(scrollYBeforeHover) +}) + +test('router.invalidate does not scroll back to the current hash', async ({ + page, +}) => { + await goToRepro(page) + const scrollYBeforeInvalidate = await scrollUpFromHashTarget(page) + const invalidateCountBefore = await page + .getByTestId('hash-scroll-repro-invalidate-count') + .textContent() + + // Click invalidate + await page.getByTestId('hash-scroll-invalidate-button').click() + + // Wait for the invalidation cycle to complete + await expect( + page.getByTestId('hash-scroll-repro-invalidate-count'), + ).not.toHaveText(invalidateCountBefore ?? '') + + // Give any erroneous scroll a chance to happen + await page.waitForTimeout(300) + + const scrollYAfterInvalidate = await page.evaluate(() => window.scrollY) + expect(scrollYAfterInvalidate).toBe(scrollYBeforeInvalidate) +}) diff --git a/e2e/react-start/scroll-restoration/tsconfig.json b/e2e/react-start/scroll-restoration/tsconfig.json index 09dd95b355d..9ea239fd313 100644 --- a/e2e/react-start/scroll-restoration/tsconfig.json +++ b/e2e/react-start/scroll-restoration/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/selective-ssr/package.json b/e2e/react-start/selective-ssr/package.json index 97ff0233e54..213ea9558dd 100644 --- a/e2e/react-start/selective-ssr/package.json +++ b/e2e/react-start/selective-ssr/package.json @@ -29,6 +29,6 @@ "@vitejs/plugin-react": "^6.0.1", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/selective-ssr/tsconfig.json b/e2e/react-start/selective-ssr/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/selective-ssr/tsconfig.json +++ b/e2e/react-start/selective-ssr/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/serialization-adapters/package.json b/e2e/react-start/serialization-adapters/package.json index a16c3bbb0b6..ada4113cf0e 100644 --- a/e2e/react-start/serialization-adapters/package.json +++ b/e2e/react-start/serialization-adapters/package.json @@ -29,6 +29,6 @@ "@vitejs/plugin-react": "^6.0.1", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/serialization-adapters/tsconfig.json b/e2e/react-start/serialization-adapters/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/serialization-adapters/tsconfig.json +++ b/e2e/react-start/serialization-adapters/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/server-functions-global-middleware/package.json b/e2e/react-start/server-functions-global-middleware/package.json index a92209a1fdd..e60becb3eda 100644 --- a/e2e/react-start/server-functions-global-middleware/package.json +++ b/e2e/react-start/server-functions-global-middleware/package.json @@ -28,6 +28,6 @@ "@vitejs/plugin-react": "^6.0.1", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/server-functions-global-middleware/tsconfig.json b/e2e/react-start/server-functions-global-middleware/tsconfig.json index a07911fe5f4..c7a0597e4bf 100644 --- a/e2e/react-start/server-functions-global-middleware/tsconfig.json +++ b/e2e/react-start/server-functions-global-middleware/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/server-functions/package.json b/e2e/react-start/server-functions/package.json index d4a9ba238e2..29a83802a56 100644 --- a/e2e/react-start/server-functions/package.json +++ b/e2e/react-start/server-functions/package.json @@ -37,6 +37,6 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/server-functions/tsconfig.json b/e2e/react-start/server-functions/tsconfig.json index d35a4b17f48..3824b148e15 100644 --- a/e2e/react-start/server-functions/tsconfig.json +++ b/e2e/react-start/server-functions/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/server-routes-global-middleware/package.json b/e2e/react-start/server-routes-global-middleware/package.json index 0a66e57ea52..0647fa5cbce 100644 --- a/e2e/react-start/server-routes-global-middleware/package.json +++ b/e2e/react-start/server-routes-global-middleware/package.json @@ -28,6 +28,6 @@ "@vitejs/plugin-react": "^6.0.1", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/server-routes-global-middleware/tsconfig.json b/e2e/react-start/server-routes-global-middleware/tsconfig.json index a07911fe5f4..c7a0597e4bf 100644 --- a/e2e/react-start/server-routes-global-middleware/tsconfig.json +++ b/e2e/react-start/server-routes-global-middleware/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/server-routes/package.json b/e2e/react-start/server-routes/package.json index 90b2c101cd1..5473bd3d213 100644 --- a/e2e/react-start/server-routes/package.json +++ b/e2e/react-start/server-routes/package.json @@ -37,6 +37,6 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/server-routes/tsconfig.json b/e2e/react-start/server-routes/tsconfig.json index d35a4b17f48..3824b148e15 100644 --- a/e2e/react-start/server-routes/tsconfig.json +++ b/e2e/react-start/server-routes/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/spa-mode/package.json b/e2e/react-start/spa-mode/package.json index c40f96663a2..ec9537de3dd 100644 --- a/e2e/react-start/spa-mode/package.json +++ b/e2e/react-start/spa-mode/package.json @@ -25,7 +25,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/e2e/react-start/spa-mode/tsconfig.json b/e2e/react-start/spa-mode/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/spa-mode/tsconfig.json +++ b/e2e/react-start/spa-mode/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/split-base-and-basepath/package.json b/e2e/react-start/split-base-and-basepath/package.json index ee2874dc682..bb25c4b92e5 100644 --- a/e2e/react-start/split-base-and-basepath/package.json +++ b/e2e/react-start/split-base-and-basepath/package.json @@ -27,7 +27,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "srvx": "^0.11.9", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/e2e/react-start/split-base-and-basepath/tsconfig.json b/e2e/react-start/split-base-and-basepath/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/split-base-and-basepath/tsconfig.json +++ b/e2e/react-start/split-base-and-basepath/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/static-server-functions/package.json b/e2e/react-start/static-server-functions/package.json index 7d7d2984f6f..91cd8302524 100644 --- a/e2e/react-start/static-server-functions/package.json +++ b/e2e/react-start/static-server-functions/package.json @@ -26,7 +26,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/e2e/react-start/static-server-functions/tsconfig.json b/e2e/react-start/static-server-functions/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/static-server-functions/tsconfig.json +++ b/e2e/react-start/static-server-functions/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/streaming-ssr/package.json b/e2e/react-start/streaming-ssr/package.json index 62433be8ca7..34b06e3f129 100644 --- a/e2e/react-start/streaming-ssr/package.json +++ b/e2e/react-start/streaming-ssr/package.json @@ -8,7 +8,9 @@ "dev:e2e": "vite dev", "build": "vite build && tsc --noEmit", "start": "pnpx srvx --prod -s ../client dist/server/server.js", - "test:e2e": "rm -rf port*.txt; playwright test --project=chromium" + "preview": "vite preview", + "test:e2e": "rm -rf port*.txt; playwright test --project=chromium", + "test:e2e:preview": "rm -rf port*.txt; MODE=preview playwright test preview-streaming.spec.ts --project=chromium" }, "dependencies": { "@tanstack/react-query": "^5.80.7", @@ -26,6 +28,6 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "srvx": "^0.11.9", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/streaming-ssr/playwright.config.ts b/e2e/react-start/streaming-ssr/playwright.config.ts index 5f9de5709e4..052ebe879d3 100644 --- a/e2e/react-start/streaming-ssr/playwright.config.ts +++ b/e2e/react-start/streaming-ssr/playwright.config.ts @@ -2,9 +2,16 @@ import { defineConfig, devices } from '@playwright/test' import { getTestServerPort } from '@tanstack/router-e2e-utils' import packageJson from './package.json' with { type: 'json' } -const PORT = await getTestServerPort(packageJson.name) +const isPreview = process.env.MODE === 'preview' + +const PORT = await getTestServerPort( + `${packageJson.name}${isPreview ? '_preview' : ''}`, +) const baseURL = `http://localhost:${PORT}` +const ssrCommand = `VITE_SERVER_PORT=${PORT} pnpm build && PORT=${PORT} VITE_SERVER_PORT=${PORT} pnpm start` +const previewCommand = `VITE_SERVER_PORT=${PORT} pnpm build && pnpm preview --port ${PORT}` + /** * See https://playwright.dev/docs/test-configuration. */ @@ -20,7 +27,7 @@ export default defineConfig({ }, webServer: { - command: `VITE_SERVER_PORT=${PORT} pnpm build && PORT=${PORT} VITE_SERVER_PORT=${PORT} pnpm start`, + command: isPreview ? previewCommand : ssrCommand, url: baseURL, reuseExistingServer: !process.env.CI, stdout: 'pipe', diff --git a/e2e/react-start/streaming-ssr/tests/preview-streaming.spec.ts b/e2e/react-start/streaming-ssr/tests/preview-streaming.spec.ts new file mode 100644 index 00000000000..319219c5195 --- /dev/null +++ b/e2e/react-start/streaming-ssr/tests/preview-streaming.spec.ts @@ -0,0 +1,21 @@ +import { expect, test } from './fixtures' + +test('vite preview streams HTML incrementally', async ({ page }) => { + // /deferred has immediate data + deferred data with a ~1s delay. + // Without streaming, compression buffers the entire response. + await page.goto('/deferred', { waitUntil: 'commit' }) + + // Immediate data should arrive in the first chunk + await expect(page.getByTestId('immediate-data')).toBeVisible({ + timeout: 3000, + }) + + // Deferred data (1s delay) should still be loading at this point + await expect(page.getByTestId('deferred-loading')).toBeVisible() + + // Wait for it to resolve + await expect(page.getByTestId('deferred-data')).toContainText( + 'Deferred data loaded!', + { timeout: 5000 }, + ) +}) diff --git a/e2e/react-start/streaming-ssr/tsconfig.json b/e2e/react-start/streaming-ssr/tsconfig.json index 3558337b0c1..f3895f6eb1d 100644 --- a/e2e/react-start/streaming-ssr/tsconfig.json +++ b/e2e/react-start/streaming-ssr/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/app/*"] }, diff --git a/e2e/react-start/transform-asset-urls/package.json b/e2e/react-start/transform-asset-urls/package.json index 7c9efd5caa5..3b482cec980 100644 --- a/e2e/react-start/transform-asset-urls/package.json +++ b/e2e/react-start/transform-asset-urls/package.json @@ -11,26 +11,28 @@ "manual:cdn": "CDN_PORT=3002 node tests/cdn-server.mjs", "manual:app": "pnpm build && PORT=3000 CDN_ORIGIN=http://localhost:3002 pnpm start", "manual:both": "sh -c \"CDN_PORT=3002 node tests/cdn-server.mjs & pnpm build && PORT=3000 CDN_ORIGIN=http://localhost:3002 pnpm start\"", - "manual:both:string": "TRANSFORM_ASSET_URLS_MODE=string pnpm manual:both", - "manual:both:function": "TRANSFORM_ASSET_URLS_MODE=function pnpm manual:both", - "manual:both:options": "TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=createTransform pnpm manual:both", - "manual:both:options:transform": "TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=transform pnpm manual:both", - "manual:both:options:createTransform": "TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=createTransform pnpm manual:both", - "test:e2e:string": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSET_URLS_MODE=string playwright test --project=chromium", - "test:e2e:function": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSET_URLS_MODE=function playwright test --project=chromium", - "test:e2e:options": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=transform playwright test --project=chromium", - "test:e2e:options:transform": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=transform playwright test --project=chromium", - "test:e2e:options:createTransform": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=createTransform playwright test --project=chromium", - "test:e2e:options:transform:cache-true:warmup-true": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=transform TRANSFORM_ASSET_URLS_OPTIONS_CACHE=true TRANSFORM_ASSET_URLS_OPTIONS_WARMUP=true playwright test --project=chromium", - "test:e2e:options:transform:cache-true:warmup-false": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=transform TRANSFORM_ASSET_URLS_OPTIONS_CACHE=true TRANSFORM_ASSET_URLS_OPTIONS_WARMUP=false playwright test --project=chromium", - "test:e2e:options:transform:cache-false:warmup-true": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=transform TRANSFORM_ASSET_URLS_OPTIONS_CACHE=false TRANSFORM_ASSET_URLS_OPTIONS_WARMUP=true playwright test --project=chromium", - "test:e2e:options:transform:cache-false:warmup-false": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=transform TRANSFORM_ASSET_URLS_OPTIONS_CACHE=false TRANSFORM_ASSET_URLS_OPTIONS_WARMUP=false playwright test --project=chromium", - "test:e2e:options:createTransform:cache-true:warmup-true": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=createTransform TRANSFORM_ASSET_URLS_OPTIONS_CACHE=true TRANSFORM_ASSET_URLS_OPTIONS_WARMUP=true playwright test --project=chromium", - "test:e2e:options:createTransform:cache-true:warmup-false": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=createTransform TRANSFORM_ASSET_URLS_OPTIONS_CACHE=true TRANSFORM_ASSET_URLS_OPTIONS_WARMUP=false playwright test --project=chromium", - "test:e2e:options:createTransform:cache-false:warmup-true": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=createTransform TRANSFORM_ASSET_URLS_OPTIONS_CACHE=false TRANSFORM_ASSET_URLS_OPTIONS_WARMUP=true playwright test --project=chromium", - "test:e2e:options:createTransform:cache-false:warmup-false": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSET_URLS_MODE=options TRANSFORM_ASSET_URLS_OPTIONS_KIND=createTransform TRANSFORM_ASSET_URLS_OPTIONS_CACHE=false TRANSFORM_ASSET_URLS_OPTIONS_WARMUP=false playwright test --project=chromium", + "manual:both:string": "TRANSFORM_ASSETS_MODE=string pnpm manual:both", + "manual:both:function": "TRANSFORM_ASSETS_MODE=function pnpm manual:both", + "manual:both:options": "TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=createTransform pnpm manual:both", + "manual:both:options:transform": "TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=transform pnpm manual:both", + "manual:both:options:createTransform": "TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=createTransform pnpm manual:both", + "manual:both:deprecated": "USE_DEPRECATED_TRANSFORM_ASSET_URLS=true TRANSFORM_ASSETS_MODE=function pnpm manual:both", + "test:e2e:string": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSETS_MODE=string playwright test --project=chromium", + "test:e2e:function": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSETS_MODE=function playwright test --project=chromium", + "test:e2e:deprecated": "rm -rf dist; rm -rf port*.txt; USE_DEPRECATED_TRANSFORM_ASSET_URLS=true TRANSFORM_ASSETS_MODE=function playwright test --project=chromium", + "test:e2e:options": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=transform playwright test --project=chromium", + "test:e2e:options:transform": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=transform playwright test --project=chromium", + "test:e2e:options:createTransform": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=createTransform playwright test --project=chromium", + "test:e2e:options:transform:cache-true:warmup-true": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=transform TRANSFORM_ASSETS_OPTIONS_CACHE=true TRANSFORM_ASSETS_OPTIONS_WARMUP=true playwright test --project=chromium", + "test:e2e:options:transform:cache-true:warmup-false": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=transform TRANSFORM_ASSETS_OPTIONS_CACHE=true TRANSFORM_ASSETS_OPTIONS_WARMUP=false playwright test --project=chromium", + "test:e2e:options:transform:cache-false:warmup-true": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=transform TRANSFORM_ASSETS_OPTIONS_CACHE=false TRANSFORM_ASSETS_OPTIONS_WARMUP=true playwright test --project=chromium", + "test:e2e:options:transform:cache-false:warmup-false": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=transform TRANSFORM_ASSETS_OPTIONS_CACHE=false TRANSFORM_ASSETS_OPTIONS_WARMUP=false playwright test --project=chromium", + "test:e2e:options:createTransform:cache-true:warmup-true": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=createTransform TRANSFORM_ASSETS_OPTIONS_CACHE=true TRANSFORM_ASSETS_OPTIONS_WARMUP=true playwright test --project=chromium", + "test:e2e:options:createTransform:cache-true:warmup-false": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=createTransform TRANSFORM_ASSETS_OPTIONS_CACHE=true TRANSFORM_ASSETS_OPTIONS_WARMUP=false playwright test --project=chromium", + "test:e2e:options:createTransform:cache-false:warmup-true": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=createTransform TRANSFORM_ASSETS_OPTIONS_CACHE=false TRANSFORM_ASSETS_OPTIONS_WARMUP=true playwright test --project=chromium", + "test:e2e:options:createTransform:cache-false:warmup-false": "rm -rf dist; rm -rf port*.txt; TRANSFORM_ASSETS_MODE=options TRANSFORM_ASSETS_OPTIONS_KIND=createTransform TRANSFORM_ASSETS_OPTIONS_CACHE=false TRANSFORM_ASSETS_OPTIONS_WARMUP=false playwright test --project=chromium", "test:e2e:options:matrix": "pnpm test:e2e:options:transform:cache-true:warmup-true && pnpm test:e2e:options:transform:cache-true:warmup-false && pnpm test:e2e:options:transform:cache-false:warmup-true && pnpm test:e2e:options:transform:cache-false:warmup-false && pnpm test:e2e:options:createTransform:cache-true:warmup-true && pnpm test:e2e:options:createTransform:cache-true:warmup-false && pnpm test:e2e:options:createTransform:cache-false:warmup-true && pnpm test:e2e:options:createTransform:cache-false:warmup-false", - "test:e2e": "pnpm test:e2e:string && pnpm test:e2e:function && pnpm test:e2e:options:matrix" + "test:e2e": "pnpm test:e2e:string && pnpm test:e2e:function && pnpm test:e2e:deprecated && pnpm test:e2e:options:matrix" }, "dependencies": { "@tanstack/react-router": "workspace:^", @@ -47,7 +49,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "srvx": "^0.11.9", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/e2e/react-start/transform-asset-urls/playwright.config.ts b/e2e/react-start/transform-asset-urls/playwright.config.ts index 53cc1b38df6..fe009fb9aff 100644 --- a/e2e/react-start/transform-asset-urls/playwright.config.ts +++ b/e2e/react-start/transform-asset-urls/playwright.config.ts @@ -7,11 +7,13 @@ const CDN_PORT = await getTestServerPort(`${packageJson.name}_cdn`) const baseURL = `http://localhost:${APP_PORT}` const cdnOrigin = `http://localhost:${CDN_PORT}` -const transformMode = process.env.TRANSFORM_ASSET_URLS_MODE || 'string' +const transformMode = process.env.TRANSFORM_ASSETS_MODE || 'string' const optionsKind = - process.env.TRANSFORM_ASSET_URLS_OPTIONS_KIND || 'createTransform' -const optionsCache = process.env.TRANSFORM_ASSET_URLS_OPTIONS_CACHE || 'true' -const optionsWarmup = process.env.TRANSFORM_ASSET_URLS_OPTIONS_WARMUP || 'true' + process.env.TRANSFORM_ASSETS_OPTIONS_KIND || 'createTransform' +const optionsCache = process.env.TRANSFORM_ASSETS_OPTIONS_CACHE || 'true' +const optionsWarmup = process.env.TRANSFORM_ASSETS_OPTIONS_WARMUP || 'true' +const useDeprecatedTransformAssetUrls = + process.env.USE_DEPRECATED_TRANSFORM_ASSET_URLS || 'false' export default defineConfig({ testDir: './tests', @@ -35,7 +37,7 @@ export default defineConfig({ }, { // App server — builds the project then starts the srvx server - // with CDN_ORIGIN so that transformAssetUrls rewrites manifest URLs + // with CDN_ORIGIN so that transformAssets rewrites manifest URLs command: `pnpm build && pnpm start`, url: baseURL, reuseExistingServer: !process.env.CI, @@ -43,10 +45,11 @@ export default defineConfig({ env: { PORT: String(APP_PORT), CDN_ORIGIN: cdnOrigin, - TRANSFORM_ASSET_URLS_MODE: transformMode, - TRANSFORM_ASSET_URLS_OPTIONS_KIND: optionsKind, - TRANSFORM_ASSET_URLS_OPTIONS_CACHE: optionsCache, - TRANSFORM_ASSET_URLS_OPTIONS_WARMUP: optionsWarmup, + TRANSFORM_ASSETS_MODE: transformMode, + TRANSFORM_ASSETS_OPTIONS_KIND: optionsKind, + TRANSFORM_ASSETS_OPTIONS_CACHE: optionsCache, + TRANSFORM_ASSETS_OPTIONS_WARMUP: optionsWarmup, + USE_DEPRECATED_TRANSFORM_ASSET_URLS: useDeprecatedTransformAssetUrls, }, timeout: 120_000, }, diff --git a/e2e/react-start/transform-asset-urls/src/routes/__root.tsx b/e2e/react-start/transform-asset-urls/src/routes/__root.tsx index 4d1f1321a1d..ff4961a1a4a 100644 --- a/e2e/react-start/transform-asset-urls/src/routes/__root.tsx +++ b/e2e/react-start/transform-asset-urls/src/routes/__root.tsx @@ -27,7 +27,12 @@ function RootComponent() { return ( - +
diff --git a/e2e/react-start/transform-asset-urls/src/routes/index.tsx b/e2e/react-start/transform-asset-urls/src/routes/index.tsx index e7aa38b8d90..1292f9757f9 100644 --- a/e2e/react-start/transform-asset-urls/src/routes/index.tsx +++ b/e2e/react-start/transform-asset-urls/src/routes/index.tsx @@ -9,7 +9,7 @@ function Home() {

Welcome Home

- This page tests the transformAssetUrls feature. + This page tests the transformAssets feature.

About diff --git a/e2e/react-start/transform-asset-urls/src/server.ts b/e2e/react-start/transform-asset-urls/src/server.ts index 1757f035962..e53d8f1f583 100644 --- a/e2e/react-start/transform-asset-urls/src/server.ts +++ b/e2e/react-start/transform-asset-urls/src/server.ts @@ -3,52 +3,127 @@ import { defaultStreamHandler, } from '@tanstack/react-start/server' import { createServerEntry } from '@tanstack/react-start/server-entry' +import type { TransformAssetUrls } from '@tanstack/react-start/server' + +type TransformAssetsFn = (ctx: { + kind: 'modulepreload' | 'stylesheet' | 'clientEntry' + url: string +}) => + | string + | { + href: string + crossOrigin?: 'anonymous' | 'use-credentials' + } const cdnOrigin = process.env.CDN_ORIGIN -const transformMode = process.env.TRANSFORM_ASSET_URLS_MODE || 'string' +const transformMode = process.env.TRANSFORM_ASSETS_MODE || 'string' const optionsKind = - process.env.TRANSFORM_ASSET_URLS_OPTIONS_KIND || 'createTransform' -const optionsCache = process.env.TRANSFORM_ASSET_URLS_OPTIONS_CACHE || 'true' -const optionsWarmup = process.env.TRANSFORM_ASSET_URLS_OPTIONS_WARMUP || 'true' + process.env.TRANSFORM_ASSETS_OPTIONS_KIND || 'createTransform' +const optionsCache = process.env.TRANSFORM_ASSETS_OPTIONS_CACHE || 'true' +const optionsWarmup = process.env.TRANSFORM_ASSETS_OPTIONS_WARMUP || 'true' +const useDeprecatedTransformAssetUrls = + process.env.USE_DEPRECATED_TRANSFORM_ASSET_URLS === 'true' const cache = optionsCache !== 'false' const warmup = optionsWarmup === 'true' console.log( - `[server-entry]: using custom server entry with transformAssetUrls (${transformMode}${transformMode === 'options' ? `:${optionsKind}` : ''})${cdnOrigin ? ` (CDN: ${cdnOrigin})` : ' (no CDN)'}`, + `[server-entry]: using custom server entry with ${useDeprecatedTransformAssetUrls ? 'transformAssetUrls' : 'transformAssets'} (${transformMode}${transformMode === 'options' ? `:${optionsKind}` : ''})${cdnOrigin ? ` (CDN: ${cdnOrigin})` : ' (no CDN)'}`, ) +const createTransformAssetsFn = + (cdn: string): TransformAssetsFn => + ({ kind, url }) => { + const href = `${cdn}${url}` + + if (kind === 'modulepreload') { + return { + href, + crossOrigin: 'anonymous', + } + } + + if (kind === 'stylesheet') { + return { + href, + crossOrigin: 'anonymous', + } + } + + return { href } + } + +const createTransformAssetsConfig = (cdn: string) => { + const transformAssetsFn = createTransformAssetsFn(cdn) + + if (transformMode === 'function') { + return transformAssetsFn + } + + if (transformMode === 'options') { + if (optionsKind === 'transform') { + return { + transform: transformAssetsFn, + cache, + warmup, + } + } + + return { + createTransform: async () => { + return transformAssetsFn + }, + cache, + warmup, + } + } + + return cdn +} + +const createDeprecatedTransformAssetUrlsConfig = ( + cdn: string, +): TransformAssetUrls => { + if (transformMode === 'function') { + return ({ url }) => `${cdn}${url}` + } + + if (transformMode === 'options') { + if (optionsKind === 'transform') { + return { + transform: ({ url }) => `${cdn}${url}`, + cache, + warmup, + } + } + + return { + createTransform: async () => { + return ({ url }) => `${cdn}${url}` + }, + cache, + warmup, + } + } + + return cdn +} + const handler = createStartHandler( cdnOrigin ? { handler: defaultStreamHandler, - transformAssetUrls: (() => { - const cdn = cdnOrigin.replace(/\/+$/, '') - - if (transformMode === 'function') { - return ({ url }: { url: string }) => `${cdn}${url}` - } - - if (transformMode === 'options') { - if (optionsKind === 'transform') { - return { - transform: ({ url }: { url: string }) => `${cdn}${url}`, - cache, - warmup, - } + ...(useDeprecatedTransformAssetUrls + ? { + transformAssetUrls: createDeprecatedTransformAssetUrlsConfig( + cdnOrigin.replace(/\/+$/, ''), + ), } - - return { - createTransform: async () => { - return ({ url }: { url: string }) => `${cdn}${url}` - }, - cache, - warmup, - } - } - - return cdn - })(), + : { + transformAssets: createTransformAssetsConfig( + cdnOrigin.replace(/\/+$/, ''), + ), + }), } : defaultStreamHandler, ) diff --git a/e2e/react-start/transform-asset-urls/tests/cdn-server.mjs b/e2e/react-start/transform-asset-urls/tests/cdn-server.mjs index 8b06bf6d606..a97f142e876 100644 --- a/e2e/react-start/transform-asset-urls/tests/cdn-server.mjs +++ b/e2e/react-start/transform-asset-urls/tests/cdn-server.mjs @@ -13,9 +13,22 @@ app.get('/health', (_req, res) => { res.status(200).send('ok') }) -// Serve the built client assets with CORS headers to simulate a CDN +// Serve the built client assets with CORS headers to simulate a CDN. +// Origin reflection is intentional for this test server: the e2e tests use +// crossorigin="use-credentials" which requires Access-Control-Allow-Origin +// to echo the requesting origin (wildcard '*' is not allowed with credentials). +// Do NOT copy this pattern for production — validate origins against an allowlist. app.use((req, res, next) => { - res.setHeader('Access-Control-Allow-Origin', '*') + const origin = req.headers.origin + + if (origin) { + res.setHeader('Access-Control-Allow-Origin', origin) + res.setHeader('Access-Control-Allow-Credentials', 'true') + res.setHeader('Vary', 'Origin') + } else { + res.setHeader('Access-Control-Allow-Origin', '*') + } + res.setHeader('Access-Control-Allow-Methods', 'GET, OPTIONS') res.setHeader('Access-Control-Allow-Headers', '*') next() diff --git a/e2e/react-start/transform-asset-urls/tests/transform-asset-urls.spec.ts b/e2e/react-start/transform-asset-urls/tests/transform-asset-urls.spec.ts index 5ab10da6f2f..b0064122433 100644 --- a/e2e/react-start/transform-asset-urls/tests/transform-asset-urls.spec.ts +++ b/e2e/react-start/transform-asset-urls/tests/transform-asset-urls.spec.ts @@ -19,23 +19,23 @@ async function getSSRHtml(page: Page, path = '/') { return response.text() } -test.describe('transformAssetUrls with CDN prefix', () => { +test.describe('transformAssets with CDN prefix', () => { test('test run mode is set (string|function|options)', async () => { - expect(process.env.TRANSFORM_ASSET_URLS_MODE).toMatch( + expect(process.env.TRANSFORM_ASSETS_MODE).toMatch( /^(string|function|options)$/, ) - if (process.env.TRANSFORM_ASSET_URLS_MODE === 'options') { - expect(process.env.TRANSFORM_ASSET_URLS_OPTIONS_KIND).toMatch( + if (process.env.TRANSFORM_ASSETS_MODE === 'options') { + const optionsCache = process.env.TRANSFORM_ASSETS_OPTIONS_CACHE || 'true' + const optionsWarmup = + process.env.TRANSFORM_ASSETS_OPTIONS_WARMUP || 'true' + + expect(process.env.TRANSFORM_ASSETS_OPTIONS_KIND).toMatch( /^(transform|createTransform)$/, ) - expect(process.env.TRANSFORM_ASSET_URLS_OPTIONS_CACHE).toMatch( - /^(true|false)$/, - ) - expect(process.env.TRANSFORM_ASSET_URLS_OPTIONS_WARMUP).toMatch( - /^(true|false)$/, - ) + expect(optionsCache).toMatch(/^(true|false)$/) + expect(optionsWarmup).toMatch(/^(true|false)$/) } }) @@ -56,6 +56,22 @@ test.describe('transformAssetUrls with CDN prefix', () => { } }) + test('SSR HTML contains expected crossorigin attributes', async ({ + page, + }) => { + const html = await getSSRHtml(page) + + const modulepreloadLink = html.match( + /]*rel="modulepreload"[^>]*crossorigin="anonymous"[^>]*>/, + ) + expect(modulepreloadLink).toBeTruthy() + + const stylesheetLink = html.match( + /]*rel="stylesheet"[^>]*crossorigin="use-credentials"[^>]*>/, + ) + expect(stylesheetLink).toBeTruthy() + }) + test('SSR HTML contains CDN-prefixed stylesheet link', async ({ page }) => { const html = await getSSRHtml(page) @@ -133,7 +149,7 @@ test.describe('transformAssetUrls with CDN prefix', () => { // Page content renders await expect(page.getByTestId('home-heading')).toHaveText('Welcome Home') await expect(page.getByTestId('home-content')).toContainText( - 'transformAssetUrls', + 'transformAssets', ) }) diff --git a/e2e/react-start/transform-asset-urls/tsconfig.json b/e2e/react-start/transform-asset-urls/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/transform-asset-urls/tsconfig.json +++ b/e2e/react-start/transform-asset-urls/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/virtual-routes/package.json b/e2e/react-start/virtual-routes/package.json index f0f142678bb..ffb57da3af8 100644 --- a/e2e/react-start/virtual-routes/package.json +++ b/e2e/react-start/virtual-routes/package.json @@ -34,6 +34,6 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/react-start/virtual-routes/tsconfig.json b/e2e/react-start/virtual-routes/tsconfig.json index d35a4b17f48..3824b148e15 100644 --- a/e2e/react-start/virtual-routes/tsconfig.json +++ b/e2e/react-start/virtual-routes/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/react-start/website/package.json b/e2e/react-start/website/package.json index 3c99c1f8173..6c888e0db4a 100644 --- a/e2e/react-start/website/package.json +++ b/e2e/react-start/website/package.json @@ -31,7 +31,7 @@ "@vitejs/plugin-react": "^6.0.1", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/e2e/react-start/website/tsconfig.json b/e2e/react-start/website/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/e2e/react-start/website/tsconfig.json +++ b/e2e/react-start/website/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-router/basic-file-based-code-splitting/src/vite-env.d.ts b/e2e/solid-router/basic-file-based-code-splitting/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/basic-file-based-code-splitting/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/basic-file-based/src/vite-env.d.ts b/e2e/solid-router/basic-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/basic-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/basic-scroll-restoration/package.json b/e2e/solid-router/basic-scroll-restoration/package.json index 4dd271be172..f1cdc3cefad 100644 --- a/e2e/solid-router/basic-scroll-restoration/package.json +++ b/e2e/solid-router/basic-scroll-restoration/package.json @@ -24,6 +24,7 @@ "@playwright/test": "^1.50.1", "@tanstack/router-e2e-utils": "workspace:^", "vite": "^8.0.0", - "vite-plugin-solid": "3.0.0-next.4" + "vite-plugin-solid": "3.0.0-next.4", + "typescript": "~5.9.0" } } diff --git a/e2e/solid-router/basic-scroll-restoration/src/vite-env.d.ts b/e2e/solid-router/basic-scroll-restoration/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/basic-scroll-restoration/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/basic-solid-query-file-based/src/vite-env.d.ts b/e2e/solid-router/basic-solid-query-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/basic-solid-query-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/basic-solid-query/src/vite-env.d.ts b/e2e/solid-router/basic-solid-query/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/basic-solid-query/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/basic-virtual-file-based/src/vite-env.d.ts b/e2e/solid-router/basic-virtual-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/basic-virtual-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/basic-virtual-named-export-config-file-based/src/vite-env.d.ts b/e2e/solid-router/basic-virtual-named-export-config-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/basic-virtual-named-export-config-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/basic/src/vite-env.d.ts b/e2e/solid-router/basic/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/basic/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/generator-cli-only/src/vite-env.d.ts b/e2e/solid-router/generator-cli-only/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/generator-cli-only/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/js-only-file-based/src/vite-env.d.ts b/e2e/solid-router/js-only-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/js-only-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/rspack-basic-file-based/package.json b/e2e/solid-router/rspack-basic-file-based/package.json index d317430b7a8..0a3f3cdddcd 100644 --- a/e2e/solid-router/rspack-basic-file-based/package.json +++ b/e2e/solid-router/rspack-basic-file-based/package.json @@ -26,6 +26,6 @@ "@tanstack/router-plugin": "workspace:^", "postcss": "^8.5.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/solid-router/rspack-basic-file-based/src/vite-env.d.ts b/e2e/solid-router/rspack-basic-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/rspack-basic-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/rspack-basic-file-based/tsconfig.json b/e2e/solid-router/rspack-basic-file-based/tsconfig.json index e4741a7cfe8..a023bcef576 100644 --- a/e2e/solid-router/rspack-basic-file-based/tsconfig.json +++ b/e2e/solid-router/rspack-basic-file-based/tsconfig.json @@ -13,6 +13,6 @@ "useDefineForClassFields": true, "allowJs": true }, - "include": ["src", "playwright.config.ts", "tests"], + "include": ["src", "tests"], "exclude": ["node_modules", "dist"] } diff --git a/e2e/solid-router/rspack-basic-virtual-named-export-config-file-based/package.json b/e2e/solid-router/rspack-basic-virtual-named-export-config-file-based/package.json index 9051de14b4a..f998fc6e06b 100644 --- a/e2e/solid-router/rspack-basic-virtual-named-export-config-file-based/package.json +++ b/e2e/solid-router/rspack-basic-virtual-named-export-config-file-based/package.json @@ -27,6 +27,6 @@ "@tanstack/virtual-file-routes": "workspace:^", "postcss": "^8.5.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/solid-router/rspack-basic-virtual-named-export-config-file-based/src/vite-env.d.ts b/e2e/solid-router/rspack-basic-virtual-named-export-config-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/rspack-basic-virtual-named-export-config-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/rspack-basic-virtual-named-export-config-file-based/tsconfig.json b/e2e/solid-router/rspack-basic-virtual-named-export-config-file-based/tsconfig.json index 88b60cea21f..ce2e856442b 100644 --- a/e2e/solid-router/rspack-basic-virtual-named-export-config-file-based/tsconfig.json +++ b/e2e/solid-router/rspack-basic-virtual-named-export-config-file-based/tsconfig.json @@ -13,6 +13,6 @@ "useDefineForClassFields": true, "allowJs": true }, - "include": ["src", "playwright.config.ts", "tests", "./routes.ts"], + "include": ["src", "tests", "./routes.ts"], "exclude": ["node_modules", "dist"] } diff --git a/e2e/solid-router/scroll-restoration-sandbox-vite/src/vite-env.d.ts b/e2e/solid-router/scroll-restoration-sandbox-vite/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/scroll-restoration-sandbox-vite/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/sentry-integration/src/vite-env.d.ts b/e2e/solid-router/sentry-integration/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/sentry-integration/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-router/view-transitions/package.json b/e2e/solid-router/view-transitions/package.json index 435b34527c7..1d66e93e567 100644 --- a/e2e/solid-router/view-transitions/package.json +++ b/e2e/solid-router/view-transitions/package.json @@ -25,7 +25,7 @@ "@playwright/test": "^1.50.1", "@tanstack/router-e2e-utils": "workspace:^", "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/e2e/solid-router/view-transitions/src/vite-env.d.ts b/e2e/solid-router/view-transitions/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-router/view-transitions/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-start/basic-auth/package.json b/e2e/solid-start/basic-auth/package.json index 5c8aaf08aa0..9e87f79a2f3 100644 --- a/e2e/solid-start/basic-auth/package.json +++ b/e2e/solid-start/basic-auth/package.json @@ -34,8 +34,7 @@ "prisma": "^7.0.0", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", - "vite-plugin-solid": "3.0.0-next.4", - "vite-tsconfig-paths": "^5.1.4" + "typescript": "^6.0.2", + "vite-plugin-solid": "3.0.0-next.4" } } diff --git a/e2e/solid-start/basic-auth/tsconfig.json b/e2e/solid-start/basic-auth/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/e2e/solid-start/basic-auth/tsconfig.json +++ b/e2e/solid-start/basic-auth/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/basic-cloudflare/package.json b/e2e/solid-start/basic-cloudflare/package.json index a3a0ea90eb8..78085489b86 100644 --- a/e2e/solid-start/basic-cloudflare/package.json +++ b/e2e/solid-start/basic-cloudflare/package.json @@ -26,7 +26,7 @@ "@tanstack/router-e2e-utils": "workspace:^", "@types/node": "^22.10.2", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4", diff --git a/e2e/solid-start/basic-cloudflare/tsconfig.json b/e2e/solid-start/basic-cloudflare/tsconfig.json index ed8b73fa2dd..c34f9d7c361 100644 --- a/e2e/solid-start/basic-cloudflare/tsconfig.json +++ b/e2e/solid-start/basic-cloudflare/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/basic-prerender/.gitignore b/e2e/solid-start/basic-prerender/.gitignore new file mode 100644 index 00000000000..6381bf3860f --- /dev/null +++ b/e2e/solid-start/basic-prerender/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/test-results/ +/playwright-report/ +/blob-report/ diff --git a/e2e/solid-start/basic-prerender/package.json b/e2e/solid-start/basic-prerender/package.json new file mode 100644 index 00000000000..eda156f8e3a --- /dev/null +++ b/e2e/solid-start/basic-prerender/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-solid-start-e2e-basic-prerender", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "test:e2e:startDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.setup.ts\").then(m => m.default())' & node -e 'import(\"../basic-test-suite/src/setup/waitForDummyServer.ts\").then(m => m.default())'", + "test:e2e:stopDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.teardown.ts\").then(m => m.default())'", + "test:e2e": "rm -rf port*.txt; MODE=prerender playwright test --project=chromium" + }, + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tanstack/router-e2e-utils": "workspace:^", + "tanstack-solid-start-e2e-basic": "workspace:*", + "tanstack-solid-start-e2e-basic-test-suite": "workspace:*" + }, + "nx": { + "targets": { + "test:e2e": { + "parallelism": false + } + } + } +} diff --git a/e2e/solid-start/basic-prerender/playwright.config.ts b/e2e/solid-start/basic-prerender/playwright.config.ts new file mode 100644 index 00000000000..cf2cf5d396e --- /dev/null +++ b/e2e/solid-start/basic-prerender/playwright.config.ts @@ -0,0 +1,48 @@ +import { defineConfig, devices } from '@playwright/test' +import { + getDummyServerPort, + getTestServerPort, +} from '@tanstack/router-e2e-utils' +import packageJson from './package.json' with { type: 'json' } + +const PORT = await getTestServerPort(packageJson.name) +const START_PORT = await getTestServerPort(`${packageJson.name}_start`) +const EXTERNAL_PORT = await getDummyServerPort(packageJson.name) +const baseURL = `http://localhost:${PORT}` + +export default defineConfig({ + testDir: '../basic-test-suite/src', + workers: 1, + reporter: [['line']], + + globalTeardown: '../basic-test-suite/src/setup/global.teardown.ts', + + use: { + baseURL, + }, + + webServer: { + command: + 'pnpm run test:e2e:startDummyServer && pnpm --dir ../basic build:prerender && pnpm --dir ../basic start', + url: baseURL, + reuseExistingServer: !process.env.CI, + stdout: 'pipe', + env: { + MODE: 'prerender', + VITE_NODE_ENV: 'test', + VITE_EXTERNAL_PORT: String(EXTERNAL_PORT), + VITE_SERVER_PORT: String(PORT), + START_PORT: String(START_PORT), + PORT: String(PORT), + }, + }, + + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + }, + }, + ], +}) diff --git a/e2e/solid-start/basic-preview/.gitignore b/e2e/solid-start/basic-preview/.gitignore new file mode 100644 index 00000000000..6381bf3860f --- /dev/null +++ b/e2e/solid-start/basic-preview/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/test-results/ +/playwright-report/ +/blob-report/ diff --git a/e2e/solid-start/basic-preview/package.json b/e2e/solid-start/basic-preview/package.json new file mode 100644 index 00000000000..233d6af6093 --- /dev/null +++ b/e2e/solid-start/basic-preview/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-solid-start-e2e-basic-preview", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "test:e2e:startDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.setup.ts\").then(m => m.default())' & node -e 'import(\"../basic-test-suite/src/setup/waitForDummyServer.ts\").then(m => m.default())'", + "test:e2e:stopDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.teardown.ts\").then(m => m.default())'", + "test:e2e": "rm -rf port*.txt; MODE=preview playwright test --project=chromium" + }, + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tanstack/router-e2e-utils": "workspace:^", + "tanstack-solid-start-e2e-basic": "workspace:*", + "tanstack-solid-start-e2e-basic-test-suite": "workspace:*" + }, + "nx": { + "targets": { + "test:e2e": { + "parallelism": false + } + } + } +} diff --git a/e2e/solid-start/basic-preview/playwright.config.ts b/e2e/solid-start/basic-preview/playwright.config.ts new file mode 100644 index 00000000000..071f336f9f1 --- /dev/null +++ b/e2e/solid-start/basic-preview/playwright.config.ts @@ -0,0 +1,47 @@ +import { defineConfig, devices } from '@playwright/test' +import { + getDummyServerPort, + getTestServerPort, +} from '@tanstack/router-e2e-utils' +import packageJson from './package.json' with { type: 'json' } + +const PORT = await getTestServerPort(packageJson.name) +const START_PORT = await getTestServerPort(`${packageJson.name}_start`) +const EXTERNAL_PORT = await getDummyServerPort(packageJson.name) +const baseURL = `http://localhost:${PORT}` + +export default defineConfig({ + testDir: '../basic-test-suite/src', + workers: 1, + reporter: [['line']], + + globalTeardown: '../basic-test-suite/src/setup/global.teardown.ts', + + use: { + baseURL, + }, + + webServer: { + command: `pnpm run test:e2e:startDummyServer && pnpm --dir ../basic build && pnpm --dir ../basic preview --port ${PORT}`, + url: baseURL, + reuseExistingServer: !process.env.CI, + stdout: 'pipe', + env: { + MODE: 'preview', + VITE_NODE_ENV: 'test', + VITE_EXTERNAL_PORT: String(EXTERNAL_PORT), + VITE_SERVER_PORT: String(PORT), + START_PORT: String(START_PORT), + PORT: String(PORT), + }, + }, + + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + }, + }, + ], +}) diff --git a/e2e/solid-start/basic-solid-query/package.json b/e2e/solid-start/basic-solid-query/package.json index 0f997ae9b17..eb06e2e333e 100644 --- a/e2e/solid-start/basic-solid-query/package.json +++ b/e2e/solid-start/basic-solid-query/package.json @@ -32,8 +32,7 @@ "@types/node": "^22.10.2", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", - "vite-plugin-solid": "3.0.0-next.4", - "vite-tsconfig-paths": "^5.1.4" + "typescript": "^6.0.2", + "vite-plugin-solid": "3.0.0-next.4" } } diff --git a/e2e/solid-start/basic-solid-query/tsconfig.json b/e2e/solid-start/basic-solid-query/tsconfig.json index ed8b73fa2dd..c34f9d7c361 100644 --- a/e2e/solid-start/basic-solid-query/tsconfig.json +++ b/e2e/solid-start/basic-solid-query/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/basic-spa/.gitignore b/e2e/solid-start/basic-spa/.gitignore new file mode 100644 index 00000000000..6381bf3860f --- /dev/null +++ b/e2e/solid-start/basic-spa/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/test-results/ +/playwright-report/ +/blob-report/ diff --git a/e2e/solid-start/basic-spa/package.json b/e2e/solid-start/basic-spa/package.json new file mode 100644 index 00000000000..c9f02837364 --- /dev/null +++ b/e2e/solid-start/basic-spa/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-solid-start-e2e-basic-spa", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "test:e2e:startDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.setup.ts\").then(m => m.default())' & node -e 'import(\"../basic-test-suite/src/setup/waitForDummyServer.ts\").then(m => m.default())'", + "test:e2e:stopDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.teardown.ts\").then(m => m.default())'", + "test:e2e": "rm -rf port*.txt; MODE=spa playwright test --project=chromium" + }, + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tanstack/router-e2e-utils": "workspace:^", + "tanstack-solid-start-e2e-basic": "workspace:*", + "tanstack-solid-start-e2e-basic-test-suite": "workspace:*" + }, + "nx": { + "targets": { + "test:e2e": { + "parallelism": false + } + } + } +} diff --git a/e2e/solid-start/basic-spa/playwright.config.ts b/e2e/solid-start/basic-spa/playwright.config.ts new file mode 100644 index 00000000000..27e85e1f1a4 --- /dev/null +++ b/e2e/solid-start/basic-spa/playwright.config.ts @@ -0,0 +1,48 @@ +import { defineConfig, devices } from '@playwright/test' +import { + getDummyServerPort, + getTestServerPort, +} from '@tanstack/router-e2e-utils' +import packageJson from './package.json' with { type: 'json' } + +const PORT = await getTestServerPort(packageJson.name) +const START_PORT = await getTestServerPort(`${packageJson.name}_start`) +const EXTERNAL_PORT = await getDummyServerPort(packageJson.name) +const baseURL = `http://localhost:${PORT}` + +export default defineConfig({ + testDir: '../basic-test-suite/src', + workers: 1, + reporter: [['line']], + + globalTeardown: '../basic-test-suite/src/setup/global.teardown.ts', + + use: { + baseURL, + }, + + webServer: { + command: + 'pnpm run test:e2e:startDummyServer && pnpm --dir ../basic build:spa && pnpm --dir ../basic start', + url: baseURL, + reuseExistingServer: !process.env.CI, + stdout: 'pipe', + env: { + MODE: 'spa', + VITE_NODE_ENV: 'test', + VITE_EXTERNAL_PORT: String(EXTERNAL_PORT), + VITE_SERVER_PORT: String(PORT), + START_PORT: String(START_PORT), + PORT: String(PORT), + }, + }, + + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + }, + }, + ], +}) diff --git a/e2e/solid-start/basic-test-suite/.gitignore b/e2e/solid-start/basic-test-suite/.gitignore new file mode 100644 index 00000000000..6381bf3860f --- /dev/null +++ b/e2e/solid-start/basic-test-suite/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/test-results/ +/playwright-report/ +/blob-report/ diff --git a/e2e/solid-start/basic-test-suite/package.json b/e2e/solid-start/basic-test-suite/package.json new file mode 100644 index 00000000000..775f9fc5988 --- /dev/null +++ b/e2e/solid-start/basic-test-suite/package.json @@ -0,0 +1,12 @@ +{ + "name": "tanstack-solid-start-e2e-basic-test-suite", + "private": true, + "sideEffects": false, + "type": "module", + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tanstack/router-e2e-utils": "workspace:^", + "@types/node": "^22.10.2", + "combinate": "^1.1.11" + } +} diff --git a/e2e/solid-start/basic/tests/navigation.spec.ts b/e2e/solid-start/basic-test-suite/src/navigation.spec.ts similarity index 100% rename from e2e/solid-start/basic/tests/navigation.spec.ts rename to e2e/solid-start/basic-test-suite/src/navigation.spec.ts diff --git a/e2e/solid-start/basic/tests/not-found.spec.ts b/e2e/solid-start/basic-test-suite/src/not-found.spec.ts similarity index 98% rename from e2e/solid-start/basic/tests/not-found.spec.ts rename to e2e/solid-start/basic-test-suite/src/not-found.spec.ts index e6b8a8540ff..e8889cca164 100644 --- a/e2e/solid-start/basic/tests/not-found.spec.ts +++ b/e2e/solid-start/basic-test-suite/src/not-found.spec.ts @@ -1,7 +1,7 @@ import { expect } from '@playwright/test' import combinateImport from 'combinate' import { test } from '@tanstack/router-e2e-utils' -import { isSpaMode } from '../tests/utils/isSpaMode' +import { isSpaMode } from './utils/isSpaMode' // somehow playwright does not correctly import default exports const combinate = (combinateImport as any).default as typeof combinateImport diff --git a/e2e/react-start/basic/tests/prerendering.spec.ts b/e2e/solid-start/basic-test-suite/src/prerendering.spec.ts similarity index 90% rename from e2e/react-start/basic/tests/prerendering.spec.ts rename to e2e/solid-start/basic-test-suite/src/prerendering.spec.ts index 8506ff9b061..66cc1f68ff2 100644 --- a/e2e/react-start/basic/tests/prerendering.spec.ts +++ b/e2e/solid-start/basic-test-suite/src/prerendering.spec.ts @@ -3,13 +3,14 @@ import { join } from 'node:path' import { expect } from '@playwright/test' import { test } from '@tanstack/router-e2e-utils' import { isPrerender } from './utils/isPrerender' +import { getBasicAppRoot } from './utils/getBasicAppRoot' test.describe('Prerender Static Path Discovery', () => { test.skip(!isPrerender, 'Skipping since not in prerender mode') test.describe('Build Output Verification', () => { test('should automatically discover and prerender static routes', () => { // Check that static routes were automatically discovered and prerendered - const distDir = join(process.cwd(), 'dist', 'client') + const distDir = join(getBasicAppRoot(), 'dist', 'client') // These static routes should be automatically discovered and prerendered expect(existsSync(join(distDir, 'index.html'))).toBe(true) @@ -34,7 +35,7 @@ test.describe('Prerender Static Path Discovery', () => { test.describe('Static Files Verification', () => { test('should contain prerendered content in posts.html', () => { - const distDir = join(process.cwd(), 'dist', 'client') + const distDir = join(getBasicAppRoot(), 'dist', 'client') expect(existsSync(join(distDir, 'posts/index.html'))).toBe(true) // "Select a post." should be in the prerendered HTML diff --git a/e2e/solid-start/basic/tests/redirect.spec.ts b/e2e/solid-start/basic-test-suite/src/redirect.spec.ts similarity index 95% rename from e2e/solid-start/basic/tests/redirect.spec.ts rename to e2e/solid-start/basic-test-suite/src/redirect.spec.ts index b52ce026afe..c25a6b0dbf4 100644 --- a/e2e/solid-start/basic/tests/redirect.spec.ts +++ b/e2e/solid-start/basic-test-suite/src/redirect.spec.ts @@ -6,17 +6,14 @@ import { getTestServerPort, test, } from '@tanstack/router-e2e-utils' -import packageJson from '../package.json' with { type: 'json' } -import { isSpaMode } from '../tests/utils/isSpaMode' -import { isPreview } from '../tests/utils/isPreview' +import { getPackageName } from './utils/getPackageName.ts' // somehow playwright does not correctly import default exports const combinate = (combinateImport as any).default as typeof combinateImport -const PORT = await getTestServerPort( - `${packageJson.name}${isSpaMode ? '_spa' : ''}${isPreview ? '_preview' : ''}`, -) -const EXTERNAL_HOST_PORT = await getDummyServerPort(packageJson.name) +const packageName = getPackageName() +const PORT = await getTestServerPort(packageName) +const EXTERNAL_HOST_PORT = await getDummyServerPort(packageName) test.describe('redirects', () => { const internalNavigationTestMatrix = combinate({ diff --git a/e2e/solid-start/basic/tests/script-duplication.spec.ts b/e2e/solid-start/basic-test-suite/src/script-duplication.spec.ts similarity index 100% rename from e2e/solid-start/basic/tests/script-duplication.spec.ts rename to e2e/solid-start/basic-test-suite/src/script-duplication.spec.ts diff --git a/e2e/solid-start/basic/tests/search-params.spec.ts b/e2e/solid-start/basic-test-suite/src/search-params.spec.ts similarity index 98% rename from e2e/solid-start/basic/tests/search-params.spec.ts rename to e2e/solid-start/basic-test-suite/src/search-params.spec.ts index 74c1aa54dc9..cdf5a21b4ae 100644 --- a/e2e/solid-start/basic/tests/search-params.spec.ts +++ b/e2e/solid-start/basic-test-suite/src/search-params.spec.ts @@ -1,6 +1,6 @@ import { expect } from '@playwright/test' import { test } from '@tanstack/router-e2e-utils' -import { isSpaMode } from 'tests/utils/isSpaMode' +import { isSpaMode } from './utils/isSpaMode' import { isPrerender } from './utils/isPrerender' import type { Response } from '@playwright/test' diff --git a/e2e/solid-start/basic-test-suite/src/setup/global.setup.ts b/e2e/solid-start/basic-test-suite/src/setup/global.setup.ts new file mode 100644 index 00000000000..fc06a655910 --- /dev/null +++ b/e2e/solid-start/basic-test-suite/src/setup/global.setup.ts @@ -0,0 +1,6 @@ +import { e2eStartDummyServer } from '@tanstack/router-e2e-utils' +import { getPackageName } from '../utils/getPackageName.ts' + +export default async function setup() { + await e2eStartDummyServer(getPackageName()) +} diff --git a/e2e/solid-start/basic-test-suite/src/setup/global.teardown.ts b/e2e/solid-start/basic-test-suite/src/setup/global.teardown.ts new file mode 100644 index 00000000000..a8a68997009 --- /dev/null +++ b/e2e/solid-start/basic-test-suite/src/setup/global.teardown.ts @@ -0,0 +1,8 @@ +import { e2eStopDummyServer } from '@tanstack/router-e2e-utils' +import { getPackageName } from '../utils/getPackageName.ts' + +export default async function teardown() { + try { + await e2eStopDummyServer(getPackageName()) + } catch {} +} diff --git a/e2e/solid-start/basic-test-suite/src/setup/waitForDummyServer.ts b/e2e/solid-start/basic-test-suite/src/setup/waitForDummyServer.ts new file mode 100644 index 00000000000..f27dc86d5b8 --- /dev/null +++ b/e2e/solid-start/basic-test-suite/src/setup/waitForDummyServer.ts @@ -0,0 +1,24 @@ +import { getDummyServerPort } from '@tanstack/router-e2e-utils' +import { getPackageName } from '../utils/getPackageName.ts' + +const timeoutMs = 10_000 +const retryIntervalMs = 100 + +export default async function waitForDummyServer() { + const port = await getDummyServerPort(getPackageName()) + const deadline = Date.now() + timeoutMs + + while (Date.now() < deadline) { + try { + const response = await fetch(`http://localhost:${port}/`) + + if (response.ok) { + return + } + } catch {} + + await new Promise((resolve) => setTimeout(resolve, retryIntervalMs)) + } + + throw new Error(`Timed out waiting for dummy server on port ${port}`) +} diff --git a/e2e/solid-start/basic/tests/special-characters.spec.ts b/e2e/solid-start/basic-test-suite/src/special-characters.spec.ts similarity index 100% rename from e2e/solid-start/basic/tests/special-characters.spec.ts rename to e2e/solid-start/basic-test-suite/src/special-characters.spec.ts diff --git a/e2e/solid-start/basic/tests/streaming.spec.ts b/e2e/solid-start/basic-test-suite/src/streaming.spec.ts similarity index 100% rename from e2e/solid-start/basic/tests/streaming.spec.ts rename to e2e/solid-start/basic-test-suite/src/streaming.spec.ts diff --git a/e2e/solid-start/basic/tests/transition.spec.ts b/e2e/solid-start/basic-test-suite/src/transition.spec.ts similarity index 51% rename from e2e/solid-start/basic/tests/transition.spec.ts rename to e2e/solid-start/basic-test-suite/src/transition.spec.ts index 36e8df6dcb5..478fdc55576 100644 --- a/e2e/solid-start/basic/tests/transition.spec.ts +++ b/e2e/solid-start/basic-test-suite/src/transition.spec.ts @@ -3,6 +3,16 @@ import { expect, test } from '@playwright/test' test('transitions/count/create-resource should keep old values visible during navigation', async ({ page, }) => { + const burstClicks = async (count: number) => { + await page + .getByTestId('increase-button') + .evaluate((element, clickCount) => { + for (let index = 0; index < clickCount; index++) { + ;(element as HTMLAnchorElement).click() + } + }, count) + } + await page.goto('/transition/count/create-resource') await expect(page.getByTestId('n-value')).toContainText('n: 1') @@ -18,7 +28,9 @@ test('transitions/count/create-resource should keep old values visible during na if (text) bodyTexts.push(text) }, 50) - await page.getByTestId('increase-button').click() + // 1 click + + await burstClicks(1) await expect(page.getByTestId('n-value')).toContainText('n: 1', { timeout: 2_000, @@ -31,7 +43,47 @@ test('transitions/count/create-resource should keep old values visible during na timeout: 5000, }) await expect(page.getByTestId('double-value')).toContainText('double: 4', { - timeout: 5000, + timeout: 2000, + }) + + // 2 clicks + + await burstClicks(2) + + await expect(page.getByTestId('n-value')).toContainText('n: 2', { + timeout: 2000, + }) + await expect(page.getByTestId('double-value')).toContainText('double: 4', { + timeout: 2000, + }) + + await page.waitForTimeout(200) + + await expect(page.getByTestId('n-value')).toContainText('n: 4', { + timeout: 2000, + }) + await expect(page.getByTestId('double-value')).toContainText('double: 8', { + timeout: 2000, + }) + + // 3 clicks + + await burstClicks(3) + + await expect(page.getByTestId('n-value')).toContainText('n: 4', { + timeout: 2000, + }) + await expect(page.getByTestId('double-value')).toContainText('double: 8', { + timeout: 2000, + }) + + await page.waitForTimeout(200) + + await expect(page.getByTestId('n-value')).toContainText('n: 7', { + timeout: 2000, + }) + await expect(page.getByTestId('double-value')).toContainText('double: 14', { + timeout: 2000, }) clearInterval(pollInterval) diff --git a/e2e/solid-start/basic-test-suite/src/utils/getBasicAppRoot.ts b/e2e/solid-start/basic-test-suite/src/utils/getBasicAppRoot.ts new file mode 100644 index 00000000000..12a411989a2 --- /dev/null +++ b/e2e/solid-start/basic-test-suite/src/utils/getBasicAppRoot.ts @@ -0,0 +1,8 @@ +import { join } from 'node:path' +import { getPackageName } from './getPackageName.ts' + +export function getBasicAppRoot() { + return getPackageName().endsWith('-basic') + ? process.cwd() + : join(process.cwd(), '../basic') +} diff --git a/e2e/solid-start/basic-test-suite/src/utils/getPackageName.ts b/e2e/solid-start/basic-test-suite/src/utils/getPackageName.ts new file mode 100644 index 00000000000..6bd2e0499ed --- /dev/null +++ b/e2e/solid-start/basic-test-suite/src/utils/getPackageName.ts @@ -0,0 +1,16 @@ +import { readFileSync } from 'node:fs' +import { join } from 'node:path' + +let packageName: string | undefined + +export function getPackageName() { + if (!packageName) { + const packageJson = JSON.parse( + readFileSync(join(process.cwd(), 'package.json'), 'utf-8'), + ) as { name: string } + + packageName = packageJson.name + } + + return packageName +} diff --git a/e2e/solid-start/basic-test-suite/src/utils/isPrerender.ts b/e2e/solid-start/basic-test-suite/src/utils/isPrerender.ts new file mode 100644 index 00000000000..d5d991d4545 --- /dev/null +++ b/e2e/solid-start/basic-test-suite/src/utils/isPrerender.ts @@ -0,0 +1 @@ +export const isPrerender: boolean = process.env.MODE === 'prerender' diff --git a/e2e/solid-start/basic-test-suite/src/utils/isPreview.ts b/e2e/solid-start/basic-test-suite/src/utils/isPreview.ts new file mode 100644 index 00000000000..7ea362a83ed --- /dev/null +++ b/e2e/solid-start/basic-test-suite/src/utils/isPreview.ts @@ -0,0 +1 @@ +export const isPreview: boolean = process.env.MODE === 'preview' diff --git a/e2e/solid-start/basic-test-suite/src/utils/isSpaMode.ts b/e2e/solid-start/basic-test-suite/src/utils/isSpaMode.ts new file mode 100644 index 00000000000..b4edb829a8f --- /dev/null +++ b/e2e/solid-start/basic-test-suite/src/utils/isSpaMode.ts @@ -0,0 +1 @@ +export const isSpaMode: boolean = process.env.MODE === 'spa' diff --git a/e2e/solid-start/basic-test-suite/tsconfig.json b/e2e/solid-start/basic-test-suite/tsconfig.json new file mode 100644 index 00000000000..3f3dbe6bcd7 --- /dev/null +++ b/e2e/solid-start/basic-test-suite/tsconfig.json @@ -0,0 +1,18 @@ +{ + "include": ["src/**/*.ts"], + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "isolatedModules": true, + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "target": "ES2022", + "types": ["node"], + "forceConsistentCasingInFileNames": true, + "noEmit": true + } +} diff --git a/e2e/solid-start/basic-tsr-config/package.json b/e2e/solid-start/basic-tsr-config/package.json index 7600b5ab9a0..3ee011203a7 100644 --- a/e2e/solid-start/basic-tsr-config/package.json +++ b/e2e/solid-start/basic-tsr-config/package.json @@ -22,8 +22,7 @@ "@tanstack/router-e2e-utils": "workspace:^", "@types/node": "^22.10.2", "srvx": "^0.11.9", - "typescript": "^5.7.2", - "vite-plugin-solid": "3.0.0-next.4", - "vite-tsconfig-paths": "^5.1.4" + "typescript": "^6.0.2", + "vite-plugin-solid": "3.0.0-next.4" } } diff --git a/e2e/solid-start/basic-tsr-config/tsconfig.json b/e2e/solid-start/basic-tsr-config/tsconfig.json index f25bc0863b2..51ca13850e9 100644 --- a/e2e/solid-start/basic-tsr-config/tsconfig.json +++ b/e2e/solid-start/basic-tsr-config/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/app/*"] }, diff --git a/e2e/solid-start/basic/package.json b/e2e/solid-start/basic/package.json index 531c80e6077..e162ef7ea67 100644 --- a/e2e/solid-start/basic/package.json +++ b/e2e/solid-start/basic/package.json @@ -11,13 +11,9 @@ "build:prerender": "MODE=prerender vite build && tsc --noEmit", "preview": "vite preview", "start": "node server.js", - "test:e2e:startDummyServer": "node -e 'import(\"./tests/setup/global.setup.ts\").then(m => m.default())' &", - "test:e2e:stopDummyServer": "node -e 'import(\"./tests/setup/global.teardown.ts\").then(m => m.default())'", - "test:e2e:spaMode": "rm -rf port*.txt; MODE=spa playwright test --project=chromium", - "test:e2e:ssrMode": "rm -rf port*.txt; playwright test --project=chromium", - "test:e2e:prerender": "rm -rf port*.txt; MODE=prerender playwright test --project=chromium", - "test:e2e:preview": "rm -rf port*.txt; MODE=preview playwright test --project=chromium", - "test:e2e": "pnpm run test:e2e:spaMode && pnpm run test:e2e:ssrMode && pnpm run test:e2e:prerender && pnpm run test:e2e:preview" + "test:e2e:startDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.setup.ts\").then(m => m.default())' & node -e 'import(\"../basic-test-suite/src/setup/waitForDummyServer.ts\").then(m => m.default())'", + "test:e2e:stopDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.teardown.ts\").then(m => m.default())'", + "test:e2e": "rm -rf dist; rm -rf port*.txt; playwright test --project=chromium" }, "dependencies": { "@tanstack/solid-router": "workspace:^", @@ -42,8 +38,15 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", - "vite-plugin-solid": "3.0.0-next.4", - "vite-tsconfig-paths": "^5.1.4" + "tanstack-solid-start-e2e-basic-test-suite": "workspace:*", + "typescript": "^6.0.2", + "vite-plugin-solid": "3.0.0-next.4" + }, + "nx": { + "targets": { + "test:e2e": { + "parallelism": false + } + } } } diff --git a/e2e/solid-start/basic/playwright.config.ts b/e2e/solid-start/basic/playwright.config.ts index 86c58bc1ce3..0bc99a1ec44 100644 --- a/e2e/solid-start/basic/playwright.config.ts +++ b/e2e/solid-start/basic/playwright.config.ts @@ -3,56 +3,32 @@ import { getDummyServerPort, getTestServerPort, } from '@tanstack/router-e2e-utils' -import { isSpaMode } from './tests/utils/isSpaMode' -import { isPrerender } from './tests/utils/isPrerender' -import { isPreview } from './tests/utils/isPreview' import packageJson from './package.json' with { type: 'json' } -const PORT = await getTestServerPort( - `${packageJson.name}${isSpaMode ? '_spa' : ''}${isPreview ? '_preview' : ''}`, -) -const START_PORT = await getTestServerPort( - `${packageJson.name}${isSpaMode ? '_spa_start' : ''}`, -) +const PORT = await getTestServerPort(packageJson.name) +const START_PORT = await getTestServerPort(`${packageJson.name}_start`) const EXTERNAL_PORT = await getDummyServerPort(packageJson.name) const baseURL = `http://localhost:${PORT}` -const spaModeCommand = `pnpm build:spa && pnpm start` const ssrModeCommand = `pnpm build && pnpm start` -const prerenderModeCommand = `pnpm run test:e2e:startDummyServer && pnpm build:prerender && pnpm run test:e2e:stopDummyServer && pnpm start` -const previewModeCommand = `pnpm build && pnpm preview --port ${PORT}` -const getCommand = () => { - if (isSpaMode) return spaModeCommand - if (isPrerender) return prerenderModeCommand - if (isPreview) return previewModeCommand - return ssrModeCommand -} -console.log('running in spa mode: ', isSpaMode.toString()) -console.log('running in prerender mode: ', isPrerender.toString()) -console.log('running in preview mode: ', isPreview.toString()) -/** - * See https://playwright.dev/docs/test-configuration. - */ export default defineConfig({ - testDir: './tests', + testDir: '../basic-test-suite/src', workers: 1, reporter: [['line']], - globalSetup: './tests/setup/global.setup.ts', - globalTeardown: './tests/setup/global.teardown.ts', + globalTeardown: '../basic-test-suite/src/setup/global.teardown.ts', use: { - /* Base URL to use in actions like `await page.goto('/')`. */ baseURL, }, webServer: { - command: getCommand(), + command: `pnpm run test:e2e:startDummyServer && ${ssrModeCommand}`, url: baseURL, reuseExistingServer: !process.env.CI, stdout: 'pipe', env: { - MODE: process.env.MODE || '', + MODE: '', VITE_NODE_ENV: 'test', VITE_EXTERNAL_PORT: String(EXTERNAL_PORT), VITE_SERVER_PORT: String(PORT), diff --git a/e2e/solid-start/basic/tests/setup/global.setup.ts b/e2e/solid-start/basic/tests/setup/global.setup.ts deleted file mode 100644 index 3593d10ab90..00000000000 --- a/e2e/solid-start/basic/tests/setup/global.setup.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { e2eStartDummyServer } from '@tanstack/router-e2e-utils' -import packageJson from '../../package.json' with { type: 'json' } - -export default async function setup() { - await e2eStartDummyServer(packageJson.name) -} diff --git a/e2e/solid-start/basic/tests/setup/global.teardown.ts b/e2e/solid-start/basic/tests/setup/global.teardown.ts deleted file mode 100644 index 62fd79911cc..00000000000 --- a/e2e/solid-start/basic/tests/setup/global.teardown.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { e2eStopDummyServer } from '@tanstack/router-e2e-utils' -import packageJson from '../../package.json' with { type: 'json' } - -export default async function teardown() { - await e2eStopDummyServer(packageJson.name) -} diff --git a/e2e/solid-start/basic/tsconfig.json b/e2e/solid-start/basic/tsconfig.json index d53f9138f5a..cb1a0b80dd2 100644 --- a/e2e/solid-start/basic/tsconfig.json +++ b/e2e/solid-start/basic/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/csp/package.json b/e2e/solid-start/csp/package.json index f316f1b0124..5f204cbcf31 100644 --- a/e2e/solid-start/csp/package.json +++ b/e2e/solid-start/csp/package.json @@ -22,7 +22,7 @@ "@tanstack/router-e2e-utils": "workspace:^", "@types/node": "^22.10.2", "srvx": "^0.11.9", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite-plugin-solid": "3.0.0-next.4" } } diff --git a/e2e/solid-start/csp/src/vite-env.d.ts b/e2e/solid-start/csp/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/solid-start/csp/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/solid-start/csp/tsconfig.json b/e2e/solid-start/csp/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/e2e/solid-start/csp/tsconfig.json +++ b/e2e/solid-start/csp/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/css-modules/package.json b/e2e/solid-start/css-modules/package.json index a0b8c118a8a..b8cc6a518e7 100644 --- a/e2e/solid-start/css-modules/package.json +++ b/e2e/solid-start/css-modules/package.json @@ -25,7 +25,7 @@ "@types/node": "^22.10.2", "sass": "^1.97.2", "srvx": "^0.11.9", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4" diff --git a/e2e/solid-start/css-modules/tsconfig.json b/e2e/solid-start/css-modules/tsconfig.json index ed8b73fa2dd..c34f9d7c361 100644 --- a/e2e/solid-start/css-modules/tsconfig.json +++ b/e2e/solid-start/css-modules/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/custom-basepath/package.json b/e2e/solid-start/custom-basepath/package.json index 10f845ec2c3..b1fc2409920 100644 --- a/e2e/solid-start/custom-basepath/package.json +++ b/e2e/solid-start/custom-basepath/package.json @@ -29,7 +29,7 @@ "srvx": "^0.11.9", "tailwindcss": "^4.2.2", "tsx": "^4.20.3", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4" diff --git a/e2e/solid-start/custom-basepath/src/vite-env.d.ts b/e2e/solid-start/custom-basepath/src/vite-env.d.ts index 0b2af560d60..d0b512cd805 100644 --- a/e2e/solid-start/custom-basepath/src/vite-env.d.ts +++ b/e2e/solid-start/custom-basepath/src/vite-env.d.ts @@ -1,3 +1,5 @@ +/// + declare module '*?url' { const url: string export default url diff --git a/e2e/solid-start/custom-basepath/tsconfig.json b/e2e/solid-start/custom-basepath/tsconfig.json index d53f9138f5a..cb1a0b80dd2 100644 --- a/e2e/solid-start/custom-basepath/tsconfig.json +++ b/e2e/solid-start/custom-basepath/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/query-integration/package.json b/e2e/solid-start/query-integration/package.json index 50658aa3cb5..403e0499432 100644 --- a/e2e/solid-start/query-integration/package.json +++ b/e2e/solid-start/query-integration/package.json @@ -30,8 +30,7 @@ "@tanstack/router-e2e-utils": "workspace:^", "@types/node": "^22.10.2", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", - "vite-plugin-solid": "3.0.0-next.4", - "vite-tsconfig-paths": "^5.1.4" + "typescript": "^6.0.2", + "vite-plugin-solid": "3.0.0-next.4" } } diff --git a/e2e/solid-start/query-integration/tsconfig.json b/e2e/solid-start/query-integration/tsconfig.json index ed8b73fa2dd..c34f9d7c361 100644 --- a/e2e/solid-start/query-integration/tsconfig.json +++ b/e2e/solid-start/query-integration/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/scroll-restoration/package.json b/e2e/solid-start/scroll-restoration/package.json index 585baae6337..fd7bd8b0582 100644 --- a/e2e/solid-start/scroll-restoration/package.json +++ b/e2e/solid-start/scroll-restoration/package.json @@ -31,8 +31,7 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", - "vite-plugin-solid": "3.0.0-next.4", - "vite-tsconfig-paths": "^5.1.4" + "typescript": "^6.0.2", + "vite-plugin-solid": "3.0.0-next.4" } } diff --git a/e2e/solid-start/scroll-restoration/src/routes/(tests)/with-loader.tsx b/e2e/solid-start/scroll-restoration/src/routes/(tests)/with-loader.tsx index 3f0d097d14e..53ee8adbe0e 100644 --- a/e2e/solid-start/scroll-restoration/src/routes/(tests)/with-loader.tsx +++ b/e2e/solid-start/scroll-restoration/src/routes/(tests)/with-loader.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/solid-router' -import { sleep } from 'src/utils/posts' +import { sleep } from '../../utils/posts' import { ScrollBlock } from '../-components/scroll-block' export const Route = createFileRoute('/(tests)/with-loader')({ diff --git a/e2e/solid-start/scroll-restoration/src/vite-env.d.ts b/e2e/solid-start/scroll-restoration/src/vite-env.d.ts index 0b2af560d60..d0b512cd805 100644 --- a/e2e/solid-start/scroll-restoration/src/vite-env.d.ts +++ b/e2e/solid-start/scroll-restoration/src/vite-env.d.ts @@ -1,3 +1,5 @@ +/// + declare module '*?url' { const url: string export default url diff --git a/e2e/solid-start/scroll-restoration/tsconfig.json b/e2e/solid-start/scroll-restoration/tsconfig.json index d53f9138f5a..cb1a0b80dd2 100644 --- a/e2e/solid-start/scroll-restoration/tsconfig.json +++ b/e2e/solid-start/scroll-restoration/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/selective-ssr/package.json b/e2e/solid-start/selective-ssr/package.json index 1e4b4e55d72..82a571db7c3 100644 --- a/e2e/solid-start/selective-ssr/package.json +++ b/e2e/solid-start/selective-ssr/package.json @@ -23,7 +23,7 @@ "@tanstack/router-e2e-utils": "workspace:^", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4" diff --git a/e2e/solid-start/selective-ssr/tsconfig.json b/e2e/solid-start/selective-ssr/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/e2e/solid-start/selective-ssr/tsconfig.json +++ b/e2e/solid-start/selective-ssr/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/serialization-adapters/package.json b/e2e/solid-start/serialization-adapters/package.json index 86afaeb71b6..1da3bc98345 100644 --- a/e2e/solid-start/serialization-adapters/package.json +++ b/e2e/solid-start/serialization-adapters/package.json @@ -27,7 +27,7 @@ "@types/node": "^22.10.2", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite-plugin-solid": "3.0.0-next.4" } } diff --git a/e2e/solid-start/serialization-adapters/tsconfig.json b/e2e/solid-start/serialization-adapters/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/e2e/solid-start/serialization-adapters/tsconfig.json +++ b/e2e/solid-start/serialization-adapters/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/server-functions/package.json b/e2e/solid-start/server-functions/package.json index 7f54b372f47..9a4bdb3297a 100644 --- a/e2e/solid-start/server-functions/package.json +++ b/e2e/solid-start/server-functions/package.json @@ -35,8 +35,7 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", - "vite-plugin-solid": "3.0.0-next.4", - "vite-tsconfig-paths": "^5.1.4" + "typescript": "^6.0.2", + "vite-plugin-solid": "3.0.0-next.4" } } diff --git a/e2e/solid-start/server-functions/src/vite-env.d.ts b/e2e/solid-start/server-functions/src/vite-env.d.ts index 0b2af560d60..d0b512cd805 100644 --- a/e2e/solid-start/server-functions/src/vite-env.d.ts +++ b/e2e/solid-start/server-functions/src/vite-env.d.ts @@ -1,3 +1,5 @@ +/// + declare module '*?url' { const url: string export default url diff --git a/e2e/solid-start/server-functions/tsconfig.json b/e2e/solid-start/server-functions/tsconfig.json index 57ea27b2868..508ace2e179 100644 --- a/e2e/solid-start/server-functions/tsconfig.json +++ b/e2e/solid-start/server-functions/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/server-routes/package.json b/e2e/solid-start/server-routes/package.json index 008275be8fe..d3d2d8f9f35 100644 --- a/e2e/solid-start/server-routes/package.json +++ b/e2e/solid-start/server-routes/package.json @@ -34,8 +34,7 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", - "vite-plugin-solid": "3.0.0-next.4", - "vite-tsconfig-paths": "^5.1.4" + "typescript": "^6.0.2", + "vite-plugin-solid": "3.0.0-next.4" } } diff --git a/e2e/solid-start/server-routes/src/vite-env.d.ts b/e2e/solid-start/server-routes/src/vite-env.d.ts index 0b2af560d60..d0b512cd805 100644 --- a/e2e/solid-start/server-routes/src/vite-env.d.ts +++ b/e2e/solid-start/server-routes/src/vite-env.d.ts @@ -1,3 +1,5 @@ +/// + declare module '*?url' { const url: string export default url diff --git a/e2e/solid-start/server-routes/tsconfig.json b/e2e/solid-start/server-routes/tsconfig.json index 57ea27b2868..508ace2e179 100644 --- a/e2e/solid-start/server-routes/tsconfig.json +++ b/e2e/solid-start/server-routes/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/spa-mode/package.json b/e2e/solid-start/spa-mode/package.json index d35dc8cbb40..b5f67f2923c 100644 --- a/e2e/solid-start/spa-mode/package.json +++ b/e2e/solid-start/spa-mode/package.json @@ -23,7 +23,7 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/router-e2e-utils": "workspace:^", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4" diff --git a/e2e/solid-start/spa-mode/tsconfig.json b/e2e/solid-start/spa-mode/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/e2e/solid-start/spa-mode/tsconfig.json +++ b/e2e/solid-start/spa-mode/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/virtual-routes/package.json b/e2e/solid-start/virtual-routes/package.json index 494d176332a..de684c45145 100644 --- a/e2e/solid-start/virtual-routes/package.json +++ b/e2e/solid-start/virtual-routes/package.json @@ -31,8 +31,7 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", - "vite-plugin-solid": "3.0.0-next.4", - "vite-tsconfig-paths": "^5.1.4" + "typescript": "^6.0.2", + "vite-plugin-solid": "3.0.0-next.4" } } diff --git a/e2e/solid-start/virtual-routes/tsconfig.json b/e2e/solid-start/virtual-routes/tsconfig.json index d53f9138f5a..cb1a0b80dd2 100644 --- a/e2e/solid-start/virtual-routes/tsconfig.json +++ b/e2e/solid-start/virtual-routes/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/solid-start/website/package.json b/e2e/solid-start/website/package.json index ef035648d3f..fc090c35144 100644 --- a/e2e/solid-start/website/package.json +++ b/e2e/solid-start/website/package.json @@ -29,8 +29,7 @@ "@types/node": "^22.10.2", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", - "vite-plugin-solid": "3.0.0-next.4", - "vite-tsconfig-paths": "^5.1.4" + "typescript": "^6.0.2", + "vite-plugin-solid": "3.0.0-next.4" } } diff --git a/e2e/solid-start/website/tsconfig.json b/e2e/solid-start/website/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/e2e/solid-start/website/tsconfig.json +++ b/e2e/solid-start/website/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-router/basic-esbuild-file-based/package.json b/e2e/vue-router/basic-esbuild-file-based/package.json index 936bb1eb6c2..ad6e6fad31c 100644 --- a/e2e/vue-router/basic-esbuild-file-based/package.json +++ b/e2e/vue-router/basic-esbuild-file-based/package.json @@ -28,7 +28,7 @@ "esbuild": "^0.27.4", "esbuild-plugin-vue3": "^0.5.1", "eslint-plugin-vue": "^9.33.0", - "typescript": "^5.8.3", + "typescript": "^6.0.2", "vue-eslint-parser": "^9.4.3", "vue-tsc": "^3.1.5" } diff --git a/e2e/vue-router/basic-esbuild-file-based/src/vite-env.d.ts b/e2e/vue-router/basic-esbuild-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/basic-esbuild-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/basic-file-based-jsx/src/vite-env.d.ts b/e2e/vue-router/basic-file-based-jsx/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/basic-file-based-jsx/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/basic-file-based-sfc/src/vite-env.d.ts b/e2e/vue-router/basic-file-based-sfc/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/basic-file-based-sfc/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/basic-scroll-restoration/package.json b/e2e/vue-router/basic-scroll-restoration/package.json index 05d59546158..e9b09ee6ab3 100644 --- a/e2e/vue-router/basic-scroll-restoration/package.json +++ b/e2e/vue-router/basic-scroll-restoration/package.json @@ -24,8 +24,8 @@ "@tanstack/router-e2e-utils": "workspace:^", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5", - "typescript": "~5.8.3", "vite": "^8.0.0", - "vue-tsc": "^3.1.5" + "vue-tsc": "^3.1.5", + "typescript": "~5.9.0" } } diff --git a/e2e/vue-router/basic-scroll-restoration/src/vite-env.d.ts b/e2e/vue-router/basic-scroll-restoration/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/basic-scroll-restoration/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/basic-virtual-file-based/src/vite-env.d.ts b/e2e/vue-router/basic-virtual-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/basic-virtual-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/basic-virtual-named-export-config-file-based/src/vite-env.d.ts b/e2e/vue-router/basic-virtual-named-export-config-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/basic-virtual-named-export-config-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/basic-vue-query-file-based/src/vite-env.d.ts b/e2e/vue-router/basic-vue-query-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/basic-vue-query-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/basic-vue-query/src/vite-env.d.ts b/e2e/vue-router/basic-vue-query/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/basic-vue-query/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/basic/src/vite-env.d.ts b/e2e/vue-router/basic/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/basic/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/generator-cli-only/src/vite-env.d.ts b/e2e/vue-router/generator-cli-only/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/generator-cli-only/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/js-only-file-based/src/vite-env.d.ts b/e2e/vue-router/js-only-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/js-only-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/rspack-basic-file-based/package.json b/e2e/vue-router/rspack-basic-file-based/package.json index 81695c82692..46b67803256 100644 --- a/e2e/vue-router/rspack-basic-file-based/package.json +++ b/e2e/vue-router/rspack-basic-file-based/package.json @@ -27,7 +27,7 @@ "@tanstack/virtual-file-routes": "workspace:^", "postcss": "^8.5.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vue-tsc": "^3.1.5" } } diff --git a/e2e/vue-router/rspack-basic-file-based/src/vite-env.d.ts b/e2e/vue-router/rspack-basic-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/rspack-basic-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/rspack-basic-file-based/tsconfig.json b/e2e/vue-router/rspack-basic-file-based/tsconfig.json index 25149257a35..8fc6c76d61a 100644 --- a/e2e/vue-router/rspack-basic-file-based/tsconfig.json +++ b/e2e/vue-router/rspack-basic-file-based/tsconfig.json @@ -13,6 +13,6 @@ "useDefineForClassFields": true, "allowJs": true }, - "include": ["src", "playwright.config.ts", "tests"], + "include": ["src", "tests"], "exclude": ["node_modules", "dist"] } diff --git a/e2e/vue-router/rspack-basic-virtual-named-export-config-file-based/package.json b/e2e/vue-router/rspack-basic-virtual-named-export-config-file-based/package.json index 48f2c2715f3..8863fc3de2a 100644 --- a/e2e/vue-router/rspack-basic-virtual-named-export-config-file-based/package.json +++ b/e2e/vue-router/rspack-basic-virtual-named-export-config-file-based/package.json @@ -27,7 +27,7 @@ "@tanstack/virtual-file-routes": "workspace:^", "postcss": "^8.5.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vue-tsc": "^3.1.5" } } diff --git a/e2e/vue-router/rspack-basic-virtual-named-export-config-file-based/src/vite-env.d.ts b/e2e/vue-router/rspack-basic-virtual-named-export-config-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/rspack-basic-virtual-named-export-config-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/rspack-basic-virtual-named-export-config-file-based/tsconfig.json b/e2e/vue-router/rspack-basic-virtual-named-export-config-file-based/tsconfig.json index 23855253ad9..ff457aa547c 100644 --- a/e2e/vue-router/rspack-basic-virtual-named-export-config-file-based/tsconfig.json +++ b/e2e/vue-router/rspack-basic-virtual-named-export-config-file-based/tsconfig.json @@ -13,6 +13,6 @@ "useDefineForClassFields": true, "allowJs": true }, - "include": ["src", "playwright.config.ts", "tests", "./routes.ts"], + "include": ["src", "tests", "./routes.ts"], "exclude": ["node_modules", "dist"] } diff --git a/e2e/vue-router/scroll-restoration-sandbox-vite/src/vite-env.d.ts b/e2e/vue-router/scroll-restoration-sandbox-vite/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/scroll-restoration-sandbox-vite/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/sentry-integration/src/vite-env.d.ts b/e2e/vue-router/sentry-integration/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/sentry-integration/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-router/view-transitions/src/vite-env.d.ts b/e2e/vue-router/view-transitions/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/e2e/vue-router/view-transitions/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/e2e/vue-start/basic-auth/package.json b/e2e/vue-start/basic-auth/package.json index 546013eacc9..603bf49ec41 100644 --- a/e2e/vue-start/basic-auth/package.json +++ b/e2e/vue-start/basic-auth/package.json @@ -33,7 +33,7 @@ "prisma": "^7.0.0", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5" } diff --git a/e2e/vue-start/basic-auth/tsconfig.json b/e2e/vue-start/basic-auth/tsconfig.json index f9f5aab3dae..390dad84c06 100644 --- a/e2e/vue-start/basic-auth/tsconfig.json +++ b/e2e/vue-start/basic-auth/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/basic-cloudflare/package.json b/e2e/vue-start/basic-cloudflare/package.json index 12d06274fa8..4efaf79c463 100644 --- a/e2e/vue-start/basic-cloudflare/package.json +++ b/e2e/vue-start/basic-cloudflare/package.json @@ -25,7 +25,7 @@ "@tanstack/router-e2e-utils": "workspace:^", "@types/node": "^22.10.2", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5", diff --git a/e2e/vue-start/basic-cloudflare/tsconfig.json b/e2e/vue-start/basic-cloudflare/tsconfig.json index 8bf3d33789b..572d8408729 100644 --- a/e2e/vue-start/basic-cloudflare/tsconfig.json +++ b/e2e/vue-start/basic-cloudflare/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/basic-prerender/.gitignore b/e2e/vue-start/basic-prerender/.gitignore new file mode 100644 index 00000000000..6381bf3860f --- /dev/null +++ b/e2e/vue-start/basic-prerender/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/test-results/ +/playwright-report/ +/blob-report/ diff --git a/e2e/vue-start/basic-prerender/package.json b/e2e/vue-start/basic-prerender/package.json new file mode 100644 index 00000000000..5b05d8f771f --- /dev/null +++ b/e2e/vue-start/basic-prerender/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-vue-start-e2e-basic-prerender", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "test:e2e:startDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.setup.ts\").then(m => m.default())' & node -e 'import(\"../basic-test-suite/src/setup/waitForDummyServer.ts\").then(m => m.default())'", + "test:e2e:stopDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.teardown.ts\").then(m => m.default())'", + "test:e2e": "rm -rf port*.txt; MODE=prerender playwright test --project=chromium" + }, + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tanstack/router-e2e-utils": "workspace:^", + "tanstack-vue-start-e2e-basic": "workspace:*", + "tanstack-vue-start-e2e-basic-test-suite": "workspace:*" + }, + "nx": { + "targets": { + "test:e2e": { + "parallelism": false + } + } + } +} diff --git a/e2e/vue-start/basic-prerender/playwright.config.ts b/e2e/vue-start/basic-prerender/playwright.config.ts new file mode 100644 index 00000000000..cf2cf5d396e --- /dev/null +++ b/e2e/vue-start/basic-prerender/playwright.config.ts @@ -0,0 +1,48 @@ +import { defineConfig, devices } from '@playwright/test' +import { + getDummyServerPort, + getTestServerPort, +} from '@tanstack/router-e2e-utils' +import packageJson from './package.json' with { type: 'json' } + +const PORT = await getTestServerPort(packageJson.name) +const START_PORT = await getTestServerPort(`${packageJson.name}_start`) +const EXTERNAL_PORT = await getDummyServerPort(packageJson.name) +const baseURL = `http://localhost:${PORT}` + +export default defineConfig({ + testDir: '../basic-test-suite/src', + workers: 1, + reporter: [['line']], + + globalTeardown: '../basic-test-suite/src/setup/global.teardown.ts', + + use: { + baseURL, + }, + + webServer: { + command: + 'pnpm run test:e2e:startDummyServer && pnpm --dir ../basic build:prerender && pnpm --dir ../basic start', + url: baseURL, + reuseExistingServer: !process.env.CI, + stdout: 'pipe', + env: { + MODE: 'prerender', + VITE_NODE_ENV: 'test', + VITE_EXTERNAL_PORT: String(EXTERNAL_PORT), + VITE_SERVER_PORT: String(PORT), + START_PORT: String(START_PORT), + PORT: String(PORT), + }, + }, + + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + }, + }, + ], +}) diff --git a/e2e/vue-start/basic-preview/.gitignore b/e2e/vue-start/basic-preview/.gitignore new file mode 100644 index 00000000000..6381bf3860f --- /dev/null +++ b/e2e/vue-start/basic-preview/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/test-results/ +/playwright-report/ +/blob-report/ diff --git a/e2e/vue-start/basic-preview/package.json b/e2e/vue-start/basic-preview/package.json new file mode 100644 index 00000000000..663b1365f1b --- /dev/null +++ b/e2e/vue-start/basic-preview/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-vue-start-e2e-basic-preview", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "test:e2e:startDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.setup.ts\").then(m => m.default())' & node -e 'import(\"../basic-test-suite/src/setup/waitForDummyServer.ts\").then(m => m.default())'", + "test:e2e:stopDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.teardown.ts\").then(m => m.default())'", + "test:e2e": "rm -rf port*.txt; MODE=preview playwright test --project=chromium" + }, + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tanstack/router-e2e-utils": "workspace:^", + "tanstack-vue-start-e2e-basic": "workspace:*", + "tanstack-vue-start-e2e-basic-test-suite": "workspace:*" + }, + "nx": { + "targets": { + "test:e2e": { + "parallelism": false + } + } + } +} diff --git a/e2e/vue-start/basic-preview/playwright.config.ts b/e2e/vue-start/basic-preview/playwright.config.ts new file mode 100644 index 00000000000..071f336f9f1 --- /dev/null +++ b/e2e/vue-start/basic-preview/playwright.config.ts @@ -0,0 +1,47 @@ +import { defineConfig, devices } from '@playwright/test' +import { + getDummyServerPort, + getTestServerPort, +} from '@tanstack/router-e2e-utils' +import packageJson from './package.json' with { type: 'json' } + +const PORT = await getTestServerPort(packageJson.name) +const START_PORT = await getTestServerPort(`${packageJson.name}_start`) +const EXTERNAL_PORT = await getDummyServerPort(packageJson.name) +const baseURL = `http://localhost:${PORT}` + +export default defineConfig({ + testDir: '../basic-test-suite/src', + workers: 1, + reporter: [['line']], + + globalTeardown: '../basic-test-suite/src/setup/global.teardown.ts', + + use: { + baseURL, + }, + + webServer: { + command: `pnpm run test:e2e:startDummyServer && pnpm --dir ../basic build && pnpm --dir ../basic preview --port ${PORT}`, + url: baseURL, + reuseExistingServer: !process.env.CI, + stdout: 'pipe', + env: { + MODE: 'preview', + VITE_NODE_ENV: 'test', + VITE_EXTERNAL_PORT: String(EXTERNAL_PORT), + VITE_SERVER_PORT: String(PORT), + START_PORT: String(START_PORT), + PORT: String(PORT), + }, + }, + + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + }, + }, + ], +}) diff --git a/e2e/vue-start/basic-spa/.gitignore b/e2e/vue-start/basic-spa/.gitignore new file mode 100644 index 00000000000..6381bf3860f --- /dev/null +++ b/e2e/vue-start/basic-spa/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/test-results/ +/playwright-report/ +/blob-report/ diff --git a/e2e/vue-start/basic-spa/package.json b/e2e/vue-start/basic-spa/package.json new file mode 100644 index 00000000000..21866365490 --- /dev/null +++ b/e2e/vue-start/basic-spa/package.json @@ -0,0 +1,24 @@ +{ + "name": "tanstack-vue-start-e2e-basic-spa", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "test:e2e:startDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.setup.ts\").then(m => m.default())' & node -e 'import(\"../basic-test-suite/src/setup/waitForDummyServer.ts\").then(m => m.default())'", + "test:e2e:stopDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.teardown.ts\").then(m => m.default())'", + "test:e2e": "rm -rf port*.txt; MODE=spa playwright test --project=chromium" + }, + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tanstack/router-e2e-utils": "workspace:^", + "tanstack-vue-start-e2e-basic": "workspace:*", + "tanstack-vue-start-e2e-basic-test-suite": "workspace:*" + }, + "nx": { + "targets": { + "test:e2e": { + "parallelism": false + } + } + } +} diff --git a/e2e/vue-start/basic-spa/playwright.config.ts b/e2e/vue-start/basic-spa/playwright.config.ts new file mode 100644 index 00000000000..27e85e1f1a4 --- /dev/null +++ b/e2e/vue-start/basic-spa/playwright.config.ts @@ -0,0 +1,48 @@ +import { defineConfig, devices } from '@playwright/test' +import { + getDummyServerPort, + getTestServerPort, +} from '@tanstack/router-e2e-utils' +import packageJson from './package.json' with { type: 'json' } + +const PORT = await getTestServerPort(packageJson.name) +const START_PORT = await getTestServerPort(`${packageJson.name}_start`) +const EXTERNAL_PORT = await getDummyServerPort(packageJson.name) +const baseURL = `http://localhost:${PORT}` + +export default defineConfig({ + testDir: '../basic-test-suite/src', + workers: 1, + reporter: [['line']], + + globalTeardown: '../basic-test-suite/src/setup/global.teardown.ts', + + use: { + baseURL, + }, + + webServer: { + command: + 'pnpm run test:e2e:startDummyServer && pnpm --dir ../basic build:spa && pnpm --dir ../basic start', + url: baseURL, + reuseExistingServer: !process.env.CI, + stdout: 'pipe', + env: { + MODE: 'spa', + VITE_NODE_ENV: 'test', + VITE_EXTERNAL_PORT: String(EXTERNAL_PORT), + VITE_SERVER_PORT: String(PORT), + START_PORT: String(START_PORT), + PORT: String(PORT), + }, + }, + + projects: [ + { + name: 'chromium', + use: { + ...devices['Desktop Chrome'], + }, + }, + ], +}) diff --git a/e2e/vue-start/basic-test-suite/.gitignore b/e2e/vue-start/basic-test-suite/.gitignore new file mode 100644 index 00000000000..6381bf3860f --- /dev/null +++ b/e2e/vue-start/basic-test-suite/.gitignore @@ -0,0 +1,5 @@ +node_modules + +/test-results/ +/playwright-report/ +/blob-report/ diff --git a/e2e/vue-start/basic-test-suite/package.json b/e2e/vue-start/basic-test-suite/package.json new file mode 100644 index 00000000000..7d5ea7c002c --- /dev/null +++ b/e2e/vue-start/basic-test-suite/package.json @@ -0,0 +1,12 @@ +{ + "name": "tanstack-vue-start-e2e-basic-test-suite", + "private": true, + "sideEffects": false, + "type": "module", + "devDependencies": { + "@playwright/test": "^1.50.1", + "@tanstack/router-e2e-utils": "workspace:^", + "@types/node": "^22.10.2", + "combinate": "^1.1.11" + } +} diff --git a/e2e/vue-start/basic/tests/navigation.spec.ts b/e2e/vue-start/basic-test-suite/src/navigation.spec.ts similarity index 100% rename from e2e/vue-start/basic/tests/navigation.spec.ts rename to e2e/vue-start/basic-test-suite/src/navigation.spec.ts diff --git a/e2e/vue-start/basic/tests/not-found.spec.ts b/e2e/vue-start/basic-test-suite/src/not-found.spec.ts similarity index 98% rename from e2e/vue-start/basic/tests/not-found.spec.ts rename to e2e/vue-start/basic-test-suite/src/not-found.spec.ts index 100f4aa3937..cfc60fe5e48 100644 --- a/e2e/vue-start/basic/tests/not-found.spec.ts +++ b/e2e/vue-start/basic-test-suite/src/not-found.spec.ts @@ -1,7 +1,7 @@ import { expect } from '@playwright/test' import combinateImport from 'combinate' import { test } from '@tanstack/router-e2e-utils' -import { isSpaMode } from '../tests/utils/isSpaMode' +import { isSpaMode } from './utils/isSpaMode' // somehow playwright does not correctly import default exports const combinate = (combinateImport as any).default as typeof combinateImport diff --git a/e2e/solid-start/basic/tests/prerendering.spec.ts b/e2e/vue-start/basic-test-suite/src/prerendering.spec.ts similarity index 90% rename from e2e/solid-start/basic/tests/prerendering.spec.ts rename to e2e/vue-start/basic-test-suite/src/prerendering.spec.ts index 8506ff9b061..66cc1f68ff2 100644 --- a/e2e/solid-start/basic/tests/prerendering.spec.ts +++ b/e2e/vue-start/basic-test-suite/src/prerendering.spec.ts @@ -3,13 +3,14 @@ import { join } from 'node:path' import { expect } from '@playwright/test' import { test } from '@tanstack/router-e2e-utils' import { isPrerender } from './utils/isPrerender' +import { getBasicAppRoot } from './utils/getBasicAppRoot' test.describe('Prerender Static Path Discovery', () => { test.skip(!isPrerender, 'Skipping since not in prerender mode') test.describe('Build Output Verification', () => { test('should automatically discover and prerender static routes', () => { // Check that static routes were automatically discovered and prerendered - const distDir = join(process.cwd(), 'dist', 'client') + const distDir = join(getBasicAppRoot(), 'dist', 'client') // These static routes should be automatically discovered and prerendered expect(existsSync(join(distDir, 'index.html'))).toBe(true) @@ -34,7 +35,7 @@ test.describe('Prerender Static Path Discovery', () => { test.describe('Static Files Verification', () => { test('should contain prerendered content in posts.html', () => { - const distDir = join(process.cwd(), 'dist', 'client') + const distDir = join(getBasicAppRoot(), 'dist', 'client') expect(existsSync(join(distDir, 'posts/index.html'))).toBe(true) // "Select a post." should be in the prerendered HTML diff --git a/e2e/vue-start/basic/tests/redirect.spec.ts b/e2e/vue-start/basic-test-suite/src/redirect.spec.ts similarity index 95% rename from e2e/vue-start/basic/tests/redirect.spec.ts rename to e2e/vue-start/basic-test-suite/src/redirect.spec.ts index b52ce026afe..c25a6b0dbf4 100644 --- a/e2e/vue-start/basic/tests/redirect.spec.ts +++ b/e2e/vue-start/basic-test-suite/src/redirect.spec.ts @@ -6,17 +6,14 @@ import { getTestServerPort, test, } from '@tanstack/router-e2e-utils' -import packageJson from '../package.json' with { type: 'json' } -import { isSpaMode } from '../tests/utils/isSpaMode' -import { isPreview } from '../tests/utils/isPreview' +import { getPackageName } from './utils/getPackageName.ts' // somehow playwright does not correctly import default exports const combinate = (combinateImport as any).default as typeof combinateImport -const PORT = await getTestServerPort( - `${packageJson.name}${isSpaMode ? '_spa' : ''}${isPreview ? '_preview' : ''}`, -) -const EXTERNAL_HOST_PORT = await getDummyServerPort(packageJson.name) +const packageName = getPackageName() +const PORT = await getTestServerPort(packageName) +const EXTERNAL_HOST_PORT = await getDummyServerPort(packageName) test.describe('redirects', () => { const internalNavigationTestMatrix = combinate({ diff --git a/e2e/vue-start/basic/tests/script-duplication.spec.ts b/e2e/vue-start/basic-test-suite/src/script-duplication.spec.ts similarity index 100% rename from e2e/vue-start/basic/tests/script-duplication.spec.ts rename to e2e/vue-start/basic-test-suite/src/script-duplication.spec.ts diff --git a/e2e/react-start/basic/tests/search-params.spec.ts b/e2e/vue-start/basic-test-suite/src/search-params.spec.ts similarity index 98% rename from e2e/react-start/basic/tests/search-params.spec.ts rename to e2e/vue-start/basic-test-suite/src/search-params.spec.ts index 74c1aa54dc9..cdf5a21b4ae 100644 --- a/e2e/react-start/basic/tests/search-params.spec.ts +++ b/e2e/vue-start/basic-test-suite/src/search-params.spec.ts @@ -1,6 +1,6 @@ import { expect } from '@playwright/test' import { test } from '@tanstack/router-e2e-utils' -import { isSpaMode } from 'tests/utils/isSpaMode' +import { isSpaMode } from './utils/isSpaMode' import { isPrerender } from './utils/isPrerender' import type { Response } from '@playwright/test' diff --git a/e2e/vue-start/basic-test-suite/src/setup/global.setup.ts b/e2e/vue-start/basic-test-suite/src/setup/global.setup.ts new file mode 100644 index 00000000000..fc06a655910 --- /dev/null +++ b/e2e/vue-start/basic-test-suite/src/setup/global.setup.ts @@ -0,0 +1,6 @@ +import { e2eStartDummyServer } from '@tanstack/router-e2e-utils' +import { getPackageName } from '../utils/getPackageName.ts' + +export default async function setup() { + await e2eStartDummyServer(getPackageName()) +} diff --git a/e2e/vue-start/basic-test-suite/src/setup/global.teardown.ts b/e2e/vue-start/basic-test-suite/src/setup/global.teardown.ts new file mode 100644 index 00000000000..a8a68997009 --- /dev/null +++ b/e2e/vue-start/basic-test-suite/src/setup/global.teardown.ts @@ -0,0 +1,8 @@ +import { e2eStopDummyServer } from '@tanstack/router-e2e-utils' +import { getPackageName } from '../utils/getPackageName.ts' + +export default async function teardown() { + try { + await e2eStopDummyServer(getPackageName()) + } catch {} +} diff --git a/e2e/vue-start/basic-test-suite/src/setup/waitForDummyServer.ts b/e2e/vue-start/basic-test-suite/src/setup/waitForDummyServer.ts new file mode 100644 index 00000000000..f27dc86d5b8 --- /dev/null +++ b/e2e/vue-start/basic-test-suite/src/setup/waitForDummyServer.ts @@ -0,0 +1,24 @@ +import { getDummyServerPort } from '@tanstack/router-e2e-utils' +import { getPackageName } from '../utils/getPackageName.ts' + +const timeoutMs = 10_000 +const retryIntervalMs = 100 + +export default async function waitForDummyServer() { + const port = await getDummyServerPort(getPackageName()) + const deadline = Date.now() + timeoutMs + + while (Date.now() < deadline) { + try { + const response = await fetch(`http://localhost:${port}/`) + + if (response.ok) { + return + } + } catch {} + + await new Promise((resolve) => setTimeout(resolve, retryIntervalMs)) + } + + throw new Error(`Timed out waiting for dummy server on port ${port}`) +} diff --git a/e2e/vue-start/basic/tests/special-characters.spec.ts b/e2e/vue-start/basic-test-suite/src/special-characters.spec.ts similarity index 100% rename from e2e/vue-start/basic/tests/special-characters.spec.ts rename to e2e/vue-start/basic-test-suite/src/special-characters.spec.ts diff --git a/e2e/vue-start/basic/tests/streaming.spec.ts b/e2e/vue-start/basic-test-suite/src/streaming.spec.ts similarity index 100% rename from e2e/vue-start/basic/tests/streaming.spec.ts rename to e2e/vue-start/basic-test-suite/src/streaming.spec.ts diff --git a/e2e/vue-start/basic-test-suite/src/utils/getBasicAppRoot.ts b/e2e/vue-start/basic-test-suite/src/utils/getBasicAppRoot.ts new file mode 100644 index 00000000000..12a411989a2 --- /dev/null +++ b/e2e/vue-start/basic-test-suite/src/utils/getBasicAppRoot.ts @@ -0,0 +1,8 @@ +import { join } from 'node:path' +import { getPackageName } from './getPackageName.ts' + +export function getBasicAppRoot() { + return getPackageName().endsWith('-basic') + ? process.cwd() + : join(process.cwd(), '../basic') +} diff --git a/e2e/vue-start/basic-test-suite/src/utils/getPackageName.ts b/e2e/vue-start/basic-test-suite/src/utils/getPackageName.ts new file mode 100644 index 00000000000..6bd2e0499ed --- /dev/null +++ b/e2e/vue-start/basic-test-suite/src/utils/getPackageName.ts @@ -0,0 +1,16 @@ +import { readFileSync } from 'node:fs' +import { join } from 'node:path' + +let packageName: string | undefined + +export function getPackageName() { + if (!packageName) { + const packageJson = JSON.parse( + readFileSync(join(process.cwd(), 'package.json'), 'utf-8'), + ) as { name: string } + + packageName = packageJson.name + } + + return packageName +} diff --git a/e2e/vue-start/basic-test-suite/src/utils/isPrerender.ts b/e2e/vue-start/basic-test-suite/src/utils/isPrerender.ts new file mode 100644 index 00000000000..d5d991d4545 --- /dev/null +++ b/e2e/vue-start/basic-test-suite/src/utils/isPrerender.ts @@ -0,0 +1 @@ +export const isPrerender: boolean = process.env.MODE === 'prerender' diff --git a/e2e/vue-start/basic-test-suite/src/utils/isPreview.ts b/e2e/vue-start/basic-test-suite/src/utils/isPreview.ts new file mode 100644 index 00000000000..7ea362a83ed --- /dev/null +++ b/e2e/vue-start/basic-test-suite/src/utils/isPreview.ts @@ -0,0 +1 @@ +export const isPreview: boolean = process.env.MODE === 'preview' diff --git a/e2e/vue-start/basic-test-suite/src/utils/isSpaMode.ts b/e2e/vue-start/basic-test-suite/src/utils/isSpaMode.ts new file mode 100644 index 00000000000..b4edb829a8f --- /dev/null +++ b/e2e/vue-start/basic-test-suite/src/utils/isSpaMode.ts @@ -0,0 +1 @@ +export const isSpaMode: boolean = process.env.MODE === 'spa' diff --git a/e2e/vue-start/basic-test-suite/tsconfig.json b/e2e/vue-start/basic-test-suite/tsconfig.json new file mode 100644 index 00000000000..3f3dbe6bcd7 --- /dev/null +++ b/e2e/vue-start/basic-test-suite/tsconfig.json @@ -0,0 +1,18 @@ +{ + "include": ["src/**/*.ts"], + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "isolatedModules": true, + "allowImportingTsExtensions": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "target": "ES2022", + "types": ["node"], + "forceConsistentCasingInFileNames": true, + "noEmit": true + } +} diff --git a/e2e/vue-start/basic-tsr-config/package.json b/e2e/vue-start/basic-tsr-config/package.json index af2b8ac3819..2d1d1028382 100644 --- a/e2e/vue-start/basic-tsr-config/package.json +++ b/e2e/vue-start/basic-tsr-config/package.json @@ -21,7 +21,7 @@ "@tanstack/router-e2e-utils": "workspace:^", "@types/node": "^22.10.2", "srvx": "^0.11.9", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5" } diff --git a/e2e/vue-start/basic-tsr-config/tsconfig.json b/e2e/vue-start/basic-tsr-config/tsconfig.json index 010db955bf1..e8f3ecf0c99 100644 --- a/e2e/vue-start/basic-tsr-config/tsconfig.json +++ b/e2e/vue-start/basic-tsr-config/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/app/*"] }, diff --git a/e2e/vue-start/basic-vue-query/package.json b/e2e/vue-start/basic-vue-query/package.json index e820457bd8d..e05e5829455 100644 --- a/e2e/vue-start/basic-vue-query/package.json +++ b/e2e/vue-start/basic-vue-query/package.json @@ -31,7 +31,7 @@ "@types/node": "^22.10.2", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5" } diff --git a/e2e/vue-start/basic-vue-query/tsconfig.json b/e2e/vue-start/basic-vue-query/tsconfig.json index 8bf3d33789b..572d8408729 100644 --- a/e2e/vue-start/basic-vue-query/tsconfig.json +++ b/e2e/vue-start/basic-vue-query/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/basic/package.json b/e2e/vue-start/basic/package.json index f1ed50117ce..ab56c475ef9 100644 --- a/e2e/vue-start/basic/package.json +++ b/e2e/vue-start/basic/package.json @@ -11,13 +11,9 @@ "build:prerender": "MODE=prerender vite build && tsc --noEmit", "preview": "vite preview", "start": "node server.js", - "test:e2e:startDummyServer": "node -e 'import(\"./tests/setup/global.setup.ts\").then(m => m.default())' &", - "test:e2e:stopDummyServer": "node -e 'import(\"./tests/setup/global.teardown.ts\").then(m => m.default())'", - "test:e2e:spaMode": "rm -rf port*.txt; MODE=spa playwright test --project=chromium", - "test:e2e:ssrMode": "rm -rf port*.txt; playwright test --project=chromium", - "test:e2e:prerender": "rm -rf port*.txt; MODE=prerender playwright test --project=chromium", - "test:e2e:preview": "rm -rf port*.txt; MODE=preview playwright test --project=chromium", - "test:e2e": "pnpm run test:e2e:spaMode && pnpm run test:e2e:ssrMode && pnpm run test:e2e:prerender && pnpm run test:e2e:preview" + "test:e2e:startDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.setup.ts\").then(m => m.default())' & node -e 'import(\"../basic-test-suite/src/setup/waitForDummyServer.ts\").then(m => m.default())'", + "test:e2e:stopDummyServer": "node -e 'import(\"../basic-test-suite/src/setup/global.teardown.ts\").then(m => m.default())'", + "test:e2e": "rm -rf dist; rm -rf port*.txt; playwright test --project=chromium" }, "dependencies": { "@tanstack/vue-router": "workspace:^", @@ -43,6 +39,14 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "tanstack-vue-start-e2e-basic-test-suite": "workspace:*", + "typescript": "^6.0.2" + }, + "nx": { + "targets": { + "test:e2e": { + "parallelism": false + } + } } } diff --git a/e2e/vue-start/basic/playwright.config.ts b/e2e/vue-start/basic/playwright.config.ts index 86c58bc1ce3..0bc99a1ec44 100644 --- a/e2e/vue-start/basic/playwright.config.ts +++ b/e2e/vue-start/basic/playwright.config.ts @@ -3,56 +3,32 @@ import { getDummyServerPort, getTestServerPort, } from '@tanstack/router-e2e-utils' -import { isSpaMode } from './tests/utils/isSpaMode' -import { isPrerender } from './tests/utils/isPrerender' -import { isPreview } from './tests/utils/isPreview' import packageJson from './package.json' with { type: 'json' } -const PORT = await getTestServerPort( - `${packageJson.name}${isSpaMode ? '_spa' : ''}${isPreview ? '_preview' : ''}`, -) -const START_PORT = await getTestServerPort( - `${packageJson.name}${isSpaMode ? '_spa_start' : ''}`, -) +const PORT = await getTestServerPort(packageJson.name) +const START_PORT = await getTestServerPort(`${packageJson.name}_start`) const EXTERNAL_PORT = await getDummyServerPort(packageJson.name) const baseURL = `http://localhost:${PORT}` -const spaModeCommand = `pnpm build:spa && pnpm start` const ssrModeCommand = `pnpm build && pnpm start` -const prerenderModeCommand = `pnpm run test:e2e:startDummyServer && pnpm build:prerender && pnpm run test:e2e:stopDummyServer && pnpm start` -const previewModeCommand = `pnpm build && pnpm preview --port ${PORT}` -const getCommand = () => { - if (isSpaMode) return spaModeCommand - if (isPrerender) return prerenderModeCommand - if (isPreview) return previewModeCommand - return ssrModeCommand -} -console.log('running in spa mode: ', isSpaMode.toString()) -console.log('running in prerender mode: ', isPrerender.toString()) -console.log('running in preview mode: ', isPreview.toString()) -/** - * See https://playwright.dev/docs/test-configuration. - */ export default defineConfig({ - testDir: './tests', + testDir: '../basic-test-suite/src', workers: 1, reporter: [['line']], - globalSetup: './tests/setup/global.setup.ts', - globalTeardown: './tests/setup/global.teardown.ts', + globalTeardown: '../basic-test-suite/src/setup/global.teardown.ts', use: { - /* Base URL to use in actions like `await page.goto('/')`. */ baseURL, }, webServer: { - command: getCommand(), + command: `pnpm run test:e2e:startDummyServer && ${ssrModeCommand}`, url: baseURL, reuseExistingServer: !process.env.CI, stdout: 'pipe', env: { - MODE: process.env.MODE || '', + MODE: '', VITE_NODE_ENV: 'test', VITE_EXTERNAL_PORT: String(EXTERNAL_PORT), VITE_SERVER_PORT: String(PORT), diff --git a/e2e/vue-start/basic/tests/setup/global.setup.ts b/e2e/vue-start/basic/tests/setup/global.setup.ts deleted file mode 100644 index 3593d10ab90..00000000000 --- a/e2e/vue-start/basic/tests/setup/global.setup.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { e2eStartDummyServer } from '@tanstack/router-e2e-utils' -import packageJson from '../../package.json' with { type: 'json' } - -export default async function setup() { - await e2eStartDummyServer(packageJson.name) -} diff --git a/e2e/vue-start/basic/tests/setup/global.teardown.ts b/e2e/vue-start/basic/tests/setup/global.teardown.ts deleted file mode 100644 index 62fd79911cc..00000000000 --- a/e2e/vue-start/basic/tests/setup/global.teardown.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { e2eStopDummyServer } from '@tanstack/router-e2e-utils' -import packageJson from '../../package.json' with { type: 'json' } - -export default async function teardown() { - await e2eStopDummyServer(packageJson.name) -} diff --git a/e2e/vue-start/basic/tsconfig.json b/e2e/vue-start/basic/tsconfig.json index 6d933a5b2c9..6f99c0f49a8 100644 --- a/e2e/vue-start/basic/tsconfig.json +++ b/e2e/vue-start/basic/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/css-modules/package.json b/e2e/vue-start/css-modules/package.json index c280bcc97fc..76506c47a2d 100644 --- a/e2e/vue-start/css-modules/package.json +++ b/e2e/vue-start/css-modules/package.json @@ -25,7 +25,7 @@ "@vitejs/plugin-vue-jsx": "^5.1.5", "sass": "^1.97.2", "srvx": "^0.11.9", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/e2e/vue-start/css-modules/tsconfig.json b/e2e/vue-start/css-modules/tsconfig.json index 8bf3d33789b..572d8408729 100644 --- a/e2e/vue-start/css-modules/tsconfig.json +++ b/e2e/vue-start/css-modules/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/custom-basepath/package.json b/e2e/vue-start/custom-basepath/package.json index 6a6970d1ce5..9d9f7781f5d 100644 --- a/e2e/vue-start/custom-basepath/package.json +++ b/e2e/vue-start/custom-basepath/package.json @@ -28,7 +28,7 @@ "srvx": "^0.11.9", "tailwindcss": "^4.2.2", "tsx": "^4.20.3", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5" diff --git a/e2e/vue-start/custom-basepath/src/vite-env.d.ts b/e2e/vue-start/custom-basepath/src/vite-env.d.ts index 0b2af560d60..d0b512cd805 100644 --- a/e2e/vue-start/custom-basepath/src/vite-env.d.ts +++ b/e2e/vue-start/custom-basepath/src/vite-env.d.ts @@ -1,3 +1,5 @@ +/// + declare module '*?url' { const url: string export default url diff --git a/e2e/vue-start/custom-basepath/tsconfig.json b/e2e/vue-start/custom-basepath/tsconfig.json index 6d933a5b2c9..6f99c0f49a8 100644 --- a/e2e/vue-start/custom-basepath/tsconfig.json +++ b/e2e/vue-start/custom-basepath/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/query-integration/package.json b/e2e/vue-start/query-integration/package.json index 435d7ca63ad..2ba30f2234a 100644 --- a/e2e/vue-start/query-integration/package.json +++ b/e2e/vue-start/query-integration/package.json @@ -31,6 +31,6 @@ "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2" + "typescript": "^6.0.2" } } diff --git a/e2e/vue-start/query-integration/tsconfig.json b/e2e/vue-start/query-integration/tsconfig.json index f9f5aab3dae..390dad84c06 100644 --- a/e2e/vue-start/query-integration/tsconfig.json +++ b/e2e/vue-start/query-integration/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/scroll-restoration/package.json b/e2e/vue-start/scroll-restoration/package.json index 4c1c4e183e2..8066e02be38 100644 --- a/e2e/vue-start/scroll-restoration/package.json +++ b/e2e/vue-start/scroll-restoration/package.json @@ -30,7 +30,7 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5" } diff --git a/e2e/vue-start/scroll-restoration/src/routes/(tests)/with-loader.tsx b/e2e/vue-start/scroll-restoration/src/routes/(tests)/with-loader.tsx index 23630b8ae41..50c2f2a47fe 100644 --- a/e2e/vue-start/scroll-restoration/src/routes/(tests)/with-loader.tsx +++ b/e2e/vue-start/scroll-restoration/src/routes/(tests)/with-loader.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/vue-router' -import { sleep } from 'src/utils/posts' +import { sleep } from '../../utils/posts' import { ScrollBlock } from '../-components/scroll-block' export const Route = createFileRoute('/(tests)/with-loader')({ diff --git a/e2e/vue-start/scroll-restoration/src/vite-env.d.ts b/e2e/vue-start/scroll-restoration/src/vite-env.d.ts index 0b2af560d60..d0b512cd805 100644 --- a/e2e/vue-start/scroll-restoration/src/vite-env.d.ts +++ b/e2e/vue-start/scroll-restoration/src/vite-env.d.ts @@ -1,3 +1,5 @@ +/// + declare module '*?url' { const url: string export default url diff --git a/e2e/vue-start/scroll-restoration/tsconfig.json b/e2e/vue-start/scroll-restoration/tsconfig.json index 6d933a5b2c9..6f99c0f49a8 100644 --- a/e2e/vue-start/scroll-restoration/tsconfig.json +++ b/e2e/vue-start/scroll-restoration/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/selective-ssr/package.json b/e2e/vue-start/selective-ssr/package.json index 4d51af28647..3024e26aa3b 100644 --- a/e2e/vue-start/selective-ssr/package.json +++ b/e2e/vue-start/selective-ssr/package.json @@ -22,7 +22,7 @@ "@tanstack/router-e2e-utils": "workspace:^", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5", diff --git a/e2e/vue-start/selective-ssr/tsconfig.json b/e2e/vue-start/selective-ssr/tsconfig.json index f9f5aab3dae..390dad84c06 100644 --- a/e2e/vue-start/selective-ssr/tsconfig.json +++ b/e2e/vue-start/selective-ssr/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/serialization-adapters/package.json b/e2e/vue-start/serialization-adapters/package.json index 94e2d015f41..8bc87bba175 100644 --- a/e2e/vue-start/serialization-adapters/package.json +++ b/e2e/vue-start/serialization-adapters/package.json @@ -23,7 +23,7 @@ "@tanstack/router-e2e-utils": "workspace:^", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5", diff --git a/e2e/vue-start/serialization-adapters/tsconfig.json b/e2e/vue-start/serialization-adapters/tsconfig.json index f9f5aab3dae..390dad84c06 100644 --- a/e2e/vue-start/serialization-adapters/tsconfig.json +++ b/e2e/vue-start/serialization-adapters/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/server-functions/package.json b/e2e/vue-start/server-functions/package.json index a021b5d4472..9fc4f2b379f 100644 --- a/e2e/vue-start/server-functions/package.json +++ b/e2e/vue-start/server-functions/package.json @@ -33,7 +33,7 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5" } diff --git a/e2e/vue-start/server-functions/src/vite-env.d.ts b/e2e/vue-start/server-functions/src/vite-env.d.ts index 0b2af560d60..d0b512cd805 100644 --- a/e2e/vue-start/server-functions/src/vite-env.d.ts +++ b/e2e/vue-start/server-functions/src/vite-env.d.ts @@ -1,3 +1,5 @@ +/// + declare module '*?url' { const url: string export default url diff --git a/e2e/vue-start/server-functions/tsconfig.json b/e2e/vue-start/server-functions/tsconfig.json index a5ae5ae7e47..d5b41741d2c 100644 --- a/e2e/vue-start/server-functions/tsconfig.json +++ b/e2e/vue-start/server-functions/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/server-routes/package.json b/e2e/vue-start/server-routes/package.json index b611852c714..4362a407ee0 100644 --- a/e2e/vue-start/server-routes/package.json +++ b/e2e/vue-start/server-routes/package.json @@ -33,7 +33,7 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5" } diff --git a/e2e/vue-start/server-routes/src/vite-env.d.ts b/e2e/vue-start/server-routes/src/vite-env.d.ts index 0b2af560d60..d0b512cd805 100644 --- a/e2e/vue-start/server-routes/src/vite-env.d.ts +++ b/e2e/vue-start/server-routes/src/vite-env.d.ts @@ -1,3 +1,5 @@ +/// + declare module '*?url' { const url: string export default url diff --git a/e2e/vue-start/server-routes/tsconfig.json b/e2e/vue-start/server-routes/tsconfig.json index a5ae5ae7e47..d5b41741d2c 100644 --- a/e2e/vue-start/server-routes/tsconfig.json +++ b/e2e/vue-start/server-routes/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/spa-mode/package.json b/e2e/vue-start/spa-mode/package.json index 3c2d215ec96..9754caf1408 100644 --- a/e2e/vue-start/spa-mode/package.json +++ b/e2e/vue-start/spa-mode/package.json @@ -22,7 +22,7 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/router-e2e-utils": "workspace:^", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5" diff --git a/e2e/vue-start/spa-mode/tsconfig.json b/e2e/vue-start/spa-mode/tsconfig.json index f9f5aab3dae..390dad84c06 100644 --- a/e2e/vue-start/spa-mode/tsconfig.json +++ b/e2e/vue-start/spa-mode/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/virtual-routes/package.json b/e2e/vue-start/virtual-routes/package.json index 4bec2251e07..c1ff5d719a6 100644 --- a/e2e/vue-start/virtual-routes/package.json +++ b/e2e/vue-start/virtual-routes/package.json @@ -30,7 +30,7 @@ "combinate": "^1.1.11", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5" } diff --git a/e2e/vue-start/virtual-routes/tsconfig.json b/e2e/vue-start/virtual-routes/tsconfig.json index 6d933a5b2c9..6f99c0f49a8 100644 --- a/e2e/vue-start/virtual-routes/tsconfig.json +++ b/e2e/vue-start/virtual-routes/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/e2e/vue-start/website/package.json b/e2e/vue-start/website/package.json index 35fb913ed87..dee9d170565 100644 --- a/e2e/vue-start/website/package.json +++ b/e2e/vue-start/website/package.json @@ -28,7 +28,7 @@ "@types/node": "^22.10.2", "srvx": "^0.11.9", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "@vitejs/plugin-vue": "^6.0.5", "@vitejs/plugin-vue-jsx": "^5.1.5" } diff --git a/e2e/vue-start/website/tsconfig.json b/e2e/vue-start/website/tsconfig.json index f9f5aab3dae..390dad84c06 100644 --- a/e2e/vue-start/website/tsconfig.json +++ b/e2e/vue-start/website/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/authenticated-routes-firebase/package.json b/examples/react/authenticated-routes-firebase/package.json index fef9c81195e..d52da2de6bb 100644 --- a/examples/react/authenticated-routes-firebase/package.json +++ b/examples/react/authenticated-routes-firebase/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "firebase": "^11.4.0", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -25,7 +25,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/authenticated-routes/package.json b/examples/react/authenticated-routes/package.json index 0a8df4069fa..32574859aef 100644 --- a/examples/react/authenticated-routes/package.json +++ b/examples/react/authenticated-routes/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -23,7 +23,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/authenticated-routes/src/vite-env.d.ts b/examples/react/authenticated-routes/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/authenticated-routes/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/basic-default-search-params/package.json b/examples/react/basic-default-search-params/package.json index 900eff120a4..de52025d5d8 100644 --- a/examples/react/basic-default-search-params/package.json +++ b/examples/react/basic-default-search-params/package.json @@ -11,8 +11,8 @@ "dependencies": { "@tailwindcss/vite": "^4.2.2", "@tanstack/react-query": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -23,7 +23,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/basic-default-search-params/src/vite-env.d.ts b/examples/react/basic-default-search-params/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/basic-default-search-params/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/basic-devtools-panel/package.json b/examples/react/basic-devtools-panel/package.json index b7813326aa6..0dab4b7102e 100644 --- a/examples/react/basic-devtools-panel/package.json +++ b/examples/react/basic-devtools-panel/package.json @@ -11,8 +11,8 @@ "dependencies": { "@tailwindcss/vite": "^4.2.2", "@tanstack/react-query-devtools": "^5.67.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -22,7 +22,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/basic-devtools-panel/src/vite-env.d.ts b/examples/react/basic-devtools-panel/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/basic-devtools-panel/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/basic-file-based/package.json b/examples/react/basic-file-based/package.json index 952051010b5..0ea2702e0fe 100644 --- a/examples/react/basic-file-based/package.json +++ b/examples/react/basic-file-based/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -23,7 +23,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/basic-file-based/src/vite-env.d.ts b/examples/react/basic-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/basic-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/basic-non-nested-devtools/package.json b/examples/react/basic-non-nested-devtools/package.json index 4db0deae868..750018a04b9 100644 --- a/examples/react/basic-non-nested-devtools/package.json +++ b/examples/react/basic-non-nested-devtools/package.json @@ -10,8 +10,8 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -21,7 +21,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/basic-non-nested-devtools/src/vite-env.d.ts b/examples/react/basic-non-nested-devtools/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/basic-non-nested-devtools/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/basic-react-query-file-based/package.json b/examples/react/basic-react-query-file-based/package.json index f65e12e528e..dfb91c5753e 100644 --- a/examples/react/basic-react-query-file-based/package.json +++ b/examples/react/basic-react-query-file-based/package.json @@ -12,9 +12,9 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/react-query": "^5.90.0", "@tanstack/react-query-devtools": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -25,7 +25,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/basic-react-query-file-based/src/vite-env.d.ts b/examples/react/basic-react-query-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/basic-react-query-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/basic-react-query/package.json b/examples/react/basic-react-query/package.json index 73d80a92970..5fecea60a7c 100644 --- a/examples/react/basic-react-query/package.json +++ b/examples/react/basic-react-query/package.json @@ -12,8 +12,8 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/react-query": "^5.90.0", "@tanstack/react-query-devtools": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -23,7 +23,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/basic-react-query/src/vite-env.d.ts b/examples/react/basic-react-query/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/basic-react-query/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/basic-ssr-file-based/package.json b/examples/react/basic-ssr-file-based/package.json index 1cf253b8175..f4967178821 100644 --- a/examples/react/basic-ssr-file-based/package.json +++ b/examples/react/basic-ssr-file-based/package.json @@ -11,8 +11,8 @@ "debug": "node --inspect-brk server" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/router-plugin": "^1.167.12", "compression": "^1.8.0", "express": "^4.21.2", "get-port": "^7.1.0", @@ -21,12 +21,12 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router-devtools": "^1.166.11", "@types/express": "^4.17.23", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.1", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.8.3", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/basic-ssr-streaming-file-based/package.json b/examples/react/basic-ssr-streaming-file-based/package.json index cccd3e9554e..d106e6bb69b 100644 --- a/examples/react/basic-ssr-streaming-file-based/package.json +++ b/examples/react/basic-ssr-streaming-file-based/package.json @@ -11,8 +11,8 @@ "debug": "node --inspect-brk server" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/router-plugin": "^1.167.12", "compression": "^1.8.0", "express": "^4.21.2", "get-port": "^7.1.0", @@ -21,12 +21,12 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router-devtools": "^1.166.11", "@types/express": "^4.17.23", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.1", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/basic-virtual-file-based/package.json b/examples/react/basic-virtual-file-based/package.json index 23e69661ca6..492ea4d0a1b 100644 --- a/examples/react/basic-virtual-file-based/package.json +++ b/examples/react/basic-virtual-file-based/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "@tanstack/virtual-file-routes": "^1.161.7", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -24,7 +24,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/basic-virtual-file-based/src/vite-env.d.ts b/examples/react/basic-virtual-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/basic-virtual-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/basic-virtual-inside-file-based/package.json b/examples/react/basic-virtual-inside-file-based/package.json index e4eb3bfe8c1..6c33994e9bd 100644 --- a/examples/react/basic-virtual-inside-file-based/package.json +++ b/examples/react/basic-virtual-inside-file-based/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "@tanstack/virtual-file-routes": "^1.161.7", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -24,7 +24,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/basic-virtual-inside-file-based/src/vite-env.d.ts b/examples/react/basic-virtual-inside-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/basic-virtual-inside-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/basic/package.json b/examples/react/basic/package.json index fde1186eeaf..1d776a57859 100644 --- a/examples/react/basic/package.json +++ b/examples/react/basic/package.json @@ -10,8 +10,8 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -21,7 +21,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/basic/src/vite-env.d.ts b/examples/react/basic/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/basic/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/deferred-data/package.json b/examples/react/deferred-data/package.json index 727ea3b0c71..c38fe713f00 100644 --- a/examples/react/deferred-data/package.json +++ b/examples/react/deferred-data/package.json @@ -10,8 +10,8 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -22,7 +22,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/deferred-data/src/vite-env.d.ts b/examples/react/deferred-data/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/deferred-data/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/i18n-paraglide/package.json b/examples/react/i18n-paraglide/package.json index 0df8e3f9e23..676dd16d88f 100644 --- a/examples/react/i18n-paraglide/package.json +++ b/examples/react/i18n-paraglide/package.json @@ -11,8 +11,8 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/router-plugin": "^1.167.12", "react": "^19.1.1", "react-dom": "^19.1.1", "tailwindcss": "^4.2.2" @@ -22,7 +22,7 @@ "@types/react": "^19.1.13", "@types/react-dom": "^19.1.9", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.9.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "@inlang/paraglide-js": "^2.4.0" } diff --git a/examples/react/i18n-paraglide/src/vite-env.d.ts b/examples/react/i18n-paraglide/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/i18n-paraglide/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/i18n-paraglide/tsconfig.json b/examples/react/i18n-paraglide/tsconfig.json index fded1fca188..c26f8f774e4 100644 --- a/examples/react/i18n-paraglide/tsconfig.json +++ b/examples/react/i18n-paraglide/tsconfig.json @@ -21,7 +21,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true, - "baseUrl": ".", "paths": { "@/*": ["./src/*"] } diff --git a/examples/react/kitchen-sink-file-based/package.json b/examples/react/kitchen-sink-file-based/package.json index 8e2bfebc35b..e691cf748f5 100644 --- a/examples/react/kitchen-sink-file-based/package.json +++ b/examples/react/kitchen-sink-file-based/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "immer": "^10.1.1", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -24,7 +24,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/kitchen-sink-file-based/src/vite-env.d.ts b/examples/react/kitchen-sink-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/kitchen-sink-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/kitchen-sink-react-query-file-based/package.json b/examples/react/kitchen-sink-react-query-file-based/package.json index 670a6143083..aa5d7a56c0b 100644 --- a/examples/react/kitchen-sink-react-query-file-based/package.json +++ b/examples/react/kitchen-sink-react-query-file-based/package.json @@ -12,9 +12,9 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/react-query": "^5.90.0", "@tanstack/react-query-devtools": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "immer": "^10.1.1", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -26,7 +26,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/kitchen-sink-react-query-file-based/src/vite-env.d.ts b/examples/react/kitchen-sink-react-query-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/kitchen-sink-react-query-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/kitchen-sink-react-query/package.json b/examples/react/kitchen-sink-react-query/package.json index 9ec02a1ee7c..908768f0a48 100644 --- a/examples/react/kitchen-sink-react-query/package.json +++ b/examples/react/kitchen-sink-react-query/package.json @@ -12,8 +12,8 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/react-query": "^5.90.0", "@tanstack/react-query-devtools": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "immer": "^10.1.1", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -25,7 +25,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/kitchen-sink-react-query/src/vite-env.d.ts b/examples/react/kitchen-sink-react-query/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/kitchen-sink-react-query/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/kitchen-sink/package.json b/examples/react/kitchen-sink/package.json index 771977f2ec2..6730131449b 100644 --- a/examples/react/kitchen-sink/package.json +++ b/examples/react/kitchen-sink/package.json @@ -10,8 +10,8 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "immer": "^10.1.1", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -23,7 +23,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/kitchen-sink/src/vite-env.d.ts b/examples/react/kitchen-sink/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/kitchen-sink/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/large-file-based/package.json b/examples/react/large-file-based/package.json index 4d47abc8754..81a3168ad30 100644 --- a/examples/react/large-file-based/package.json +++ b/examples/react/large-file-based/package.json @@ -13,9 +13,9 @@ "dependencies": { "@tailwindcss/vite": "^4.2.2", "@tanstack/react-query": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -26,7 +26,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/large-file-based/src/vite-env.d.ts b/examples/react/large-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/large-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/location-masking/package.json b/examples/react/location-masking/package.json index 12d22f9b74f..c1ad5b7be18 100644 --- a/examples/react/location-masking/package.json +++ b/examples/react/location-masking/package.json @@ -12,8 +12,8 @@ "@radix-ui/react-dialog": "^1.1.6", "@tailwindcss/vite": "^4.2.2", "@tanstack/react-query": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -23,7 +23,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/location-masking/src/vite-env.d.ts b/examples/react/location-masking/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/location-masking/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/navigation-blocking/package.json b/examples/react/navigation-blocking/package.json index c846dda927c..ad2a2e8ec31 100644 --- a/examples/react/navigation-blocking/package.json +++ b/examples/react/navigation-blocking/package.json @@ -11,8 +11,8 @@ "dependencies": { "@tailwindcss/vite": "^4.2.2", "@tanstack/react-query": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -22,7 +22,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/navigation-blocking/src/vite-env.d.ts b/examples/react/navigation-blocking/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/navigation-blocking/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/quickstart-esbuild-file-based/package.json b/examples/react/quickstart-esbuild-file-based/package.json index 6e5c4c586fd..6aff4c361de 100644 --- a/examples/react/quickstart-esbuild-file-based/package.json +++ b/examples/react/quickstart-esbuild-file-based/package.json @@ -9,9 +9,9 @@ "start": "dev" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", diff --git a/examples/react/quickstart-file-based/package.json b/examples/react/quickstart-file-based/package.json index 419bc3deae2..babc6e48a7c 100644 --- a/examples/react/quickstart-file-based/package.json +++ b/examples/react/quickstart-file-based/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -23,7 +23,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/quickstart-file-based/src/vite-env.d.ts b/examples/react/quickstart-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/quickstart-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/quickstart-rspack-file-based/package.json b/examples/react/quickstart-rspack-file-based/package.json index 3df374e58fb..477073e1809 100644 --- a/examples/react/quickstart-rspack-file-based/package.json +++ b/examples/react/quickstart-rspack-file-based/package.json @@ -9,8 +9,8 @@ }, "dependencies": { "@tailwindcss/postcss": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "postcss": "^8.5.1", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -19,9 +19,9 @@ "devDependencies": { "@rsbuild/core": "^1.2.4", "@rsbuild/plugin-react": "^1.1.0", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", - "typescript": "^5.6.2" + "typescript": "^6.0.2" } } diff --git a/examples/react/quickstart-rspack-file-based/src/vite-env.d.ts b/examples/react/quickstart-rspack-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/quickstart-rspack-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/quickstart-webpack-file-based/package.json b/examples/react/quickstart-webpack-file-based/package.json index e31fae09db8..82d5c701476 100644 --- a/examples/react/quickstart-webpack-file-based/package.json +++ b/examples/react/quickstart-webpack-file-based/package.json @@ -7,19 +7,19 @@ "build": "webpack build && tsc --noEmit" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "react": "^19.0.0", "react-dom": "^19.0.0" }, "devDependencies": { "@swc/core": "^1.10.15", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "html-webpack-plugin": "^5.6.3", "swc-loader": "^0.2.6", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "webpack": "^5.97.1", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.2.0" diff --git a/examples/react/quickstart/package.json b/examples/react/quickstart/package.json index 73fbed591fa..c800c4744ae 100644 --- a/examples/react/quickstart/package.json +++ b/examples/react/quickstart/package.json @@ -10,8 +10,8 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "react": "^19.0.0", "react-dom": "^19.0.0", "tailwindcss": "^4.2.2" @@ -20,7 +20,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/quickstart/src/vite-env.d.ts b/examples/react/quickstart/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/quickstart/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/router-monorepo-react-query/package.json b/examples/react/router-monorepo-react-query/package.json index 96b75bde912..44ff29eb77e 100644 --- a/examples/react/router-monorepo-react-query/package.json +++ b/examples/react/router-monorepo-react-query/package.json @@ -12,9 +12,9 @@ "dependencies": { "@tanstack/react-query": "^5.90.0", "@tanstack/react-query-devtools": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1" @@ -23,7 +23,7 @@ "@types/node": "^22.10.2", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "@vitejs/plugin-react": "^6.0.1", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" diff --git a/examples/react/router-monorepo-react-query/packages/app/package.json b/examples/react/router-monorepo-react-query/packages/app/package.json index 7931f67b5d8..17338f62bbc 100644 --- a/examples/react/router-monorepo-react-query/packages/app/package.json +++ b/examples/react/router-monorepo-react-query/packages/app/package.json @@ -16,12 +16,12 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router-devtools": "^1.166.11", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4", "@tailwindcss/vite": "^4.2.2" diff --git a/examples/react/router-monorepo-react-query/packages/app/src/vite-env.d.ts b/examples/react/router-monorepo-react-query/packages/app/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/router-monorepo-react-query/packages/app/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/router-monorepo-react-query/packages/post-feature/package.json b/examples/react/router-monorepo-react-query/packages/post-feature/package.json index edd19337fdb..13a04ca8114 100644 --- a/examples/react/router-monorepo-react-query/packages/post-feature/package.json +++ b/examples/react/router-monorepo-react-query/packages/post-feature/package.json @@ -18,7 +18,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" } diff --git a/examples/react/router-monorepo-react-query/packages/post-query/package.json b/examples/react/router-monorepo-react-query/packages/post-query/package.json index a6fad5b810c..976f63750dc 100644 --- a/examples/react/router-monorepo-react-query/packages/post-query/package.json +++ b/examples/react/router-monorepo-react-query/packages/post-query/package.json @@ -14,7 +14,7 @@ }, "devDependencies": { "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/router-monorepo-react-query/packages/router/package.json b/examples/react/router-monorepo-react-query/packages/router/package.json index 579c5d3a68f..cc40d7130ef 100644 --- a/examples/react/router-monorepo-react-query/packages/router/package.json +++ b/examples/react/router-monorepo-react-query/packages/router/package.json @@ -10,8 +10,8 @@ "dependencies": { "@tanstack/history": "^1.161.6", "@tanstack/react-query": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/router-plugin": "^1.167.12", "@router-mono-react-query/post-query": "workspace:*", "redaxios": "^0.5.1", "zod": "^3.24.2", @@ -22,7 +22,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" } diff --git a/examples/react/router-monorepo-react-query/packages/router/tsconfig.json b/examples/react/router-monorepo-react-query/packages/router/tsconfig.json index 0d04c7789d9..aeb605df287 100644 --- a/examples/react/router-monorepo-react-query/packages/router/tsconfig.json +++ b/examples/react/router-monorepo-react-query/packages/router/tsconfig.json @@ -7,7 +7,8 @@ "moduleResolution": "Bundler", "module": "ESNext", "lib": ["DOM", "DOM.Iterable", "ES2022"], - "skipLibCheck": true + "skipLibCheck": true, + "rootDir": "src" }, "include": ["src"] } diff --git a/examples/react/router-monorepo-simple-lazy/package.json b/examples/react/router-monorepo-simple-lazy/package.json index 8169a94151c..67f4995b79c 100644 --- a/examples/react/router-monorepo-simple-lazy/package.json +++ b/examples/react/router-monorepo-simple-lazy/package.json @@ -8,9 +8,9 @@ "dev": "pnpm router build && pnpm post-feature build && pnpm app dev" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1" @@ -20,7 +20,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" }, diff --git a/examples/react/router-monorepo-simple-lazy/packages/app/package.json b/examples/react/router-monorepo-simple-lazy/packages/app/package.json index 247246080e2..0820496d40d 100644 --- a/examples/react/router-monorepo-simple-lazy/packages/app/package.json +++ b/examples/react/router-monorepo-simple-lazy/packages/app/package.json @@ -15,12 +15,12 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router-devtools": "^1.166.11", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4", "@tailwindcss/vite": "^4.2.2" diff --git a/examples/react/router-monorepo-simple-lazy/packages/app/src/vite-env.d.ts b/examples/react/router-monorepo-simple-lazy/packages/app/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/router-monorepo-simple-lazy/packages/app/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/router-monorepo-simple-lazy/packages/post-feature/package.json b/examples/react/router-monorepo-simple-lazy/packages/post-feature/package.json index d6a5967ed85..4bbd045eebd 100644 --- a/examples/react/router-monorepo-simple-lazy/packages/post-feature/package.json +++ b/examples/react/router-monorepo-simple-lazy/packages/post-feature/package.json @@ -25,7 +25,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" } diff --git a/examples/react/router-monorepo-simple-lazy/packages/router/package.json b/examples/react/router-monorepo-simple-lazy/packages/router/package.json index 558a9acf323..d46cc9738a2 100644 --- a/examples/react/router-monorepo-simple-lazy/packages/router/package.json +++ b/examples/react/router-monorepo-simple-lazy/packages/router/package.json @@ -9,8 +9,8 @@ "types": "./dist/index.d.ts", "dependencies": { "@tanstack/history": "^1.161.6", - "@tanstack/react-router": "^1.168.1", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/router-plugin": "^1.167.12", "redaxios": "^0.5.1", "zod": "^3.24.2", "react": "^19.0.0", @@ -20,7 +20,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" } diff --git a/examples/react/router-monorepo-simple-lazy/packages/router/tsconfig.json b/examples/react/router-monorepo-simple-lazy/packages/router/tsconfig.json index 0d04c7789d9..aeb605df287 100644 --- a/examples/react/router-monorepo-simple-lazy/packages/router/tsconfig.json +++ b/examples/react/router-monorepo-simple-lazy/packages/router/tsconfig.json @@ -7,7 +7,8 @@ "moduleResolution": "Bundler", "module": "ESNext", "lib": ["DOM", "DOM.Iterable", "ES2022"], - "skipLibCheck": true + "skipLibCheck": true, + "rootDir": "src" }, "include": ["src"] } diff --git a/examples/react/router-monorepo-simple/package.json b/examples/react/router-monorepo-simple/package.json index e270144314b..145bc1ef013 100644 --- a/examples/react/router-monorepo-simple/package.json +++ b/examples/react/router-monorepo-simple/package.json @@ -8,9 +8,9 @@ "dev": "pnpm router build && pnpm post-feature build && pnpm app dev" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1" @@ -20,7 +20,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" }, diff --git a/examples/react/router-monorepo-simple/packages/app/package.json b/examples/react/router-monorepo-simple/packages/app/package.json index 4cd0044f4f9..fd2cc2777d0 100644 --- a/examples/react/router-monorepo-simple/packages/app/package.json +++ b/examples/react/router-monorepo-simple/packages/app/package.json @@ -15,12 +15,12 @@ "react-dom": "^19.0.0" }, "devDependencies": { - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router-devtools": "^1.166.11", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4", "@tailwindcss/vite": "^4.2.2" diff --git a/examples/react/router-monorepo-simple/packages/app/src/vite-env.d.ts b/examples/react/router-monorepo-simple/packages/app/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/router-monorepo-simple/packages/app/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/router-monorepo-simple/packages/post-feature/package.json b/examples/react/router-monorepo-simple/packages/post-feature/package.json index ee6280402af..6823f49b073 100644 --- a/examples/react/router-monorepo-simple/packages/post-feature/package.json +++ b/examples/react/router-monorepo-simple/packages/post-feature/package.json @@ -16,7 +16,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" } diff --git a/examples/react/router-monorepo-simple/packages/router/package.json b/examples/react/router-monorepo-simple/packages/router/package.json index d7945424d4c..a53713ac5e8 100644 --- a/examples/react/router-monorepo-simple/packages/router/package.json +++ b/examples/react/router-monorepo-simple/packages/router/package.json @@ -9,8 +9,8 @@ "types": "./dist/index.d.ts", "dependencies": { "@tanstack/history": "^1.161.6", - "@tanstack/react-router": "^1.168.1", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/router-plugin": "^1.167.12", "redaxios": "^0.5.1", "zod": "^3.24.2", "react": "^19.0.0", @@ -20,7 +20,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" } diff --git a/examples/react/router-monorepo-simple/packages/router/tsconfig.json b/examples/react/router-monorepo-simple/packages/router/tsconfig.json index 0d04c7789d9..aeb605df287 100644 --- a/examples/react/router-monorepo-simple/packages/router/tsconfig.json +++ b/examples/react/router-monorepo-simple/packages/router/tsconfig.json @@ -7,7 +7,8 @@ "moduleResolution": "Bundler", "module": "ESNext", "lib": ["DOM", "DOM.Iterable", "ES2022"], - "skipLibCheck": true + "skipLibCheck": true, + "rootDir": "src" }, "include": ["src"] } diff --git a/examples/react/scroll-restoration/package.json b/examples/react/scroll-restoration/package.json index 192475f5d72..0e807da3db5 100644 --- a/examples/react/scroll-restoration/package.json +++ b/examples/react/scroll-restoration/package.json @@ -10,8 +10,8 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "@tanstack/react-virtual": "^3.13.0", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -21,7 +21,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/scroll-restoration/src/vite-env.d.ts b/examples/react/scroll-restoration/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/scroll-restoration/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/search-validator-adapters/package.json b/examples/react/search-validator-adapters/package.json index 7685df899e2..95087c5a878 100644 --- a/examples/react/search-validator-adapters/package.json +++ b/examples/react/search-validator-adapters/package.json @@ -13,9 +13,9 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/arktype-adapter": "^1.166.9", "@tanstack/react-query": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "@tanstack/valibot-adapter": "^1.166.9", "@tanstack/zod-adapter": "^1.166.9", "arktype": "^2.1.7", @@ -31,7 +31,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/search-validator-adapters/src/vite-env.d.ts b/examples/react/search-validator-adapters/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/search-validator-adapters/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/start-bare/package.json b/examples/react/start-bare/package.json index dfc301ad60f..d1eded97ea3 100644 --- a/examples/react/start-bare/package.json +++ b/examples/react/start-bare/package.json @@ -10,9 +10,9 @@ "start": "pnpx srvx --prod -s ../client dist/server/server.js" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "react": "^19.0.0", "react-dom": "^19.0.0", "zod": "^3.24.2" @@ -22,7 +22,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/start-bare/tsconfig.json b/examples/react/start-bare/tsconfig.json index b3a2d67dfa6..af81492efb0 100644 --- a/examples/react/start-bare/tsconfig.json +++ b/examples/react/start-bare/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-basic-auth/package.json b/examples/react/start-basic-auth/package.json index 09bab58feff..da7b6c36169 100644 --- a/examples/react/start-basic-auth/package.json +++ b/examples/react/start-basic-auth/package.json @@ -14,9 +14,9 @@ "@libsql/client": "^0.15.15", "@prisma/adapter-libsql": "^7.0.0", "@prisma/client": "^7.0.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -31,7 +31,7 @@ "dotenv": "^17.2.3", "prisma": "^7.0.0", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/start-basic-auth/tsconfig.json b/examples/react/start-basic-auth/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/examples/react/start-basic-auth/tsconfig.json +++ b/examples/react/start-basic-auth/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-basic-authjs/package.json b/examples/react/start-basic-authjs/package.json index dc315cf2b66..8618bb36a48 100644 --- a/examples/react/start-basic-authjs/package.json +++ b/examples/react/start-basic-authjs/package.json @@ -11,9 +11,9 @@ }, "dependencies": { "@auth/core": "^0.41.1", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "start-authjs": "^1.0.0", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -25,7 +25,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "@vitejs/plugin-react": "^6.0.1" } diff --git a/examples/react/start-basic-authjs/tsconfig.json b/examples/react/start-basic-authjs/tsconfig.json index 70cbbc5ce37..ff21ac7cfaa 100644 --- a/examples/react/start-basic-authjs/tsconfig.json +++ b/examples/react/start-basic-authjs/tsconfig.json @@ -15,7 +15,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "allowSyntheticDefaultImports": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] } diff --git a/examples/react/start-basic-cloudflare/package.json b/examples/react/start-basic-cloudflare/package.json index 9ac6f300e5e..6ba516f679e 100644 --- a/examples/react/start-basic-cloudflare/package.json +++ b/examples/react/start-basic-cloudflare/package.json @@ -12,9 +12,9 @@ "postinstall": "npm run cf-typegen" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "react": "^19.0.0", "react-dom": "^19.0.0" }, @@ -26,7 +26,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "wrangler": "^4.74.0" } diff --git a/examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx b/examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx index 212e83d8fe8..fe22eb86c38 100644 --- a/examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx +++ b/examples/react/start-basic-cloudflare/src/routes/users.$userId.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/react-router' -import { NotFound } from 'src/components/NotFound' -import { UserErrorComponent } from 'src/components/UserError' +import { NotFound } from '../components/NotFound' +import { UserErrorComponent } from '../components/UserError' import type { User } from '~/utils/users' export const Route = createFileRoute('/users/$userId')({ diff --git a/examples/react/start-basic-cloudflare/tsconfig.json b/examples/react/start-basic-cloudflare/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/examples/react/start-basic-cloudflare/tsconfig.json +++ b/examples/react/start-basic-cloudflare/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-basic-react-query/package.json b/examples/react/start-basic-react-query/package.json index 3b78a551f30..9cd113c5624 100644 --- a/examples/react/start-basic-react-query/package.json +++ b/examples/react/start-basic-react-query/package.json @@ -12,10 +12,10 @@ "dependencies": { "@tanstack/react-query": "^5.90.0", "@tanstack/react-query-devtools": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "@tanstack/react-router-ssr-query": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-start": "^1.167.16", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -28,7 +28,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/start-basic-react-query/tsconfig.json b/examples/react/start-basic-react-query/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/examples/react/start-basic-react-query/tsconfig.json +++ b/examples/react/start-basic-react-query/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-basic-rsc/package.json b/examples/react/start-basic-rsc/package.json index 3916003ffef..b083ad70f1b 100644 --- a/examples/react/start-basic-rsc/package.json +++ b/examples/react/start-basic-rsc/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@babel/plugin-syntax-typescript": "^7.25.9", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -23,7 +23,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "@tailwindcss/vite": "^4.2.2" }, diff --git a/examples/react/start-basic-rsc/tsconfig.json b/examples/react/start-basic-rsc/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/examples/react/start-basic-rsc/tsconfig.json +++ b/examples/react/start-basic-rsc/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-basic-static/package.json b/examples/react/start-basic-static/package.json index d1113b4f219..0936b46b18f 100644 --- a/examples/react/start-basic-static/package.json +++ b/examples/react/start-basic-static/package.json @@ -10,10 +10,10 @@ "start": "pnpx srvx --prod -s ../client dist/server/server.js" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", - "@tanstack/start-static-server-functions": "^1.166.17", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", + "@tanstack/start-static-server-functions": "^1.166.25", "@vitejs/plugin-react": "^6.0.1", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -25,7 +25,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "tailwindcss": "^4.2.2", - "typescript": "^5.6.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "@tailwindcss/vite": "^4.2.2" } diff --git a/examples/react/start-basic-static/tsconfig.json b/examples/react/start-basic-static/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/examples/react/start-basic-static/tsconfig.json +++ b/examples/react/start-basic-static/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-basic/package.json b/examples/react/start-basic/package.json index 1c753cb87e9..efba12ffdf6 100644 --- a/examples/react/start-basic/package.json +++ b/examples/react/start-basic/package.json @@ -10,9 +10,9 @@ "start": "node .output/server/index.mjs" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "react": "^19.0.0", "react-dom": "^19.0.0", "tailwind-merge": "^2.6.0", @@ -26,7 +26,7 @@ "@vitejs/plugin-react": "^6.0.1", "nitro": "^3.0.260311-beta", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/start-basic/src/routes/users.$userId.tsx b/examples/react/start-basic/src/routes/users.$userId.tsx index 1df768344d7..4e4d470075f 100644 --- a/examples/react/start-basic/src/routes/users.$userId.tsx +++ b/examples/react/start-basic/src/routes/users.$userId.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/react-router' -import { NotFound } from 'src/components/NotFound' -import { UserErrorComponent } from 'src/components/UserError' +import { NotFound } from '../components/NotFound' +import { UserErrorComponent } from '../components/UserError' import type { User } from '../utils/users' export const Route = createFileRoute('/users/$userId')({ diff --git a/examples/react/start-basic/tsconfig.json b/examples/react/start-basic/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/examples/react/start-basic/tsconfig.json +++ b/examples/react/start-basic/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-bun/package.json b/examples/react/start-bun/package.json index ba14098a2c9..2749cc82d8a 100644 --- a/examples/react/start-bun/package.json +++ b/examples/react/start-bun/package.json @@ -14,11 +14,12 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-devtools": "^0.7.0", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "@tanstack/react-router-ssr-query": "^1.166.10", - "@tanstack/react-start": "^1.167.2", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-start": "^1.167.16", + "@tanstack/router-plugin": "^1.167.12", "react": "^19.1.1", "react-dom": "^19.1.1", "tailwindcss": "^4.2.2" @@ -34,7 +35,7 @@ "@vitejs/plugin-react": "^6.0.1", "jsdom": "^27.0.0", "prettier": "^3.6.2", - "typescript": "^5.9.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vitest": "^3.2.4", "web-vitals": "^5.1.0" diff --git a/examples/react/start-bun/src/vite-env.d.ts b/examples/react/start-bun/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/start-bun/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/start-bun/tsconfig.json b/examples/react/start-bun/tsconfig.json index 2cc3abd5d4d..2f09fb43be8 100644 --- a/examples/react/start-bun/tsconfig.json +++ b/examples/react/start-bun/tsconfig.json @@ -27,7 +27,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true, - "baseUrl": ".", "paths": { "@/*": ["./src/*"] } diff --git a/examples/react/start-clerk-basic/package.json b/examples/react/start-clerk-basic/package.json index 16e7f4f04ce..5e2ce132367 100644 --- a/examples/react/start-clerk-basic/package.json +++ b/examples/react/start-clerk-basic/package.json @@ -11,9 +11,9 @@ }, "dependencies": { "@clerk/tanstack-react-start": "^0.27.14", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "@vitejs/plugin-react": "^6.0.1", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -27,7 +27,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/start-clerk-basic/tsconfig.json b/examples/react/start-clerk-basic/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/examples/react/start-clerk-basic/tsconfig.json +++ b/examples/react/start-clerk-basic/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-convex-trellaux/convex/board.ts b/examples/react/start-convex-trellaux/convex/board.ts index bae241a7734..f585a01cd33 100644 --- a/examples/react/start-convex-trellaux/convex/board.ts +++ b/examples/react/start-convex-trellaux/convex/board.ts @@ -1,4 +1,4 @@ -import invariant from 'tiny-invariant' +import { invariant } from './invariant' import { v } from 'convex/values' import { type QueryCtx, diff --git a/examples/react/start-convex-trellaux/convex/invariant.ts b/examples/react/start-convex-trellaux/convex/invariant.ts new file mode 100644 index 00000000000..41fcded35ef --- /dev/null +++ b/examples/react/start-convex-trellaux/convex/invariant.ts @@ -0,0 +1,5 @@ +export function invariant(value: unknown, message?: string): asserts value { + if (!value) { + throw new Error(message ?? 'Invariant failed') + } +} diff --git a/examples/react/start-convex-trellaux/package.json b/examples/react/start-convex-trellaux/package.json index 171c516d08a..2a712d3e1af 100644 --- a/examples/react/start-convex-trellaux/package.json +++ b/examples/react/start-convex-trellaux/package.json @@ -15,10 +15,10 @@ "@convex-dev/react-query": "0.0.0-alpha.8", "@tanstack/react-query": "^5.90.0", "@tanstack/react-query-devtools": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "@tanstack/react-router-ssr-query": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-start": "^1.167.16", "concurrently": "^8.2.2", "convex": "^1.19.0", "ky": "^1.7.4", @@ -28,7 +28,6 @@ "react-hot-toast": "^2.5.1", "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", - "tiny-invariant": "^1.3.3", "zod": "^3.24.2" }, "devDependencies": { @@ -38,7 +37,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/start-convex-trellaux/src/components/Board.tsx b/examples/react/start-convex-trellaux/src/components/Board.tsx index 327603e2046..ac78c7baae5 100644 --- a/examples/react/start-convex-trellaux/src/components/Board.tsx +++ b/examples/react/start-convex-trellaux/src/components/Board.tsx @@ -1,5 +1,5 @@ import { useCallback, useMemo, useRef } from 'react' -import invariant from 'tiny-invariant' +import { invariant } from '../invariant' import { useSuspenseQuery } from '@tanstack/react-query' import { convexQuery } from '@convex-dev/react-query' import { api } from '../../convex/_generated/api.js' diff --git a/examples/react/start-convex-trellaux/src/components/Card.tsx b/examples/react/start-convex-trellaux/src/components/Card.tsx index eacf87d7598..23f77ca2b2c 100644 --- a/examples/react/start-convex-trellaux/src/components/Card.tsx +++ b/examples/react/start-convex-trellaux/src/components/Card.tsx @@ -1,4 +1,4 @@ -import invariant from 'tiny-invariant' +import { invariant } from '../invariant' import { forwardRef, useState } from 'react' import { CONTENT_TYPES } from '../types' diff --git a/examples/react/start-convex-trellaux/src/components/Column.tsx b/examples/react/start-convex-trellaux/src/components/Column.tsx index dd90e02ee71..fdf2916f6b1 100644 --- a/examples/react/start-convex-trellaux/src/components/Column.tsx +++ b/examples/react/start-convex-trellaux/src/components/Column.tsx @@ -1,8 +1,8 @@ import { forwardRef, useCallback, useMemo, useRef, useState } from 'react' -import invariant from 'tiny-invariant' import { twMerge } from 'tailwind-merge' import { flushSync } from 'react-dom' +import { invariant } from '../invariant' import { CONTENT_TYPES } from '../types' import { Icon } from '../icons/icons' import { diff --git a/examples/react/start-convex-trellaux/src/components/NewCard.tsx b/examples/react/start-convex-trellaux/src/components/NewCard.tsx index 47cadcf5aee..99b0b148390 100644 --- a/examples/react/start-convex-trellaux/src/components/NewCard.tsx +++ b/examples/react/start-convex-trellaux/src/components/NewCard.tsx @@ -1,5 +1,5 @@ import { useRef } from 'react' -import invariant from 'tiny-invariant' +import { invariant } from '../invariant' import { ItemMutationFields } from '../types' import { useCreateItemMutation } from '../queries' diff --git a/examples/react/start-convex-trellaux/src/components/NewColumn.tsx b/examples/react/start-convex-trellaux/src/components/NewColumn.tsx index 50a7d608c55..0cd1f6aa532 100644 --- a/examples/react/start-convex-trellaux/src/components/NewColumn.tsx +++ b/examples/react/start-convex-trellaux/src/components/NewColumn.tsx @@ -1,5 +1,5 @@ import { useRef, useState } from 'react' -import invariant from 'tiny-invariant' +import { invariant } from '../invariant' import { Icon } from '../icons/icons' import { useCreateColumnMutation } from '../queries' diff --git a/examples/react/start-convex-trellaux/src/invariant.ts b/examples/react/start-convex-trellaux/src/invariant.ts new file mode 100644 index 00000000000..41fcded35ef --- /dev/null +++ b/examples/react/start-convex-trellaux/src/invariant.ts @@ -0,0 +1,5 @@ +export function invariant(value: unknown, message?: string): asserts value { + if (!value) { + throw new Error(message ?? 'Invariant failed') + } +} diff --git a/examples/react/start-convex-trellaux/tsconfig.json b/examples/react/start-convex-trellaux/tsconfig.json index 3a9fb7cd716..8de1ae61be4 100644 --- a/examples/react/start-convex-trellaux/tsconfig.json +++ b/examples/react/start-convex-trellaux/tsconfig.json @@ -13,9 +13,9 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { - "~/*": ["./src/*"] + "~/*": ["./src/*"], + "convex/*": ["./convex/*"] }, "noEmit": true } diff --git a/examples/react/start-counter/package.json b/examples/react/start-counter/package.json index a60f15bcd25..b586634cf89 100644 --- a/examples/react/start-counter/package.json +++ b/examples/react/start-counter/package.json @@ -10,9 +10,9 @@ "start": "pnpx srvx --prod -s ../client dist/server/server.js" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "react": "^19.0.0", "react-dom": "^19.0.0" }, @@ -21,7 +21,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/start-counter/tsconfig.json b/examples/react/start-counter/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/examples/react/start-counter/tsconfig.json +++ b/examples/react/start-counter/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-i18n-paraglide/package.json b/examples/react/start-i18n-paraglide/package.json index ec55663e6d3..0cd8e2a0879 100644 --- a/examples/react/start-i18n-paraglide/package.json +++ b/examples/react/start-i18n-paraglide/package.json @@ -9,9 +9,10 @@ "preview": "vite preview" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-devtools": "^0.7.0", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "react": "^19.1.1", "react-dom": "^19.1.1" }, @@ -20,7 +21,7 @@ "@types/react": "^19.1.13", "@types/react-dom": "^19.1.9", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.9.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "@tailwindcss/vite": "^4.2.2", "tailwindcss": "^4.2.2", diff --git a/examples/react/start-i18n-paraglide/src/vite-env.d.ts b/examples/react/start-i18n-paraglide/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/start-i18n-paraglide/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/start-i18n-paraglide/tsconfig.json b/examples/react/start-i18n-paraglide/tsconfig.json index 3e42c72626a..471d55aed83 100644 --- a/examples/react/start-i18n-paraglide/tsconfig.json +++ b/examples/react/start-i18n-paraglide/tsconfig.json @@ -21,7 +21,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true, - "baseUrl": ".", "paths": { "@/*": ["./src/*"] } diff --git a/examples/react/start-large/package.json b/examples/react/start-large/package.json index aae67d405dd..ac681479d9c 100644 --- a/examples/react/start-large/package.json +++ b/examples/react/start-large/package.json @@ -13,9 +13,9 @@ }, "dependencies": { "@tanstack/react-query": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -29,7 +29,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" }, "keywords": [], diff --git a/examples/react/start-large/tsconfig.json b/examples/react/start-large/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/examples/react/start-large/tsconfig.json +++ b/examples/react/start-large/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-material-ui/package.json b/examples/react/start-material-ui/package.json index a0083c70416..01bc1db2446 100644 --- a/examples/react/start-material-ui/package.json +++ b/examples/react/start-material-ui/package.json @@ -15,9 +15,9 @@ "@emotion/styled": "11.14.0", "@fontsource-variable/roboto": "5.2.5", "@mui/material": "6.4.7", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-start": "^1.167.2", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-start": "^1.167.16", + "@tanstack/react-router-devtools": "^1.166.11", "react": "^19.0.0", "react-dom": "^19.0.0", "zod": "^3.24.2" @@ -27,7 +27,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/start-material-ui/tsconfig.json b/examples/react/start-material-ui/tsconfig.json index b3a2d67dfa6..af81492efb0 100644 --- a/examples/react/start-material-ui/tsconfig.json +++ b/examples/react/start-material-ui/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-streaming-data-from-server-functions/package.json b/examples/react/start-streaming-data-from-server-functions/package.json index 2fbae64edb9..c83091c1b03 100644 --- a/examples/react/start-streaming-data-from-server-functions/package.json +++ b/examples/react/start-streaming-data-from-server-functions/package.json @@ -10,9 +10,9 @@ "start": "pnpx srvx --prod -s ../client dist/server/server.js" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "react": "^19.0.0", "react-dom": "^19.0.0", "zod": "^3.24.2" @@ -22,7 +22,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/start-streaming-data-from-server-functions/tsconfig.json b/examples/react/start-streaming-data-from-server-functions/tsconfig.json index b3a2d67dfa6..af81492efb0 100644 --- a/examples/react/start-streaming-data-from-server-functions/tsconfig.json +++ b/examples/react/start-streaming-data-from-server-functions/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-supabase-basic/package.json b/examples/react/start-supabase-basic/package.json index 6cb67740e72..74bc42b9e38 100644 --- a/examples/react/start-supabase-basic/package.json +++ b/examples/react/start-supabase-basic/package.json @@ -15,9 +15,9 @@ "dependencies": { "@supabase/ssr": "^0.5.2", "@supabase/supabase-js": "^2.48.1", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1" @@ -28,7 +28,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/start-supabase-basic/tsconfig.json b/examples/react/start-supabase-basic/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/examples/react/start-supabase-basic/tsconfig.json +++ b/examples/react/start-supabase-basic/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-tailwind-v4/package.json b/examples/react/start-tailwind-v4/package.json index 61232a810a8..adf8936efc1 100644 --- a/examples/react/start-tailwind-v4/package.json +++ b/examples/react/start-tailwind-v4/package.json @@ -10,9 +10,9 @@ "start": "node .output/server/index.mjs" }, "dependencies": { - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "react": "^19.0.0", "react-dom": "^19.0.0", "tailwind-merge": "^2.6.0", @@ -25,7 +25,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/start-tailwind-v4/tsconfig.json b/examples/react/start-tailwind-v4/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/examples/react/start-tailwind-v4/tsconfig.json +++ b/examples/react/start-tailwind-v4/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-trellaux/package.json b/examples/react/start-trellaux/package.json index 7a76758fe8d..59d729c59a4 100644 --- a/examples/react/start-trellaux/package.json +++ b/examples/react/start-trellaux/package.json @@ -12,10 +12,10 @@ "dependencies": { "@tanstack/react-query": "^5.90.0", "@tanstack/react-query-devtools": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "@tanstack/react-router-ssr-query": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-start": "^1.167.16", "ky": "^1.7.4", "msw": "^2.7.0", "react": "^19.0.0", @@ -23,7 +23,6 @@ "react-hot-toast": "^2.5.1", "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", - "tiny-invariant": "^1.3.3", "zod": "^3.24.2" }, "devDependencies": { @@ -33,7 +32,7 @@ "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", "tailwindcss": "^4.2.2", - "typescript": "^5.6.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/start-trellaux/src/components/Board.tsx b/examples/react/start-trellaux/src/components/Board.tsx index 0b43e1d9237..0ba9a3c288d 100644 --- a/examples/react/start-trellaux/src/components/Board.tsx +++ b/examples/react/start-trellaux/src/components/Board.tsx @@ -1,5 +1,5 @@ import { useCallback, useMemo, useRef } from 'react' -import invariant from 'tiny-invariant' +import { invariant } from '../invariant' import { useSuspenseQuery } from '@tanstack/react-query' import { boardQueries, useUpdateBoardMutation } from '../queries.js' import { NewColumn } from './NewColumn.js' diff --git a/examples/react/start-trellaux/src/components/Card.tsx b/examples/react/start-trellaux/src/components/Card.tsx index 6c73ca079fb..729b93d2f85 100644 --- a/examples/react/start-trellaux/src/components/Card.tsx +++ b/examples/react/start-trellaux/src/components/Card.tsx @@ -1,4 +1,4 @@ -import invariant from 'tiny-invariant' +import { invariant } from '../invariant' import { forwardRef, useState } from 'react' import { CONTENT_TYPES } from '../types' diff --git a/examples/react/start-trellaux/src/components/Column.tsx b/examples/react/start-trellaux/src/components/Column.tsx index f9fddaaf5f3..a95faedb54a 100644 --- a/examples/react/start-trellaux/src/components/Column.tsx +++ b/examples/react/start-trellaux/src/components/Column.tsx @@ -1,8 +1,8 @@ import { forwardRef, useCallback, useMemo, useRef, useState } from 'react' -import invariant from 'tiny-invariant' import { twMerge } from 'tailwind-merge' import { flushSync } from 'react-dom' +import { invariant } from '../invariant' import { CONTENT_TYPES } from '../types' import { Icon } from '../icons/icons' import { diff --git a/examples/react/start-trellaux/src/components/NewCard.tsx b/examples/react/start-trellaux/src/components/NewCard.tsx index 8201083bb36..b46f965c8b5 100644 --- a/examples/react/start-trellaux/src/components/NewCard.tsx +++ b/examples/react/start-trellaux/src/components/NewCard.tsx @@ -1,5 +1,5 @@ import { useRef } from 'react' -import invariant from 'tiny-invariant' +import { invariant } from '../invariant' import { ItemMutationFields } from '../types' import { useCreateItemMutation } from '../queries' diff --git a/examples/react/start-trellaux/src/components/NewColumn.tsx b/examples/react/start-trellaux/src/components/NewColumn.tsx index acb6c82cfb9..655b380743c 100644 --- a/examples/react/start-trellaux/src/components/NewColumn.tsx +++ b/examples/react/start-trellaux/src/components/NewColumn.tsx @@ -1,5 +1,5 @@ import { useRef, useState } from 'react' -import invariant from 'tiny-invariant' +import { invariant } from '../invariant' import { Icon } from '../icons/icons' import { useCreateColumnMutation } from '../queries' diff --git a/examples/react/start-trellaux/src/db/board.ts b/examples/react/start-trellaux/src/db/board.ts index 92f94967e9c..ee80aeb9f7f 100644 --- a/examples/react/start-trellaux/src/db/board.ts +++ b/examples/react/start-trellaux/src/db/board.ts @@ -1,6 +1,6 @@ import crypto from 'node:crypto' import { createServerFn } from '@tanstack/react-start' -import invariant from 'tiny-invariant' +import { invariant } from '../invariant' import * as z from 'zod' import { deleteColumnSchema, diff --git a/examples/react/start-trellaux/src/invariant.ts b/examples/react/start-trellaux/src/invariant.ts new file mode 100644 index 00000000000..41fcded35ef --- /dev/null +++ b/examples/react/start-trellaux/src/invariant.ts @@ -0,0 +1,5 @@ +export function invariant(value: unknown, message?: string): asserts value { + if (!value) { + throw new Error(message ?? 'Invariant failed') + } +} diff --git a/examples/react/start-trellaux/tsconfig.json b/examples/react/start-trellaux/tsconfig.json index 3a9fb7cd716..cef9369516a 100644 --- a/examples/react/start-trellaux/tsconfig.json +++ b/examples/react/start-trellaux/tsconfig.json @@ -13,7 +13,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/react/start-workos/package.json b/examples/react/start-workos/package.json index 199298251b8..39dabee60bd 100644 --- a/examples/react/start-workos/package.json +++ b/examples/react/start-workos/package.json @@ -14,9 +14,9 @@ "license": "MIT", "dependencies": { "@radix-ui/themes": "^3.3.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/react-start": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/react-start": "^1.167.16", "@workos/authkit-tanstack-react-start": "^0.5.0", "react": "^19.0.0", "react-dom": "^19.0.0" @@ -25,7 +25,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/view-transitions/package.json b/examples/react/view-transitions/package.json index 08edfa06c1a..8d869f25487 100644 --- a/examples/react/view-transitions/package.json +++ b/examples/react/view-transitions/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", @@ -23,7 +23,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/view-transitions/src/vite-env.d.ts b/examples/react/view-transitions/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/view-transitions/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/with-framer-motion/package.json b/examples/react/with-framer-motion/package.json index f6e42623df6..6f593c4750f 100644 --- a/examples/react/with-framer-motion/package.json +++ b/examples/react/with-framer-motion/package.json @@ -10,8 +10,8 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", "framer-motion": "^11.18.2", "react": "^19.0.0", "react-dom": "^19.0.0", @@ -23,7 +23,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/react/with-framer-motion/src/vite-env.d.ts b/examples/react/with-framer-motion/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/with-framer-motion/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/with-trpc-react-query/package.json b/examples/react/with-trpc-react-query/package.json index 03b228b426b..e80e1a65e2a 100644 --- a/examples/react/with-trpc-react-query/package.json +++ b/examples/react/with-trpc-react-query/package.json @@ -13,9 +13,9 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/react-query": "^5.90.0", "@tanstack/react-query-devtools": "^5.90.0", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "@trpc/client": "^11.4.3", "@trpc/server": "^11.4.3", "@trpc/tanstack-react-query": "^11.4.3", diff --git a/examples/react/with-trpc-react-query/src/vite-env.d.ts b/examples/react/with-trpc-react-query/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/with-trpc-react-query/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/react/with-trpc/package.json b/examples/react/with-trpc/package.json index 0861caa138d..83b9aa74814 100644 --- a/examples/react/with-trpc/package.json +++ b/examples/react/with-trpc/package.json @@ -11,9 +11,9 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/react-router": "^1.168.1", - "@tanstack/react-router-devtools": "^1.166.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/react-router": "^1.168.10", + "@tanstack/react-router-devtools": "^1.166.11", + "@tanstack/router-plugin": "^1.167.12", "@trpc/client": "^11.4.3", "@trpc/server": "^11.4.3", "express": "^4.21.2", diff --git a/examples/react/with-trpc/src/vite-env.d.ts b/examples/react/with-trpc/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/react/with-trpc/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/authenticated-routes-firebase/package.json b/examples/solid/authenticated-routes-firebase/package.json index 38910b0fd9b..beffa627dfb 100644 --- a/examples/solid/authenticated-routes-firebase/package.json +++ b/examples/solid/authenticated-routes-firebase/package.json @@ -12,7 +12,7 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/solid-router": "^2.0.0-alpha.9", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "firebase": "^11.4.0", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", @@ -23,7 +23,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/authenticated-routes/package.json b/examples/solid/authenticated-routes/package.json index 50c40a4d0e4..687b0fde5a1 100644 --- a/examples/solid/authenticated-routes/package.json +++ b/examples/solid/authenticated-routes/package.json @@ -12,7 +12,7 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/solid-router": "^2.0.0-alpha.9", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", "redaxios": "^0.5.1", @@ -21,7 +21,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/authenticated-routes/src/vite-env.d.ts b/examples/solid/authenticated-routes/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/authenticated-routes/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/basic-default-search-params/package.json b/examples/solid/basic-default-search-params/package.json index f91770dc53e..4c93a6c40df 100644 --- a/examples/solid/basic-default-search-params/package.json +++ b/examples/solid/basic-default-search-params/package.json @@ -21,7 +21,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/basic-default-search-params/src/vite-env.d.ts b/examples/solid/basic-default-search-params/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/basic-default-search-params/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/basic-devtools-panel/package.json b/examples/solid/basic-devtools-panel/package.json index e00acb15f08..338697bc3de 100644 --- a/examples/solid/basic-devtools-panel/package.json +++ b/examples/solid/basic-devtools-panel/package.json @@ -15,8 +15,10 @@ "redaxios": "^0.5.1", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", - "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "tailwindcss": "^4.2.2" + }, + "devDependencies": { + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4" } diff --git a/examples/solid/basic-file-based/package.json b/examples/solid/basic-file-based/package.json index 74411b861e8..e61681e4e08 100644 --- a/examples/solid/basic-file-based/package.json +++ b/examples/solid/basic-file-based/package.json @@ -19,8 +19,8 @@ "zod": "^3.24.2" }, "devDependencies": { - "@tanstack/router-plugin": "^1.167.2", - "typescript": "^5.7.2", + "@tanstack/router-plugin": "^1.167.12", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4" } diff --git a/examples/solid/basic-file-based/src/vite-env.d.ts b/examples/solid/basic-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/basic-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/basic-non-nested-devtools/package.json b/examples/solid/basic-non-nested-devtools/package.json index 457f7b6e8f2..060b61a63e1 100644 --- a/examples/solid/basic-non-nested-devtools/package.json +++ b/examples/solid/basic-non-nested-devtools/package.json @@ -20,7 +20,7 @@ "devDependencies": { "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4" } diff --git a/examples/solid/basic-non-nested-devtools/src/vite-env.d.ts b/examples/solid/basic-non-nested-devtools/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/basic-non-nested-devtools/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/basic-solid-query-file-based/package.json b/examples/solid/basic-solid-query-file-based/package.json index eebb1c61c8b..6ae5697e4aa 100644 --- a/examples/solid/basic-solid-query-file-based/package.json +++ b/examples/solid/basic-solid-query-file-based/package.json @@ -22,8 +22,8 @@ "zod": "^3.24.2" }, "devDependencies": { - "@tanstack/router-plugin": "^1.167.2", - "typescript": "^5.7.2", + "@tanstack/router-plugin": "^1.167.12", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4" } diff --git a/examples/solid/basic-solid-query-file-based/src/vite-env.d.ts b/examples/solid/basic-solid-query-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/basic-solid-query-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/basic-solid-query/package.json b/examples/solid/basic-solid-query/package.json index 0d8ade939ee..531c244de74 100644 --- a/examples/solid/basic-solid-query/package.json +++ b/examples/solid/basic-solid-query/package.json @@ -20,8 +20,8 @@ "tailwindcss": "^4.2.2" }, "devDependencies": { - "@tanstack/router-plugin": "^1.167.2", - "typescript": "^5.7.2", + "@tanstack/router-plugin": "^1.167.12", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4" } diff --git a/examples/solid/basic-solid-query/src/vite-env.d.ts b/examples/solid/basic-solid-query/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/basic-solid-query/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/basic-ssr-file-based/package.json b/examples/solid/basic-ssr-file-based/package.json index 68c72a9ba83..b12606f343d 100644 --- a/examples/solid/basic-ssr-file-based/package.json +++ b/examples/solid/basic-ssr-file-based/package.json @@ -12,7 +12,7 @@ }, "dependencies": { "@tanstack/solid-router": "^2.0.0-alpha.9", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "compression": "^1.8.0", "express": "^4.21.2", "get-port": "^7.1.0", @@ -24,7 +24,7 @@ "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", "@types/express": "^4.17.23", "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.8.3", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/basic-ssr-streaming-file-based/package.json b/examples/solid/basic-ssr-streaming-file-based/package.json index 0226d0bba1a..8ed14ae178b 100644 --- a/examples/solid/basic-ssr-streaming-file-based/package.json +++ b/examples/solid/basic-ssr-streaming-file-based/package.json @@ -25,9 +25,9 @@ "zod": "^3.24.2" }, "devDependencies": { - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "@types/express": "^4.17.23", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4" } diff --git a/examples/solid/basic-ssr-streaming-file-based/src/vite-env.d.ts b/examples/solid/basic-ssr-streaming-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/basic-ssr-streaming-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/basic-virtual-file-based/package.json b/examples/solid/basic-virtual-file-based/package.json index ba31ff9f2c8..d944855014d 100644 --- a/examples/solid/basic-virtual-file-based/package.json +++ b/examples/solid/basic-virtual-file-based/package.json @@ -12,7 +12,7 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/solid-router": "^2.0.0-alpha.9", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "@tanstack/virtual-file-routes": "^1.161.7", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", @@ -22,7 +22,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/basic-virtual-file-based/src/vite-env.d.ts b/examples/solid/basic-virtual-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/basic-virtual-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/basic-virtual-inside-file-based/package.json b/examples/solid/basic-virtual-inside-file-based/package.json index b74f2e46ca7..1eff28d7a90 100644 --- a/examples/solid/basic-virtual-inside-file-based/package.json +++ b/examples/solid/basic-virtual-inside-file-based/package.json @@ -12,7 +12,7 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/solid-router": "^2.0.0-alpha.9", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "@tanstack/virtual-file-routes": "^1.161.7", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", @@ -22,7 +22,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/basic-virtual-inside-file-based/src/vite-env.d.ts b/examples/solid/basic-virtual-inside-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/basic-virtual-inside-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/basic/package.json b/examples/solid/basic/package.json index 16ff2676dfc..2e63f364920 100644 --- a/examples/solid/basic/package.json +++ b/examples/solid/basic/package.json @@ -20,7 +20,7 @@ "devDependencies": { "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4" } diff --git a/examples/solid/basic/src/vite-env.d.ts b/examples/solid/basic/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/basic/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/deferred-data/package.json b/examples/solid/deferred-data/package.json index afe60e0e47a..bfa9fb6f5fd 100644 --- a/examples/solid/deferred-data/package.json +++ b/examples/solid/deferred-data/package.json @@ -20,7 +20,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/deferred-data/src/vite-env.d.ts b/examples/solid/deferred-data/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/deferred-data/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/i18n-paraglide/package.json b/examples/solid/i18n-paraglide/package.json index 6116d0cc7ef..539b72d59f6 100644 --- a/examples/solid/i18n-paraglide/package.json +++ b/examples/solid/i18n-paraglide/package.json @@ -12,13 +12,15 @@ "dependencies": { "@tailwindcss/vite": "^4.2.2", "@tanstack/solid-router": "^2.0.0-alpha.9", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", - "tailwindcss": "^4.2.2", + "tailwindcss": "^4.2.2" + }, + "devDependencies": { "@types/node": "^22.18.6", "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.9.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "@inlang/paraglide-js": "^2.4.0" } diff --git a/examples/solid/i18n-paraglide/src/vite-env.d.ts b/examples/solid/i18n-paraglide/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/i18n-paraglide/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/i18n-paraglide/tsconfig.json b/examples/solid/i18n-paraglide/tsconfig.json index f3fadb414f8..9dcde39a0f5 100644 --- a/examples/solid/i18n-paraglide/tsconfig.json +++ b/examples/solid/i18n-paraglide/tsconfig.json @@ -22,7 +22,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true, - "baseUrl": ".", "paths": { "@/*": ["./src/*"] } diff --git a/examples/solid/kitchen-sink-file-based/package.json b/examples/solid/kitchen-sink-file-based/package.json index f4bda4a98cb..3895be9597e 100644 --- a/examples/solid/kitchen-sink-file-based/package.json +++ b/examples/solid/kitchen-sink-file-based/package.json @@ -20,8 +20,8 @@ "zod": "^3.24.2" }, "devDependencies": { - "@tanstack/router-plugin": "^1.167.2", - "typescript": "^5.7.2", + "@tanstack/router-plugin": "^1.167.12", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4" } diff --git a/examples/solid/kitchen-sink-file-based/src/vite-env.d.ts b/examples/solid/kitchen-sink-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/kitchen-sink-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/kitchen-sink-solid-query-file-based/package.json b/examples/solid/kitchen-sink-solid-query-file-based/package.json index b2c99a7b6bd..3b80ab29dd0 100644 --- a/examples/solid/kitchen-sink-solid-query-file-based/package.json +++ b/examples/solid/kitchen-sink-solid-query-file-based/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "@tanstack/solid-query": "6.0.0-beta.3", "@tanstack/solid-query-devtools": "6.0.0-beta.3", "@tanstack/solid-router": "^2.0.0-alpha.9", @@ -23,7 +23,7 @@ "zod": "^3.24.2" }, "devDependencies": { - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4" } diff --git a/examples/solid/kitchen-sink-solid-query-file-based/src/vite-env.d.ts b/examples/solid/kitchen-sink-solid-query-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/kitchen-sink-solid-query-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/kitchen-sink-solid-query/package.json b/examples/solid/kitchen-sink-solid-query/package.json index 02163edf5e6..d61b40f6ce6 100644 --- a/examples/solid/kitchen-sink-solid-query/package.json +++ b/examples/solid/kitchen-sink-solid-query/package.json @@ -22,7 +22,7 @@ "zod": "^3.24.2" }, "devDependencies": { - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4" } diff --git a/examples/solid/kitchen-sink-solid-query/src/vite-env.d.ts b/examples/solid/kitchen-sink-solid-query/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/kitchen-sink-solid-query/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/kitchen-sink/package.json b/examples/solid/kitchen-sink/package.json index f5d043fc2c1..01fb5109d44 100644 --- a/examples/solid/kitchen-sink/package.json +++ b/examples/solid/kitchen-sink/package.json @@ -21,7 +21,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/kitchen-sink/src/vite-env.d.ts b/examples/solid/kitchen-sink/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/kitchen-sink/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/large-file-based/package.json b/examples/solid/large-file-based/package.json index 5eb5d4bd6bb..58583372b6d 100644 --- a/examples/solid/large-file-based/package.json +++ b/examples/solid/large-file-based/package.json @@ -15,7 +15,7 @@ "@tanstack/solid-query": "6.0.0-beta.3", "@tanstack/solid-router": "^2.0.0-alpha.9", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", "redaxios": "^0.5.1", @@ -24,7 +24,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/large-file-based/src/vite-env.d.ts b/examples/solid/large-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/large-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/location-masking/package.json b/examples/solid/location-masking/package.json index d25951a660f..6c0e089d930 100644 --- a/examples/solid/location-masking/package.json +++ b/examples/solid/location-masking/package.json @@ -20,7 +20,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/location-masking/src/vite-env.d.ts b/examples/solid/location-masking/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/location-masking/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/navigation-blocking/package.json b/examples/solid/navigation-blocking/package.json index 07038b1709a..5b47d56e120 100644 --- a/examples/solid/navigation-blocking/package.json +++ b/examples/solid/navigation-blocking/package.json @@ -20,7 +20,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/navigation-blocking/src/vite-env.d.ts b/examples/solid/navigation-blocking/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/navigation-blocking/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/quickstart-esbuild-file-based/package.json b/examples/solid/quickstart-esbuild-file-based/package.json index da59109c023..d97b74c3f64 100644 --- a/examples/solid/quickstart-esbuild-file-based/package.json +++ b/examples/solid/quickstart-esbuild-file-based/package.json @@ -9,7 +9,7 @@ "start": "dev" }, "dependencies": { - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "@tanstack/solid-router": "^2.0.0-alpha.9", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", "redaxios": "^0.5.1", diff --git a/examples/solid/quickstart-esbuild-file-based/src/vite-env.d.ts b/examples/solid/quickstart-esbuild-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/quickstart-esbuild-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/quickstart-file-based/package.json b/examples/solid/quickstart-file-based/package.json index b8482a1e501..80976269576 100644 --- a/examples/solid/quickstart-file-based/package.json +++ b/examples/solid/quickstart-file-based/package.json @@ -19,8 +19,8 @@ "zod": "^3.24.2" }, "devDependencies": { - "@tanstack/router-plugin": "^1.167.2", - "typescript": "^5.7.2", + "@tanstack/router-plugin": "^1.167.12", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4" } diff --git a/examples/solid/quickstart-file-based/src/vite-env.d.ts b/examples/solid/quickstart-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/quickstart-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/quickstart-rspack-file-based/package.json b/examples/solid/quickstart-rspack-file-based/package.json index 73724409649..4960a33926c 100644 --- a/examples/solid/quickstart-rspack-file-based/package.json +++ b/examples/solid/quickstart-rspack-file-based/package.json @@ -20,7 +20,7 @@ "@rsbuild/core": "^1.2.4", "@rsbuild/plugin-babel": "^1.0.6", "@rsbuild/plugin-solid": "^1.0.6", - "@tanstack/router-plugin": "^1.167.2", - "typescript": "^5.6.2" + "@tanstack/router-plugin": "^1.167.12", + "typescript": "^6.0.2" } } diff --git a/examples/solid/quickstart-rspack-file-based/src/vite-env.d.ts b/examples/solid/quickstart-rspack-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/quickstart-rspack-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/quickstart-webpack-file-based/package.json b/examples/solid/quickstart-webpack-file-based/package.json index cd613f4909f..8e6e829ae5c 100644 --- a/examples/solid/quickstart-webpack-file-based/package.json +++ b/examples/solid/quickstart-webpack-file-based/package.json @@ -16,7 +16,7 @@ "devDependencies": { "@babel/core": "^7.28.5", "@babel/preset-typescript": "^7.27.1", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "babel-loader": "^10.0.0", "babel-preset-solid": "2.0.0-beta.5", "css-loader": "^7.1.2", @@ -24,7 +24,7 @@ "postcss": "^8.5.6", "postcss-loader": "^8.2.0", "style-loader": "^4.0.0", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "webpack": "^5.97.1", "webpack-cli": "^5.1.4", "webpack-dev-server": "^5.2.0" diff --git a/examples/solid/quickstart-webpack-file-based/src/vite-env.d.ts b/examples/solid/quickstart-webpack-file-based/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/quickstart-webpack-file-based/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/quickstart/package.json b/examples/solid/quickstart/package.json index d01db8f571f..42169b535a9 100644 --- a/examples/solid/quickstart/package.json +++ b/examples/solid/quickstart/package.json @@ -14,9 +14,11 @@ "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", - "tailwindcss": "^4.2.2", + "tailwindcss": "^4.2.2" + }, + "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/quickstart/src/vite-env.d.ts b/examples/solid/quickstart/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/quickstart/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/router-monorepo-simple-lazy/package.json b/examples/solid/router-monorepo-simple-lazy/package.json index 99d7901cc30..d5363e62a52 100644 --- a/examples/solid/router-monorepo-simple-lazy/package.json +++ b/examples/solid/router-monorepo-simple-lazy/package.json @@ -10,7 +10,7 @@ "dependencies": { "@tanstack/solid-router": "^2.0.0-alpha.9", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", "redaxios": "^0.5.1" @@ -18,7 +18,7 @@ "devDependencies": { "@types/node": "^22.7.4", "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" }, diff --git a/examples/solid/router-monorepo-simple-lazy/packages/app/package.json b/examples/solid/router-monorepo-simple-lazy/packages/app/package.json index bb5760e2e67..8f502254d0c 100644 --- a/examples/solid/router-monorepo-simple-lazy/packages/app/package.json +++ b/examples/solid/router-monorepo-simple-lazy/packages/app/package.json @@ -18,7 +18,7 @@ "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", "@vitejs/plugin-react": "^6.0.1", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", "tailwindcss": "^4.2.2", "vite": "^8.0.0", diff --git a/examples/solid/router-monorepo-simple-lazy/packages/post-feature/package.json b/examples/solid/router-monorepo-simple-lazy/packages/post-feature/package.json index ac7e190786b..40fec522f6a 100644 --- a/examples/solid/router-monorepo-simple-lazy/packages/post-feature/package.json +++ b/examples/solid/router-monorepo-simple-lazy/packages/post-feature/package.json @@ -23,7 +23,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" } diff --git a/examples/solid/router-monorepo-simple-lazy/packages/router/package.json b/examples/solid/router-monorepo-simple-lazy/packages/router/package.json index f46ecdba47d..8335db85929 100644 --- a/examples/solid/router-monorepo-simple-lazy/packages/router/package.json +++ b/examples/solid/router-monorepo-simple-lazy/packages/router/package.json @@ -10,7 +10,7 @@ "dependencies": { "@tanstack/history": "^1.161.6", "@tanstack/solid-router": "^2.0.0-alpha.9", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "redaxios": "^0.5.1", "zod": "^3.24.2", "solid-js": "2.0.0-beta.5", @@ -18,7 +18,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" } diff --git a/examples/solid/router-monorepo-simple/package.json b/examples/solid/router-monorepo-simple/package.json index a2480fc5367..97c81a1d4b1 100644 --- a/examples/solid/router-monorepo-simple/package.json +++ b/examples/solid/router-monorepo-simple/package.json @@ -10,7 +10,7 @@ "dependencies": { "@tanstack/solid-router": "^2.0.0-alpha.9", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", "redaxios": "^0.5.1" @@ -18,7 +18,7 @@ "devDependencies": { "@types/node": "^22.7.4", "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" }, diff --git a/examples/solid/router-monorepo-simple/packages/app/package.json b/examples/solid/router-monorepo-simple/packages/app/package.json index ecd0d477fcd..40cdb138938 100644 --- a/examples/solid/router-monorepo-simple/packages/app/package.json +++ b/examples/solid/router-monorepo-simple/packages/app/package.json @@ -16,7 +16,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", "vite": "^8.0.0", "tailwindcss": "^4.2.2", diff --git a/examples/solid/router-monorepo-simple/packages/post-feature/package.json b/examples/solid/router-monorepo-simple/packages/post-feature/package.json index e7922f1649e..36fa3741d4f 100644 --- a/examples/solid/router-monorepo-simple/packages/post-feature/package.json +++ b/examples/solid/router-monorepo-simple/packages/post-feature/package.json @@ -14,7 +14,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" } diff --git a/examples/solid/router-monorepo-simple/packages/router/package.json b/examples/solid/router-monorepo-simple/packages/router/package.json index 4fb39cc002a..9be36abb8b5 100644 --- a/examples/solid/router-monorepo-simple/packages/router/package.json +++ b/examples/solid/router-monorepo-simple/packages/router/package.json @@ -10,7 +10,7 @@ "dependencies": { "@tanstack/history": "^1.161.6", "@tanstack/solid-router": "^2.0.0-alpha.9", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "redaxios": "^0.5.1", "zod": "^3.24.2", "solid-js": "2.0.0-beta.5", @@ -18,7 +18,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" } diff --git a/examples/solid/router-monorepo-solid-query/package.json b/examples/solid/router-monorepo-solid-query/package.json index bcafa967723..056de75b379 100644 --- a/examples/solid/router-monorepo-solid-query/package.json +++ b/examples/solid/router-monorepo-solid-query/package.json @@ -14,14 +14,14 @@ "@tanstack/solid-query-devtools": "6.0.0-beta.3", "@tanstack/solid-router": "^2.0.0-alpha.9", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", "redaxios": "^0.5.1" }, "devDependencies": { "@types/node": "^22.10.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite-plugin-solid": "3.0.0-next.4", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" diff --git a/examples/solid/router-monorepo-solid-query/packages/app/package.json b/examples/solid/router-monorepo-solid-query/packages/app/package.json index 619d880421a..ebef2fb2513 100644 --- a/examples/solid/router-monorepo-solid-query/packages/app/package.json +++ b/examples/solid/router-monorepo-solid-query/packages/app/package.json @@ -17,7 +17,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", "tailwindcss": "^4.2.2", "vite": "^8.0.0", diff --git a/examples/solid/router-monorepo-solid-query/packages/post-feature/package.json b/examples/solid/router-monorepo-solid-query/packages/post-feature/package.json index d07a0e1d59f..90cacdc43d0 100644 --- a/examples/solid/router-monorepo-solid-query/packages/post-feature/package.json +++ b/examples/solid/router-monorepo-solid-query/packages/post-feature/package.json @@ -16,7 +16,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" } diff --git a/examples/solid/router-monorepo-solid-query/packages/post-query/package.json b/examples/solid/router-monorepo-solid-query/packages/post-query/package.json index c97cc5feb30..178636a52ef 100644 --- a/examples/solid/router-monorepo-solid-query/packages/post-query/package.json +++ b/examples/solid/router-monorepo-solid-query/packages/post-query/package.json @@ -14,7 +14,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/router-monorepo-solid-query/packages/router/package.json b/examples/solid/router-monorepo-solid-query/packages/router/package.json index ac9b1609792..916a16fc7e7 100644 --- a/examples/solid/router-monorepo-solid-query/packages/router/package.json +++ b/examples/solid/router-monorepo-solid-query/packages/router/package.json @@ -11,7 +11,7 @@ "@tanstack/history": "^1.161.6", "@tanstack/solid-query": "6.0.0-beta.3", "@tanstack/solid-router": "^2.0.0-alpha.9", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "@router-solid-mono-solid-query/post-query": "workspace:*", "redaxios": "^0.5.1", "zod": "^3.24.2", @@ -20,7 +20,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-dts": "^4.5.4" } diff --git a/examples/solid/scroll-restoration/package.json b/examples/solid/scroll-restoration/package.json index 9b8d031319f..0bbfee27c2e 100644 --- a/examples/solid/scroll-restoration/package.json +++ b/examples/solid/scroll-restoration/package.json @@ -15,9 +15,11 @@ "@tanstack/solid-virtual": "^3.13.0", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", - "tailwindcss": "^4.2.2", + "tailwindcss": "^4.2.2" + }, + "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/scroll-restoration/src/vite-env.d.ts b/examples/solid/scroll-restoration/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/scroll-restoration/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/search-validator-adapters/package.json b/examples/solid/search-validator-adapters/package.json index 68f49f497b5..1bd3419a684 100644 --- a/examples/solid/search-validator-adapters/package.json +++ b/examples/solid/search-validator-adapters/package.json @@ -15,7 +15,7 @@ "@tanstack/solid-query": "6.0.0-beta.3", "@tanstack/solid-router": "^2.0.0-alpha.9", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "@tanstack/valibot-adapter": "^1.166.9", "@tanstack/zod-adapter": "^1.166.9", "arktype": "^2.1.7", @@ -29,7 +29,7 @@ "@testing-library/jest-dom": "^6.6.3", "@solidjs/testing-library": "^0.8.10", "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/search-validator-adapters/src/vite-env.d.ts b/examples/solid/search-validator-adapters/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/search-validator-adapters/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/start-basic-auth/package.json b/examples/solid/start-basic-auth/package.json index 89ce0ba628f..bea685f4055 100644 --- a/examples/solid/start-basic-auth/package.json +++ b/examples/solid/start-basic-auth/package.json @@ -28,7 +28,7 @@ "dotenv": "^17.2.3", "prisma": "^7.0.0", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4" diff --git a/examples/solid/start-basic-auth/tsconfig.json b/examples/solid/start-basic-auth/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/examples/solid/start-basic-auth/tsconfig.json +++ b/examples/solid/start-basic-auth/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/solid/start-basic-authjs/package.json b/examples/solid/start-basic-authjs/package.json index 68c91d8375b..2e0a46f9fc1 100644 --- a/examples/solid/start-basic-authjs/package.json +++ b/examples/solid/start-basic-authjs/package.json @@ -23,7 +23,7 @@ "@tailwindcss/vite": "^4.2.2", "@types/node": "^22.5.4", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4" diff --git a/examples/solid/start-basic-authjs/tsconfig.json b/examples/solid/start-basic-authjs/tsconfig.json index 608d3ba5f39..726f20245f5 100644 --- a/examples/solid/start-basic-authjs/tsconfig.json +++ b/examples/solid/start-basic-authjs/tsconfig.json @@ -16,7 +16,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "allowSyntheticDefaultImports": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] } diff --git a/examples/solid/start-basic-cloudflare/package.json b/examples/solid/start-basic-cloudflare/package.json index 401bc35630f..a65824dd372 100644 --- a/examples/solid/start-basic-cloudflare/package.json +++ b/examples/solid/start-basic-cloudflare/package.json @@ -23,7 +23,7 @@ "@tailwindcss/vite": "^4.2.2", "@types/node": "^22.5.4", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4", diff --git a/examples/solid/start-basic-cloudflare/src/routes/users.$userId.tsx b/examples/solid/start-basic-cloudflare/src/routes/users.$userId.tsx index ffd624dcce7..d2aeeb448ce 100644 --- a/examples/solid/start-basic-cloudflare/src/routes/users.$userId.tsx +++ b/examples/solid/start-basic-cloudflare/src/routes/users.$userId.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/solid-router' -import { NotFound } from 'src/components/NotFound' -import { UserErrorComponent } from 'src/components/UserError' +import { NotFound } from '../components/NotFound' +import { UserErrorComponent } from '../components/UserError' import type { User } from '../utils/users' export const Route = createFileRoute('/users/$userId')({ diff --git a/examples/solid/start-basic-cloudflare/tsconfig.json b/examples/solid/start-basic-cloudflare/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/examples/solid/start-basic-cloudflare/tsconfig.json +++ b/examples/solid/start-basic-cloudflare/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/solid/start-basic-netlify/package.json b/examples/solid/start-basic-netlify/package.json index 83dfa831521..36e7ea83f62 100644 --- a/examples/solid/start-basic-netlify/package.json +++ b/examples/solid/start-basic-netlify/package.json @@ -20,7 +20,7 @@ "@tailwindcss/vite": "^4.2.2", "@types/node": "^22.5.4", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4" diff --git a/examples/solid/start-basic-netlify/src/routes/users.$userId.tsx b/examples/solid/start-basic-netlify/src/routes/users.$userId.tsx index ffd624dcce7..d2aeeb448ce 100644 --- a/examples/solid/start-basic-netlify/src/routes/users.$userId.tsx +++ b/examples/solid/start-basic-netlify/src/routes/users.$userId.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/solid-router' -import { NotFound } from 'src/components/NotFound' -import { UserErrorComponent } from 'src/components/UserError' +import { NotFound } from '../components/NotFound' +import { UserErrorComponent } from '../components/UserError' import type { User } from '../utils/users' export const Route = createFileRoute('/users/$userId')({ diff --git a/examples/solid/start-basic-netlify/tsconfig.json b/examples/solid/start-basic-netlify/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/examples/solid/start-basic-netlify/tsconfig.json +++ b/examples/solid/start-basic-netlify/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/solid/start-basic-nitro/package.json b/examples/solid/start-basic-nitro/package.json index 1e2ab499d38..988d02b6f82 100644 --- a/examples/solid/start-basic-nitro/package.json +++ b/examples/solid/start-basic-nitro/package.json @@ -20,7 +20,7 @@ "@types/node": "^22.5.4", "nitro": "^3.0.260311-beta", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4" diff --git a/examples/solid/start-basic-nitro/src/routes/users.$userId.tsx b/examples/solid/start-basic-nitro/src/routes/users.$userId.tsx index ffd624dcce7..d2aeeb448ce 100644 --- a/examples/solid/start-basic-nitro/src/routes/users.$userId.tsx +++ b/examples/solid/start-basic-nitro/src/routes/users.$userId.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/solid-router' -import { NotFound } from 'src/components/NotFound' -import { UserErrorComponent } from 'src/components/UserError' +import { NotFound } from '../components/NotFound' +import { UserErrorComponent } from '../components/UserError' import type { User } from '../utils/users' export const Route = createFileRoute('/users/$userId')({ diff --git a/examples/solid/start-basic-nitro/tsconfig.json b/examples/solid/start-basic-nitro/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/examples/solid/start-basic-nitro/tsconfig.json +++ b/examples/solid/start-basic-nitro/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/solid/start-basic-solid-query/package.json b/examples/solid/start-basic-solid-query/package.json index 4115b13ecc9..23bf2ecad8d 100644 --- a/examples/solid/start-basic-solid-query/package.json +++ b/examples/solid/start-basic-solid-query/package.json @@ -25,7 +25,7 @@ "@tailwindcss/vite": "^4.2.2", "@types/node": "^22.5.4", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4" diff --git a/examples/solid/start-basic-solid-query/tsconfig.json b/examples/solid/start-basic-solid-query/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/examples/solid/start-basic-solid-query/tsconfig.json +++ b/examples/solid/start-basic-solid-query/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/solid/start-basic-static/package.json b/examples/solid/start-basic-static/package.json index 2ca8d2e7892..183cafb55f1 100644 --- a/examples/solid/start-basic-static/package.json +++ b/examples/solid/start-basic-static/package.json @@ -13,16 +13,16 @@ "@tanstack/solid-router": "^2.0.0-alpha.9", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", "@tanstack/solid-start": "^2.0.0-alpha.10", + "@tanstack/start-static-server-functions": "^1.166.25", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", - "@tanstack/start-static-server-functions": "^1.166.17", "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0" }, "devDependencies": { "@types/node": "^22.5.4", "tailwindcss": "^4.2.2", - "typescript": "^5.6.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-tsconfig-paths": "^5.1.3", "vite-plugin-solid": "3.0.0-next.4", diff --git a/examples/solid/start-basic-static/tsconfig.json b/examples/solid/start-basic-static/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/examples/solid/start-basic-static/tsconfig.json +++ b/examples/solid/start-basic-static/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/solid/start-basic/package.json b/examples/solid/start-basic/package.json index 498438f4e77..6dff152b31e 100644 --- a/examples/solid/start-basic/package.json +++ b/examples/solid/start-basic/package.json @@ -23,7 +23,7 @@ "@types/node": "^22.5.4", "nitro": "^3.0.260311-beta", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4" diff --git a/examples/solid/start-basic/src/routes/users.$userId.tsx b/examples/solid/start-basic/src/routes/users.$userId.tsx index 74279aa20ed..489abd1d3d9 100644 --- a/examples/solid/start-basic/src/routes/users.$userId.tsx +++ b/examples/solid/start-basic/src/routes/users.$userId.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/solid-router' -import { NotFound } from 'src/components/NotFound' -import { UserErrorComponent } from 'src/components/UserError' +import { NotFound } from '../components/NotFound' +import { UserErrorComponent } from '../components/UserError' export const Route = createFileRoute('/users/$userId')({ loader: async ({ params: { userId } }) => { diff --git a/examples/solid/start-basic/tsconfig.json b/examples/solid/start-basic/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/examples/solid/start-basic/tsconfig.json +++ b/examples/solid/start-basic/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/solid/start-bun/package.json b/examples/solid/start-bun/package.json index 13999690905..182b1bb5c97 100644 --- a/examples/solid/start-bun/package.json +++ b/examples/solid/start-bun/package.json @@ -19,11 +19,10 @@ "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", "@tanstack/solid-router-ssr-query": "^2.0.0-alpha.11", "@tanstack/solid-start": "^2.0.0-alpha.10", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", - "tailwindcss": "^4.2.2", - "vite-tsconfig-paths": "^5.1.4" + "tailwindcss": "^4.2.2" }, "devDependencies": { "@tanstack/eslint-config": "^0.3.2", @@ -34,7 +33,7 @@ "vite-plugin-solid": "3.0.0-next.4", "jsdom": "^27.0.0", "prettier": "^3.6.2", - "typescript": "^5.9.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vitest": "^3.2.4", "web-vitals": "^5.1.0" diff --git a/examples/solid/start-bun/src/vite-env.d.ts b/examples/solid/start-bun/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/start-bun/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/start-bun/tsconfig.json b/examples/solid/start-bun/tsconfig.json index 70c9888deae..7d5e1c1aaf5 100644 --- a/examples/solid/start-bun/tsconfig.json +++ b/examples/solid/start-bun/tsconfig.json @@ -28,7 +28,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true, - "baseUrl": ".", "paths": { "@/*": ["./src/*"] } diff --git a/examples/solid/start-convex-better-auth/package.json b/examples/solid/start-convex-better-auth/package.json index 86b080f6770..9110292a07e 100644 --- a/examples/solid/start-convex-better-auth/package.json +++ b/examples/solid/start-convex-better-auth/package.json @@ -30,7 +30,7 @@ "devDependencies": { "@types/node": "^22.10.2", "combinate": "^1.1.11", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4" diff --git a/examples/solid/start-convex-better-auth/tsconfig.json b/examples/solid/start-convex-better-auth/tsconfig.json index 57ea27b2868..4b77b70bcf3 100644 --- a/examples/solid/start-convex-better-auth/tsconfig.json +++ b/examples/solid/start-convex-better-auth/tsconfig.json @@ -14,9 +14,9 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { - "~/*": ["./src/*"] + "~/*": ["./src/*"], + "convex/*": ["./convex/*"] }, "noEmit": true } diff --git a/examples/solid/start-counter/package.json b/examples/solid/start-counter/package.json index 71cf04e0811..88077d99919 100644 --- a/examples/solid/start-counter/package.json +++ b/examples/solid/start-counter/package.json @@ -23,7 +23,7 @@ "@types/node": "^22.10.2", "vite-plugin-solid": "3.0.0-next.4", "combinate": "^1.1.11", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/start-counter/tsconfig.json b/examples/solid/start-counter/tsconfig.json index 57ea27b2868..508ace2e179 100644 --- a/examples/solid/start-counter/tsconfig.json +++ b/examples/solid/start-counter/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/solid/start-i18n-paraglide/package.json b/examples/solid/start-i18n-paraglide/package.json index 763f9f05f5e..4761b5c16a7 100644 --- a/examples/solid/start-i18n-paraglide/package.json +++ b/examples/solid/start-i18n-paraglide/package.json @@ -14,10 +14,12 @@ "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", "@tanstack/solid-start": "^2.0.0-alpha.10", "solid-js": "2.0.0-beta.5", - "@solidjs/web": "2.0.0-beta.5", + "@solidjs/web": "2.0.0-beta.5" + }, + "devDependencies": { "@types/node": "^22.18.6", "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.9.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "@tailwindcss/vite": "^4.2.2", "tailwindcss": "^4.2.2", diff --git a/examples/solid/start-i18n-paraglide/src/vite-env.d.ts b/examples/solid/start-i18n-paraglide/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/start-i18n-paraglide/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/start-i18n-paraglide/tsconfig.json b/examples/solid/start-i18n-paraglide/tsconfig.json index 522b26852d0..8d23f745d03 100644 --- a/examples/solid/start-i18n-paraglide/tsconfig.json +++ b/examples/solid/start-i18n-paraglide/tsconfig.json @@ -22,7 +22,6 @@ "noUnusedParameters": true, "noFallthroughCasesInSwitch": true, "noUncheckedSideEffectImports": true, - "baseUrl": ".", "paths": { "@/*": ["./src/*"] } diff --git a/examples/solid/start-large/package.json b/examples/solid/start-large/package.json index 8986a62a170..6fea1e3991d 100644 --- a/examples/solid/start-large/package.json +++ b/examples/solid/start-large/package.json @@ -27,7 +27,7 @@ "@types/node": "^22.5.4", "vite-plugin-solid": "3.0.0-next.4", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" }, "keywords": [], diff --git a/examples/solid/start-large/tsconfig.json b/examples/solid/start-large/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/examples/solid/start-large/tsconfig.json +++ b/examples/solid/start-large/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/solid/start-streaming-data-from-server-functions/package.json b/examples/solid/start-streaming-data-from-server-functions/package.json index c84e30d70df..38805059a8e 100644 --- a/examples/solid/start-streaming-data-from-server-functions/package.json +++ b/examples/solid/start-streaming-data-from-server-functions/package.json @@ -20,7 +20,7 @@ "devDependencies": { "@types/node": "^22.5.4", "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/start-streaming-data-from-server-functions/tsconfig.json b/examples/solid/start-streaming-data-from-server-functions/tsconfig.json index 57ea27b2868..508ace2e179 100644 --- a/examples/solid/start-streaming-data-from-server-functions/tsconfig.json +++ b/examples/solid/start-streaming-data-from-server-functions/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/solid/start-supabase-basic/package.json b/examples/solid/start-supabase-basic/package.json index 5235a452a8d..884687fc428 100644 --- a/examples/solid/start-supabase-basic/package.json +++ b/examples/solid/start-supabase-basic/package.json @@ -25,7 +25,7 @@ "@tailwindcss/vite": "^4.2.2", "@types/node": "^22.5.4", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4" diff --git a/examples/solid/start-supabase-basic/tsconfig.json b/examples/solid/start-supabase-basic/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/examples/solid/start-supabase-basic/tsconfig.json +++ b/examples/solid/start-supabase-basic/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/solid/start-tailwind-v4/package.json b/examples/solid/start-tailwind-v4/package.json index 4c1733d3912..3914cf99058 100644 --- a/examples/solid/start-tailwind-v4/package.json +++ b/examples/solid/start-tailwind-v4/package.json @@ -22,7 +22,7 @@ "@tailwindcss/vite": "^4.2.2", "@types/node": "^22.5.4", "tailwindcss": "^4.2.2", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4", "vite-tsconfig-paths": "^5.1.4" diff --git a/examples/solid/start-tailwind-v4/tsconfig.json b/examples/solid/start-tailwind-v4/tsconfig.json index a40235b863f..ff0556e7a83 100644 --- a/examples/solid/start-tailwind-v4/tsconfig.json +++ b/examples/solid/start-tailwind-v4/tsconfig.json @@ -14,7 +14,6 @@ "target": "ES2022", "allowJs": true, "forceConsistentCasingInFileNames": true, - "baseUrl": ".", "paths": { "~/*": ["./src/*"] }, diff --git a/examples/solid/view-transitions/package.json b/examples/solid/view-transitions/package.json index 7b3ae4864f3..ef1129c93a9 100644 --- a/examples/solid/view-transitions/package.json +++ b/examples/solid/view-transitions/package.json @@ -12,7 +12,7 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/solid-router": "^2.0.0-alpha.9", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "solid-js": "2.0.0-beta.5", "@solidjs/web": "2.0.0-beta.5", "redaxios": "^0.5.1", @@ -21,7 +21,7 @@ }, "devDependencies": { "vite-plugin-solid": "3.0.0-next.4", - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0" } } diff --git a/examples/solid/view-transitions/src/vite-env.d.ts b/examples/solid/view-transitions/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/view-transitions/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/with-framer-motion/package.json b/examples/solid/with-framer-motion/package.json index 2de582a0542..337672a059f 100644 --- a/examples/solid/with-framer-motion/package.json +++ b/examples/solid/with-framer-motion/package.json @@ -20,7 +20,7 @@ "zod": "^3.24.2" }, "devDependencies": { - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vite-plugin-solid": "3.0.0-next.4" } diff --git a/examples/solid/with-framer-motion/src/vite-env.d.ts b/examples/solid/with-framer-motion/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/with-framer-motion/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/solid/with-trpc/package.json b/examples/solid/with-trpc/package.json index cdc1bccddf2..bcb4cdfc278 100644 --- a/examples/solid/with-trpc/package.json +++ b/examples/solid/with-trpc/package.json @@ -13,7 +13,7 @@ "@tailwindcss/vite": "^4.2.2", "@tanstack/solid-router": "^2.0.0-alpha.9", "@tanstack/solid-router-devtools": "^2.0.0-alpha.6", - "@tanstack/router-plugin": "^1.167.2", + "@tanstack/router-plugin": "^1.167.12", "@trpc/client": "^11.4.3", "@trpc/server": "^11.4.3", "express": "^4.21.2", diff --git a/examples/solid/with-trpc/src/vite-env.d.ts b/examples/solid/with-trpc/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/solid/with-trpc/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/vue/basic-file-based-jsx/package.json b/examples/vue/basic-file-based-jsx/package.json index 362039a82c7..7bb468ea33f 100644 --- a/examples/vue/basic-file-based-jsx/package.json +++ b/examples/vue/basic-file-based-jsx/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/router-plugin": "^1.167.2", - "@tanstack/vue-router": "^1.168.1", - "@tanstack/vue-router-devtools": "^1.166.10", + "@tanstack/router-plugin": "^1.167.12", + "@tanstack/vue-router": "^1.168.9", + "@tanstack/vue-router-devtools": "^1.166.11", "@tanstack/zod-adapter": "^1.166.9", "redaxios": "^0.5.1", "tailwindcss": "^4.2.2", diff --git a/examples/vue/basic-file-based-jsx/src/vite-env.d.ts b/examples/vue/basic-file-based-jsx/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/vue/basic-file-based-jsx/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/vue/basic-file-based-sfc/package.json b/examples/vue/basic-file-based-sfc/package.json index eebf7574e7d..38996573a01 100644 --- a/examples/vue/basic-file-based-sfc/package.json +++ b/examples/vue/basic-file-based-sfc/package.json @@ -10,9 +10,9 @@ }, "dependencies": { "@tailwindcss/vite": "^4.2.2", - "@tanstack/router-plugin": "^1.167.2", - "@tanstack/vue-router": "^1.168.1", - "@tanstack/vue-router-devtools": "^1.166.10", + "@tanstack/router-plugin": "^1.167.12", + "@tanstack/vue-router": "^1.168.9", + "@tanstack/vue-router-devtools": "^1.166.11", "@tanstack/zod-adapter": "^1.166.9", "redaxios": "^0.5.1", "tailwindcss": "^4.2.2", diff --git a/examples/vue/basic-file-based-sfc/src/vite-env.d.ts b/examples/vue/basic-file-based-sfc/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/vue/basic-file-based-sfc/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/examples/vue/basic/package.json b/examples/vue/basic/package.json index 75e84f30e77..89bf0b75395 100644 --- a/examples/vue/basic/package.json +++ b/examples/vue/basic/package.json @@ -9,14 +9,14 @@ "start": "vite" }, "dependencies": { - "@tanstack/vue-router": "^1.168.1", - "@tanstack/vue-router-devtools": "^1.166.10", + "@tanstack/vue-router": "^1.168.9", + "@tanstack/vue-router-devtools": "^1.166.11", "redaxios": "^0.5.1", "vue": "^3.5.13", "tailwindcss": "4.1.18" }, "devDependencies": { - "typescript": "^5.7.2", + "typescript": "^6.0.2", "vite": "^8.0.0", "vue-tsc": "^3.1.5", "@vitejs/plugin-vue": "^6.0.5", diff --git a/examples/vue/basic/src/vite-env.d.ts b/examples/vue/basic/src/vite-env.d.ts new file mode 100644 index 00000000000..11f02fe2a00 --- /dev/null +++ b/examples/vue/basic/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/nx.json b/nx.json index 3c404cd55bc..797ac916589 100644 --- a/nx.json +++ b/nx.json @@ -55,6 +55,11 @@ "dependsOn": ["^build"], "inputs": ["default", "^production"] }, + "test:e2e:preview": { + "cache": true, + "dependsOn": ["^build"], + "inputs": ["default", "^production"] + }, "test:types": { "cache": true, "dependsOn": ["^build"], diff --git a/package.json b/package.json index f090a3e0763..a9b10bf80df 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "test:docs": "node scripts/verify-links.ts", "vite-ecosystem-ci:build": "nx run-many --targets=build --projects=@tanstack/router-plugin,@tanstack/start-plugin-core,@tanstack/react-start,@tanstack/react-start-client,@tanstack/react-start-server --skipRemoteCache", "vite-ecosystem-ci:before-test": "pnpm exec playwright install chromium", - "vite-ecosystem-ci:test": "nx run-many --targets=test:unit --projects=@tanstack/router-plugin,@tanstack/start-plugin-core,@tanstack/react-start-client --skipRemoteCache && nx run-many --target=test:e2e --projects=tanstack-router-e2e-react-basic-file-based,tanstack-router-e2e-react-basic-file-based-code-splitting,tanstack-react-start-e2e-basic --skipRemoteCache" + "vite-ecosystem-ci:test": "nx run-many --targets=test:unit --projects=@tanstack/router-plugin,@tanstack/start-plugin-core,@tanstack/react-start-client --skipRemoteCache && nx run-many --target=test:e2e --projects=tanstack-router-e2e-react-basic-file-based,tanstack-router-e2e-react-basic-file-based-code-splitting,tanstack-react-start-e2e-basic,tanstack-react-start-e2e-basic-spa,tanstack-react-start-e2e-basic-prerender,tanstack-react-start-e2e-basic-preview,tanstack-vue-start-e2e-basic,tanstack-vue-start-e2e-basic-spa,tanstack-vue-start-e2e-basic-prerender,tanstack-vue-start-e2e-basic-preview,tanstack-solid-start-e2e-basic,tanstack-solid-start-e2e-basic-spa,tanstack-solid-start-e2e-basic-prerender,tanstack-solid-start-e2e-basic-preview --skipRemoteCache" }, "nx": { "includedScripts": [ @@ -72,12 +72,12 @@ "redaxios": "^0.5.1", "rimraf": "^6.1.2", "tinyglobby": "^0.2.15", - "typescript": "^5.9.3", - "typescript54": "npm:typescript@5.4", + "typescript": "^6.0.2", "typescript55": "npm:typescript@5.5", "typescript56": "npm:typescript@5.6", "typescript57": "npm:typescript@5.7", "typescript58": "npm:typescript@5.8", + "typescript59": "npm:typescript@5.9", "vite": "^8.0.0", "vitest": "^4.0.17" }, diff --git a/packages/arktype-adapter/package.json b/packages/arktype-adapter/package.json index e3ccdbc9bb4..8062da5093f 100644 --- a/packages/arktype-adapter/package.json +++ b/packages/arktype-adapter/package.json @@ -27,12 +27,12 @@ "clean": "rimraf ./dist && rimraf ./coverage", "test:eslint": "eslint ./src", "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"", - "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js", "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js", "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js", "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js", "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js", - "test:types:ts59": "tsc", + "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js", + "test:types:ts60": "tsc", "test:unit": "vitest", "test:unit:dev": "pnpm run test:unit --watch --typecheck", "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .", diff --git a/packages/arktype-adapter/tsconfig.build.json b/packages/arktype-adapter/tsconfig.build.json new file mode 100644 index 00000000000..92be18587f2 --- /dev/null +++ b/packages/arktype-adapter/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src"] +} diff --git a/packages/arktype-adapter/vite.config.ts b/packages/arktype-adapter/vite.config.ts index 830c03f4313..8c8c0c519f9 100644 --- a/packages/arktype-adapter/vite.config.ts +++ b/packages/arktype-adapter/vite.config.ts @@ -15,6 +15,7 @@ const config = defineConfig({ export default mergeConfig( config, tanstackViteConfig({ + tsconfigPath: './tsconfig.build.json', entry: './src/index.ts', srcDir: './src', }), diff --git a/packages/eslint-plugin-router/package.json b/packages/eslint-plugin-router/package.json index da86e5c009f..54438681423 100644 --- a/packages/eslint-plugin-router/package.json +++ b/packages/eslint-plugin-router/package.json @@ -18,12 +18,12 @@ "clean": "rimraf ./dist ./coverage", "test:eslint": "eslint ./src", "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"", - "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js", "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js", "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js", "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js", "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js", - "test:types:ts59": "tsc", + "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js", + "test:types:ts60": "tsc", "test:unit": "vitest", "test:unit:dev": "pnpm run test:unit --watch --typecheck", "test:build": "publint --strict && attw --pack .", diff --git a/packages/eslint-plugin-router/tsconfig.build.json b/packages/eslint-plugin-router/tsconfig.build.json new file mode 100644 index 00000000000..92be18587f2 --- /dev/null +++ b/packages/eslint-plugin-router/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src"] +} diff --git a/packages/eslint-plugin-router/vite.config.ts b/packages/eslint-plugin-router/vite.config.ts index 8769e2779e0..77ecb53a975 100644 --- a/packages/eslint-plugin-router/vite.config.ts +++ b/packages/eslint-plugin-router/vite.config.ts @@ -16,6 +16,7 @@ const config = defineConfig({ export default mergeConfig( config, tanstackViteConfig({ + tsconfigPath: './tsconfig.build.json', entry: './src/index.ts', srcDir: './src', exclude: ['./src/__tests__'], diff --git a/packages/history/package.json b/packages/history/package.json index 2fad180b244..2b99b6a18f5 100644 --- a/packages/history/package.json +++ b/packages/history/package.json @@ -22,12 +22,12 @@ "clean": "rimraf ./dist && rimraf ./coverage", "test:eslint": "eslint ./src", "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"", - "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js", "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js", "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js", "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js", "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js", - "test:types:ts59": "tsc", + "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js", + "test:types:ts60": "tsc", "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .", "test:unit": "vitest", "test:unit:dev": "pnpm run test:unit --watch", diff --git a/packages/history/tsconfig.build.json b/packages/history/tsconfig.build.json new file mode 100644 index 00000000000..92be18587f2 --- /dev/null +++ b/packages/history/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src"] +} diff --git a/packages/history/vite.config.ts b/packages/history/vite.config.ts index 830c03f4313..5eef55c1d9f 100644 --- a/packages/history/vite.config.ts +++ b/packages/history/vite.config.ts @@ -17,5 +17,6 @@ export default mergeConfig( tanstackViteConfig({ entry: './src/index.ts', srcDir: './src', + tsconfigPath: './tsconfig.build.json', }), ) diff --git a/packages/nitro-v2-vite-plugin/package.json b/packages/nitro-v2-vite-plugin/package.json index c315a0dbc4c..29bae2c3d6c 100644 --- a/packages/nitro-v2-vite-plugin/package.json +++ b/packages/nitro-v2-vite-plugin/package.json @@ -29,12 +29,12 @@ "test:unit": "echo 'No unit tests are needed here since we do them in @tanstack/router-plugin!'", "test:eslint": "eslint ./src", "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"", - "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js", "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js", "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js", "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js", "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js", - "test:types:ts59": "tsc", + "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js", + "test:types:ts60": "tsc", "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .", "build": "vite build" }, diff --git a/packages/nitro-v2-vite-plugin/tsconfig.build.json b/packages/nitro-v2-vite-plugin/tsconfig.build.json new file mode 100644 index 00000000000..92be18587f2 --- /dev/null +++ b/packages/nitro-v2-vite-plugin/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src"] +} diff --git a/packages/nitro-v2-vite-plugin/vite.config.ts b/packages/nitro-v2-vite-plugin/vite.config.ts index 7e4ae12a997..7401092b136 100644 --- a/packages/nitro-v2-vite-plugin/vite.config.ts +++ b/packages/nitro-v2-vite-plugin/vite.config.ts @@ -6,6 +6,7 @@ const config = defineConfig({}) export default mergeConfig( config, tanstackViteConfig({ + tsconfigPath: './tsconfig.build.json', entry: './src/index.ts', srcDir: './src', exclude: ['./src/tests/'], diff --git a/packages/react-router-devtools/CHANGELOG.md b/packages/react-router-devtools/CHANGELOG.md index 5cf7264cc06..611ab6b783b 100644 --- a/packages/react-router-devtools/CHANGELOG.md +++ b/packages/react-router-devtools/CHANGELOG.md @@ -1,5 +1,14 @@ # @tanstack/react-router-devtools +## 1.166.11 + +### Patch Changes + +- Updated dependencies [[`c9e1855`](https://github.com/TanStack/router/commit/c9e18555f3a5531e96de8f574cfca9edcdb18e5c)]: + - @tanstack/router-devtools-core@1.167.1 + - @tanstack/react-router@1.168.2 + - @tanstack/router-core@1.168.2 + ## 1.166.10 ### Patch Changes diff --git a/packages/react-router-devtools/package.json b/packages/react-router-devtools/package.json index 928198fc71a..37a8b5543e5 100644 --- a/packages/react-router-devtools/package.json +++ b/packages/react-router-devtools/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/react-router-devtools", - "version": "1.166.10", + "version": "1.166.11", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", @@ -27,12 +27,12 @@ "clean": "rimraf ./dist && rimraf ./coverage", "test:eslint": "eslint ./src", "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"", - "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js", "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js", "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js", "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js", "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js", - "test:types:ts59": "tsc", + "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js", + "test:types:ts60": "tsc", "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .", "build": "vite build" }, @@ -68,7 +68,8 @@ "@vitejs/plugin-react": "^4.3.4", "react": ">=19", "react-dom": ">=19", - "vite": "*" + "vite": "*", + "@types/node": ">=20" }, "peerDependencies": { "@tanstack/react-router": "workspace:^", diff --git a/packages/react-router-devtools/tsconfig.build.json b/packages/react-router-devtools/tsconfig.build.json new file mode 100644 index 00000000000..92be18587f2 --- /dev/null +++ b/packages/react-router-devtools/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src"] +} diff --git a/packages/react-router-devtools/tsconfig.json b/packages/react-router-devtools/tsconfig.json index 1599b212c02..fc0a511b1a9 100644 --- a/packages/react-router-devtools/tsconfig.json +++ b/packages/react-router-devtools/tsconfig.json @@ -2,7 +2,8 @@ "extends": "../../tsconfig.json", "compilerOptions": { "jsx": "react-jsx", - "jsxImportSource": "react" + "jsxImportSource": "react", + "types": ["node"] }, "include": ["src", "tests", "vite.config.ts"] } diff --git a/packages/react-router-devtools/vite.config.ts b/packages/react-router-devtools/vite.config.ts index 9cbd5e51799..0f6d3b9227d 100644 --- a/packages/react-router-devtools/vite.config.ts +++ b/packages/react-router-devtools/vite.config.ts @@ -17,6 +17,7 @@ const config = defineConfig({ export default mergeConfig( config, tanstackViteConfig({ + tsconfigPath: './tsconfig.build.json', entry: './src/index.ts', srcDir: './src', }), diff --git a/packages/react-router-ssr-query/package.json b/packages/react-router-ssr-query/package.json index a6982e9ea6c..f36973d8a08 100644 --- a/packages/react-router-ssr-query/package.json +++ b/packages/react-router-ssr-query/package.json @@ -27,12 +27,12 @@ "clean": "rimraf ./dist && rimraf ./coverage", "test:eslint": "eslint ./src", "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"", - "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js", "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js", "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js", "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js", "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js", - "test:types:ts59": "tsc", + "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js", + "test:types:ts60": "tsc", "test:unit": "exit 0; vitest", "test:unit:dev": "pnpm run test:unit --watch", "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .", diff --git a/packages/react-router-ssr-query/tsconfig.build.json b/packages/react-router-ssr-query/tsconfig.build.json new file mode 100644 index 00000000000..92be18587f2 --- /dev/null +++ b/packages/react-router-ssr-query/tsconfig.build.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "rootDir": "./src" + }, + "include": ["src"] +} diff --git a/packages/react-router-ssr-query/vite.config.ts b/packages/react-router-ssr-query/vite.config.ts index 7b2f860743c..ffe4359c131 100644 --- a/packages/react-router-ssr-query/vite.config.ts +++ b/packages/react-router-ssr-query/vite.config.ts @@ -17,6 +17,7 @@ const config = defineConfig({ export default mergeConfig( config, tanstackViteConfig({ + tsconfigPath: './tsconfig.build.json', entry: './src/index.tsx', srcDir: './src', }), diff --git a/packages/react-router/CHANGELOG.md b/packages/react-router/CHANGELOG.md index b86a3527b6f..48c7e69d6be 100644 --- a/packages/react-router/CHANGELOG.md +++ b/packages/react-router/CHANGELOG.md @@ -1,5 +1,79 @@ # @tanstack/react-router +## 1.168.10 + +### Patch Changes + +- Preserve component-thrown `notFound()` errors through framework error boundaries so route `notFoundComponent` handlers render without requiring an explicit `routeId`. ([#7077](https://github.com/TanStack/router/pull/7077)) + +- Updated dependencies [[`796406d`](https://github.com/TanStack/router/commit/796406da66cfb12b518bb3ca326c9d541368fb06)]: + - @tanstack/router-core@1.168.9 + +## 1.168.9 + +### Patch Changes + +- Updated dependencies [[`2d1ec86`](https://github.com/TanStack/router/commit/2d1ec865a446926f7db6e29dbbde82d265de6d36)]: + - @tanstack/router-core@1.168.8 + +## 1.168.8 + +### Patch Changes + +- Updated dependencies [[`6ee0e79`](https://github.com/TanStack/router/commit/6ee0e795b085651beb2f1ac6503cdbd7eaffedd1)]: + - @tanstack/router-core@1.168.7 + +## 1.168.7 + +### Patch Changes + +- Updated dependencies [[`42c3f3b`](https://github.com/TanStack/router/commit/42c3f3b3a3a478fd6d6894310ef94b2d23794b8e)]: + - @tanstack/router-core@1.168.6 + +## 1.168.6 + +### Patch Changes + +- Remove the extra SSR sentinel tag used for `onRendered` in React Router while ([#7054](https://github.com/TanStack/router/pull/7054)) + preserving the client-side render timing needed for scroll restoration and + `onRendered` subscribers. + +## 1.168.5 + +### Patch Changes + +- fix: scroll restoration without throttling ([#7042](https://github.com/TanStack/router/pull/7042)) + +- Updated dependencies [[`cf5f554`](https://github.com/TanStack/router/commit/cf5f5542476137a81515099ad740747e84512f9a)]: + - @tanstack/router-core@1.168.5 + +## 1.168.4 + +### Patch Changes + +- tanstack/store 0.9.3 ([#7041](https://github.com/TanStack/router/pull/7041)) + +- Updated dependencies [[`71a8b68`](https://github.com/TanStack/router/commit/71a8b684c87c37fd4a033d99f5ba4a05c7a179f5)]: + - @tanstack/router-core@1.168.4 + +## 1.168.3 + +### Patch Changes + +- feat: transformAssets ([#7023](https://github.com/TanStack/router/pull/7023)) + +- Updated dependencies [[`d81d21a`](https://github.com/TanStack/router/commit/d81d21ad05c9401bf54b24acd29401e1e4fd624c)]: + - @tanstack/router-core@1.168.3 + +## 1.168.2 + +### Patch Changes + +- Replace tiny-invariant and tiny-warning with in-house solution for bundle-size ([#7007](https://github.com/TanStack/router/pull/7007)) + +- Updated dependencies [[`c9e1855`](https://github.com/TanStack/router/commit/c9e18555f3a5531e96de8f574cfca9edcdb18e5c)]: + - @tanstack/router-core@1.168.2 + ## 1.168.1 ### Patch Changes diff --git a/packages/react-router/package.json b/packages/react-router/package.json index cfc57e0077f..92d39f038dd 100644 --- a/packages/react-router/package.json +++ b/packages/react-router/package.json @@ -1,6 +1,6 @@ { "name": "@tanstack/react-router", - "version": "1.168.1", + "version": "1.168.10", "description": "Modern and scalable routing for React applications", "author": "Tanner Linsley", "license": "MIT", @@ -27,12 +27,12 @@ "clean": "rimraf ./dist && rimraf ./coverage", "test:eslint": "eslint", "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"", - "test:types:ts54": "node ../../node_modules/typescript54/lib/tsc.js -p tsconfig.legacy.json", "test:types:ts55": "node ../../node_modules/typescript55/lib/tsc.js -p tsconfig.legacy.json", "test:types:ts56": "node ../../node_modules/typescript56/lib/tsc.js -p tsconfig.legacy.json", "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js -p tsconfig.legacy.json", "test:types:ts58": "node ../../node_modules/typescript58/lib/tsc.js -p tsconfig.legacy.json", - "test:types:ts59": "tsc -p tsconfig.legacy.json", + "test:types:ts59": "node ../../node_modules/typescript59/lib/tsc.js -p tsconfig.legacy.json", + "test:types:ts60": "tsc -p tsconfig.legacy.json", "test:unit": "vitest", "test:unit:dev": "pnpm run test:unit --watch --hideSkippedTests", "test:perf": "vitest bench", @@ -97,11 +97,9 @@ }, "dependencies": { "@tanstack/history": "workspace:*", - "@tanstack/react-store": "^0.9.2", + "@tanstack/react-store": "^0.9.3", "@tanstack/router-core": "workspace:*", - "isbot": "^5.1.22", - "tiny-invariant": "^1.3.3", - "tiny-warning": "^1.0.3" + "isbot": "^5.1.22" }, "devDependencies": { "@testing-library/jest-dom": "^6.6.3", @@ -112,7 +110,8 @@ "react-dom": "^19.0.0", "vibe-rules": "^0.2.57", "vite": "*", - "zod": "^3.24.2" + "zod": "^3.24.2", + "@types/node": ">=20" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", diff --git a/packages/react-router/src/HeadContent.dev.tsx b/packages/react-router/src/HeadContent.dev.tsx index 3dfaa6613e0..25cb4e410ce 100644 --- a/packages/react-router/src/HeadContent.dev.tsx +++ b/packages/react-router/src/HeadContent.dev.tsx @@ -3,6 +3,7 @@ import { Asset } from './Asset' import { useRouter } from './useRouter' import { useHydrated } from './ClientOnly' import { useTags } from './headContentUtils' +import type { HeadContentProps } from './HeadContent' const DEV_STYLES_ATTR = 'data-tanstack-router-dev-styles' @@ -15,8 +16,8 @@ const DEV_STYLES_ATTR = 'data-tanstack-router-dev-styles' * * @link https://tanstack.com/router/latest/docs/framework/react/guide/document-head-management */ -export function HeadContent() { - const tags = useTags() +export function HeadContent(props: HeadContentProps) { + const tags = useTags(props.assetCrossOrigin) const router = useRouter() const nonce = router.options.ssr?.nonce const hydrated = useHydrated() diff --git a/packages/react-router/src/HeadContent.tsx b/packages/react-router/src/HeadContent.tsx index e917fd95964..c5d87a1778f 100644 --- a/packages/react-router/src/HeadContent.tsx +++ b/packages/react-router/src/HeadContent.tsx @@ -2,14 +2,19 @@ import * as React from 'react' import { Asset } from './Asset' import { useRouter } from './useRouter' import { useTags } from './headContentUtils' +import type { AssetCrossOriginConfig } from '@tanstack/router-core' + +export interface HeadContentProps { + assetCrossOrigin?: AssetCrossOriginConfig +} /** * Render route-managed head tags (title, meta, links, styles, head scripts). * Place inside the document head of your app shell. * @link https://tanstack.com/router/latest/docs/framework/react/guide/document-head-management */ -export function HeadContent() { - const tags = useTags() +export function HeadContent(props: HeadContentProps) { + const tags = useTags(props.assetCrossOrigin) const router = useRouter() const nonce = router.options.ssr?.nonce return ( diff --git a/packages/react-router/src/Match.tsx b/packages/react-router/src/Match.tsx index 36b41ef1240..ae30f4b7ec4 100644 --- a/packages/react-router/src/Match.tsx +++ b/packages/react-router/src/Match.tsx @@ -1,10 +1,9 @@ import * as React from 'react' import { useStore } from '@tanstack/react-store' -import invariant from 'tiny-invariant' -import warning from 'tiny-warning' import { createControlledPromise, getLocationChangeInfo, + invariant, isNotFound, isRedirect, rootRouteId, @@ -18,11 +17,8 @@ import { SafeFragment } from './SafeFragment' import { renderRouteNotFound } from './renderRouteNotFound' import { ScrollRestoration } from './scroll-restoration' import { ClientOnly } from './ClientOnly' -import type { - AnyRoute, - ParsedLocation, - RootRouteOptions, -} from '@tanstack/router-core' +import { useLayoutEffect } from './utils' +import type { AnyRoute, RootRouteOptions } from '@tanstack/router-core' export const Match = React.memo(function MatchImpl({ matchId, @@ -33,10 +29,15 @@ export const Match = React.memo(function MatchImpl({ if (isServer ?? router.isServer) { const match = router.stores.activeMatchStoresById.get(matchId)?.state - invariant( - match, - `Could not find match for matchId "${matchId}". Please file an issue!`, - ) + if (!match) { + if (process.env.NODE_ENV !== 'production') { + throw new Error( + `Invariant failed: Could not find match for matchId "${matchId}". Please file an issue!`, + ) + } + + invariant() + } const routeId = match.routeId as string const parentRouteId = (router.routesById[routeId] as AnyRoute).parentRoute @@ -60,12 +61,17 @@ export const Match = React.memo(function MatchImpl({ // Subscribe directly to the match store from the pool. // The matchId prop is stable for this component's lifetime (set by Outlet), // and reconcileMatchPool reuses stores for the same matchId. - // eslint-disable-next-line react-hooks/rules-of-hooks + const matchStore = router.stores.activeMatchStoresById.get(matchId) - invariant( - matchStore, - `Could not find match for matchId "${matchId}". Please file an issue!`, - ) + if (!matchStore) { + if (process.env.NODE_ENV !== 'production') { + throw new Error( + `Invariant failed: Could not find match for matchId "${matchId}". Please file an issue!`, + ) + } + + invariant() + } // eslint-disable-next-line react-hooks/rules-of-hooks const resetKey = useStore(router.stores.loadedAt, (loadedAt) => loadedAt) // eslint-disable-next-line react-hooks/rules-of-hooks @@ -161,13 +167,20 @@ function MatchView({ errorComponent={routeErrorComponent || ErrorComponent} onCatch={(error, errorInfo) => { // Forward not found errors (we don't want to show the error component for these) - if (isNotFound(error)) throw error - warning(false, `Error in route match: ${matchId}`) + if (isNotFound(error)) { + error.routeId ??= matchState.routeId as any + throw error + } + if (process.env.NODE_ENV !== 'production') { + console.warn(`Warning: Error in route match: ${matchId}`) + } routeOnCatch?.(error, errorInfo) }} > { + error.routeId ??= matchState.routeId as any + // If the current not found handler doesn't exist or it has a // route ID which doesn't match the current route, rethrow the error if ( @@ -191,53 +204,52 @@ function MatchView({ - {matchState.parentRouteId === rootRouteId && - router.options.scrollRestoration ? ( + {matchState.parentRouteId === rootRouteId ? ( <> - - + + {router.options.scrollRestoration && (isServer ?? router.isServer) ? ( + + ) : null} ) : null} ) } -// On Rendered can't happen above the root layout because it actually -// renders a dummy dom element to track the rendered state of the app. -// We render a script tag with a key that changes based on the current -// location state.__TSR_key. Also, because it's below the root layout, it -// allows us to fire onRendered events even after a hydration mismatch -// error that occurred above the root layout (like bad head/link tags, -// which is common). -function OnRendered() { +// On Rendered can't happen above the root layout because it needs to run after +// the route subtree has committed below the root layout. Keeping it here lets +// us fire onRendered even after a hydration mismatch above the root layout +// (like bad head/link tags, which is common). +function OnRendered({ resetKey }: { resetKey: number }) { const router = useRouter() - const prevLocationRef = React.useRef>( - undefined, - ) + if (isServer ?? router.isServer) { + return null + } - return ( -