From b3af7f39b3262c471e5641d47ea7c1d2de436378 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Thu, 20 Feb 2025 22:09:50 -0700 Subject: [PATCH 001/155] fix: global middleware Fixes global middleware with a solution to ensuring registerGlobalMiddleware runs on both the client and server no matter what --- docs/start/framework/react/middleware.md | 8 +- .../react/start-basic/app/server-functions.ts | 8 ++ packages/react-start-plugin/src/index.ts | 124 +++++++++++------- packages/start-config/src/index.ts | 9 +- packages/start-config/src/schema.ts | 2 +- 5 files changed, 98 insertions(+), 53 deletions(-) create mode 100644 examples/react/start-basic/app/server-functions.ts diff --git a/docs/start/framework/react/middleware.md b/docs/start/framework/react/middleware.md index c908f5b895..5d0f0d67d1 100644 --- a/docs/start/framework/react/middleware.md +++ b/docs/start/framework/react/middleware.md @@ -296,13 +296,13 @@ Middleware can be used in two different ways: Global middleware runs automatically for every server function in your application. This is useful for functionality like authentication, logging, and monitoring that should apply to all requests. -To use global middleware, create a `global-middleware.ts` file in your project (typically at `app/global-middleware.ts`). This file runs in both client and server environments and is where you register global middleware. +To use global middleware, create a `server-functions.ts` file in your project (typically at `app/server-functions.ts`). This file runs in both client and server environments and is where you register global middleware. Here's how to register global middleware: ```tsx -// app/global-middleware.ts -import { registerGlobalMiddleware } from '@tanstack/react-start' +// app/server-functions.ts +import { registerGlobalMiddleware } from '@tanstack/start' import { authMiddleware } from './middleware' registerGlobalMiddleware({ @@ -315,7 +315,7 @@ registerGlobalMiddleware({ Global middleware types are inherently **detached** from server functions themselves. This means that if a global middleware supplies additional context to server functions or other server function specific middleware, the types will not be automatically passed through to the server function or other server function specific middleware. ```tsx -// app/global-middleware.ts +// app/server-functions.ts registerGlobalMiddleware({ middleware: [authMiddleware], }) diff --git a/examples/react/start-basic/app/server-functions.ts b/examples/react/start-basic/app/server-functions.ts new file mode 100644 index 0000000000..3896ec3143 --- /dev/null +++ b/examples/react/start-basic/app/server-functions.ts @@ -0,0 +1,8 @@ +import { registerGlobalMiddleware } from '@tanstack/start' +import { logMiddleware } from './utils/loggingMiddleware' + +registerGlobalMiddleware({ + middleware: [logMiddleware], +}) + +console.log('hello') diff --git a/packages/react-start-plugin/src/index.ts b/packages/react-start-plugin/src/index.ts index 6ab529afca..963b1b5d9f 100644 --- a/packages/react-start-plugin/src/index.ts +++ b/packages/react-start-plugin/src/index.ts @@ -1,16 +1,17 @@ import { fileURLToPath, pathToFileURL } from 'node:url' import path from 'node:path' -import { existsSync } from 'node:fs' import { logDiff } from '@tanstack/router-utils' import { compileStartOutput } from './compilers' + import type { Plugin } from 'vite' const debug = process.env.TSR_VITE_DEBUG && - ['true', 'react-start-plugin'].includes(process.env.TSR_VITE_DEBUG) + ['true', 'start-plugin'].includes(process.env.TSR_VITE_DEBUG) export type TanStackStartViteOptions = { - globalMiddlewareEntry: string + manifestVirtualImportId: string + serverFnEntry: string } const transformFuncs = [ @@ -30,54 +31,89 @@ export function createTanStackStartPlugin(opts: TanStackStartViteOptions): { ssr: Array server: Array } { - const globalMiddlewarePlugin = (): Plugin => { - let entry: string | null = null - let resolvedGlobalMiddlewareEntry: string | null = null - let globalMiddlewareEntryExists = false - let ROOT: string = process.cwd() - return { - name: 'vite-plugin-tanstack-start-ensure-global-middleware', - enforce: 'pre', - configResolved: (config) => { - ROOT = config.root - entry = path.resolve(ROOT, (config as any).router.handler) - resolvedGlobalMiddlewareEntry = path.resolve( - ROOT, - opts.globalMiddlewareEntry, - ) - globalMiddlewareEntryExists = existsSync(resolvedGlobalMiddlewareEntry) - - if (!entry) { - throw new Error( - '@tanstack/react-start-plugin: No server entry found!', - ) - } - }, - transform(code, id) { - if (entry && id.includes(entry)) { - if (globalMiddlewareEntryExists) { - return { - code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, - map: null, - } - } - } - return null - }, - } - } - return { client: [ - globalMiddlewarePlugin(), + (() => { + let entry: string | null = null + let ROOT: string = process.cwd() + return { + name: 'vite-plugin-tanstack-start-server-entry-client', + enforce: 'pre', + configResolved: (config) => { + ROOT = config.root + entry = path.resolve(ROOT, (config as any).router.handler) + + if (!entry) { + throw new Error('@tanstack/start-plugin: No server entry found!') + } + }, + transform(code, id) { + if (entry && id.includes(entry)) { + return { + code: `${code}\n\nimport '${path.resolve(ROOT, opts.serverFnEntry)}'`, + map: null, + } + } + return null + }, + } + })(), TanStackStartServerFnsAndMiddleware({ ...opts, env: 'client' }), ], ssr: [ - globalMiddlewarePlugin(), + (() => { + let entry: string | null = null + let ROOT: string = process.cwd() + return { + name: 'vite-plugin-tanstack-start-server-entry-ssr', + enforce: 'pre', + configResolved: (config) => { + ROOT = config.root + entry = path.resolve(ROOT, (config as any).router.handler) + + if (!entry) { + throw new Error('@tanstack/start-plugin: No server entry found!') + } + }, + transform(code, id) { + if (entry && id.includes(entry)) { + return { + code: `${code}\n\nimport '${path.resolve(ROOT, opts.serverFnEntry)}'`, + map: null, + } + } + return null + }, + } + })(), TanStackStartServerFnsAndMiddleware({ ...opts, env: 'ssr' }), ], server: [ - globalMiddlewarePlugin(), + (() => { + let entry: string | null = null + let ROOT: string = process.cwd() + return { + name: 'vite-plugin-tanstack-start-server-entry-server', + enforce: 'pre', + configResolved: (config) => { + ROOT = config.root + entry = path.resolve(ROOT, (config as any).router.handler) + + if (!entry) { + throw new Error('@tanstack/start-plugin: No server entry found!') + } + }, + transform(code, id) { + if (entry && id.includes(entry)) { + return { + code: `${code}\n\nimport '${path.resolve(ROOT, opts.serverFnEntry)}'`, + map: null, + } + } + return null + }, + } + })(), TanStackStartServerFnsAndMiddleware({ ...opts, env: 'server' }), ], } @@ -112,7 +148,7 @@ export function TanStackStartServerFnsAndMiddleware(opts: { if (code.includes('@react-refresh')) { throw new Error( - `We detected that the '@vitejs/plugin-react' was passed before '@tanstack/react-start-plugin'. Please make sure that '@tanstack/router-vite-plugin' is passed before '@vitejs/plugin-react' and try again: + `We detected that the '@vitejs/plugin-react' was passed before '@tanstack/start-plugin'. Please make sure that '@tanstack/router-vite-plugin' is passed before '@vitejs/plugin-react' and try again: e.g. plugins: [ diff --git a/packages/start-config/src/index.ts b/packages/start-config/src/index.ts index f2d1d06d1a..3fd5a46664 100644 --- a/packages/start-config/src/index.ts +++ b/packages/start-config/src/index.ts @@ -110,9 +110,9 @@ export async function defineConfig( const ssrEntry = opts.routers?.ssr?.entry || path.join(appDirectory, 'ssr.tsx') const apiEntry = opts.routers?.api?.entry || path.join(appDirectory, 'api.ts') - const globalMiddlewareEntry = - opts.routers?.server?.globalMiddlewareEntry || - path.join(appDirectory, 'global-middleware.ts') + const serverFnEntry = + opts.routers?.server?.entry || + path.join(appDirectory, 'server-functions.ts') const apiEntryExists = existsSync(apiEntry) const viteConfig = getUserViteConfig(opts.vite) @@ -141,7 +141,8 @@ export async function defineConfig( }) const TanStackStartPlugin = createTanStackStartPlugin({ - globalMiddlewareEntry, + serverFnEntry, + manifestVirtualImportId: 'tsr:start-manifest', }) // Create a dummy nitro app to get the resolved public output path diff --git a/packages/start-config/src/schema.ts b/packages/start-config/src/schema.ts index 516e4e86fa..5dc171bdd9 100644 --- a/packages/start-config/src/schema.ts +++ b/packages/start-config/src/schema.ts @@ -158,7 +158,7 @@ const routersSchema = z.object({ server: z .object({ base: z.string().optional(), - globalMiddlewareEntry: z.string().optional(), + entry: z.string().optional(), middleware: z.string().optional(), vite: viteSchema.optional(), }) From 346174a1550dd0f27e5bb808cfe849f9091434ba Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Fri, 21 Feb 2025 09:51:41 -0700 Subject: [PATCH 002/155] fix: rename to global-middleware.ts --- docs/start/framework/react/middleware.md | 6 +++--- examples/react/start-basic/app/server-functions.ts | 8 -------- packages/react-start-plugin/src/index.ts | 9 ++++----- packages/start-config/src/index.ts | 9 ++++----- packages/start-config/src/schema.ts | 2 +- 5 files changed, 12 insertions(+), 22 deletions(-) delete mode 100644 examples/react/start-basic/app/server-functions.ts diff --git a/docs/start/framework/react/middleware.md b/docs/start/framework/react/middleware.md index 5d0f0d67d1..a8e71d26b1 100644 --- a/docs/start/framework/react/middleware.md +++ b/docs/start/framework/react/middleware.md @@ -296,12 +296,12 @@ Middleware can be used in two different ways: Global middleware runs automatically for every server function in your application. This is useful for functionality like authentication, logging, and monitoring that should apply to all requests. -To use global middleware, create a `server-functions.ts` file in your project (typically at `app/server-functions.ts`). This file runs in both client and server environments and is where you register global middleware. +To use global middleware, create a `global-middleware.ts` file in your project (typically at `app/global-middleware.ts`). This file runs in both client and server environments and is where you register global middleware. Here's how to register global middleware: ```tsx -// app/server-functions.ts +// app/global-middleware.ts import { registerGlobalMiddleware } from '@tanstack/start' import { authMiddleware } from './middleware' @@ -315,7 +315,7 @@ registerGlobalMiddleware({ Global middleware types are inherently **detached** from server functions themselves. This means that if a global middleware supplies additional context to server functions or other server function specific middleware, the types will not be automatically passed through to the server function or other server function specific middleware. ```tsx -// app/server-functions.ts +// app/global-middleware.ts registerGlobalMiddleware({ middleware: [authMiddleware], }) diff --git a/examples/react/start-basic/app/server-functions.ts b/examples/react/start-basic/app/server-functions.ts deleted file mode 100644 index 3896ec3143..0000000000 --- a/examples/react/start-basic/app/server-functions.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { registerGlobalMiddleware } from '@tanstack/start' -import { logMiddleware } from './utils/loggingMiddleware' - -registerGlobalMiddleware({ - middleware: [logMiddleware], -}) - -console.log('hello') diff --git a/packages/react-start-plugin/src/index.ts b/packages/react-start-plugin/src/index.ts index 963b1b5d9f..4d08a9d165 100644 --- a/packages/react-start-plugin/src/index.ts +++ b/packages/react-start-plugin/src/index.ts @@ -10,8 +10,7 @@ const debug = ['true', 'start-plugin'].includes(process.env.TSR_VITE_DEBUG) export type TanStackStartViteOptions = { - manifestVirtualImportId: string - serverFnEntry: string + globalMiddlewareEntry: string } const transformFuncs = [ @@ -50,7 +49,7 @@ export function createTanStackStartPlugin(opts: TanStackStartViteOptions): { transform(code, id) { if (entry && id.includes(entry)) { return { - code: `${code}\n\nimport '${path.resolve(ROOT, opts.serverFnEntry)}'`, + code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, map: null, } } @@ -78,7 +77,7 @@ export function createTanStackStartPlugin(opts: TanStackStartViteOptions): { transform(code, id) { if (entry && id.includes(entry)) { return { - code: `${code}\n\nimport '${path.resolve(ROOT, opts.serverFnEntry)}'`, + code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, map: null, } } @@ -106,7 +105,7 @@ export function createTanStackStartPlugin(opts: TanStackStartViteOptions): { transform(code, id) { if (entry && id.includes(entry)) { return { - code: `${code}\n\nimport '${path.resolve(ROOT, opts.serverFnEntry)}'`, + code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, map: null, } } diff --git a/packages/start-config/src/index.ts b/packages/start-config/src/index.ts index 3fd5a46664..f2d1d06d1a 100644 --- a/packages/start-config/src/index.ts +++ b/packages/start-config/src/index.ts @@ -110,9 +110,9 @@ export async function defineConfig( const ssrEntry = opts.routers?.ssr?.entry || path.join(appDirectory, 'ssr.tsx') const apiEntry = opts.routers?.api?.entry || path.join(appDirectory, 'api.ts') - const serverFnEntry = - opts.routers?.server?.entry || - path.join(appDirectory, 'server-functions.ts') + const globalMiddlewareEntry = + opts.routers?.server?.globalMiddlewareEntry || + path.join(appDirectory, 'global-middleware.ts') const apiEntryExists = existsSync(apiEntry) const viteConfig = getUserViteConfig(opts.vite) @@ -141,8 +141,7 @@ export async function defineConfig( }) const TanStackStartPlugin = createTanStackStartPlugin({ - serverFnEntry, - manifestVirtualImportId: 'tsr:start-manifest', + globalMiddlewareEntry, }) // Create a dummy nitro app to get the resolved public output path diff --git a/packages/start-config/src/schema.ts b/packages/start-config/src/schema.ts index 5dc171bdd9..516e4e86fa 100644 --- a/packages/start-config/src/schema.ts +++ b/packages/start-config/src/schema.ts @@ -158,7 +158,7 @@ const routersSchema = z.object({ server: z .object({ base: z.string().optional(), - entry: z.string().optional(), + globalMiddlewareEntry: z.string().optional(), middleware: z.string().optional(), vite: viteSchema.optional(), }) From 0e2a7aa406ae0364dc1c9b3aa1057c1343d6ea53 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Fri, 21 Feb 2025 10:23:16 -0700 Subject: [PATCH 003/155] example: fix duration --- examples/react/start-basic/app/utils/loggingMiddleware.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/react/start-basic/app/utils/loggingMiddleware.tsx b/examples/react/start-basic/app/utils/loggingMiddleware.tsx index 3944490725..d743ba5340 100644 --- a/examples/react/start-basic/app/utils/loggingMiddleware.tsx +++ b/examples/react/start-basic/app/utils/loggingMiddleware.tsx @@ -32,7 +32,7 @@ export const logMiddleware = createMiddleware() const now = new Date() console.log('Client Req/Res:', { - duration: res.context.clientTime.getTime() - now.getTime(), + duration: now.getTime() - res.context.clientTime.getTime(), durationToServer: res.context.durationToServer, durationFromServer: now.getTime() - res.context.serverTime.getTime(), }) From 7d0c293812fab034773602fbf404b708be75a718 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Fri, 21 Feb 2025 10:51:06 -0700 Subject: [PATCH 004/155] rebased on fix:globalmiddleware --- .github/labeler.yml | 18 +++- examples/react/start-basic/app.config.ts | 12 --- examples/react/start-basic/vite.config.ts | 12 +++ package.json | 1 - .../src/config.ts} | 0 .../src/schema.ts | 0 .../src/vinxi-file-router.ts | 0 packages/start-config/README.md | 33 ------- packages/start-config/eslint.config.js | 31 ------ packages/start-config/package.json | 73 -------------- packages/start-config/tsconfig.json | 10 -- packages/start/package.json | 12 +-- packages/start/src/config.tsx | 4 - packages/start/src/plugin.tsx | 1 + packages/start/vite.config.ts | 4 +- pnpm-lock.yaml | 95 +++++-------------- scripts/publish.js | 8 -- 17 files changed, 60 insertions(+), 254 deletions(-) delete mode 100644 examples/react/start-basic/app.config.ts create mode 100644 examples/react/start-basic/vite.config.ts rename packages/{start-config/src/index.ts => react-start-plugin/src/config.ts} (100%) rename packages/{start-config => react-start-plugin}/src/schema.ts (100%) rename packages/{start-config => react-start-plugin}/src/vinxi-file-router.ts (100%) delete mode 100644 packages/start-config/README.md delete mode 100644 packages/start-config/eslint.config.js delete mode 100644 packages/start-config/package.json delete mode 100644 packages/start-config/tsconfig.json delete mode 100644 packages/start/src/config.tsx create mode 100644 packages/start/src/plugin.tsx diff --git a/.github/labeler.yml b/.github/labeler.yml index 138f2f8d5d..76b074f192 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -84,8 +84,22 @@ - 'packages/solid-start-server-functions-ssr/**/*' 'package: start': - 'packages/start/**/*' -'package: start-config': - - 'packages/start-config/**/*' +'package: start-api-routes': + - 'packages/start-api-routes/**/*' +'package: start-client': + - 'packages/start-client/**/*' +'package: start-plugin': + - 'packages/start-plugin/**/*' +'package: start-router-manifest': + - 'packages/start-router-manifest/**/*' +'package: start-server': + - 'packages/start-server/**/*' +'package: start-server-functions-client': + - 'packages/start-server-functions-client/**/*' +'package: start-server-functions-fetcher': + - 'packages/start-server-functions-fetcher/**/*' +'package: start-server-functions-handler': + - 'packages/start-server-functions-handler/**/*' 'package: start-server-functions-server': - 'packages/start-server-functions-server/**/*' 'package: valibot-adapter': diff --git a/examples/react/start-basic/app.config.ts b/examples/react/start-basic/app.config.ts deleted file mode 100644 index 346ac63390..0000000000 --- a/examples/react/start-basic/app.config.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { defineConfig } from '@tanstack/react-start/config' -import tsConfigPaths from 'vite-tsconfig-paths' - -export default defineConfig({ - vite: { - plugins: [ - tsConfigPaths({ - projects: ['./tsconfig.json'], - }), - ], - }, -}) diff --git a/examples/react/start-basic/vite.config.ts b/examples/react/start-basic/vite.config.ts new file mode 100644 index 0000000000..487b4bf09f --- /dev/null +++ b/examples/react/start-basic/vite.config.ts @@ -0,0 +1,12 @@ +import { defineConfig } from 'vite' +import tsConfigPaths from 'vite-tsconfig-paths' +import { TanStackStartVitePlugin } from '@tanstack/start/plugin' + +export default defineConfig({ + plugins: [ + tsConfigPaths({ + projects: ['./tsconfig.json'], + }), + TanStackStartVitePlugin(), + ], +}) diff --git a/package.json b/package.json index 59409a03fe..2fb22d4277 100644 --- a/package.json +++ b/package.json @@ -103,7 +103,6 @@ "@tanstack/react-start-server-functions-ssr": "workspace:*", "@tanstack/start-server-functions-server": "workspace:*", "@tanstack/react-start-router-manifest": "workspace:*", - "@tanstack/react-start-config": "workspace:*", "@tanstack/react-start-plugin": "workspace:*", "@tanstack/eslint-plugin-router": "workspace:*", "@tanstack/server-functions-plugin": "workspace:*", diff --git a/packages/start-config/src/index.ts b/packages/react-start-plugin/src/config.ts similarity index 100% rename from packages/start-config/src/index.ts rename to packages/react-start-plugin/src/config.ts diff --git a/packages/start-config/src/schema.ts b/packages/react-start-plugin/src/schema.ts similarity index 100% rename from packages/start-config/src/schema.ts rename to packages/react-start-plugin/src/schema.ts diff --git a/packages/start-config/src/vinxi-file-router.ts b/packages/react-start-plugin/src/vinxi-file-router.ts similarity index 100% rename from packages/start-config/src/vinxi-file-router.ts rename to packages/react-start-plugin/src/vinxi-file-router.ts diff --git a/packages/start-config/README.md b/packages/start-config/README.md deleted file mode 100644 index bb009b0c87..0000000000 --- a/packages/start-config/README.md +++ /dev/null @@ -1,33 +0,0 @@ -> 🤫 we're cooking up something special! - - - -# TanStack Start - -![TanStack Router Header](https://github.com/tanstack/router/raw/main/media/header.png) - -🤖 Type-safe router w/ built-in caching & URL state management for React! - - - #TanStack - - - - - - - - semantic-release - - Join the discussion on Github -Best of JS - - - - - - - -Enjoy this library? Try the entire [TanStack](https://tanstack.com)! [React Query](https://github.com/tannerlinsley/react-query), [React Table](https://github.com/tanstack/react-table), [React Charts](https://github.com/tannerlinsley/react-charts), [React Virtual](https://github.com/tannerlinsley/react-virtual) - -## Visit [tanstack.com/router](https://tanstack.com/router) for docs, guides, API and more! diff --git a/packages/start-config/eslint.config.js b/packages/start-config/eslint.config.js deleted file mode 100644 index 931f0ec774..0000000000 --- a/packages/start-config/eslint.config.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check - -import pluginReact from '@eslint-react/eslint-plugin' -import pluginReactHooks from 'eslint-plugin-react-hooks' -import rootConfig from '../../eslint.config.js' - -export default [ - ...rootConfig, - { - ...pluginReact.configs.recommended, - files: ['**/*.{ts,tsx}'], - }, - { - plugins: { - 'react-hooks': pluginReactHooks, - }, - rules: { - '@eslint-react/no-unstable-context-value': 'off', - '@eslint-react/no-unstable-default-props': 'off', - '@eslint-react/dom/no-missing-button-type': 'off', - 'react-hooks/exhaustive-deps': 'error', - 'react-hooks/rules-of-hooks': 'error', - }, - }, - { - files: ['**/__tests__/**'], - rules: { - '@typescript-eslint/no-unnecessary-condition': 'off', - }, - }, -] diff --git a/packages/start-config/package.json b/packages/start-config/package.json deleted file mode 100644 index 9e7841ee23..0000000000 --- a/packages/start-config/package.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "name": "@tanstack/start-config", - "version": "1.114.3", - "description": "Modern and scalable routing for React applications", - "author": "Tanner Linsley", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/TanStack/router.git", - "directory": "packages/start-config" - }, - "homepage": "https://tanstack.com/start", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "keywords": [ - "react", - "location", - "router", - "routing", - "async", - "async router", - "typescript" - ], - "scripts": { - "clean": "rimraf ./dist && rimraf ./coverage", - "build": "tsc", - "test": "pnpm test:eslint && pnpm test:types && pnpm test:build && pnpm test:unit", - "test:unit": "exit 0;vitest", - "test:eslint": "eslint ./src", - "test:types": "exit 0; vitest" - }, - "type": "module", - "types": "dist/esm/index.d.ts", - "exports": { - ".": { - "import": { - "types": "./dist/esm/index.d.ts", - "default": "./dist/esm/index.js" - } - }, - "./package.json": "./package.json" - }, - "sideEffects": false, - "files": [ - "dist", - "src" - ], - "engines": { - "node": ">=12" - }, - "dependencies": { - "@tanstack/react-router": "workspace:^", - "@tanstack/router-generator": "workspace:^", - "@tanstack/router-plugin": "workspace:^", - "@tanstack/server-functions-plugin": "workspace:^", - "@tanstack/react-start-plugin": "workspace:^", - "@tanstack/react-start-server-functions-handler": "workspace:^", - "@vitejs/plugin-react": "^4.3.4", - "import-meta-resolve": "^4.1.0", - "nitropack": "^2.10.4", - "ofetch": "^1.4.1", - "vite": "^6.1.0", - "vinxi": "0.5.3", - "zod": "^3.24.1" - }, - "peerDependencies": { - "react": ">=18.0.0 || >=19.0.0", - "react-dom": ">=18.0.0 || >=19.0.0", - "vite": "^6.0.0" - } -} diff --git a/packages/start-config/tsconfig.json b/packages/start-config/tsconfig.json deleted file mode 100644 index 940a9cce0a..0000000000 --- a/packages/start-config/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "include": ["src/index.ts"], - "compilerOptions": { - "rootDir": "src", - "outDir": "dist/esm", - "target": "esnext", - "noEmit": false - } -} diff --git a/packages/start/package.json b/packages/start/package.json index d863ca385b..0457100311 100644 --- a/packages/start/package.json +++ b/packages/start/package.json @@ -62,14 +62,14 @@ "default": "./dist/cjs/server.cjs" } }, - "./config": { + "./plugin": { "import": { - "types": "./dist/esm/config.d.ts", - "default": "./dist/esm/config.js" + "types": "./dist/esm/plugin.d.ts", + "default": "./dist/esm/plugin.js" }, "require": { - "types": "./dist/cjs/config.d.cts", - "default": "./dist/cjs/config.cjs" + "types": "./dist/cjs/plugin.d.cts", + "default": "./dist/cjs/plugin.cjs" } }, "./api": { @@ -145,7 +145,7 @@ "dependencies": { "@tanstack/react-start-client": "workspace:^", "@tanstack/react-start-server": "workspace:^", - "@tanstack/start-config": "workspace:^", + "@tanstack/react-start-plugin": "workspace:^", "@tanstack/react-start-router-manifest": "workspace:^", "@tanstack/react-start-server-functions-client": "workspace:^", "@tanstack/start-server-functions-server": "workspace:^", diff --git a/packages/start/src/config.tsx b/packages/start/src/config.tsx deleted file mode 100644 index 262bac966c..0000000000 --- a/packages/start/src/config.tsx +++ /dev/null @@ -1,4 +0,0 @@ -console.warn( - '[@tanstack/start] Warning: This package has moved to @tanstack/react-start. Please switch to the new package, as this package will be dropped soon.', -) -export * from '@tanstack/start-config' diff --git a/packages/start/src/plugin.tsx b/packages/start/src/plugin.tsx new file mode 100644 index 0000000000..d991c3b71c --- /dev/null +++ b/packages/start/src/plugin.tsx @@ -0,0 +1 @@ +export * from '@tanstack/react-start-plugin' diff --git a/packages/start/vite.config.ts b/packages/start/vite.config.ts index c0d7ce210e..8c696b7b37 100644 --- a/packages/start/vite.config.ts +++ b/packages/start/vite.config.ts @@ -17,7 +17,7 @@ export default mergeConfig( entry: [ './src/client.tsx', './src/server.tsx', - './src/config.tsx', + './src/plugin.tsx', './src/router-manifest.tsx', './src/server-functions-client.tsx', './src/server-functions-server.tsx', @@ -27,7 +27,7 @@ export default mergeConfig( externalDeps: [ '@tanstack/react-start-client', '@tanstack/react-start-server', - '@tanstack/start-config', + '@tanstack/react-start-plugin', '@tanstack/react-start-router-manifest', '@tanstack/react-start-server-functions-client', '@tanstack/start-server-functions-server', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9a683ec999..f4d98db7ef 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -39,7 +39,6 @@ overrides: '@tanstack/react-start-server-functions-ssr': workspace:* '@tanstack/start-server-functions-server': workspace:* '@tanstack/react-start-router-manifest': workspace:* - '@tanstack/react-start-config': workspace:* '@tanstack/react-start-plugin': workspace:* '@tanstack/eslint-plugin-router': workspace:* '@tanstack/server-functions-plugin': workspace:* @@ -3470,10 +3469,10 @@ importers: version: 19.0.3(@types/react@19.0.8) html-webpack-plugin: specifier: ^5.6.3 - version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1) + version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) swc-loader: specifier: ^0.2.6 - version: 0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1) + version: 0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) typescript: specifier: ^5.7.2 version: 5.8.2 @@ -5469,7 +5468,7 @@ importers: version: 7.0.6 html-webpack-plugin: specifier: ^5.6.0 - version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1) + version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) picocolors: specifier: ^1.1.1 version: 1.1.1 @@ -5481,7 +5480,7 @@ importers: version: 19.0.0(react@19.0.0) swc-loader: specifier: ^0.2.6 - version: 0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1) + version: 0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) tinyglobby: specifier: ^0.2.10 version: 0.2.12 @@ -5767,7 +5766,7 @@ importers: specifier: workspace:* version: link:../react-start-client '@tanstack/react-start-config': - specifier: workspace:* + specifier: workspace:^ version: link:../react-start-config '@tanstack/react-start-router-manifest': specifier: workspace:* @@ -6768,6 +6767,9 @@ importers: '@tanstack/react-start-client': specifier: workspace:* version: link:../react-start-client + '@tanstack/react-start-plugin': + specifier: workspace:* + version: link:../react-start-plugin '@tanstack/react-start-router-manifest': specifier: workspace:* version: link:../react-start-router-manifest @@ -6783,61 +6785,10 @@ importers: '@tanstack/react-start-server-functions-ssr': specifier: workspace:* version: link:../react-start-server-functions-ssr - '@tanstack/start-config': - specifier: workspace:^ - version: link:../start-config '@tanstack/start-server-functions-server': specifier: workspace:* version: link:../start-server-functions-server - packages/start-config: - dependencies: - '@tanstack/react-router': - specifier: workspace:* - version: link:../react-router - '@tanstack/react-start-plugin': - specifier: workspace:* - version: link:../react-start-plugin - '@tanstack/react-start-server-functions-handler': - specifier: workspace:* - version: link:../react-start-server-functions-handler - '@tanstack/router-generator': - specifier: workspace:* - version: link:../router-generator - '@tanstack/router-plugin': - specifier: workspace:* - version: link:../router-plugin - '@tanstack/server-functions-plugin': - specifier: workspace:* - version: link:../server-functions-plugin - '@vitejs/plugin-react': - specifier: ^4.3.4 - version: 4.3.4(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) - import-meta-resolve: - specifier: ^4.1.0 - version: 4.1.0 - nitropack: - specifier: ^2.10.4 - version: 2.10.4(typescript@5.8.2) - ofetch: - specifier: ^1.4.1 - version: 1.4.1 - react: - specifier: ^19.0.0 - version: 19.0.0 - react-dom: - specifier: ^19.0.0 - version: 19.0.0(react@19.0.0) - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) - vite: - specifier: 6.1.0 - version: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - zod: - specifier: ^3.24.1 - version: 3.24.1 - packages/start-server-functions-server: dependencies: '@tanstack/server-functions-plugin': @@ -18725,17 +18676,17 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.97.1)': + '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4))': dependencies: webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.97.1)': + '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4))': dependencies: webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.2.0)(webpack@5.97.1)': + '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack-dev-server@5.2.0(webpack-cli@5.1.4)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4))': dependencies: webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1) @@ -20702,7 +20653,7 @@ snapshots: html-tags@3.3.1: {} - html-webpack-plugin@5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1): + html-webpack-plugin@5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -23001,7 +22952,7 @@ snapshots: csso: 5.0.5 picocolors: 1.1.1 - swc-loader@0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1): + swc-loader@0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)): dependencies: '@swc/core': 1.10.15(@swc/helpers@0.5.15) '@swc/counter': 0.1.3 @@ -23091,26 +23042,26 @@ snapshots: type-fest: 2.19.0 unique-string: 3.0.0 - terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)): + terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.37.0 - webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0) + webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4) optionalDependencies: '@swc/core': 1.10.15(@swc/helpers@0.5.15) esbuild: 0.25.0 - terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack@5.97.1): + terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.37.0 - webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4) + webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0) optionalDependencies: '@swc/core': 1.10.15(@swc/helpers@0.5.15) esbuild: 0.25.0 @@ -23979,9 +23930,9 @@ snapshots: webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1): dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.97.1) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.97.1) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.2.0)(webpack@5.97.1) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack-dev-server@5.2.0(webpack-cli@5.1.4)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.6 @@ -23995,7 +23946,7 @@ snapshots: optionalDependencies: webpack-dev-server: 5.2.0(webpack-cli@5.1.4)(webpack@5.97.1) - webpack-dev-middleware@7.4.2(webpack@5.97.1): + webpack-dev-middleware@7.4.2(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)): dependencies: colorette: 2.0.20 memfs: 4.17.0 @@ -24033,7 +23984,7 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.2(webpack@5.97.1) + webpack-dev-middleware: 7.4.2(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) ws: 8.18.0 optionalDependencies: webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4) @@ -24108,7 +24059,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack@5.97.1) + terser-webpack-plugin: 5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: diff --git a/scripts/publish.js b/scripts/publish.js index fa381c0912..8d825110f7 100644 --- a/scripts/publish.js +++ b/scripts/publish.js @@ -156,14 +156,6 @@ await publish({ name: '@tanstack/react-start-server', packageDir: 'packages/react-start-server', }, - { - name: '@tanstack/start-config', - packageDir: 'packages/start-config', - }, - { - name: '@tanstack/react-start-config', - packageDir: 'packages/react-start-config', - }, { name: '@tanstack/react-start-api-routes', packageDir: 'packages/react-start-api-routes', From 4d130676e8f252619efeaae75defef9451d7059e Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Mon, 24 Feb 2025 22:01:42 -0700 Subject: [PATCH 005/155] initial --- examples/react/start-basic/package.json | 10 +- .../vite.config.timestamp_1740425668217.js | 15 + examples/react/start-basic/vite.config.ts | 5 +- packages/react-start-config/src/schema.ts | 249 +++++------- .../src/vinxi-file-router.ts | 3 + packages/react-start-plugin/package.json | 15 +- packages/react-start-plugin/src/index.ts | 369 ++++++++++-------- .../src/nitro/build-server.ts | 39 ++ .../src/nitro/build-sitemap.ts | 79 ++++ .../react-start-plugin/src/nitro/build-ssr.ts | 25 ++ .../src/nitro/hooks/post-rendering-hook.ts | 12 + .../nitro/hooks/post-rendering-hooks.spec.ts | 33 ++ .../src/nitro/nitro-plugin.ts | 257 ++++++++++++ .../react-start-plugin/src/nitro/options.ts | 80 ++++ .../src/nitro/plugins/dev-server-plugin.ts | 124 ++++++ .../src/nitro/utils/load-esm.ts | 27 ++ .../nitro/utils/register-dev-middleware.ts | 25 ++ .../src/nitro/vite-plugin-nitro.ts | 3 + .../src/routesManifestPlugin.ts | 172 ++++++++ packages/react-start-plugin/src/server-fns.ts | 178 +++++++++ packages/react-start-plugin/tsconfig.json | 5 +- pnpm-lock.yaml | 85 +++- 22 files changed, 1484 insertions(+), 326 deletions(-) create mode 100644 examples/react/start-basic/vite.config.timestamp_1740425668217.js create mode 100644 packages/react-start-plugin/src/nitro/build-server.ts create mode 100644 packages/react-start-plugin/src/nitro/build-sitemap.ts create mode 100644 packages/react-start-plugin/src/nitro/build-ssr.ts create mode 100644 packages/react-start-plugin/src/nitro/hooks/post-rendering-hook.ts create mode 100644 packages/react-start-plugin/src/nitro/hooks/post-rendering-hooks.spec.ts create mode 100644 packages/react-start-plugin/src/nitro/nitro-plugin.ts create mode 100644 packages/react-start-plugin/src/nitro/options.ts create mode 100644 packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts create mode 100644 packages/react-start-plugin/src/nitro/utils/load-esm.ts create mode 100644 packages/react-start-plugin/src/nitro/utils/register-dev-middleware.ts create mode 100644 packages/react-start-plugin/src/nitro/vite-plugin-nitro.ts create mode 100644 packages/react-start-plugin/src/routesManifestPlugin.ts create mode 100644 packages/react-start-plugin/src/server-fns.ts diff --git a/examples/react/start-basic/package.json b/examples/react/start-basic/package.json index 1a79a5a641..7f662fc169 100644 --- a/examples/react/start-basic/package.json +++ b/examples/react/start-basic/package.json @@ -4,9 +4,9 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" + "dev": "vite dev", + "build": "vite build", + "start": "vite start" }, "dependencies": { "@tanstack/react-router": "^1.114.3", @@ -16,14 +16,14 @@ "react-dom": "^19.0.0", "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", - "vinxi": "0.5.3" + "vite": "6.1.0" }, "devDependencies": { "@types/node": "^22.5.4", "@types/react": "^19.0.8", "@types/react-dom": "^19.0.3", - "postcss": "^8.5.1", "autoprefixer": "^10.4.20", + "postcss": "^8.5.1", "tailwindcss": "^3.4.17", "typescript": "^5.7.2", "vite-tsconfig-paths": "^5.1.4" diff --git a/examples/react/start-basic/vite.config.timestamp_1740425668217.js b/examples/react/start-basic/vite.config.timestamp_1740425668217.js new file mode 100644 index 0000000000..70db1b8430 --- /dev/null +++ b/examples/react/start-basic/vite.config.timestamp_1740425668217.js @@ -0,0 +1,15 @@ +// vite.config.ts +import { defineConfig } from "vite"; +import tsConfigPaths from "vite-tsconfig-paths"; +import { TanStackStartVitePlugin } from "@tanstack/start/plugin"; +var vite_config_default = defineConfig({ + plugins: [ + tsConfigPaths({ + projects: ["./tsconfig.json"] + }), + TanStackStartVitePlugin() + ] +}); +export { + vite_config_default as default +}; diff --git a/examples/react/start-basic/vite.config.ts b/examples/react/start-basic/vite.config.ts index 487b4bf09f..1bf4c44472 100644 --- a/examples/react/start-basic/vite.config.ts +++ b/examples/react/start-basic/vite.config.ts @@ -3,10 +3,13 @@ import tsConfigPaths from 'vite-tsconfig-paths' import { TanStackStartVitePlugin } from '@tanstack/start/plugin' export default defineConfig({ + server: { + port: 3000, + }, plugins: [ tsConfigPaths({ projects: ['./tsconfig.json'], }), - TanStackStartVitePlugin(), + TanStackStartVitePlugin({}), ], }) diff --git a/packages/react-start-config/src/schema.ts b/packages/react-start-config/src/schema.ts index 516e4e86fa..e0882a17d4 100644 --- a/packages/react-start-config/src/schema.ts +++ b/packages/react-start-config/src/schema.ts @@ -1,102 +1,10 @@ -import { configSchema } from '@tanstack/router-generator' +import path from 'node:path' +import { existsSync } from 'node:fs' import { z } from 'zod' -import type { PluginOption } from 'vite' -import type { AppOptions as VinxiAppOptions } from 'vinxi' -import type { NitroOptions } from 'nitropack' +import { configSchema, getConfig } from '@tanstack/router-generator' +import type { UserConfig } from 'vite' +import type { NitroConfig } from 'nitropack' import type { Options as ViteReactOptions } from '@vitejs/plugin-react' -import type { CustomizableConfig } from 'vinxi/dist/types/lib/vite-dev' - -type StartUserViteConfig = CustomizableConfig | (() => CustomizableConfig) - -export function getUserViteConfig(config?: StartUserViteConfig): { - plugins: Array | undefined - userConfig: CustomizableConfig -} { - const { plugins, ...userConfig } = - typeof config === 'function' ? config() : { ...config } - return { plugins, userConfig } -} - -/** - * Not all the deployment presets are fully functional or tested. - * @see https://github.com/TanStack/router/pull/2002 - */ -const vinxiDeploymentPresets = [ - 'alwaysdata', // untested - 'aws-amplify', // untested - 'aws-lambda', // untested - 'azure', // untested - 'azure-functions', // untested - 'base-worker', // untested - 'bun', // ✅ working - 'cleavr', // untested - 'cli', // untested - 'cloudflare', // untested - 'cloudflare-module', // untested - 'cloudflare-pages', // ✅ working - 'cloudflare-pages-static', // untested - 'deno', // untested - 'deno-deploy', // untested - 'deno-server', // untested - 'digital-ocean', // untested - 'edgio', // untested - 'firebase', // untested - 'flight-control', // untested - 'github-pages', // untested - 'heroku', // untested - 'iis', // untested - 'iis-handler', // untested - 'iis-node', // untested - 'koyeb', // untested - 'layer0', // untested - 'netlify', // ✅ working - 'netlify-builder', // untested - 'netlify-edge', // untested - 'netlify-static', // untested - 'nitro-dev', // untested - 'nitro-prerender', // untested - 'node', // partially working - 'node-cluster', // untested - 'node-server', // ✅ working - 'platform-sh', // untested - 'service-worker', // untested - 'static', // 🟧 partially working - 'stormkit', // untested - 'vercel', // ✅ working - 'vercel-edge', // untested - 'vercel-static', // untested - 'winterjs', // untested - 'zeabur', // untested - 'zeabur-static', // untested -] as const - -type DeploymentPreset = (typeof vinxiDeploymentPresets)[number] | (string & {}) - -const testedDeploymentPresets: Array = [ - 'bun', - 'netlify', - 'vercel', - 'cloudflare-pages', - 'node-server', -] - -export function checkDeploymentPresetInput(preset: string): DeploymentPreset { - if (!vinxiDeploymentPresets.includes(preset as any)) { - console.warn( - `Invalid deployment preset "${preset}". Available presets are: ${vinxiDeploymentPresets - .map((p) => `"${p}"`) - .join(', ')}.`, - ) - } - - if (!testedDeploymentPresets.includes(preset as any)) { - console.warn( - `The deployment preset '${preset}' is not fully supported yet and may not work as expected.`, - ) - } - - return preset -} type HTTPSOptions = { cert?: string @@ -107,88 +15,131 @@ type HTTPSOptions = { domains?: Array } -type ServerOptions_ = VinxiAppOptions['server'] & { +type ServerOptions = NitroConfig & { https?: boolean | HTTPSOptions } -type ServerOptions = { - [K in keyof ServerOptions_]: ServerOptions_[K] -} - -export const serverSchema = z - .object({ - routeRules: z.custom().optional(), - preset: z.custom().optional(), - static: z.boolean().optional(), - prerender: z - .object({ - routes: z.array(z.string()), - ignore: z - .array( - z.custom< - string | RegExp | ((path: string) => undefined | null | boolean) - >(), - ) - .optional(), - crawlLinks: z.boolean().optional(), - }) - .optional(), - }) - .and(z.custom()) +export const serverSchema = z.custom().and( + z.object({ + preset: z + .custom() + .optional() + .default('node-server'), + }), +) -const viteSchema = z.custom() +const viteSchema = z.custom() const viteReactSchema = z.custom() const routersSchema = z.object({ ssr: z .object({ - entry: z.string().optional(), - middleware: z.string().optional(), + entry: z.string().optional().default('ssr.tsx'), + // middleware: z.string().optional(), vite: viteSchema.optional(), }) - .optional(), + .optional() + .default({}), client: z .object({ - entry: z.string().optional(), - base: z.string().optional(), + entry: z.string().optional().default('client.tsx'), + base: z.string().optional().default('/_build'), vite: viteSchema.optional(), }) - .optional(), + .optional() + .default({}), server: z .object({ - base: z.string().optional(), - globalMiddlewareEntry: z.string().optional(), - middleware: z.string().optional(), + base: z.string().optional().default('/_server'), + globalMiddlewareEntry: z + .string() + .optional() + .default('global-middleware.ts'), + // middleware: z.string().optional(), vite: viteSchema.optional(), }) - .optional(), + .optional() + .default({}), api: z .object({ - entry: z.string().optional(), - middleware: z.string().optional(), + base: z.string().optional().default('/api'), + entry: z.string().optional().default('api.ts'), + // middleware: z.string().optional(), vite: viteSchema.optional(), }) - .optional(), + .optional() + .default({}), public: z .object({ - dir: z.string().optional(), - base: z.string().optional(), + dir: z.string().optional().default('public'), + base: z.string().optional().default('/'), }) - .optional(), + .optional() + .default({}), }) -const tsrConfig = configSchema.partial().extend({ - appDirectory: z.string().optional(), +const sitemapSchema = z.object({ + host: z.string(), }) -export const inlineConfigSchema = z.object({ - react: viteReactSchema.optional(), - vite: viteSchema.optional(), - tsr: tsrConfig.optional(), - routers: routersSchema.optional(), - server: serverSchema.optional(), +const tsrConfig = configSchema.partial().extend({ + // Normally these are `./src/___`, but we're using `./app/___` for Start stuff + appDirectory: z.string().optional().default('app'), }) -export type TanStackStartInputConfig = z.input -export type TanStackStartOutputConfig = z.infer +const TanStackStartOptionsSchema = z + .object({ + root: z.string().optional().default(process.cwd()), + react: viteReactSchema.optional(), + vite: viteSchema.optional(), + tsr: tsrConfig.optional().default({}), + routers: routersSchema.optional().default({}), + server: serverSchema.optional().default({}), + sitemap: sitemapSchema.optional(), + }) + .optional() + .default({}) + +export function getTanStackStartOptions(opts?: TanStackStartInputConfig) { + const options = TanStackStartOptionsSchema.parse(opts) + + const appDirectory = options.tsr.appDirectory + const routesDirectory = + options.tsr.routesDirectory ?? path.join(appDirectory, 'routes') + const generatedRouteTree = + options.tsr.generatedRouteTree ?? + path.join(appDirectory, 'routeTree.gen.ts') + const clientEntryPath = path.join(appDirectory, options.routers.client.entry) + const ssrEntryPath = path.join(appDirectory, options.routers.ssr.entry) + const apiEntryPath = path.join(appDirectory, options.routers.api.entry) + const globalMiddlewareEntryPath = path.join( + appDirectory, + options.routers.server.globalMiddlewareEntry, + ) + const hasApiEntry = existsSync(apiEntryPath) + + return { + ...options, + tsr: { + ...options.tsr, + ...getConfig({ + ...options.tsr, + routesDirectory, + generatedRouteTree, + }), + }, + clientEntryPath, + ssrEntryPath, + apiEntryPath, + globalMiddlewareEntryPath, + hasApiEntry, + } +} + +export type TanStackStartInputConfig = z.input< + typeof TanStackStartOptionsSchema +> +export type TanStackStartOutputConfig = ReturnType< + typeof getTanStackStartOptions +> diff --git a/packages/react-start-config/src/vinxi-file-router.ts b/packages/react-start-config/src/vinxi-file-router.ts index 9e6d829d1b..a60d71585c 100644 --- a/packages/react-start-config/src/vinxi-file-router.ts +++ b/packages/react-start-config/src/vinxi-file-router.ts @@ -1,3 +1,6 @@ +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-nocheck + import { BaseFileSystemRouter as VinxiBaseFileSystemRouter, analyzeModule as vinxiFsRouterAnalyzeModule, diff --git a/packages/react-start-plugin/package.json b/packages/react-start-plugin/package.json index 44bd491dcd..d932328a1c 100644 --- a/packages/react-start-plugin/package.json +++ b/packages/react-start-plugin/package.json @@ -72,7 +72,11 @@ "@babel/template": "^7.26.8", "@babel/traverse": "^7.26.8", "@babel/types": "^7.26.8", + "@tanstack/react-router": "workspace:^", + "@tanstack/router-generator": "workspace:^", + "@tanstack/router-plugin": "workspace:^", "@tanstack/router-utils": "workspace:^", + "@tanstack/server-functions-plugin": "workspace:^", "babel-dead-code-elimination": "^1.0.9", "tiny-invariant": "^1.3.3", "vite": "6.1.0" @@ -81,6 +85,15 @@ "@types/babel__code-frame": "^7.0.6", "@types/babel__core": "^7.20.5", "@types/babel__template": "^7.4.4", - "@types/babel__traverse": "^7.20.6" + "@types/babel__traverse": "^7.20.6", + "@vitejs/plugin-react": "^4.3.4", + "babel-dead-code-elimination": "^1.0.9", + "fast-glob": "^3.3.3", + "h3": "1.13.0", + "nitropack": "^2.10.4", + "tiny-invariant": "^1.3.3", + "vite": "6.1.0", + "xmlbuilder2": "^3.1.1", + "zod": "^3.24.2" } } diff --git a/packages/react-start-plugin/src/index.ts b/packages/react-start-plugin/src/index.ts index 4d08a9d165..a649b905f2 100644 --- a/packages/react-start-plugin/src/index.ts +++ b/packages/react-start-plugin/src/index.ts @@ -1,178 +1,215 @@ -import { fileURLToPath, pathToFileURL } from 'node:url' -import path from 'node:path' -import { logDiff } from '@tanstack/router-utils' -import { compileStartOutput } from './compilers' - -import type { Plugin } from 'vite' - -const debug = - process.env.TSR_VITE_DEBUG && - ['true', 'start-plugin'].includes(process.env.TSR_VITE_DEBUG) +// import { importMetaResolve } from 'import-meta-resolve' +// // @ts-expect-error +// import { serverComponents } from '@vinxi/server-components/plugin' -export type TanStackStartViteOptions = { - globalMiddlewareEntry: string -} +// import { tanstackStartVinxiFileRouter } from './vinxi-file-router.js' +import path from 'node:path' +import { createTanStackServerFnPlugin } from '@tanstack/server-functions-plugin' +import { mergeConfig, perEnvironmentPlugin } from 'vite' +import viteReact from '@vitejs/plugin-react' +import { createNitro } from 'nitropack' +import { TanStackRouterVite } from '@tanstack/router-plugin/vite' +import { createTanStackStartPlugin } from './server-fns.js' +import { getTanStackStartOptions } from './schema.js' +import { nitroPlugin } from './nitro/nitro-plugin.js' +import { tsrRoutesManifestPlugin } from './routesManifestPlugin.js' +import type { PluginOption } from 'vite' +import type { TanStackStartInputConfig } from './schema.js' + +export type { + TanStackStartInputConfig, + TanStackStartOutputConfig, +} from './schema.js' + +export function TanStackStartVitePlugin( + opts?: TanStackStartInputConfig, +): Array { + const options = getTanStackStartOptions(opts) + + const TanStackServerFnsPlugin = createTanStackServerFnPlugin({ + // This is the ID that will be available to look up and import + // our server function manifest and resolve its module + manifestVirtualImportId: 'tsr:server-fn-manifest', + client: { + getRuntimeCode: () => + `import { createClientRpc } from '@tanstack/start/server-functions-client'`, + replacer: (d) => + `createClientRpc('${d.functionId}', '${options.routers.server.base}')`, + }, + ssr: { + getRuntimeCode: () => + `import { createSsrRpc } from '@tanstack/start/server-functions-ssr'`, + replacer: (d) => + `createSsrRpc('${d.functionId}', '${options.routers.server.base}')`, + }, + server: { + getRuntimeCode: () => + `import { createServerRpc } from '@tanstack/start/server-functions-server'`, + replacer: (d) => + `createServerRpc('${d.functionId}', '${options.routers.server.base}', ${d.fn})`, + }, + }) + + const TanStackStartPlugin = createTanStackStartPlugin({ + globalMiddlewareEntry: options.routers.server.globalMiddlewareEntry, + }) + + const globalPlugins: Array = [ + { + name: 'tss-vite-config-client', + ...options.vite, + async config() { + // Create a dummy nitro app to get the resolved public output path + const dummyNitroApp = await createNitro({ + preset: options.server.preset, + compatibilityDate: '2024-12-01', + }) + + const nitroOutputPublicDir = dummyNitroApp.options.output.publicDir + await dummyNitroApp.close() -const transformFuncs = [ - 'createServerFn', - 'createMiddleware', - 'serverOnly', - 'clientOnly', - 'createIsomorphicFn', -] -const tokenRegex = new RegExp(transformFuncs.join('|')) -// const eitherFuncRegex = new RegExp( -// `(function ${transformFuncs.join('|function ')})`, -// ) - -export function createTanStackStartPlugin(opts: TanStackStartViteOptions): { - client: Array - ssr: Array - server: Array -} { - return { - client: [ - (() => { - let entry: string | null = null - let ROOT: string = process.cwd() return { - name: 'vite-plugin-tanstack-start-server-entry-client', - enforce: 'pre', - configResolved: (config) => { - ROOT = config.root - entry = path.resolve(ROOT, (config as any).router.handler) - - if (!entry) { - throw new Error('@tanstack/start-plugin: No server entry found!') - } + resolve: { + noExternal: [ + '@tanstack/start', + '@tanstack/start/server', + '@tanstack/start-client', + '@tanstack/start-server', + '@tanstack/start-server-functions-fetcher', + '@tanstack/start-server-functions-handler', + '@tanstack/start-server-functions-client', + '@tanstack/start-server-functions-ssr', + '@tanstack/start-server-functions-server', + '@tanstack/start-router-manifest', + '@tanstack/start-config', + '@tanstack/start-api-routes', + '@tanstack/server-functions-plugin', + 'tsr:routes-manifest', + 'tsr:server-fn-manifest', + ], }, - transform(code, id) { - if (entry && id.includes(entry)) { - return { - code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, - map: null, - } - } - return null - }, - } - })(), - TanStackStartServerFnsAndMiddleware({ ...opts, env: 'client' }), - ], - ssr: [ - (() => { - let entry: string | null = null - let ROOT: string = process.cwd() - return { - name: 'vite-plugin-tanstack-start-server-entry-ssr', - enforce: 'pre', - configResolved: (config) => { - ROOT = config.root - entry = path.resolve(ROOT, (config as any).router.handler) - - if (!entry) { - throw new Error('@tanstack/start-plugin: No server entry found!') - } + optimizeDeps: { + entries: [], + ...(options.vite?.optimizeDeps || {}), }, - transform(code, id) { - if (entry && id.includes(entry)) { - return { - code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, - map: null, - } - } - return null + define: { + ...(options.vite?.define || {}), + ...injectDefineEnv('TSS_PUBLIC_BASE', options.routers.public.base), + ...injectDefineEnv('TSS_CLIENT_BASE', options.routers.client.base), + ...injectDefineEnv('TSS_API_BASE', options.routers.server.base), + ...injectDefineEnv('TSS_OUTPUT_PUBLIC_DIR', nitroOutputPublicDir), }, } - })(), - TanStackStartServerFnsAndMiddleware({ ...opts, env: 'ssr' }), - ], - server: [ - (() => { - let entry: string | null = null - let ROOT: string = process.cwd() - return { - name: 'vite-plugin-tanstack-start-server-entry-server', - enforce: 'pre', - configResolved: (config) => { - ROOT = config.root - entry = path.resolve(ROOT, (config as any).router.handler) - - if (!entry) { - throw new Error('@tanstack/start-plugin: No server entry found!') - } - }, - transform(code, id) { - if (entry && id.includes(entry)) { - return { - code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, - map: null, - } - } - return null - }, + }, + configEnvironment(env, config) { + if (env === 'client') { + return mergeConfig(config, options.routers.client.vite || {}) } - })(), - TanStackStartServerFnsAndMiddleware({ ...opts, env: 'server' }), - ], - } -} -export function TanStackStartServerFnsAndMiddleware(opts: { - env: 'server' | 'ssr' | 'client' -}): Plugin { - let ROOT: string = process.cwd() + if (env === 'ssr') { + return mergeConfig(config, options.routers.ssr.vite || {}) + } - return { - name: 'vite-plugin-tanstack-start-create-server-fn', - enforce: 'pre', - configResolved: (config) => { - ROOT = config.root + return config + }, }, - transform(code, id) { - const url = pathToFileURL(id) - url.searchParams.delete('v') - id = fileURLToPath(url).replace(/\\/g, '/') - - const includesToken = tokenRegex.test(code) - // const includesEitherFunc = eitherFuncRegex.test(code) - - if ( - !includesToken - // includesEitherFunc - // /node_modules/.test(id) - ) { - return null - } - - if (code.includes('@react-refresh')) { - throw new Error( - `We detected that the '@vitejs/plugin-react' was passed before '@tanstack/start-plugin'. Please make sure that '@tanstack/router-vite-plugin' is passed before '@vitejs/plugin-react' and try again: -e.g. - -plugins: [ - TanStackStartVite(), // Place this before viteReact() - viteReact(), -] -`, - ) - } - - if (debug) console.info(`${opts.env} Compiling Start: `, id) - - const compiled = compileStartOutput({ - code, - root: ROOT, - filename: id, - env: opts.env, - }) - - if (debug) { - logDiff(code, compiled.code) - console.log('Output:\n', compiled.code + '\n\n') - } - - return compiled - }, - } + TanStackRouterVite({ + ...options.tsr, + enableRouteGeneration: true, + autoCodeSplitting: true, + }), + viteReact(options.react), + ] + + return [ + perEnvironmentPlugin('tanstack-start-plugin-client', (environment) => + environment.name === 'client' + ? TanStackStartPlugin.client + : TanStackStartPlugin.server, + ), + ...globalPlugins, + perEnvironmentPlugin( + 'tanstack-server-fns-plugin-client-server', + (environment) => + environment.name === 'client' + ? TanStackServerFnsPlugin.client + : TanStackServerFnsPlugin.server, + ), + perEnvironmentPlugin( + 'tanstack-router-manifest-plugin', + (environment) => + environment.name === 'ssr' && + tsrRoutesManifestPlugin({ + clientBase: options.routers.client.base, + tsrConfig: options.tsr, + }), + ), + nitroPlugin({ + ...options, + server: { + ...options.server, + handlers: [ + ...(options.hasApiEntry + ? [ + { + route: options.routers.api.base, + handler: path.join( + options.root, + options.tsr.appDirectory, + options.routers.api.entry, + ), + }, + ] + : []), + ], + }, + plugins: [ + TanStackStartPlugin.server, + ...globalPlugins, + TanStackServerFnsPlugin.server, + ], + }), + ] } + +// // Because Vinxi doesn't use the normal nitro dev server, it doesn't +// // supply $fetch during dev. We need to hook into the dev server creation, +// // nab the proper utils from the custom nitro instance that is used +// // during dev and supply the $fetch to app. +// // Hopefully and likely, this will just get removed when we move to +// // Nitro directly. +// vinxiApp.hooks.hook('app:dev:nitro:config', (devServer) => { +// vinxiApp.hooks.hook( +// 'app:dev:server:created', +// ({ devApp: { localFetch } }) => { +// const $fetch = createFetch({ +// fetch: localFetch, +// defaults: { +// baseURL: devServer.nitro.options.runtimeConfig.app.baseURL, +// }, +// }) + +// // @ts-expect-error +// globalThis.$fetch = $fetch +// }, +// ) +// }) + +// return vinxiApp + +function injectDefineEnv( + key: TKey, + value: TValue, +): { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } { + return { + [`process.env.${key}`]: JSON.stringify(value), + [`import.meta.env.${key}`]: JSON.stringify(value), + } as { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } +} + +// function isEmptyPrerenderRoutes(options?: Options): boolean { +// if (!options || isArrayWithElements(nitroConfig.prerender?.routes)) { +// return false +// } +// return !options.server.prerender?.routes +// } diff --git a/packages/react-start-plugin/src/nitro/build-server.ts b/packages/react-start-plugin/src/nitro/build-server.ts new file mode 100644 index 0000000000..052ffd66dc --- /dev/null +++ b/packages/react-start-plugin/src/nitro/build-server.ts @@ -0,0 +1,39 @@ +import { + build, + copyPublicAssets, + createNitro, + prepare, + prerender, +} from 'nitropack' + +import type { NitroConfig } from 'nitropack' + +export async function buildServer(nitroConfig: NitroConfig) { + const nitro = await createNitro({ + dev: false, + preset: process.env['BUILD_PRESET'], + ...nitroConfig, + }) + + // if (nitroConfig.prerender?.postRenderingHooks) { + // addPostRenderingHooks(nitro, nitroConfig.prerender.postRenderingHooks) + // } + + await prepare(nitro) + await copyPublicAssets(nitro) + + if ( + nitroConfig.prerender?.routes && + nitroConfig.prerender.routes.length > 0 + ) { + console.log(`Prerendering static pages...`) + await prerender(nitro) + } + + if (!nitroConfig.static) { + console.log('Building Server...') + await build(nitro) + } + + await nitro.close() +} diff --git a/packages/react-start-plugin/src/nitro/build-sitemap.ts b/packages/react-start-plugin/src/nitro/build-sitemap.ts new file mode 100644 index 0000000000..c06ed77d0e --- /dev/null +++ b/packages/react-start-plugin/src/nitro/build-sitemap.ts @@ -0,0 +1,79 @@ +import { writeFileSync } from 'node:fs' +import { resolve } from 'node:path' +import { create } from 'xmlbuilder2' +import type { XMLBuilder } from 'xmlbuilder2/lib/interfaces' + +export type PagesJson = { + page: string + lastMod: string +} + +export async function buildSitemap({ + host, + routes, + outputDir, +}: { + host: string + routes: Array | (() => Promise>) + outputDir: string +}) { + const routeList: Array = await optionHasRoutes(routes) + + if (routeList.length) { + const slash = checkSlash(host) + const sitemapData: Array = routeList.map((page: string) => ({ + page: `${host}${slash}${page.replace(/^\/+/g, '')}`, + lastMod: new Date().toISOString().split('T')[0]!, + })) + + const sitemap = createXml('urlset') + + for (const item of sitemapData) { + const page = sitemap.ele('url') + page.ele('loc').txt(item.page) + page.ele('lastmod').txt(item.lastMod) + } + + const mapPath = `${resolve(outputDir)}/sitemap.xml` + try { + console.log(`Writing sitemap at ${mapPath}`) + writeFileSync(mapPath, sitemap.end({ prettyPrint: true })) + } catch (e) { + console.error(`Unable to write file at ${mapPath}`, e) + } + } +} + +function createXml(elementName: 'urlset' | 'sitemapindex'): XMLBuilder { + return create({ version: '1.0', encoding: 'UTF-8' }) + .ele(elementName, { + xmlns: 'https://www.sitemaps.org/schemas/sitemap/0.9', + }) + .com(`This file was automatically generated by Analog.`) +} + +function checkSlash(host: string): string { + const finalChar = host.slice(-1) + return finalChar === '/' ? '' : '/' +} + +async function optionHasRoutes( + routes: + | Array + | (() => Promise>), +): Promise> { + let routeList: Array + + if (typeof routes === 'function') { + // returns an array or undefined + routeList = await routes() + } else if (Array.isArray(routes)) { + // returns an array of strings + routeList = routes + } else { + // default it to an empty of array + routeList = [] + } + + return routeList.filter(Boolean) as Array +} diff --git a/packages/react-start-plugin/src/nitro/build-ssr.ts b/packages/react-start-plugin/src/nitro/build-ssr.ts new file mode 100644 index 0000000000..ff2a769437 --- /dev/null +++ b/packages/react-start-plugin/src/nitro/build-ssr.ts @@ -0,0 +1,25 @@ +import { resolve } from 'node:path' +import { build, mergeConfig } from 'vite' +import type { UserConfig } from 'vite' + +export async function buildSSRApp({ + root, + viteConfig, + ssrEntry, +}: { + root: string + viteConfig: UserConfig + ssrEntry: string +}) { + const ssrBuildConfig = mergeConfig(viteConfig, { + build: { + ssr: true, + rollupOptions: { + input: ssrEntry, + }, + outDir: resolve(root, 'dist/ssr'), + }, + }) + + await build(ssrBuildConfig) +} diff --git a/packages/react-start-plugin/src/nitro/hooks/post-rendering-hook.ts b/packages/react-start-plugin/src/nitro/hooks/post-rendering-hook.ts new file mode 100644 index 0000000000..5bc1168c8f --- /dev/null +++ b/packages/react-start-plugin/src/nitro/hooks/post-rendering-hook.ts @@ -0,0 +1,12 @@ +import type { Nitro, PrerenderRoute } from 'nitropack' + +export function addPostRenderingHooks( + nitro: Nitro, + hooks: Array<(pr: PrerenderRoute) => Promise>, +): void { + hooks.forEach((hook: (preRoute: PrerenderRoute) => void) => { + nitro.hooks.hook('prerender:generate', (route: PrerenderRoute) => { + hook(route) + }) + }) +} diff --git a/packages/react-start-plugin/src/nitro/hooks/post-rendering-hooks.spec.ts b/packages/react-start-plugin/src/nitro/hooks/post-rendering-hooks.spec.ts new file mode 100644 index 0000000000..bda3dbc7f3 --- /dev/null +++ b/packages/react-start-plugin/src/nitro/hooks/post-rendering-hooks.spec.ts @@ -0,0 +1,33 @@ +import { describe, expect, it, vi } from 'vitest' + +import { addPostRenderingHooks } from './post-rendering-hook' +import type { Nitro } from 'nitropack' + +describe('postRenderingHook', () => { + const genRoute = { + route: 'test/testRoute', + contents: 'This is a test.', + } + + const nitroMock = { + hooks: { + hook: vi.fn((name: string, callback: (route: any) => void) => + callback(genRoute), + ), + }, + } as unknown as Nitro + + const mockFunc1 = vi.fn() + const mockFunc2 = vi.fn() + + it('should not attempt to call nitro mocks if no callbacks provided', () => { + addPostRenderingHooks(nitroMock, []) + expect(nitroMock.hooks.hook).not.toHaveBeenCalled() + }) + + it('should call provided hooks', () => { + addPostRenderingHooks(nitroMock, [mockFunc1, mockFunc2]) + expect(mockFunc1).toHaveBeenCalledWith(genRoute) + expect(mockFunc2).toHaveBeenCalled() + }) +}) diff --git a/packages/react-start-plugin/src/nitro/nitro-plugin.ts b/packages/react-start-plugin/src/nitro/nitro-plugin.ts new file mode 100644 index 0000000000..f620a9fff6 --- /dev/null +++ b/packages/react-start-plugin/src/nitro/nitro-plugin.ts @@ -0,0 +1,257 @@ +import { dirname, resolve } from 'node:path' +import { writeFileSync } from 'node:fs' +import { platform } from 'node:os' +import { fileURLToPath } from 'node:url' +import { build, createDevServer, createNitro } from 'nitropack' +import { normalizePath } from 'vite' + +import { buildServer } from './build-server.js' +import { buildSSRApp } from './build-ssr.js' +import { buildSitemap } from './build-sitemap.js' +import { devServerPlugin } from './plugins/dev-server-plugin.js' +import type { TanStackStartOutputConfig } from '../schema.js' +import type { NitroConfig } from 'nitropack' + +import type { PluginOption, UserConfig, ViteDevServer } from 'vite' + +export type { + TanStackStartInputConfig, + TanStackStartOutputConfig, +} from '../schema.js' + +const isWindows = platform() === 'win32' +const filePrefix = isWindows ? 'file:///' : '' +let clientOutputPath = '' + +const __filename = fileURLToPath( + // @ts-ignore Cannot figure out for the life of me why tsconfig.json won't let me fix this. Only shows up during build, not in editor. + import.meta.url, +) +const __dirname = dirname(__filename) + +export function nitroPlugin( + options: TanStackStartOutputConfig & { + plugins: Array + }, +): Array { + let isTest = process.env['NODE_ENV'] === 'test' || !!process.env['VITEST'] + + let isBuild = false + let isServe = false + let ssrBuild = false + let config: UserConfig + let nitroConfig: NitroConfig + let environmentBuild = false + + return [ + devServerPlugin(options), + { + name: 'tanstack-vite-plugin-nitro', + config(userConfig, { mode, command }) { + isServe = command === 'serve' + isBuild = command === 'build' + ssrBuild = userConfig.build?.ssr === true + config = userConfig + isTest = isTest ? isTest : mode === 'test' + + const buildPreset = + process.env['BUILD_PRESET'] ?? + (options.server.preset as string | undefined) + + const rendererEntry = + filePrefix + normalizePath(options.routers.ssr.entry) + + nitroConfig = { + ...options.server, + preset: buildPreset, + compatibilityDate: '2024-11-19', + logLevel: options.server.logLevel || 0, + srcDir: normalizePath(options.tsr.appDirectory), + typescript: { + generateTsConfig: false, + }, + rollupConfig: { + onwarn(warning) { + if ( + warning.message.includes('empty chunk') && + warning.message.endsWith('.server') + ) { + return + } + }, + plugins: options.plugins, + }, + handlers: [], + } + + if (!ssrBuild && !isTest) { + // store the client output path for the SSR build config + clientOutputPath = resolve( + options.root, + config.build?.outDir || 'dist/client', + ) + } + + nitroConfig.alias = { + '#start/ssr': options.ssrEntryPath, + } + + if (isBuild) { + nitroConfig.publicAssets = [{ dir: clientOutputPath }] + nitroConfig.serverAssets = [ + { + baseName: 'public', + dir: clientOutputPath, + }, + ] + nitroConfig.renderer = rendererEntry + + if (ssrBuild) { + if (isWindows) { + // Write out the renderer manually because + // Windows doesn't resolve the aliases + // correctly in its native environment + writeFileSync( + normalizePath(rendererEntry.replace(filePrefix, '')), + ` + /** + * This file is shipped as ESM for Windows support, + * as it won't resolve the renderer.ts file correctly in node. + */ + import ssrEntry from '${options.ssrEntryPath}'; + export default ssrEntry + `, + ) + + nitroConfig.externals = { + inline: ['std-env'], + } + } + + nitroConfig = { + ...nitroConfig, + externals: { + ...nitroConfig.externals, + external: ['node-fetch-native/dist/polyfill'], + }, + // moduleSideEffects: [], + handlers: [], + } + } + } + + return { + environments: { + ssr: { + build: { + ssr: true, + rollupOptions: { + input: options.ssrEntryPath, + }, + outDir: resolve(options.root, 'dist/ssr'), + }, + }, + }, + builder: { + sharedPlugins: true, + buildApp: async (builder) => { + environmentBuild = true + + if (!builder.environments['client']) { + throw new Error('Client environment not found') + } + + if (!builder.environments['ssr']) { + throw new Error('SSR environment not found') + } + + await Promise.all([ + builder.build(builder.environments['client']), + builder.build(builder.environments['ssr']), + ]) + + await buildServer(nitroConfig) + + if (nitroConfig.prerender?.routes?.length && options.sitemap) { + console.log('Building Sitemap...') + // sitemap needs to be built after all directories are built + await buildSitemap({ + host: options.sitemap.host, + routes: nitroConfig.prerender.routes, + outputDir: resolve(options.root, 'dist/public'), + }) + } + + console.log( + `\n\nThe 'tanstack-platform' server has been successfully built.`, + ) + }, + }, + } + }, + async configureServer(viteServer: ViteDevServer) { + if (isServe && !isTest) { + const nitro = await createNitro({ + dev: true, + ...nitroConfig, + }) + const server = createDevServer(nitro) + + await build(nitro) + + // viteServer.middlewares.use( + // apiBase, + // toNodeListener(server.app as unknown as App), + // ) + + viteServer.httpServer?.once('listening', () => { + process.env['START_HOST'] = !viteServer.config.server.host + ? 'localhost' + : (viteServer.config.server.host as string) + process.env['START_PORT'] = `${viteServer.config.server.port}` + }) + + // handle upgrades if websockets are enabled + if (nitroConfig.experimental?.websocket) { + viteServer.httpServer?.on('upgrade', server.upgrade) + } + } + }, + async closeBundle() { + // Skip when build is triggered by the Environment API + if (environmentBuild) { + return + } + + if (ssrBuild) { + return + } + + if (isBuild) { + console.log('Building SSR application...') + await buildSSRApp({ + root: options.root, + ssrEntry: options.ssrEntryPath, + viteConfig: config, + }) + + if (options.sitemap) { + console.log('Building Sitemap...') + // sitemap needs to be built after all directories are built + await buildSitemap({ + host: options.sitemap.host, + routes: nitroConfig.prerender?.routes || [], // TODO: Can we get these routes from the final crawled routes from prerender? + outputDir: resolve(options.root, 'dist/public'), + }) + } + + await buildServer(nitroConfig) + + console.log( + `\n\nThe 'tanstack-platform' server has been successfully built.`, + ) + } + }, + }, + ] +} diff --git a/packages/react-start-plugin/src/nitro/options.ts b/packages/react-start-plugin/src/nitro/options.ts new file mode 100644 index 0000000000..d250d3e2ec --- /dev/null +++ b/packages/react-start-plugin/src/nitro/options.ts @@ -0,0 +1,80 @@ +import { PrerenderRoute } from 'nitropack'; + +export interface Options { + ssr?: boolean; + ssrBuildDir?: string; + /** + * Prerender the static pages without producing the server output. + */ + static?: boolean; + prerender?: PrerenderOptions; + entryServer?: string; + index?: string; + workspaceRoot?: string; + /** + * Additional page paths to include + */ + additionalPagesDirs?: string[]; + /** + * Additional API paths to include + */ + additionalAPIDirs?: string[]; + apiPrefix?: string; + + /** + * Toggles internal API middleware. + * If disabled, a proxy request is used to route /api + * requests to / in the production server build. + */ + useAPIMiddleware?: boolean; +} + +export interface PrerenderOptions { + /** + * Add additional routes to prerender through crawling page links. + */ + discover?: boolean; + + /** + * List of routes to prerender resolved statically or dynamically. + */ + routes?: + | (string | PrerenderContentDir)[] + | (() => Promise<(string | PrerenderContentDir | undefined)[]>); + sitemap?: SitemapConfig; + /** List of functions that run for each route after pre-rendering is complete. */ + postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[]; +} + +export interface SitemapConfig { + host: string; +} + +export interface PrerenderContentDir { + /** + * The directory where files should be grabbed from. + * @example `/src/contents/blog` + */ + contentDir: string; + /** + * Transform the matching content files path into a route. + * The function is called for each matching content file within the specified contentDir. + * @param file information of the matching file (`path`, `name`, `extension`, `attributes`) + * @returns a string with the route should be returned (e. g. `/blog/`) or the value `false`, when the route should not be prerendered. + */ + transform: (file: PrerenderContentFile) => string | false; +} + +/** + * @param path the path to the content file + * @param name the basename of the matching content file without the file extension + * @param extension the file extension + * @param attributes the frontmatter attributes extracted from the frontmatter section of the file + * @returns a string with the route should be returned (e. g. `/blog/`) or the value `false`, when the route should not be prerendered. + */ +export interface PrerenderContentFile { + path: string; + attributes: Record; + name: string; + extension: string; +} diff --git a/packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts b/packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts new file mode 100644 index 0000000000..912361c336 --- /dev/null +++ b/packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts @@ -0,0 +1,124 @@ +// SSR dev server, middleware and error page source modified from +// https://github.com/solidjs/solid-start/blob/main/packages/start/dev/server.js + +import { createEvent, sendWebResponse } from 'h3' + +import { registerDevServerMiddleware } from '../utils/register-dev-middleware.js' +import type { Connect, Plugin, ViteDevServer } from 'vite' +import type { TanStackStartOutputConfig } from '../../schema.js' + +export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { + // let config: UserConfig + let isTest = false + + return { + name: 'startjs-dev-ssr-plugin', + config(userConfig, { mode }) { + // config = userConfig + isTest = isTest ? isTest : mode === 'test' + return { + resolve: { + alias: { + '~start/ssr-entry': options.ssrEntryPath, + }, + }, + } + }, + configureServer(viteServer) { + if (isTest) { + return + } + + return () => { + remove_html_middlewares(viteServer.middlewares) + registerDevServerMiddleware(options.root, viteServer) + + viteServer.middlewares.use(async (req, res) => { + const template = await viteServer.transformIndexHtml( + req.originalUrl as string, + ` + + + `, + ) + + console.log('template, maybe use?', template) + + try { + const serverEntry = ( + await viteServer.ssrLoadModule('~start/ssr-entry') + )['default'] + const event = createEvent(req, res) + const result: string | Response = await serverEntry(event) + + if (result instanceof Response) { + sendWebResponse(event, result) + return + } + res.setHeader('Content-Type', 'text/html') + res.end(result) + } catch (e) { + viteServer.ssrFixStacktrace(e as Error) + res.statusCode = 500 + res.end(` + + + + + Error + + + + + + `) + } + }) + } + }, + } +} + +/** + * Removes Vite internal middleware + * + * @param server + */ +function remove_html_middlewares(server: ViteDevServer['middlewares']) { + const html_middlewares = [ + 'viteIndexHtmlMiddleware', + 'vite404Middleware', + 'viteSpaFallbackMiddleware', + ] + for (let i = server.stack.length - 1; i > 0; i--) { + if ( + html_middlewares.includes( + // @ts-expect-error + server.stack[i].handle.name, + ) + ) { + server.stack.splice(i, 1) + } + } +} + +/** + * Formats error for SSR message in error overlay + * @param req + * @param error + * @returns + */ +function prepareError(req: Connect.IncomingMessage, error: unknown) { + const e = error as Error + return { + message: `An error occured while server rendering ${req.url}:\n\n\t${ + typeof e === 'string' ? e : e.message + } `, + stack: typeof e === 'string' ? '' : e.stack, + } +} diff --git a/packages/react-start-plugin/src/nitro/utils/load-esm.ts b/packages/react-start-plugin/src/nitro/utils/load-esm.ts new file mode 100644 index 0000000000..f9a76f683e --- /dev/null +++ b/packages/react-start-plugin/src/nitro/utils/load-esm.ts @@ -0,0 +1,27 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { URL } from 'node:url'; + +/** + * This uses a dynamic import to load a module which may be ESM. + * CommonJS code can load ESM code via a dynamic import. Unfortunately, TypeScript + * will currently, unconditionally downlevel dynamic import into a require call. + * require calls cannot load ESM code and will result in a runtime error. To workaround + * this, a Function constructor is used to prevent TypeScript from changing the dynamic import. + * Once TypeScript provides support for keeping the dynamic import this workaround can + * be dropped. + * + * @param modulePath The path of the module to load. + * @returns A Promise that resolves to the dynamically imported module. + */ +export function loadEsmModule(modulePath: string | URL): Promise { + return new Function('modulePath', `return import(modulePath);`)( + modulePath, + ) as Promise; +} diff --git a/packages/react-start-plugin/src/nitro/utils/register-dev-middleware.ts b/packages/react-start-plugin/src/nitro/utils/register-dev-middleware.ts new file mode 100644 index 0000000000..78d1389515 --- /dev/null +++ b/packages/react-start-plugin/src/nitro/utils/register-dev-middleware.ts @@ -0,0 +1,25 @@ +import { createEvent } from 'h3' +import fg from 'fast-glob' +import type { ViteDevServer } from 'vite' +import type { EventHandler } from 'h3' + +export function registerDevServerMiddleware( + root: string, + viteServer: ViteDevServer, +) { + const middlewareFiles = fg.sync([`${root}/src/server/middleware/**/*.ts`]) + + middlewareFiles.forEach((file) => { + viteServer.middlewares.use(async (req, res, next) => { + const middlewareHandler: EventHandler = await viteServer + .ssrLoadModule(file) + .then((m: unknown) => (m as { default: EventHandler }).default) + + const result = await middlewareHandler(createEvent(req, res)) + + if (!result) { + next() + } + }) + }) +} diff --git a/packages/react-start-plugin/src/nitro/vite-plugin-nitro.ts b/packages/react-start-plugin/src/nitro/vite-plugin-nitro.ts new file mode 100644 index 0000000000..b28b04f643 --- /dev/null +++ b/packages/react-start-plugin/src/nitro/vite-plugin-nitro.ts @@ -0,0 +1,3 @@ + + + diff --git a/packages/react-start-plugin/src/routesManifestPlugin.ts b/packages/react-start-plugin/src/routesManifestPlugin.ts new file mode 100644 index 0000000000..0fde46ec3c --- /dev/null +++ b/packages/react-start-plugin/src/routesManifestPlugin.ts @@ -0,0 +1,172 @@ +import { readFileSync } from 'node:fs' +import path from 'node:path' +import type { configSchema } from '@tanstack/router-generator' +import type { PluginOption, ResolvedConfig } from 'vite' +import type { z } from 'zod' +import type { Manifest } from '@tanstack/react-router' + +export function tsrRoutesManifestPlugin(opts: { + tsrConfig: z.infer + clientBase: string +}): PluginOption { + let config: ResolvedConfig + + return { + name: 'tsr-routes-manifest', + configResolved(resolvedConfig) { + config = resolvedConfig + }, + resolveId(id) { + if (id === 'tsr:routes-manifest') { + return id + } + return + }, + load(id) { + if (id === 'tsr:routes-manifest') { + // If we're in development, return a dummy manifest + + if (config.command === 'serve') { + return `export default () => ({ + routes: {} + })` + } + + const clientViteManifestPath = path.resolve( + config.build.outDir, + `../client/${opts.clientBase}/.vite/manifest.json`, + ) + + type ViteManifest = Record< + string, + { + file: string + isEntry: boolean + imports: Array + } + > + + let manifest: ViteManifest + try { + manifest = JSON.parse(readFileSync(clientViteManifestPath, 'utf-8')) + } catch (err) { + console.error(err) + throw new Error( + `Could not find the production client vite manifest at '${clientViteManifestPath}'!`, + ) + } + + const routeTreePath = path.resolve(opts.tsrConfig.generatedRouteTree) + + let routeTreeContent: string + try { + routeTreeContent = readFileSync(routeTreePath, 'utf-8') + } catch (err) { + console.error(err) + throw new Error( + `Could not find the generated route tree at '${routeTreePath}'!`, + ) + } + + // Extract the routesManifest JSON from the route tree file. + // It's located between the /* ROUTE_MANIFEST_START and ROUTE_MANIFEST_END */ comment block. + + const routerManifest = JSON.parse( + routeTreeContent.match( + /\/\* ROUTE_MANIFEST_START([\s\S]*?)ROUTE_MANIFEST_END \*\//, + )?.[1] || '{ routes: {} }', + ) as Manifest + + const routes = routerManifest.routes + + let entryFile: + | { + file: string + imports: Array + } + | undefined + + const filesByRouteFilePath: ViteManifest = Object.fromEntries( + Object.entries(manifest).map(([k, v]) => { + if (v.isEntry) { + entryFile = v + } + + const rPath = k.split('?')[0] + + return [rPath, v] + }, {}), + ) + + // Add preloads to the routes from the vite manifest + Object.entries(routes).forEach(([k, v]) => { + const file = + filesByRouteFilePath[ + path.join(opts.tsrConfig.routesDirectory, v.filePath as string) + ] + + if (file) { + const preloads = file.imports.map((d) => + path.join(opts.clientBase, manifest[d]!.file), + ) + + preloads.unshift(path.join(opts.clientBase, file.file)) + + routes[k] = { + ...v, + preloads, + } + } + }) + + if (entryFile) { + routes.__root__!.preloads = [ + path.join(opts.clientBase, entryFile.file), + ...entryFile.imports.map((d) => + path.join(opts.clientBase, manifest[d]!.file), + ), + ] + } + + const recurseRoute = ( + route: { + preloads?: Array + children?: Array + }, + seenPreloads = {} as Record, + ) => { + route.preloads = route.preloads?.filter((preload) => { + if (seenPreloads[preload]) { + return false + } + seenPreloads[preload] = true + return true + }) + + if (route.children) { + route.children.forEach((child) => { + const childRoute = routes[child]! + recurseRoute(childRoute, { ...seenPreloads }) + }) + } + } + + // @ts-expect-error + recurseRoute(routes.__root__) + + const routesManifest = { + routes, + } + + if (process.env.TSR_VITE_DEBUG) { + console.info( + 'Routes Manifest: \n' + JSON.stringify(routesManifest, null, 2), + ) + } + + return `export default () => (${JSON.stringify(routesManifest)})` + } + return + }, + } +} diff --git a/packages/react-start-plugin/src/server-fns.ts b/packages/react-start-plugin/src/server-fns.ts new file mode 100644 index 0000000000..4d08a9d165 --- /dev/null +++ b/packages/react-start-plugin/src/server-fns.ts @@ -0,0 +1,178 @@ +import { fileURLToPath, pathToFileURL } from 'node:url' +import path from 'node:path' +import { logDiff } from '@tanstack/router-utils' +import { compileStartOutput } from './compilers' + +import type { Plugin } from 'vite' + +const debug = + process.env.TSR_VITE_DEBUG && + ['true', 'start-plugin'].includes(process.env.TSR_VITE_DEBUG) + +export type TanStackStartViteOptions = { + globalMiddlewareEntry: string +} + +const transformFuncs = [ + 'createServerFn', + 'createMiddleware', + 'serverOnly', + 'clientOnly', + 'createIsomorphicFn', +] +const tokenRegex = new RegExp(transformFuncs.join('|')) +// const eitherFuncRegex = new RegExp( +// `(function ${transformFuncs.join('|function ')})`, +// ) + +export function createTanStackStartPlugin(opts: TanStackStartViteOptions): { + client: Array + ssr: Array + server: Array +} { + return { + client: [ + (() => { + let entry: string | null = null + let ROOT: string = process.cwd() + return { + name: 'vite-plugin-tanstack-start-server-entry-client', + enforce: 'pre', + configResolved: (config) => { + ROOT = config.root + entry = path.resolve(ROOT, (config as any).router.handler) + + if (!entry) { + throw new Error('@tanstack/start-plugin: No server entry found!') + } + }, + transform(code, id) { + if (entry && id.includes(entry)) { + return { + code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, + map: null, + } + } + return null + }, + } + })(), + TanStackStartServerFnsAndMiddleware({ ...opts, env: 'client' }), + ], + ssr: [ + (() => { + let entry: string | null = null + let ROOT: string = process.cwd() + return { + name: 'vite-plugin-tanstack-start-server-entry-ssr', + enforce: 'pre', + configResolved: (config) => { + ROOT = config.root + entry = path.resolve(ROOT, (config as any).router.handler) + + if (!entry) { + throw new Error('@tanstack/start-plugin: No server entry found!') + } + }, + transform(code, id) { + if (entry && id.includes(entry)) { + return { + code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, + map: null, + } + } + return null + }, + } + })(), + TanStackStartServerFnsAndMiddleware({ ...opts, env: 'ssr' }), + ], + server: [ + (() => { + let entry: string | null = null + let ROOT: string = process.cwd() + return { + name: 'vite-plugin-tanstack-start-server-entry-server', + enforce: 'pre', + configResolved: (config) => { + ROOT = config.root + entry = path.resolve(ROOT, (config as any).router.handler) + + if (!entry) { + throw new Error('@tanstack/start-plugin: No server entry found!') + } + }, + transform(code, id) { + if (entry && id.includes(entry)) { + return { + code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, + map: null, + } + } + return null + }, + } + })(), + TanStackStartServerFnsAndMiddleware({ ...opts, env: 'server' }), + ], + } +} + +export function TanStackStartServerFnsAndMiddleware(opts: { + env: 'server' | 'ssr' | 'client' +}): Plugin { + let ROOT: string = process.cwd() + + return { + name: 'vite-plugin-tanstack-start-create-server-fn', + enforce: 'pre', + configResolved: (config) => { + ROOT = config.root + }, + transform(code, id) { + const url = pathToFileURL(id) + url.searchParams.delete('v') + id = fileURLToPath(url).replace(/\\/g, '/') + + const includesToken = tokenRegex.test(code) + // const includesEitherFunc = eitherFuncRegex.test(code) + + if ( + !includesToken + // includesEitherFunc + // /node_modules/.test(id) + ) { + return null + } + + if (code.includes('@react-refresh')) { + throw new Error( + `We detected that the '@vitejs/plugin-react' was passed before '@tanstack/start-plugin'. Please make sure that '@tanstack/router-vite-plugin' is passed before '@vitejs/plugin-react' and try again: +e.g. + +plugins: [ + TanStackStartVite(), // Place this before viteReact() + viteReact(), +] +`, + ) + } + + if (debug) console.info(`${opts.env} Compiling Start: `, id) + + const compiled = compileStartOutput({ + code, + root: ROOT, + filename: id, + env: opts.env, + }) + + if (debug) { + logDiff(code, compiled.code) + console.log('Output:\n', compiled.code + '\n\n') + } + + return compiled + }, + } +} diff --git a/packages/react-start-plugin/tsconfig.json b/packages/react-start-plugin/tsconfig.json index 37d21ef6ca..6c8c904b07 100644 --- a/packages/react-start-plugin/tsconfig.json +++ b/packages/react-start-plugin/tsconfig.json @@ -3,6 +3,9 @@ "include": ["src", "vite.config.ts", "tests"], "exclude": ["tests/**/test-files/**", "tests/**/snapshots/**"], "compilerOptions": { - "jsx": "react-jsx" + "rootDir": "src", + "outDir": "dist/esm", + "target": "esnext", + "noEmit": false } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f4d98db7ef..5e6cf54032 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4203,9 +4203,9 @@ importers: tailwind-merge: specifier: ^2.6.0 version: 2.6.0 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) + vite: + specifier: 6.1.0 + version: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) devDependencies: '@types/node': specifier: ^22.5.4 @@ -5927,9 +5927,21 @@ importers: '@babel/types': specifier: ^7.26.8 version: 7.26.8 + '@tanstack/react-router': + specifier: workspace:* + version: link:../react-router + '@tanstack/router-generator': + specifier: workspace:* + version: link:../router-generator + '@tanstack/router-plugin': + specifier: workspace:* + version: link:../router-plugin '@tanstack/router-utils': specifier: workspace:* version: link:../router-utils + '@tanstack/server-functions-plugin': + specifier: workspace:* + version: link:../server-functions-plugin babel-dead-code-elimination: specifier: ^1.0.9 version: 1.0.9 @@ -5952,6 +5964,24 @@ importers: '@types/babel__traverse': specifier: ^7.20.6 version: 7.20.6 + '@vitejs/plugin-react': + specifier: ^4.3.4 + version: 4.3.4(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) + fast-glob: + specifier: ^3.3.3 + version: 3.3.3 + h3: + specifier: 1.13.0 + version: 1.13.0 + nitropack: + specifier: ^2.10.4 + version: 2.10.4(typescript@5.7.3) + xmlbuilder2: + specifier: ^3.1.1 + version: 3.1.1 + zod: + specifier: ^3.24.2 + version: 3.24.2 packages/react-start-router-manifest: dependencies: @@ -8619,6 +8649,22 @@ packages: cpu: [x64] os: [win32] + '@oozcitak/dom@1.15.10': + resolution: {integrity: sha512-0JT29/LaxVgRcGKvHmSrUTEvZ8BXvZhGl2LASRUgHqDTC1M5g1pLmVv56IYNyt3bG2CUjDkc67wnyZC14pbQrQ==} + engines: {node: '>=8.0'} + + '@oozcitak/infra@1.0.8': + resolution: {integrity: sha512-JRAUc9VR6IGHOL7OGF+yrvs0LO8SlqGnPAMqyzOuFZPSZSXI7Xf2O9+awQPSMXgIWGtgUf/dA6Hs6X6ySEaWTg==} + engines: {node: '>=6.0'} + + '@oozcitak/url@1.0.4': + resolution: {integrity: sha512-kDcD8y+y3FCSOvnBI6HJgl00viO/nGbQoCINmQ0h98OhnGITrWR3bOGfwYCthgcrV8AnTJz8MzslTQbC3SOAmw==} + engines: {node: '>=8.0'} + + '@oozcitak/util@8.3.8': + resolution: {integrity: sha512-T8TbSnGsxo6TDBJx/Sgv/BlVJL3tshxZP7Aq5R1mSnM5OcHY2dQaxLMu2+E8u3gN0MLOzdjurqN4ZRVuzQycOQ==} + engines: {node: '>=8.0'} + '@open-draft/deferred-promise@2.2.0': resolution: {integrity: sha512-CecwLWx3rhxVQF6V4bAgPS5t+So2sTbPgAzafKkVizyi7tlwpcFpdFqq+wqF2OwNBmqFuu6tOyouTuxgpMfzmA==} @@ -14999,6 +15045,10 @@ packages: resolution: {integrity: sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==} engines: {node: '>=18'} + xmlbuilder2@3.1.1: + resolution: {integrity: sha512-WCSfbfZnQDdLQLiMdGUQpMxxckeQ4oZNMNhLVkcekTu7xhD4tuUDyAPoY8CwXvBYE6LwBHd6QW2WZXlOWr1vCw==} + engines: {node: '>=12.0'} + xmlchars@2.2.0: resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} @@ -15067,6 +15117,9 @@ packages: zod@3.24.1: resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} + zod@3.24.2: + resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} + snapshots: '@adobe/css-tools@4.4.1': {} @@ -16881,6 +16934,23 @@ snapshots: '@nx/nx-win32-x64-msvc@20.4.2': optional: true + '@oozcitak/dom@1.15.10': + dependencies: + '@oozcitak/infra': 1.0.8 + '@oozcitak/url': 1.0.4 + '@oozcitak/util': 8.3.8 + + '@oozcitak/infra@1.0.8': + dependencies: + '@oozcitak/util': 8.3.8 + + '@oozcitak/url@1.0.4': + dependencies: + '@oozcitak/infra': 1.0.8 + '@oozcitak/util': 8.3.8 + + '@oozcitak/util@8.3.8': {} + '@open-draft/deferred-promise@2.2.0': {} '@open-draft/logger@0.3.0': @@ -24146,6 +24216,13 @@ snapshots: xml-name-validator@5.0.0: {} + xmlbuilder2@3.1.1: + dependencies: + '@oozcitak/dom': 1.15.10 + '@oozcitak/infra': 1.0.8 + '@oozcitak/util': 8.3.8 + js-yaml: 3.14.1 + xmlchars@2.2.0: {} y18n@5.0.8: {} @@ -24203,3 +24280,5 @@ snapshots: readable-stream: 4.7.0 zod@3.24.1: {} + + zod@3.24.2: {} From 5a3da487a8e4aa3971dc512b0c9568d72f971703 Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Wed, 26 Feb 2025 01:43:07 +1300 Subject: [PATCH 006/155] chore: gitignore timestamp files --- .gitignore | 2 ++ .../vite.config.timestamp_1740425668217.js | 15 --------------- 2 files changed, 2 insertions(+), 15 deletions(-) delete mode 100644 examples/react/start-basic/vite.config.timestamp_1740425668217.js diff --git a/.gitignore b/.gitignore index 5cc3e94113..36785455d3 100644 --- a/.gitignore +++ b/.gitignore @@ -61,12 +61,14 @@ nx-cloud.env gpt/db.json app.config.timestamp-* +vite.config.timestamp-* vite.config.js.timestamp-* vite.config.ts.timestamp-* app.config.js.timestamp-* app.config.ts.timestamp-* app.config.timestamp_* +vite.config.timestamp_* vite.config.js.timestamp_* vite.config.ts.timestamp_* app.config.js.timestamp_* diff --git a/examples/react/start-basic/vite.config.timestamp_1740425668217.js b/examples/react/start-basic/vite.config.timestamp_1740425668217.js deleted file mode 100644 index 70db1b8430..0000000000 --- a/examples/react/start-basic/vite.config.timestamp_1740425668217.js +++ /dev/null @@ -1,15 +0,0 @@ -// vite.config.ts -import { defineConfig } from "vite"; -import tsConfigPaths from "vite-tsconfig-paths"; -import { TanStackStartVitePlugin } from "@tanstack/start/plugin"; -var vite_config_default = defineConfig({ - plugins: [ - tsConfigPaths({ - projects: ["./tsconfig.json"] - }), - TanStackStartVitePlugin() - ] -}); -export { - vite_config_default as default -}; From e8c6f189bd4e31ce8789744380d099c720470e6f Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 26 Feb 2025 00:15:55 +0100 Subject: [PATCH 007/155] remove react-start-config --- .github/labeler.yml | 2 - packages/react-start-config/README.md | 33 - packages/react-start-config/eslint.config.js | 31 - packages/react-start-config/package.json | 73 -- packages/react-start-config/src/index.ts | 665 ------------------ packages/react-start-config/src/schema.ts | 145 ---- .../src/vinxi-file-router.ts | 90 --- packages/react-start-config/tsconfig.json | 10 - packages/react-start/src/config.tsx | 1 - packages/react-start/vite.config.ts | 2 - 10 files changed, 1052 deletions(-) delete mode 100644 packages/react-start-config/README.md delete mode 100644 packages/react-start-config/eslint.config.js delete mode 100644 packages/react-start-config/package.json delete mode 100644 packages/react-start-config/src/index.ts delete mode 100644 packages/react-start-config/src/schema.ts delete mode 100644 packages/react-start-config/src/vinxi-file-router.ts delete mode 100644 packages/react-start-config/tsconfig.json delete mode 100644 packages/react-start/src/config.tsx diff --git a/.github/labeler.yml b/.github/labeler.yml index 76b074f192..b71b1f4c35 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -22,8 +22,6 @@ - 'packages/react-start-api-routes/**/*' 'package: react-start-client': - 'packages/react-start-client/**/*' -'package: react-start-config': - - 'packages/react-start-config/**/*' 'package: react-start-plugin': - 'packages/react-start-plugin/**/*' 'package: react-start-router-manifest': diff --git a/packages/react-start-config/README.md b/packages/react-start-config/README.md deleted file mode 100644 index bb009b0c87..0000000000 --- a/packages/react-start-config/README.md +++ /dev/null @@ -1,33 +0,0 @@ -> 🤫 we're cooking up something special! - - - -# TanStack Start - -![TanStack Router Header](https://github.com/tanstack/router/raw/main/media/header.png) - -🤖 Type-safe router w/ built-in caching & URL state management for React! - - - #TanStack - - - - - - - - semantic-release - - Join the discussion on Github -Best of JS - - - - - - - -Enjoy this library? Try the entire [TanStack](https://tanstack.com)! [React Query](https://github.com/tannerlinsley/react-query), [React Table](https://github.com/tanstack/react-table), [React Charts](https://github.com/tannerlinsley/react-charts), [React Virtual](https://github.com/tannerlinsley/react-virtual) - -## Visit [tanstack.com/router](https://tanstack.com/router) for docs, guides, API and more! diff --git a/packages/react-start-config/eslint.config.js b/packages/react-start-config/eslint.config.js deleted file mode 100644 index 931f0ec774..0000000000 --- a/packages/react-start-config/eslint.config.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check - -import pluginReact from '@eslint-react/eslint-plugin' -import pluginReactHooks from 'eslint-plugin-react-hooks' -import rootConfig from '../../eslint.config.js' - -export default [ - ...rootConfig, - { - ...pluginReact.configs.recommended, - files: ['**/*.{ts,tsx}'], - }, - { - plugins: { - 'react-hooks': pluginReactHooks, - }, - rules: { - '@eslint-react/no-unstable-context-value': 'off', - '@eslint-react/no-unstable-default-props': 'off', - '@eslint-react/dom/no-missing-button-type': 'off', - 'react-hooks/exhaustive-deps': 'error', - 'react-hooks/rules-of-hooks': 'error', - }, - }, - { - files: ['**/__tests__/**'], - rules: { - '@typescript-eslint/no-unnecessary-condition': 'off', - }, - }, -] diff --git a/packages/react-start-config/package.json b/packages/react-start-config/package.json deleted file mode 100644 index efed5ca44e..0000000000 --- a/packages/react-start-config/package.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "name": "@tanstack/react-start-config", - "version": "1.114.3", - "description": "Modern and scalable routing for React applications", - "author": "Tanner Linsley", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/TanStack/router.git", - "directory": "packages/react-start-config" - }, - "homepage": "https://tanstack.com/start", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "keywords": [ - "react", - "location", - "router", - "routing", - "async", - "async router", - "typescript" - ], - "scripts": { - "clean": "rimraf ./dist && rimraf ./coverage", - "build": "tsc", - "test": "pnpm test:eslint && pnpm test:types && pnpm test:build && pnpm test:unit", - "test:unit": "exit 0;vitest", - "test:eslint": "eslint ./src", - "test:types": "exit 0; vitest" - }, - "type": "module", - "types": "dist/esm/index.d.ts", - "exports": { - ".": { - "import": { - "types": "./dist/esm/index.d.ts", - "default": "./dist/esm/index.js" - } - }, - "./package.json": "./package.json" - }, - "sideEffects": false, - "files": [ - "dist", - "src" - ], - "engines": { - "node": ">=12" - }, - "dependencies": { - "@tanstack/router-core": "workspace:^", - "@tanstack/router-generator": "workspace:^", - "@tanstack/router-plugin": "workspace:^", - "@tanstack/server-functions-plugin": "workspace:^", - "@tanstack/react-start-plugin": "workspace:^", - "@tanstack/react-start-server-functions-handler": "workspace:^", - "@vitejs/plugin-react": "^4.3.4", - "import-meta-resolve": "^4.1.0", - "nitropack": "^2.10.4", - "ofetch": "^1.4.1", - "vite": "^6.1.0", - "vinxi": "0.5.3", - "zod": "^3.24.1" - }, - "peerDependencies": { - "react": ">=18.0.0 || >=19.0.0", - "react-dom": ">=18.0.0 || >=19.0.0", - "vite": "^6.0.0" - } -} diff --git a/packages/react-start-config/src/index.ts b/packages/react-start-config/src/index.ts deleted file mode 100644 index 8fc7c3f5a8..0000000000 --- a/packages/react-start-config/src/index.ts +++ /dev/null @@ -1,665 +0,0 @@ -import path from 'node:path' -import { existsSync, readFileSync } from 'node:fs' -import { readFile } from 'node:fs/promises' -import { fileURLToPath } from 'node:url' -import viteReact from '@vitejs/plugin-react' -import { resolve } from 'import-meta-resolve' -import { TanStackRouterVite } from '@tanstack/router-plugin/vite' -import { getConfig } from '@tanstack/router-generator' -import { createApp } from 'vinxi' -import { config } from 'vinxi/plugins/config' -// // @ts-expect-error -// import { serverComponents } from '@vinxi/server-components/plugin' -import { createTanStackServerFnPlugin } from '@tanstack/server-functions-plugin' -import { createTanStackStartPlugin } from '@tanstack/react-start-plugin' -import { createFetch } from 'ofetch' -import { createNitro } from 'nitropack' -import { tanstackStartVinxiFileRouter } from './vinxi-file-router.js' -import { - checkDeploymentPresetInput, - getUserViteConfig, - inlineConfigSchema, - serverSchema, -} from './schema.js' -import type { configSchema } from '@tanstack/router-generator' -import type { z } from 'zod' -import type { - TanStackStartInputConfig, - TanStackStartOutputConfig, -} from './schema.js' -import type { App as VinxiApp } from 'vinxi' -import type { Manifest } from '@tanstack/router-core' -import type * as vite from 'vite' - -export type { - TanStackStartInputConfig, - TanStackStartOutputConfig, -} from './schema.js' - -function setTsrDefaults(config: TanStackStartOutputConfig['tsr']) { - // Normally these are `./src/___`, but we're using `./app/___` for Start stuff - const appDirectory = config?.appDirectory ?? './app' - return { - ...config, - appDirectory: config?.appDirectory ?? appDirectory, - routesDirectory: - config?.routesDirectory ?? path.join(appDirectory, 'routes'), - generatedRouteTree: - config?.generatedRouteTree ?? path.join(appDirectory, 'routeTree.gen.ts'), - } -} - -function mergeSsrOptions(options: Array) { - let ssrOptions: vite.SSROptions = {} - let noExternal: vite.SSROptions['noExternal'] = [] - for (const option of options) { - if (!option) { - continue - } - - if (option.noExternal) { - if (option.noExternal === true) { - noExternal = true - } else if (noExternal !== true) { - if (Array.isArray(option.noExternal)) { - noExternal.push(...option.noExternal) - } else { - noExternal.push(option.noExternal) - } - } - } - - ssrOptions = { - ...ssrOptions, - ...option, - noExternal, - } - } - - return ssrOptions -} - -export async function defineConfig( - inlineConfig: TanStackStartInputConfig = {}, -): Promise { - const opts = inlineConfigSchema.parse(inlineConfig) - - const { preset: configDeploymentPreset, ...serverOptions } = - serverSchema.parse(opts.server || {}) - - const deploymentPreset = checkDeploymentPresetInput( - configDeploymentPreset || 'node-server', - ) - const tsr = setTsrDefaults(opts.tsr) - const tsrConfig = getConfig(tsr) - - const appDirectory = tsr.appDirectory - const publicDir = opts.routers?.public?.dir || './public' - - const publicBase = opts.routers?.public?.base || '/' - const clientBase = opts.routers?.client?.base || '/_build' - const apiBase = opts.tsr?.apiBase || '/api' - const serverBase = opts.routers?.server?.base || '/_server' - - const apiMiddleware = opts.routers?.api?.middleware || undefined - const serverMiddleware = opts.routers?.server?.middleware || undefined - const ssrMiddleware = opts.routers?.ssr?.middleware || undefined - - const clientEntry = - opts.routers?.client?.entry || path.join(appDirectory, 'client.tsx') - const ssrEntry = - opts.routers?.ssr?.entry || path.join(appDirectory, 'ssr.tsx') - const apiEntry = opts.routers?.api?.entry || path.join(appDirectory, 'api.ts') - const globalMiddlewareEntry = - opts.routers?.server?.globalMiddlewareEntry || - path.join(appDirectory, 'global-middleware.ts') - const apiEntryExists = existsSync(apiEntry) - - const viteConfig = getUserViteConfig(opts.vite) - - const TanStackServerFnsPlugin = createTanStackServerFnPlugin({ - // This is the ID that will be available to look up and import - // our server function manifest and resolve its module - manifestVirtualImportId: 'tsr:server-fn-manifest', - client: { - getRuntimeCode: () => - `import { createClientRpc } from '@tanstack/react-start/server-functions-client'`, - replacer: (opts) => - `createClientRpc('${opts.functionId}', '${serverBase}')`, - }, - ssr: { - getRuntimeCode: () => - `import { createSsrRpc } from '@tanstack/react-start/server-functions-ssr'`, - replacer: (opts) => `createSsrRpc('${opts.functionId}', '${serverBase}')`, - }, - server: { - getRuntimeCode: () => - `import { createServerRpc } from '@tanstack/react-start/server-functions-server'`, - replacer: (opts) => - `createServerRpc('${opts.functionId}', '${serverBase}', ${opts.fn})`, - }, - }) - - const TanStackStartPlugin = createTanStackStartPlugin({ - globalMiddlewareEntry, - }) - - // Create a dummy nitro app to get the resolved public output path - const dummyNitroApp = await createNitro({ - preset: deploymentPreset, - compatibilityDate: '2024-12-01', - }) - - const nitroOutputPublicDir = dummyNitroApp.options.output.publicDir - await dummyNitroApp.close() - - let vinxiApp = createApp({ - server: { - ...serverOptions, - preset: deploymentPreset, - experimental: { - ...serverOptions.experimental, - asyncContext: true, - }, - }, - routers: [ - { - name: 'public', - type: 'static', - dir: publicDir, - base: publicBase, - }, - { - name: 'client', - type: 'client', - target: 'browser', - handler: clientEntry, - base: clientBase, - // @ts-expect-error - build: { - sourcemap: true, - }, - plugins: () => { - const routerType = 'client' - const clientViteConfig = getUserViteConfig( - opts.routers?.[routerType]?.vite, - ) - - return [ - config('tss-vite-config-client', { - ...viteConfig.userConfig, - ...clientViteConfig.userConfig, - define: { - ...(viteConfig.userConfig.define || {}), - ...(clientViteConfig.userConfig.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', publicBase), - ...injectDefineEnv('TSS_CLIENT_BASE', clientBase), - ...injectDefineEnv('TSS_API_BASE', apiBase), - ...injectDefineEnv( - 'TSS_OUTPUT_PUBLIC_DIR', - nitroOutputPublicDir, - ), - }, - ssr: mergeSsrOptions([ - viteConfig.userConfig.ssr, - clientViteConfig.userConfig.ssr, - { - noExternal, - }, - ]), - optimizeDeps: { - entries: [], - ...(viteConfig.userConfig.optimizeDeps || {}), - ...(clientViteConfig.userConfig.optimizeDeps || {}), - }, - }), - TanStackRouterVite({ - ...tsrConfig, - enableRouteGeneration: true, - autoCodeSplitting: true, - __enableAPIRoutesGeneration: true, - experimental: { - ...tsrConfig.experimental, - }, - }), - TanStackStartPlugin.client, - TanStackServerFnsPlugin.client, - ...(viteConfig.plugins || []), - ...(clientViteConfig.plugins || []), - viteReact(opts.react), - // TODO: RSCS - enable this - // serverComponents.client(), - ] - }, - }, - { - name: 'ssr', - type: 'http', - target: 'server', - handler: ssrEntry, - middleware: ssrMiddleware, - // @ts-expect-error - link: { - client: 'client', - }, - plugins: () => { - const routerType = 'ssr' - const ssrViteConfig = getUserViteConfig( - opts.routers?.[routerType]?.vite, - ) - - return [ - config('tss-vite-config-ssr', { - ...viteConfig.userConfig, - ...ssrViteConfig.userConfig, - define: { - ...(viteConfig.userConfig.define || {}), - ...(ssrViteConfig.userConfig.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', publicBase), - ...injectDefineEnv('TSS_CLIENT_BASE', clientBase), - ...injectDefineEnv('TSS_API_BASE', apiBase), - ...injectDefineEnv( - 'TSS_OUTPUT_PUBLIC_DIR', - nitroOutputPublicDir, - ), - }, - ssr: mergeSsrOptions([ - viteConfig.userConfig.ssr, - ssrViteConfig.userConfig.ssr, - { - noExternal, - external: ['@vinxi/react-server-dom/client'], - }, - ]), - optimizeDeps: { - entries: [], - ...(viteConfig.userConfig.optimizeDeps || {}), - ...(ssrViteConfig.userConfig.optimizeDeps || {}), - }, - }), - TanStackRouterVite({ - ...tsrConfig, - enableRouteGeneration: false, - autoCodeSplitting: true, - __enableAPIRoutesGeneration: true, - experimental: { - ...tsrConfig.experimental, - }, - }), - TanStackStartPlugin.ssr, - TanStackServerFnsPlugin.ssr, - tsrRoutesManifest({ - tsrConfig, - clientBase, - }), - ...(getUserViteConfig(opts.vite).plugins || []), - ...(getUserViteConfig(opts.routers?.ssr?.vite).plugins || []), - viteReact(opts.react), - ] - }, - }, - { - name: 'server', - type: 'http', - target: 'server', - base: serverBase, - middleware: serverMiddleware, - // TODO: RSCS - enable this - // worker: true, - handler: importToProjectRelative( - '@tanstack/react-start-server-functions-handler', - ), - plugins: () => { - const routerType = 'server' - const serverViteConfig = getUserViteConfig( - opts.routers?.[routerType]?.vite, - ) - - return [ - config('tss-vite-config-server', { - ...viteConfig.userConfig, - ...serverViteConfig.userConfig, - define: { - ...(viteConfig.userConfig.define || {}), - ...(serverViteConfig.userConfig.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', publicBase), - ...injectDefineEnv('TSS_CLIENT_BASE', clientBase), - ...injectDefineEnv('TSS_API_BASE', apiBase), - ...injectDefineEnv('TSS_SERVER_FN_BASE', serverBase), - ...injectDefineEnv( - 'TSS_OUTPUT_PUBLIC_DIR', - nitroOutputPublicDir, - ), - }, - ssr: mergeSsrOptions([ - viteConfig.userConfig.ssr, - serverViteConfig.userConfig.ssr, - { - noExternal, - }, - ]), - optimizeDeps: { - entries: [], - ...(viteConfig.userConfig.optimizeDeps || {}), - ...(serverViteConfig.userConfig.optimizeDeps || {}), - }, - }), - TanStackRouterVite({ - ...tsrConfig, - enableRouteGeneration: false, - autoCodeSplitting: true, - __enableAPIRoutesGeneration: true, - experimental: { - ...tsrConfig.experimental, - }, - }), - TanStackStartPlugin.server, - TanStackServerFnsPlugin.server, - // TODO: RSCS - remove this - // resolve: { - // conditions: [], - // }, - // TODO: RSCs - add this - // serverComponents.serverActions({ - // resolve: { - // conditions: [ - // 'react-server', - // // 'node', - // 'import', - // process.env.NODE_ENV, - // ], - // }, - // runtime: '@vinxi/react-server-dom/runtime', - // transpileDeps: ['react', 'react-dom', '@vinxi/react-server-dom'], - // }), - ...(viteConfig.plugins || []), - ...(serverViteConfig.plugins || []), - ] - }, - }, - ], - }) - - const noExternal = [ - '@tanstack/start', - '@tanstack/react-start', - '@tanstack/react-start/server', - '@tanstack/react-start-client', - '@tanstack/react-start-server', - '@tanstack/react-start-server-functions-fetcher', - '@tanstack/react-start-server-functions-handler', - '@tanstack/react-start-server-functions-client', - '@tanstack/react-start-server-functions-ssr', - '@tanstack/start-server-functions-server', - '@tanstack/react-start-router-manifest', - '@tanstack/react-start-config', - '@tanstack/react-start-api-routes', - '@tanstack/server-functions-plugin', - 'tsr:routes-manifest', - 'tsr:server-fn-manifest', - ] - - // If API routes handler exists, add a router for it - if (apiEntryExists) { - vinxiApp = vinxiApp.addRouter({ - name: 'api', - type: 'http', - target: 'server', - base: apiBase, - handler: apiEntry, - middleware: apiMiddleware, - routes: tanstackStartVinxiFileRouter({ tsrConfig, apiBase }), - plugins: () => { - const viteConfig = getUserViteConfig(opts.vite) - const apiViteConfig = getUserViteConfig(opts.routers?.api?.vite) - - return [ - config('tsr-vite-config-api', { - ...viteConfig.userConfig, - ...apiViteConfig.userConfig, - ssr: mergeSsrOptions([ - viteConfig.userConfig.ssr, - apiViteConfig.userConfig.ssr, - { - noExternal, - }, - ]), - optimizeDeps: { - entries: [], - ...(viteConfig.userConfig.optimizeDeps || {}), - ...(apiViteConfig.userConfig.optimizeDeps || {}), - }, - define: { - ...(viteConfig.userConfig.define || {}), - ...(apiViteConfig.userConfig.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', publicBase), - ...injectDefineEnv('TSS_CLIENT_BASE', clientBase), - ...injectDefineEnv('TSS_API_BASE', apiBase), - ...injectDefineEnv('TSS_OUTPUT_PUBLIC_DIR', nitroOutputPublicDir), - }, - }), - TanStackRouterVite({ - ...tsrConfig, - enableRouteGeneration: false, - autoCodeSplitting: true, - __enableAPIRoutesGeneration: true, - experimental: { - ...tsrConfig.experimental, - }, - }), - ...(viteConfig.plugins || []), - ...(apiViteConfig.plugins || []), - ] - }, - }) - } - - // Because Vinxi doesn't use the normal nitro dev server, it doesn't - // supply $fetch during dev. We need to hook into the dev server creation, - // nab the proper utils from the custom nitro instance that is used - // during dev and supply the $fetch to app. - // Hopefully and likely, this will just get removed when we move to - // Nitro directly. - vinxiApp.hooks.hook('app:dev:nitro:config', (devServer) => { - vinxiApp.hooks.hook( - 'app:dev:server:created', - ({ devApp: { localFetch } }) => { - const $fetch = createFetch({ - fetch: localFetch, - defaults: { - baseURL: devServer.nitro.options.runtimeConfig.app.baseURL, - }, - }) - - // @ts-expect-error - globalThis.$fetch = $fetch - }, - ) - }) - - return vinxiApp -} - -function importToProjectRelative(p: string) { - const resolved = fileURLToPath(resolve(p, import.meta.url)) - - const relative = path.relative(process.cwd(), resolved) - - return relative -} - -function tsrRoutesManifest(opts: { - tsrConfig: z.infer - clientBase: string -}): vite.Plugin { - let config: vite.ResolvedConfig - - return { - name: 'tsr-routes-manifest', - configResolved(resolvedConfig) { - config = resolvedConfig - }, - resolveId(id) { - if (id === 'tsr:routes-manifest') { - return id - } - return - }, - async load(id) { - if (id === 'tsr:routes-manifest') { - // If we're in development, return a dummy manifest - - if (config.command === 'serve') { - return `export default () => ({ - routes: {} - })` - } - - const clientViteManifestPath = path.resolve( - config.build.outDir, - `../client/${opts.clientBase}/.vite/manifest.json`, - ) - - type ViteManifest = Record< - string, - { - file: string - isEntry: boolean - imports: Array - } - > - - let manifest: ViteManifest - try { - manifest = JSON.parse(await readFile(clientViteManifestPath, 'utf-8')) - } catch (err) { - console.error(err) - throw new Error( - `Could not find the production client vite manifest at '${clientViteManifestPath}'!`, - ) - } - - const routeTreePath = path.resolve(opts.tsrConfig.generatedRouteTree) - - let routeTreeContent: string - try { - routeTreeContent = readFileSync(routeTreePath, 'utf-8') - } catch (err) { - console.error(err) - throw new Error( - `Could not find the generated route tree at '${routeTreePath}'!`, - ) - } - - // Extract the routesManifest JSON from the route tree file. - // It's located between the /* ROUTE_MANIFEST_START and ROUTE_MANIFEST_END */ comment block. - - const routerManifest = JSON.parse( - routeTreeContent.match( - /\/\* ROUTE_MANIFEST_START([\s\S]*?)ROUTE_MANIFEST_END \*\//, - )?.[1] || '{ routes: {} }', - ) as Manifest - - const routes = routerManifest.routes - - let entryFile: - | { - file: string - imports: Array - } - | undefined - - const filesByRouteFilePath: ViteManifest = Object.fromEntries( - Object.entries(manifest).map(([k, v]) => { - if (v.isEntry) { - entryFile = v - } - - const rPath = k.split('?')[0] - - return [rPath, v] - }, {}), - ) - - // Add preloads to the routes from the vite manifest - Object.entries(routes).forEach(([k, v]) => { - const file = - filesByRouteFilePath[ - path.join(opts.tsrConfig.routesDirectory, v.filePath as string) - ] - - if (file) { - const preloads = file.imports.map((d) => - path.join(opts.clientBase, manifest[d]!.file), - ) - - preloads.unshift(path.join(opts.clientBase, file.file)) - - routes[k] = { - ...v, - preloads, - } - } - }) - - if (entryFile) { - routes.__root__!.preloads = [ - path.join(opts.clientBase, entryFile.file), - ...entryFile.imports.map((d) => - path.join(opts.clientBase, manifest[d]!.file), - ), - ] - } - - const recurseRoute = ( - route: { - preloads?: Array - children?: Array - }, - seenPreloads = {} as Record, - ) => { - route.preloads = route.preloads?.filter((preload) => { - if (seenPreloads[preload]) { - return false - } - seenPreloads[preload] = true - return true - }) - - if (route.children) { - route.children.forEach((child) => { - const childRoute = routes[child]! - recurseRoute(childRoute, { ...seenPreloads }) - }) - } - } - - // @ts-expect-error - recurseRoute(routes.__root__) - - const routesManifest = { - routes, - } - - if (process.env.TSR_VITE_DEBUG) { - console.info( - 'Routes Manifest: \n' + JSON.stringify(routesManifest, null, 2), - ) - } - - return `export default () => (${JSON.stringify(routesManifest)})` - } - return - }, - } -} - -function injectDefineEnv( - key: TKey, - value: TValue, -): { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } { - return { - [`process.env.${key}`]: JSON.stringify(value), - [`import.meta.env.${key}`]: JSON.stringify(value), - } as { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } -} diff --git a/packages/react-start-config/src/schema.ts b/packages/react-start-config/src/schema.ts deleted file mode 100644 index e0882a17d4..0000000000 --- a/packages/react-start-config/src/schema.ts +++ /dev/null @@ -1,145 +0,0 @@ -import path from 'node:path' -import { existsSync } from 'node:fs' -import { z } from 'zod' -import { configSchema, getConfig } from '@tanstack/router-generator' -import type { UserConfig } from 'vite' -import type { NitroConfig } from 'nitropack' -import type { Options as ViteReactOptions } from '@vitejs/plugin-react' - -type HTTPSOptions = { - cert?: string - key?: string - pfx?: string - passphrase?: string - validityDays?: number - domains?: Array -} - -type ServerOptions = NitroConfig & { - https?: boolean | HTTPSOptions -} - -export const serverSchema = z.custom().and( - z.object({ - preset: z - .custom() - .optional() - .default('node-server'), - }), -) - -const viteSchema = z.custom() - -const viteReactSchema = z.custom() - -const routersSchema = z.object({ - ssr: z - .object({ - entry: z.string().optional().default('ssr.tsx'), - // middleware: z.string().optional(), - vite: viteSchema.optional(), - }) - .optional() - .default({}), - client: z - .object({ - entry: z.string().optional().default('client.tsx'), - base: z.string().optional().default('/_build'), - vite: viteSchema.optional(), - }) - .optional() - .default({}), - server: z - .object({ - base: z.string().optional().default('/_server'), - globalMiddlewareEntry: z - .string() - .optional() - .default('global-middleware.ts'), - // middleware: z.string().optional(), - vite: viteSchema.optional(), - }) - .optional() - .default({}), - api: z - .object({ - base: z.string().optional().default('/api'), - entry: z.string().optional().default('api.ts'), - // middleware: z.string().optional(), - vite: viteSchema.optional(), - }) - .optional() - .default({}), - public: z - .object({ - dir: z.string().optional().default('public'), - base: z.string().optional().default('/'), - }) - .optional() - .default({}), -}) - -const sitemapSchema = z.object({ - host: z.string(), -}) - -const tsrConfig = configSchema.partial().extend({ - // Normally these are `./src/___`, but we're using `./app/___` for Start stuff - appDirectory: z.string().optional().default('app'), -}) - -const TanStackStartOptionsSchema = z - .object({ - root: z.string().optional().default(process.cwd()), - react: viteReactSchema.optional(), - vite: viteSchema.optional(), - tsr: tsrConfig.optional().default({}), - routers: routersSchema.optional().default({}), - server: serverSchema.optional().default({}), - sitemap: sitemapSchema.optional(), - }) - .optional() - .default({}) - -export function getTanStackStartOptions(opts?: TanStackStartInputConfig) { - const options = TanStackStartOptionsSchema.parse(opts) - - const appDirectory = options.tsr.appDirectory - const routesDirectory = - options.tsr.routesDirectory ?? path.join(appDirectory, 'routes') - const generatedRouteTree = - options.tsr.generatedRouteTree ?? - path.join(appDirectory, 'routeTree.gen.ts') - const clientEntryPath = path.join(appDirectory, options.routers.client.entry) - const ssrEntryPath = path.join(appDirectory, options.routers.ssr.entry) - const apiEntryPath = path.join(appDirectory, options.routers.api.entry) - const globalMiddlewareEntryPath = path.join( - appDirectory, - options.routers.server.globalMiddlewareEntry, - ) - const hasApiEntry = existsSync(apiEntryPath) - - return { - ...options, - tsr: { - ...options.tsr, - ...getConfig({ - ...options.tsr, - routesDirectory, - generatedRouteTree, - }), - }, - clientEntryPath, - ssrEntryPath, - apiEntryPath, - globalMiddlewareEntryPath, - hasApiEntry, - } -} - -export type TanStackStartInputConfig = z.input< - typeof TanStackStartOptionsSchema -> -export type TanStackStartOutputConfig = ReturnType< - typeof getTanStackStartOptions -> diff --git a/packages/react-start-config/src/vinxi-file-router.ts b/packages/react-start-config/src/vinxi-file-router.ts deleted file mode 100644 index a60d71585c..0000000000 --- a/packages/react-start-config/src/vinxi-file-router.ts +++ /dev/null @@ -1,90 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-nocheck - -import { - BaseFileSystemRouter as VinxiBaseFileSystemRouter, - analyzeModule as vinxiFsRouterAnalyzeModule, - cleanPath as vinxiFsRouterCleanPath, -} from 'vinxi/fs-router' -import { - CONSTANTS as GENERATOR_CONSTANTS, - startAPIRouteSegmentsFromTSRFilePath, -} from '@tanstack/router-generator' -import type { configSchema } from '@tanstack/router-generator' -import type { - AppOptions as VinxiAppOptions, - RouterSchemaInput as VinxiRouterSchemaInput, -} from 'vinxi' -import type { z } from 'zod' - -export function tanstackStartVinxiFileRouter(opts: { - tsrConfig: z.infer - apiBase: string -}) { - const apiBaseSegment = opts.apiBase.split('/').filter(Boolean).join('/') - const isAPIPath = new RegExp(`/${apiBaseSegment}/`) - - return function (router: VinxiRouterSchemaInput, app: VinxiAppOptions) { - // Our own custom File Router that extends the VinxiBaseFileSystemRouter - // for splitting the API routes into its own "bundle" - // and adding the $APIRoute metadata to the route object - // This could be customized in future to support more complex splits - class TanStackStartFsRouter extends VinxiBaseFileSystemRouter { - toPath(src: string): string { - const inputPath = vinxiFsRouterCleanPath(src, this.config) - - const segments = startAPIRouteSegmentsFromTSRFilePath( - inputPath, - opts.tsrConfig, - ) - - const pathname = segments - .map((part) => { - if (part.type === 'splat') { - return `*splat` - } - - if (part.type === 'param') { - return `:${part.value}?` - } - - return part.value - }) - .join('/') - - return pathname.length > 0 ? `/${pathname}` : '/' - } - - toRoute(src: string) { - const webPath = this.toPath(src) - - const [_, exports] = vinxiFsRouterAnalyzeModule(src) - - const hasAPIRoute = exports.find( - (exp) => exp.n === GENERATOR_CONSTANTS.APIRouteExportVariable, - ) - - return { - path: webPath, - filePath: src, - $APIRoute: - isAPIPath.test(webPath) && hasAPIRoute - ? { - src, - pick: [GENERATOR_CONSTANTS.APIRouteExportVariable], - } - : undefined, - } - } - } - - return new TanStackStartFsRouter( - { - dir: opts.tsrConfig.routesDirectory, - extensions: ['js', 'jsx', 'ts', 'tsx'], - }, - router, - app, - ) - } -} diff --git a/packages/react-start-config/tsconfig.json b/packages/react-start-config/tsconfig.json deleted file mode 100644 index 940a9cce0a..0000000000 --- a/packages/react-start-config/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "include": ["src/index.ts"], - "compilerOptions": { - "rootDir": "src", - "outDir": "dist/esm", - "target": "esnext", - "noEmit": false - } -} diff --git a/packages/react-start/src/config.tsx b/packages/react-start/src/config.tsx deleted file mode 100644 index 57a7ae394d..0000000000 --- a/packages/react-start/src/config.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from '@tanstack/react-start-config' diff --git a/packages/react-start/vite.config.ts b/packages/react-start/vite.config.ts index cf9244f281..dd8d715d1d 100644 --- a/packages/react-start/vite.config.ts +++ b/packages/react-start/vite.config.ts @@ -17,7 +17,6 @@ export default mergeConfig( entry: [ './src/client.tsx', './src/server.tsx', - './src/config.tsx', './src/router-manifest.tsx', './src/server-functions-client.tsx', './src/server-functions-server.tsx', @@ -27,7 +26,6 @@ export default mergeConfig( externalDeps: [ '@tanstack/react-start-client', '@tanstack/react-start-server', - '@tanstack/react-start-config', '@tanstack/react-start-router-manifest', '@tanstack/react-start-server-functions-client', '@tanstack/start-server-functions-server', From b4dd06ca1d2014b5a6faaaf28cb722364691f79c Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 26 Feb 2025 00:18:53 +0100 Subject: [PATCH 008/155] remove vinxi-file-router --- .../src/vinxi-file-router.ts | 87 ------------------- 1 file changed, 87 deletions(-) delete mode 100644 packages/react-start-plugin/src/vinxi-file-router.ts diff --git a/packages/react-start-plugin/src/vinxi-file-router.ts b/packages/react-start-plugin/src/vinxi-file-router.ts deleted file mode 100644 index 9e6d829d1b..0000000000 --- a/packages/react-start-plugin/src/vinxi-file-router.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { - BaseFileSystemRouter as VinxiBaseFileSystemRouter, - analyzeModule as vinxiFsRouterAnalyzeModule, - cleanPath as vinxiFsRouterCleanPath, -} from 'vinxi/fs-router' -import { - CONSTANTS as GENERATOR_CONSTANTS, - startAPIRouteSegmentsFromTSRFilePath, -} from '@tanstack/router-generator' -import type { configSchema } from '@tanstack/router-generator' -import type { - AppOptions as VinxiAppOptions, - RouterSchemaInput as VinxiRouterSchemaInput, -} from 'vinxi' -import type { z } from 'zod' - -export function tanstackStartVinxiFileRouter(opts: { - tsrConfig: z.infer - apiBase: string -}) { - const apiBaseSegment = opts.apiBase.split('/').filter(Boolean).join('/') - const isAPIPath = new RegExp(`/${apiBaseSegment}/`) - - return function (router: VinxiRouterSchemaInput, app: VinxiAppOptions) { - // Our own custom File Router that extends the VinxiBaseFileSystemRouter - // for splitting the API routes into its own "bundle" - // and adding the $APIRoute metadata to the route object - // This could be customized in future to support more complex splits - class TanStackStartFsRouter extends VinxiBaseFileSystemRouter { - toPath(src: string): string { - const inputPath = vinxiFsRouterCleanPath(src, this.config) - - const segments = startAPIRouteSegmentsFromTSRFilePath( - inputPath, - opts.tsrConfig, - ) - - const pathname = segments - .map((part) => { - if (part.type === 'splat') { - return `*splat` - } - - if (part.type === 'param') { - return `:${part.value}?` - } - - return part.value - }) - .join('/') - - return pathname.length > 0 ? `/${pathname}` : '/' - } - - toRoute(src: string) { - const webPath = this.toPath(src) - - const [_, exports] = vinxiFsRouterAnalyzeModule(src) - - const hasAPIRoute = exports.find( - (exp) => exp.n === GENERATOR_CONSTANTS.APIRouteExportVariable, - ) - - return { - path: webPath, - filePath: src, - $APIRoute: - isAPIPath.test(webPath) && hasAPIRoute - ? { - src, - pick: [GENERATOR_CONSTANTS.APIRouteExportVariable], - } - : undefined, - } - } - } - - return new TanStackStartFsRouter( - { - dir: opts.tsrConfig.routesDirectory, - extensions: ['js', 'jsx', 'ts', 'tsx'], - }, - router, - app, - ) - } -} From 441b36e2942659bbba627d6305a2f145f2c27bc7 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 26 Feb 2025 00:27:58 +0100 Subject: [PATCH 009/155] fix package name --- packages/react-start-plugin/package.json | 7 +----- packages/react-start/package.json | 1 - pnpm-lock.yaml | 27 ++++++++---------------- 3 files changed, 10 insertions(+), 25 deletions(-) diff --git a/packages/react-start-plugin/package.json b/packages/react-start-plugin/package.json index d932328a1c..87f20c1e47 100644 --- a/packages/react-start-plugin/package.json +++ b/packages/react-start-plugin/package.json @@ -7,7 +7,7 @@ "repository": { "type": "git", "url": "https://github.com/TanStack/router.git", - "directory": "packages/react-start-plugin" + "directory": "packages/start-plugin" }, "homepage": "https://tanstack.com/start", "funding": { @@ -77,11 +77,6 @@ "@tanstack/router-plugin": "workspace:^", "@tanstack/router-utils": "workspace:^", "@tanstack/server-functions-plugin": "workspace:^", - "babel-dead-code-elimination": "^1.0.9", - "tiny-invariant": "^1.3.3", - "vite": "6.1.0" - }, - "devDependencies": { "@types/babel__code-frame": "^7.0.6", "@types/babel__core": "^7.20.5", "@types/babel__template": "^7.4.4", diff --git a/packages/react-start/package.json b/packages/react-start/package.json index ae6242d1c7..e9e977cebe 100644 --- a/packages/react-start/package.json +++ b/packages/react-start/package.json @@ -145,7 +145,6 @@ "dependencies": { "@tanstack/react-start-client": "workspace:^", "@tanstack/react-start-server": "workspace:^", - "@tanstack/react-start-config": "workspace:^", "@tanstack/react-start-router-manifest": "workspace:^", "@tanstack/react-start-server-functions-client": "workspace:^", "@tanstack/start-server-functions-server": "workspace:^", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5e6cf54032..c0d1263b2c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5765,9 +5765,6 @@ importers: '@tanstack/react-start-client': specifier: workspace:* version: link:../react-start-client - '@tanstack/react-start-config': - specifier: workspace:^ - version: link:../react-start-config '@tanstack/react-start-router-manifest': specifier: workspace:* version: link:../react-start-router-manifest @@ -5942,16 +5939,6 @@ importers: '@tanstack/server-functions-plugin': specifier: workspace:* version: link:../server-functions-plugin - babel-dead-code-elimination: - specifier: ^1.0.9 - version: 1.0.9 - tiny-invariant: - specifier: ^1.3.3 - version: 1.3.3 - vite: - specifier: 6.1.0 - version: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - devDependencies: '@types/babel__code-frame': specifier: ^7.0.6 version: 7.0.6 @@ -5967,6 +5954,9 @@ importers: '@vitejs/plugin-react': specifier: ^4.3.4 version: 4.3.4(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) + babel-dead-code-elimination: + specifier: ^1.0.9 + version: 1.0.9 fast-glob: specifier: ^3.3.3 version: 3.3.3 @@ -5976,6 +5966,12 @@ importers: nitropack: specifier: ^2.10.4 version: 2.10.4(typescript@5.7.3) + tiny-invariant: + specifier: ^1.3.3 + version: 1.3.3 + vite: + specifier: 6.1.0 + version: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) xmlbuilder2: specifier: ^3.1.1 version: 3.1.1 @@ -12130,9 +12126,6 @@ packages: engines: {node: '>=8'} hasBin: true - import-meta-resolve@4.1.0: - resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} - imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -20837,8 +20830,6 @@ snapshots: pkg-dir: 4.2.0 resolve-cwd: 3.0.0 - import-meta-resolve@4.1.0: {} - imurmurhash@0.1.4: {} indent-string@4.0.0: {} From 69d8d963a65427cb292f88f918e4501225c3a758 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 26 Feb 2025 00:34:58 +0100 Subject: [PATCH 010/155] fix merge, format --- packages/react-start-plugin/src/config.ts | 665 ------------------ .../react-start-plugin/src/nitro/options.ts | 46 +- .../src/nitro/utils/load-esm.ts | 4 +- .../src/nitro/vite-plugin-nitro.ts | 3 - packages/react-start-plugin/src/schema.ts | 249 +++---- 5 files changed, 125 insertions(+), 842 deletions(-) delete mode 100644 packages/react-start-plugin/src/config.ts diff --git a/packages/react-start-plugin/src/config.ts b/packages/react-start-plugin/src/config.ts deleted file mode 100644 index f2d1d06d1a..0000000000 --- a/packages/react-start-plugin/src/config.ts +++ /dev/null @@ -1,665 +0,0 @@ -import path from 'node:path' -import { existsSync, readFileSync } from 'node:fs' -import { readFile } from 'node:fs/promises' -import { fileURLToPath } from 'node:url' -import viteReact from '@vitejs/plugin-react' -import { resolve } from 'import-meta-resolve' -import { TanStackRouterVite } from '@tanstack/router-plugin/vite' -import { getConfig } from '@tanstack/router-generator' -import { createApp } from 'vinxi' -import { config } from 'vinxi/plugins/config' -// // @ts-expect-error -// import { serverComponents } from '@vinxi/server-components/plugin' -import { createTanStackServerFnPlugin } from '@tanstack/server-functions-plugin' -import { createTanStackStartPlugin } from '@tanstack/react-start-plugin' -import { createFetch } from 'ofetch' -import { createNitro } from 'nitropack' -import { tanstackStartVinxiFileRouter } from './vinxi-file-router.js' -import { - checkDeploymentPresetInput, - getUserViteConfig, - inlineConfigSchema, - serverSchema, -} from './schema.js' -import type { configSchema } from '@tanstack/router-generator' -import type { z } from 'zod' -import type { - TanStackStartInputConfig, - TanStackStartOutputConfig, -} from './schema.js' -import type { App as VinxiApp } from 'vinxi' -import type { Manifest } from '@tanstack/react-router' -import type * as vite from 'vite' - -export type { - TanStackStartInputConfig, - TanStackStartOutputConfig, -} from './schema.js' - -function setTsrDefaults(config: TanStackStartOutputConfig['tsr']) { - // Normally these are `./src/___`, but we're using `./app/___` for Start stuff - const appDirectory = config?.appDirectory ?? './app' - return { - ...config, - appDirectory: config?.appDirectory ?? appDirectory, - routesDirectory: - config?.routesDirectory ?? path.join(appDirectory, 'routes'), - generatedRouteTree: - config?.generatedRouteTree ?? path.join(appDirectory, 'routeTree.gen.ts'), - } -} - -function mergeSsrOptions(options: Array) { - let ssrOptions: vite.SSROptions = {} - let noExternal: vite.SSROptions['noExternal'] = [] - for (const option of options) { - if (!option) { - continue - } - - if (option.noExternal) { - if (option.noExternal === true) { - noExternal = true - } else if (noExternal !== true) { - if (Array.isArray(option.noExternal)) { - noExternal.push(...option.noExternal) - } else { - noExternal.push(option.noExternal) - } - } - } - - ssrOptions = { - ...ssrOptions, - ...option, - noExternal, - } - } - - return ssrOptions -} - -export async function defineConfig( - inlineConfig: TanStackStartInputConfig = {}, -): Promise { - const opts = inlineConfigSchema.parse(inlineConfig) - - const { preset: configDeploymentPreset, ...serverOptions } = - serverSchema.parse(opts.server || {}) - - const deploymentPreset = checkDeploymentPresetInput( - configDeploymentPreset || 'node-server', - ) - const tsr = setTsrDefaults(opts.tsr) - const tsrConfig = getConfig(tsr) - - const appDirectory = tsr.appDirectory - const publicDir = opts.routers?.public?.dir || './public' - - const publicBase = opts.routers?.public?.base || '/' - const clientBase = opts.routers?.client?.base || '/_build' - const apiBase = opts.tsr?.apiBase || '/api' - const serverBase = opts.routers?.server?.base || '/_server' - - const apiMiddleware = opts.routers?.api?.middleware || undefined - const serverMiddleware = opts.routers?.server?.middleware || undefined - const ssrMiddleware = opts.routers?.ssr?.middleware || undefined - - const clientEntry = - opts.routers?.client?.entry || path.join(appDirectory, 'client.tsx') - const ssrEntry = - opts.routers?.ssr?.entry || path.join(appDirectory, 'ssr.tsx') - const apiEntry = opts.routers?.api?.entry || path.join(appDirectory, 'api.ts') - const globalMiddlewareEntry = - opts.routers?.server?.globalMiddlewareEntry || - path.join(appDirectory, 'global-middleware.ts') - const apiEntryExists = existsSync(apiEntry) - - const viteConfig = getUserViteConfig(opts.vite) - - const TanStackServerFnsPlugin = createTanStackServerFnPlugin({ - // This is the ID that will be available to look up and import - // our server function manifest and resolve its module - manifestVirtualImportId: 'tsr:server-fn-manifest', - client: { - getRuntimeCode: () => - `import { createClientRpc } from '@tanstack/start/server-functions-client'`, - replacer: (opts) => - `createClientRpc('${opts.functionId}', '${serverBase}')`, - }, - ssr: { - getRuntimeCode: () => - `import { createSsrRpc } from '@tanstack/start/server-functions-ssr'`, - replacer: (opts) => `createSsrRpc('${opts.functionId}', '${serverBase}')`, - }, - server: { - getRuntimeCode: () => - `import { createServerRpc } from '@tanstack/start/server-functions-server'`, - replacer: (opts) => - `createServerRpc('${opts.functionId}', '${serverBase}', ${opts.fn})`, - }, - }) - - const TanStackStartPlugin = createTanStackStartPlugin({ - globalMiddlewareEntry, - }) - - // Create a dummy nitro app to get the resolved public output path - const dummyNitroApp = await createNitro({ - preset: deploymentPreset, - compatibilityDate: '2024-12-01', - }) - - const nitroOutputPublicDir = dummyNitroApp.options.output.publicDir - await dummyNitroApp.close() - - let vinxiApp = createApp({ - server: { - ...serverOptions, - preset: deploymentPreset, - experimental: { - ...serverOptions.experimental, - asyncContext: true, - }, - }, - routers: [ - { - name: 'public', - type: 'static', - dir: publicDir, - base: publicBase, - }, - { - name: 'client', - type: 'client', - target: 'browser', - handler: clientEntry, - base: clientBase, - // @ts-expect-error - build: { - sourcemap: true, - }, - plugins: () => { - const routerType = 'client' - const clientViteConfig = getUserViteConfig( - opts.routers?.[routerType]?.vite, - ) - - return [ - config('tss-vite-config-client', { - ...viteConfig.userConfig, - ...clientViteConfig.userConfig, - define: { - ...(viteConfig.userConfig.define || {}), - ...(clientViteConfig.userConfig.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', publicBase), - ...injectDefineEnv('TSS_CLIENT_BASE', clientBase), - ...injectDefineEnv('TSS_API_BASE', apiBase), - ...injectDefineEnv( - 'TSS_OUTPUT_PUBLIC_DIR', - nitroOutputPublicDir, - ), - }, - ssr: mergeSsrOptions([ - viteConfig.userConfig.ssr, - clientViteConfig.userConfig.ssr, - { - noExternal, - }, - ]), - optimizeDeps: { - entries: [], - ...(viteConfig.userConfig.optimizeDeps || {}), - ...(clientViteConfig.userConfig.optimizeDeps || {}), - }, - }), - TanStackRouterVite({ - ...tsrConfig, - enableRouteGeneration: true, - autoCodeSplitting: true, - __enableAPIRoutesGeneration: true, - experimental: { - ...tsrConfig.experimental, - }, - }), - TanStackStartPlugin.client, - TanStackServerFnsPlugin.client, - ...(viteConfig.plugins || []), - ...(clientViteConfig.plugins || []), - viteReact(opts.react), - // TODO: RSCS - enable this - // serverComponents.client(), - ] - }, - }, - { - name: 'ssr', - type: 'http', - target: 'server', - handler: ssrEntry, - middleware: ssrMiddleware, - // @ts-expect-error - link: { - client: 'client', - }, - plugins: () => { - const routerType = 'ssr' - const ssrViteConfig = getUserViteConfig( - opts.routers?.[routerType]?.vite, - ) - - return [ - config('tss-vite-config-ssr', { - ...viteConfig.userConfig, - ...ssrViteConfig.userConfig, - define: { - ...(viteConfig.userConfig.define || {}), - ...(ssrViteConfig.userConfig.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', publicBase), - ...injectDefineEnv('TSS_CLIENT_BASE', clientBase), - ...injectDefineEnv('TSS_API_BASE', apiBase), - ...injectDefineEnv( - 'TSS_OUTPUT_PUBLIC_DIR', - nitroOutputPublicDir, - ), - }, - ssr: mergeSsrOptions([ - viteConfig.userConfig.ssr, - ssrViteConfig.userConfig.ssr, - { - noExternal, - external: ['@vinxi/react-server-dom/client'], - }, - ]), - optimizeDeps: { - entries: [], - ...(viteConfig.userConfig.optimizeDeps || {}), - ...(ssrViteConfig.userConfig.optimizeDeps || {}), - }, - }), - TanStackRouterVite({ - ...tsrConfig, - enableRouteGeneration: false, - autoCodeSplitting: true, - __enableAPIRoutesGeneration: true, - experimental: { - ...tsrConfig.experimental, - }, - }), - TanStackStartPlugin.ssr, - TanStackServerFnsPlugin.ssr, - tsrRoutesManifest({ - tsrConfig, - clientBase, - }), - ...(getUserViteConfig(opts.vite).plugins || []), - ...(getUserViteConfig(opts.routers?.ssr?.vite).plugins || []), - viteReact(opts.react), - ] - }, - }, - { - name: 'server', - type: 'http', - target: 'server', - base: serverBase, - middleware: serverMiddleware, - // TODO: RSCS - enable this - // worker: true, - handler: importToProjectRelative( - '@tanstack/react-start-server-functions-handler', - ), - plugins: () => { - const routerType = 'server' - const serverViteConfig = getUserViteConfig( - opts.routers?.[routerType]?.vite, - ) - - return [ - config('tss-vite-config-server', { - ...viteConfig.userConfig, - ...serverViteConfig.userConfig, - define: { - ...(viteConfig.userConfig.define || {}), - ...(serverViteConfig.userConfig.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', publicBase), - ...injectDefineEnv('TSS_CLIENT_BASE', clientBase), - ...injectDefineEnv('TSS_API_BASE', apiBase), - ...injectDefineEnv('TSS_SERVER_FN_BASE', serverBase), - ...injectDefineEnv( - 'TSS_OUTPUT_PUBLIC_DIR', - nitroOutputPublicDir, - ), - }, - ssr: mergeSsrOptions([ - viteConfig.userConfig.ssr, - serverViteConfig.userConfig.ssr, - { - noExternal, - }, - ]), - optimizeDeps: { - entries: [], - ...(viteConfig.userConfig.optimizeDeps || {}), - ...(serverViteConfig.userConfig.optimizeDeps || {}), - }, - }), - TanStackRouterVite({ - ...tsrConfig, - enableRouteGeneration: false, - autoCodeSplitting: true, - __enableAPIRoutesGeneration: true, - experimental: { - ...tsrConfig.experimental, - }, - }), - TanStackStartPlugin.server, - TanStackServerFnsPlugin.server, - // TODO: RSCS - remove this - // resolve: { - // conditions: [], - // }, - // TODO: RSCs - add this - // serverComponents.serverActions({ - // resolve: { - // conditions: [ - // 'react-server', - // // 'node', - // 'import', - // process.env.NODE_ENV, - // ], - // }, - // runtime: '@vinxi/react-server-dom/runtime', - // transpileDeps: ['react', 'react-dom', '@vinxi/react-server-dom'], - // }), - ...(viteConfig.plugins || []), - ...(serverViteConfig.plugins || []), - ] - }, - }, - ], - }) - - const noExternal = [ - '@tanstack/start', - '@tanstack/react-start', - '@tanstack/react-start/server', - '@tanstack/react-start-client', - '@tanstack/react-start-server', - '@tanstack/react-start-server-functions-fetcher', - '@tanstack/react-start-server-functions-handler', - '@tanstack/react-start-server-functions-client', - '@tanstack/react-start-server-functions-ssr', - '@tanstack/start-server-functions-server', - '@tanstack/react-start-router-manifest', - '@tanstack/start-config', - '@tanstack/react-start-api-routes', - '@tanstack/server-functions-plugin', - 'tsr:routes-manifest', - 'tsr:server-fn-manifest', - ] - - // If API routes handler exists, add a router for it - if (apiEntryExists) { - vinxiApp = vinxiApp.addRouter({ - name: 'api', - type: 'http', - target: 'server', - base: apiBase, - handler: apiEntry, - middleware: apiMiddleware, - routes: tanstackStartVinxiFileRouter({ tsrConfig, apiBase }), - plugins: () => { - const viteConfig = getUserViteConfig(opts.vite) - const apiViteConfig = getUserViteConfig(opts.routers?.api?.vite) - - return [ - config('tsr-vite-config-api', { - ...viteConfig.userConfig, - ...apiViteConfig.userConfig, - ssr: mergeSsrOptions([ - viteConfig.userConfig.ssr, - apiViteConfig.userConfig.ssr, - { - noExternal, - }, - ]), - optimizeDeps: { - entries: [], - ...(viteConfig.userConfig.optimizeDeps || {}), - ...(apiViteConfig.userConfig.optimizeDeps || {}), - }, - define: { - ...(viteConfig.userConfig.define || {}), - ...(apiViteConfig.userConfig.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', publicBase), - ...injectDefineEnv('TSS_CLIENT_BASE', clientBase), - ...injectDefineEnv('TSS_API_BASE', apiBase), - ...injectDefineEnv('TSS_OUTPUT_PUBLIC_DIR', nitroOutputPublicDir), - }, - }), - TanStackRouterVite({ - ...tsrConfig, - enableRouteGeneration: false, - autoCodeSplitting: true, - __enableAPIRoutesGeneration: true, - experimental: { - ...tsrConfig.experimental, - }, - }), - ...(viteConfig.plugins || []), - ...(apiViteConfig.plugins || []), - ] - }, - }) - } - - // Because Vinxi doesn't use the normal nitro dev server, it doesn't - // supply $fetch during dev. We need to hook into the dev server creation, - // nab the proper utils from the custom nitro instance that is used - // during dev and supply the $fetch to app. - // Hopefully and likely, this will just get removed when we move to - // Nitro directly. - vinxiApp.hooks.hook('app:dev:nitro:config', (devServer) => { - vinxiApp.hooks.hook( - 'app:dev:server:created', - ({ devApp: { localFetch } }) => { - const $fetch = createFetch({ - fetch: localFetch, - defaults: { - baseURL: devServer.nitro.options.runtimeConfig.app.baseURL, - }, - }) - - // @ts-expect-error - globalThis.$fetch = $fetch - }, - ) - }) - - return vinxiApp -} - -function importToProjectRelative(p: string) { - const resolved = fileURLToPath(resolve(p, import.meta.url)) - - const relative = path.relative(process.cwd(), resolved) - - return relative -} - -function tsrRoutesManifest(opts: { - tsrConfig: z.infer - clientBase: string -}): vite.Plugin { - let config: vite.ResolvedConfig - - return { - name: 'tsr-routes-manifest', - configResolved(resolvedConfig) { - config = resolvedConfig - }, - resolveId(id) { - if (id === 'tsr:routes-manifest') { - return id - } - return - }, - async load(id) { - if (id === 'tsr:routes-manifest') { - // If we're in development, return a dummy manifest - - if (config.command === 'serve') { - return `export default () => ({ - routes: {} - })` - } - - const clientViteManifestPath = path.resolve( - config.build.outDir, - `../client/${opts.clientBase}/.vite/manifest.json`, - ) - - type ViteManifest = Record< - string, - { - file: string - isEntry: boolean - imports: Array - } - > - - let manifest: ViteManifest - try { - manifest = JSON.parse(await readFile(clientViteManifestPath, 'utf-8')) - } catch (err) { - console.error(err) - throw new Error( - `Could not find the production client vite manifest at '${clientViteManifestPath}'!`, - ) - } - - const routeTreePath = path.resolve(opts.tsrConfig.generatedRouteTree) - - let routeTreeContent: string - try { - routeTreeContent = readFileSync(routeTreePath, 'utf-8') - } catch (err) { - console.error(err) - throw new Error( - `Could not find the generated route tree at '${routeTreePath}'!`, - ) - } - - // Extract the routesManifest JSON from the route tree file. - // It's located between the /* ROUTE_MANIFEST_START and ROUTE_MANIFEST_END */ comment block. - - const routerManifest = JSON.parse( - routeTreeContent.match( - /\/\* ROUTE_MANIFEST_START([\s\S]*?)ROUTE_MANIFEST_END \*\//, - )?.[1] || '{ routes: {} }', - ) as Manifest - - const routes = routerManifest.routes - - let entryFile: - | { - file: string - imports: Array - } - | undefined - - const filesByRouteFilePath: ViteManifest = Object.fromEntries( - Object.entries(manifest).map(([k, v]) => { - if (v.isEntry) { - entryFile = v - } - - const rPath = k.split('?')[0] - - return [rPath, v] - }, {}), - ) - - // Add preloads to the routes from the vite manifest - Object.entries(routes).forEach(([k, v]) => { - const file = - filesByRouteFilePath[ - path.join(opts.tsrConfig.routesDirectory, v.filePath as string) - ] - - if (file) { - const preloads = file.imports.map((d) => - path.join(opts.clientBase, manifest[d]!.file), - ) - - preloads.unshift(path.join(opts.clientBase, file.file)) - - routes[k] = { - ...v, - preloads, - } - } - }) - - if (entryFile) { - routes.__root__!.preloads = [ - path.join(opts.clientBase, entryFile.file), - ...entryFile.imports.map((d) => - path.join(opts.clientBase, manifest[d]!.file), - ), - ] - } - - const recurseRoute = ( - route: { - preloads?: Array - children?: Array - }, - seenPreloads = {} as Record, - ) => { - route.preloads = route.preloads?.filter((preload) => { - if (seenPreloads[preload]) { - return false - } - seenPreloads[preload] = true - return true - }) - - if (route.children) { - route.children.forEach((child) => { - const childRoute = routes[child]! - recurseRoute(childRoute, { ...seenPreloads }) - }) - } - } - - // @ts-expect-error - recurseRoute(routes.__root__) - - const routesManifest = { - routes, - } - - if (process.env.TSR_VITE_DEBUG) { - console.info( - 'Routes Manifest: \n' + JSON.stringify(routesManifest, null, 2), - ) - } - - return `export default () => (${JSON.stringify(routesManifest)})` - } - return - }, - } -} - -function injectDefineEnv( - key: TKey, - value: TValue, -): { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } { - return { - [`process.env.${key}`]: JSON.stringify(value), - [`import.meta.env.${key}`]: JSON.stringify(value), - } as { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } -} diff --git a/packages/react-start-plugin/src/nitro/options.ts b/packages/react-start-plugin/src/nitro/options.ts index d250d3e2ec..c8c8a3d15f 100644 --- a/packages/react-start-plugin/src/nitro/options.ts +++ b/packages/react-start-plugin/src/nitro/options.ts @@ -1,53 +1,53 @@ -import { PrerenderRoute } from 'nitropack'; +import { PrerenderRoute } from 'nitropack' export interface Options { - ssr?: boolean; - ssrBuildDir?: string; + ssr?: boolean + ssrBuildDir?: string /** * Prerender the static pages without producing the server output. */ - static?: boolean; - prerender?: PrerenderOptions; - entryServer?: string; - index?: string; - workspaceRoot?: string; + static?: boolean + prerender?: PrerenderOptions + entryServer?: string + index?: string + workspaceRoot?: string /** * Additional page paths to include */ - additionalPagesDirs?: string[]; + additionalPagesDirs?: string[] /** * Additional API paths to include */ - additionalAPIDirs?: string[]; - apiPrefix?: string; + additionalAPIDirs?: string[] + apiPrefix?: string /** * Toggles internal API middleware. * If disabled, a proxy request is used to route /api * requests to / in the production server build. */ - useAPIMiddleware?: boolean; + useAPIMiddleware?: boolean } export interface PrerenderOptions { /** * Add additional routes to prerender through crawling page links. */ - discover?: boolean; + discover?: boolean /** * List of routes to prerender resolved statically or dynamically. */ routes?: | (string | PrerenderContentDir)[] - | (() => Promise<(string | PrerenderContentDir | undefined)[]>); - sitemap?: SitemapConfig; + | (() => Promise<(string | PrerenderContentDir | undefined)[]>) + sitemap?: SitemapConfig /** List of functions that run for each route after pre-rendering is complete. */ - postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[]; + postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[] } export interface SitemapConfig { - host: string; + host: string } export interface PrerenderContentDir { @@ -55,14 +55,14 @@ export interface PrerenderContentDir { * The directory where files should be grabbed from. * @example `/src/contents/blog` */ - contentDir: string; + contentDir: string /** * Transform the matching content files path into a route. * The function is called for each matching content file within the specified contentDir. * @param file information of the matching file (`path`, `name`, `extension`, `attributes`) * @returns a string with the route should be returned (e. g. `/blog/`) or the value `false`, when the route should not be prerendered. */ - transform: (file: PrerenderContentFile) => string | false; + transform: (file: PrerenderContentFile) => string | false } /** @@ -73,8 +73,8 @@ export interface PrerenderContentDir { * @returns a string with the route should be returned (e. g. `/blog/`) or the value `false`, when the route should not be prerendered. */ export interface PrerenderContentFile { - path: string; - attributes: Record; - name: string; - extension: string; + path: string + attributes: Record + name: string + extension: string } diff --git a/packages/react-start-plugin/src/nitro/utils/load-esm.ts b/packages/react-start-plugin/src/nitro/utils/load-esm.ts index f9a76f683e..78e8049184 100644 --- a/packages/react-start-plugin/src/nitro/utils/load-esm.ts +++ b/packages/react-start-plugin/src/nitro/utils/load-esm.ts @@ -6,7 +6,7 @@ * found in the LICENSE file at https://angular.dev/license */ -import { URL } from 'node:url'; +import { URL } from 'node:url' /** * This uses a dynamic import to load a module which may be ESM. @@ -23,5 +23,5 @@ import { URL } from 'node:url'; export function loadEsmModule(modulePath: string | URL): Promise { return new Function('modulePath', `return import(modulePath);`)( modulePath, - ) as Promise; + ) as Promise } diff --git a/packages/react-start-plugin/src/nitro/vite-plugin-nitro.ts b/packages/react-start-plugin/src/nitro/vite-plugin-nitro.ts index b28b04f643..e69de29bb2 100644 --- a/packages/react-start-plugin/src/nitro/vite-plugin-nitro.ts +++ b/packages/react-start-plugin/src/nitro/vite-plugin-nitro.ts @@ -1,3 +0,0 @@ - - - diff --git a/packages/react-start-plugin/src/schema.ts b/packages/react-start-plugin/src/schema.ts index 516e4e86fa..e0882a17d4 100644 --- a/packages/react-start-plugin/src/schema.ts +++ b/packages/react-start-plugin/src/schema.ts @@ -1,102 +1,10 @@ -import { configSchema } from '@tanstack/router-generator' +import path from 'node:path' +import { existsSync } from 'node:fs' import { z } from 'zod' -import type { PluginOption } from 'vite' -import type { AppOptions as VinxiAppOptions } from 'vinxi' -import type { NitroOptions } from 'nitropack' +import { configSchema, getConfig } from '@tanstack/router-generator' +import type { UserConfig } from 'vite' +import type { NitroConfig } from 'nitropack' import type { Options as ViteReactOptions } from '@vitejs/plugin-react' -import type { CustomizableConfig } from 'vinxi/dist/types/lib/vite-dev' - -type StartUserViteConfig = CustomizableConfig | (() => CustomizableConfig) - -export function getUserViteConfig(config?: StartUserViteConfig): { - plugins: Array | undefined - userConfig: CustomizableConfig -} { - const { plugins, ...userConfig } = - typeof config === 'function' ? config() : { ...config } - return { plugins, userConfig } -} - -/** - * Not all the deployment presets are fully functional or tested. - * @see https://github.com/TanStack/router/pull/2002 - */ -const vinxiDeploymentPresets = [ - 'alwaysdata', // untested - 'aws-amplify', // untested - 'aws-lambda', // untested - 'azure', // untested - 'azure-functions', // untested - 'base-worker', // untested - 'bun', // ✅ working - 'cleavr', // untested - 'cli', // untested - 'cloudflare', // untested - 'cloudflare-module', // untested - 'cloudflare-pages', // ✅ working - 'cloudflare-pages-static', // untested - 'deno', // untested - 'deno-deploy', // untested - 'deno-server', // untested - 'digital-ocean', // untested - 'edgio', // untested - 'firebase', // untested - 'flight-control', // untested - 'github-pages', // untested - 'heroku', // untested - 'iis', // untested - 'iis-handler', // untested - 'iis-node', // untested - 'koyeb', // untested - 'layer0', // untested - 'netlify', // ✅ working - 'netlify-builder', // untested - 'netlify-edge', // untested - 'netlify-static', // untested - 'nitro-dev', // untested - 'nitro-prerender', // untested - 'node', // partially working - 'node-cluster', // untested - 'node-server', // ✅ working - 'platform-sh', // untested - 'service-worker', // untested - 'static', // 🟧 partially working - 'stormkit', // untested - 'vercel', // ✅ working - 'vercel-edge', // untested - 'vercel-static', // untested - 'winterjs', // untested - 'zeabur', // untested - 'zeabur-static', // untested -] as const - -type DeploymentPreset = (typeof vinxiDeploymentPresets)[number] | (string & {}) - -const testedDeploymentPresets: Array = [ - 'bun', - 'netlify', - 'vercel', - 'cloudflare-pages', - 'node-server', -] - -export function checkDeploymentPresetInput(preset: string): DeploymentPreset { - if (!vinxiDeploymentPresets.includes(preset as any)) { - console.warn( - `Invalid deployment preset "${preset}". Available presets are: ${vinxiDeploymentPresets - .map((p) => `"${p}"`) - .join(', ')}.`, - ) - } - - if (!testedDeploymentPresets.includes(preset as any)) { - console.warn( - `The deployment preset '${preset}' is not fully supported yet and may not work as expected.`, - ) - } - - return preset -} type HTTPSOptions = { cert?: string @@ -107,88 +15,131 @@ type HTTPSOptions = { domains?: Array } -type ServerOptions_ = VinxiAppOptions['server'] & { +type ServerOptions = NitroConfig & { https?: boolean | HTTPSOptions } -type ServerOptions = { - [K in keyof ServerOptions_]: ServerOptions_[K] -} - -export const serverSchema = z - .object({ - routeRules: z.custom().optional(), - preset: z.custom().optional(), - static: z.boolean().optional(), - prerender: z - .object({ - routes: z.array(z.string()), - ignore: z - .array( - z.custom< - string | RegExp | ((path: string) => undefined | null | boolean) - >(), - ) - .optional(), - crawlLinks: z.boolean().optional(), - }) - .optional(), - }) - .and(z.custom()) +export const serverSchema = z.custom().and( + z.object({ + preset: z + .custom() + .optional() + .default('node-server'), + }), +) -const viteSchema = z.custom() +const viteSchema = z.custom() const viteReactSchema = z.custom() const routersSchema = z.object({ ssr: z .object({ - entry: z.string().optional(), - middleware: z.string().optional(), + entry: z.string().optional().default('ssr.tsx'), + // middleware: z.string().optional(), vite: viteSchema.optional(), }) - .optional(), + .optional() + .default({}), client: z .object({ - entry: z.string().optional(), - base: z.string().optional(), + entry: z.string().optional().default('client.tsx'), + base: z.string().optional().default('/_build'), vite: viteSchema.optional(), }) - .optional(), + .optional() + .default({}), server: z .object({ - base: z.string().optional(), - globalMiddlewareEntry: z.string().optional(), - middleware: z.string().optional(), + base: z.string().optional().default('/_server'), + globalMiddlewareEntry: z + .string() + .optional() + .default('global-middleware.ts'), + // middleware: z.string().optional(), vite: viteSchema.optional(), }) - .optional(), + .optional() + .default({}), api: z .object({ - entry: z.string().optional(), - middleware: z.string().optional(), + base: z.string().optional().default('/api'), + entry: z.string().optional().default('api.ts'), + // middleware: z.string().optional(), vite: viteSchema.optional(), }) - .optional(), + .optional() + .default({}), public: z .object({ - dir: z.string().optional(), - base: z.string().optional(), + dir: z.string().optional().default('public'), + base: z.string().optional().default('/'), }) - .optional(), + .optional() + .default({}), }) -const tsrConfig = configSchema.partial().extend({ - appDirectory: z.string().optional(), +const sitemapSchema = z.object({ + host: z.string(), }) -export const inlineConfigSchema = z.object({ - react: viteReactSchema.optional(), - vite: viteSchema.optional(), - tsr: tsrConfig.optional(), - routers: routersSchema.optional(), - server: serverSchema.optional(), +const tsrConfig = configSchema.partial().extend({ + // Normally these are `./src/___`, but we're using `./app/___` for Start stuff + appDirectory: z.string().optional().default('app'), }) -export type TanStackStartInputConfig = z.input -export type TanStackStartOutputConfig = z.infer +const TanStackStartOptionsSchema = z + .object({ + root: z.string().optional().default(process.cwd()), + react: viteReactSchema.optional(), + vite: viteSchema.optional(), + tsr: tsrConfig.optional().default({}), + routers: routersSchema.optional().default({}), + server: serverSchema.optional().default({}), + sitemap: sitemapSchema.optional(), + }) + .optional() + .default({}) + +export function getTanStackStartOptions(opts?: TanStackStartInputConfig) { + const options = TanStackStartOptionsSchema.parse(opts) + + const appDirectory = options.tsr.appDirectory + const routesDirectory = + options.tsr.routesDirectory ?? path.join(appDirectory, 'routes') + const generatedRouteTree = + options.tsr.generatedRouteTree ?? + path.join(appDirectory, 'routeTree.gen.ts') + const clientEntryPath = path.join(appDirectory, options.routers.client.entry) + const ssrEntryPath = path.join(appDirectory, options.routers.ssr.entry) + const apiEntryPath = path.join(appDirectory, options.routers.api.entry) + const globalMiddlewareEntryPath = path.join( + appDirectory, + options.routers.server.globalMiddlewareEntry, + ) + const hasApiEntry = existsSync(apiEntryPath) + + return { + ...options, + tsr: { + ...options.tsr, + ...getConfig({ + ...options.tsr, + routesDirectory, + generatedRouteTree, + }), + }, + clientEntryPath, + ssrEntryPath, + apiEntryPath, + globalMiddlewareEntryPath, + hasApiEntry, + } +} + +export type TanStackStartInputConfig = z.input< + typeof TanStackStartOptionsSchema +> +export type TanStackStartOutputConfig = ReturnType< + typeof getTanStackStartOptions +> From a3ce53e27dd900554fbfe105bb4fc19ef0f8250a Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 26 Feb 2025 00:38:17 +0100 Subject: [PATCH 011/155] fix labeler --- .github/labeler.yml | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index b71b1f4c35..7b5316ac2a 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -82,22 +82,6 @@ - 'packages/solid-start-server-functions-ssr/**/*' 'package: start': - 'packages/start/**/*' -'package: start-api-routes': - - 'packages/start-api-routes/**/*' -'package: start-client': - - 'packages/start-client/**/*' -'package: start-plugin': - - 'packages/start-plugin/**/*' -'package: start-router-manifest': - - 'packages/start-router-manifest/**/*' -'package: start-server': - - 'packages/start-server/**/*' -'package: start-server-functions-client': - - 'packages/start-server-functions-client/**/*' -'package: start-server-functions-fetcher': - - 'packages/start-server-functions-fetcher/**/*' -'package: start-server-functions-handler': - - 'packages/start-server-functions-handler/**/*' 'package: start-server-functions-server': - 'packages/start-server-functions-server/**/*' 'package: valibot-adapter': From 4dc7d6e520bd25c37f480a139cf1fef86f09c7d4 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 26 Feb 2025 00:39:18 +0100 Subject: [PATCH 012/155] fix docs --- docs/start/framework/react/middleware.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/start/framework/react/middleware.md b/docs/start/framework/react/middleware.md index a8e71d26b1..c908f5b895 100644 --- a/docs/start/framework/react/middleware.md +++ b/docs/start/framework/react/middleware.md @@ -302,7 +302,7 @@ Here's how to register global middleware: ```tsx // app/global-middleware.ts -import { registerGlobalMiddleware } from '@tanstack/start' +import { registerGlobalMiddleware } from '@tanstack/react-start' import { authMiddleware } from './middleware' registerGlobalMiddleware({ From 9db72f27d865034d4e9d61ac74489e5151bd6005 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 26 Feb 2025 00:40:12 +0100 Subject: [PATCH 013/155] fix package.json --- packages/react-start-plugin/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/react-start-plugin/package.json b/packages/react-start-plugin/package.json index 87f20c1e47..7d2e2977aa 100644 --- a/packages/react-start-plugin/package.json +++ b/packages/react-start-plugin/package.json @@ -7,7 +7,7 @@ "repository": { "type": "git", "url": "https://github.com/TanStack/router.git", - "directory": "packages/start-plugin" + "directory": "packages/react-start-plugin" }, "homepage": "https://tanstack.com/start", "funding": { From 3157b19e02ce67df6f26d938a080d7e9ea76dfec Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 26 Feb 2025 00:53:09 +0100 Subject: [PATCH 014/155] update react-start --- packages/react-start/package.json | 11 ++++++----- packages/react-start/src/plugin.ts | 1 + pnpm-lock.yaml | 3 +++ 3 files changed, 10 insertions(+), 5 deletions(-) create mode 100644 packages/react-start/src/plugin.ts diff --git a/packages/react-start/package.json b/packages/react-start/package.json index e9e977cebe..9acc663ba4 100644 --- a/packages/react-start/package.json +++ b/packages/react-start/package.json @@ -62,14 +62,14 @@ "default": "./dist/cjs/server.cjs" } }, - "./config": { + "./plugin": { "import": { - "types": "./dist/esm/config.d.ts", - "default": "./dist/esm/config.js" + "types": "./dist/esm/plugin.d.ts", + "default": "./dist/esm/plugin.js" }, "require": { - "types": "./dist/cjs/config.d.cts", - "default": "./dist/cjs/config.cjs" + "types": "./dist/cjs/plugin.d.cts", + "default": "./dist/cjs/plugin.cjs" } }, "./api": { @@ -145,6 +145,7 @@ "dependencies": { "@tanstack/react-start-client": "workspace:^", "@tanstack/react-start-server": "workspace:^", + "@tanstack/react-start-plugin": "workspace:^", "@tanstack/react-start-router-manifest": "workspace:^", "@tanstack/react-start-server-functions-client": "workspace:^", "@tanstack/start-server-functions-server": "workspace:^", diff --git a/packages/react-start/src/plugin.ts b/packages/react-start/src/plugin.ts new file mode 100644 index 0000000000..f2f0c6372d --- /dev/null +++ b/packages/react-start/src/plugin.ts @@ -0,0 +1 @@ +export * from '@tanstack/react-start-plugin' \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c0d1263b2c..de497a11c1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5765,6 +5765,9 @@ importers: '@tanstack/react-start-client': specifier: workspace:* version: link:../react-start-client + '@tanstack/react-start-plugin': + specifier: workspace:* + version: link:../react-start-plugin '@tanstack/react-start-router-manifest': specifier: workspace:* version: link:../react-start-router-manifest From b09e263fa5da695e3f915059453f9e5042bae3ef Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 26 Feb 2025 00:59:48 +0100 Subject: [PATCH 015/155] bump zod --- .../basic-esbuild-file-based/package.json | 2 +- .../package.json | 2 +- .../basic-file-based/package.json | 2 +- .../basic-react-query-file-based/package.json | 2 +- .../basic-virtual-file-based/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- e2e/react-start/basic/package.json | 2 +- .../scroll-restoration/package.json | 2 +- e2e/react-start/server-functions/package.json | 2 +- e2e/react-start/website/package.json | 2 +- .../basic-esbuild-file-based/package.json | 2 +- .../package.json | 2 +- .../basic-file-based/package.json | 2 +- .../basic-solid-query-file-based/package.json | 2 +- .../basic-virtual-file-based/package.json | 2 +- .../package.json | 2 +- .../package.json | 2 +- .../react/authenticated-routes/package.json | 2 +- .../basic-default-search-params/package.json | 2 +- examples/react/basic-file-based/package.json | 2 +- .../basic-react-query-file-based/package.json | 2 +- .../basic-virtual-file-based/package.json | 2 +- .../package.json | 2 +- examples/react/deferred-data/package.json | 2 +- .../kitchen-sink-file-based/package.json | 2 +- .../package.json | 2 +- .../kitchen-sink-react-query/package.json | 2 +- examples/react/kitchen-sink/package.json | 2 +- examples/react/large-file-based/package.json | 2 +- .../package.json | 2 +- .../react/quickstart-file-based/package.json | 2 +- .../packages/post-query/package.json | 2 +- .../packages/router/package.json | 2 +- .../packages/router/package.json | 2 +- .../packages/router/package.json | 2 +- .../search-validator-adapters/package.json | 2 +- examples/react/start-bare/package.json | 2 +- .../react/start-convex-trellaux/package.json | 2 +- examples/react/start-trellaux/package.json | 2 +- .../react/with-framer-motion/package.json | 2 +- .../react/with-trpc-react-query/package.json | 2 +- examples/react/with-trpc/package.json | 2 +- .../kitchen-sink-file-based/package.json | 2 +- packages/create-start/package.json | 2 +- packages/react-router/package.json | 2 +- packages/react-start-plugin/src/schema.ts | 2 +- packages/router-generator/package.json | 2 +- packages/router-plugin/package.json | 2 +- packages/zod-adapter/package.json | 2 +- pnpm-lock.yaml | 200 +++++++++--------- 51 files changed, 150 insertions(+), 150 deletions(-) diff --git a/e2e/react-router/basic-esbuild-file-based/package.json b/e2e/react-router/basic-esbuild-file-based/package.json index 0f61ed5f2b..3da8230e83 100644 --- a/e2e/react-router/basic-esbuild-file-based/package.json +++ b/e2e/react-router/basic-esbuild-file-based/package.json @@ -17,7 +17,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/react-router/basic-file-based-code-splitting/package.json b/e2e/react-router/basic-file-based-code-splitting/package.json index b4953d4105..d3cd1e2425 100644 --- a/e2e/react-router/basic-file-based-code-splitting/package.json +++ b/e2e/react-router/basic-file-based-code-splitting/package.json @@ -19,7 +19,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/react-router/basic-file-based/package.json b/e2e/react-router/basic-file-based/package.json index f370c254c1..33c69421d1 100644 --- a/e2e/react-router/basic-file-based/package.json +++ b/e2e/react-router/basic-file-based/package.json @@ -21,7 +21,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/react-router/basic-react-query-file-based/package.json b/e2e/react-router/basic-react-query-file-based/package.json index 57eb2d2afb..444b508488 100644 --- a/e2e/react-router/basic-react-query-file-based/package.json +++ b/e2e/react-router/basic-react-query-file-based/package.json @@ -22,7 +22,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/react-router/basic-virtual-file-based/package.json b/e2e/react-router/basic-virtual-file-based/package.json index c11b54ff41..5d881fc0a4 100644 --- a/e2e/react-router/basic-virtual-file-based/package.json +++ b/e2e/react-router/basic-virtual-file-based/package.json @@ -21,7 +21,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/react-router/basic-virtual-named-export-config-file-based/package.json b/e2e/react-router/basic-virtual-named-export-config-file-based/package.json index 48e74e0fe9..e8548b0db3 100644 --- a/e2e/react-router/basic-virtual-named-export-config-file-based/package.json +++ b/e2e/react-router/basic-virtual-named-export-config-file-based/package.json @@ -21,7 +21,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/react-router/scroll-restoration-sandbox-vite/package.json b/e2e/react-router/scroll-restoration-sandbox-vite/package.json index 133244f7c7..9382a05e28 100644 --- a/e2e/react-router/scroll-restoration-sandbox-vite/package.json +++ b/e2e/react-router/scroll-restoration-sandbox-vite/package.json @@ -24,7 +24,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/react-start/basic/package.json b/e2e/react-start/basic/package.json index ad30aa50f0..2046e82f17 100644 --- a/e2e/react-start/basic/package.json +++ b/e2e/react-start/basic/package.json @@ -19,7 +19,7 @@ "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", "vinxi": "0.5.3", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/react-start/scroll-restoration/package.json b/e2e/react-start/scroll-restoration/package.json index 18c7721181..73a72f7300 100644 --- a/e2e/react-start/scroll-restoration/package.json +++ b/e2e/react-start/scroll-restoration/package.json @@ -20,7 +20,7 @@ "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", "vinxi": "0.5.3", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/react-start/server-functions/package.json b/e2e/react-start/server-functions/package.json index 0e7cfdc8e7..2107818357 100644 --- a/e2e/react-start/server-functions/package.json +++ b/e2e/react-start/server-functions/package.json @@ -20,7 +20,7 @@ "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", "vinxi": "0.5.3", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/react-start/website/package.json b/e2e/react-start/website/package.json index 68a8d611c4..e69c2b3ffa 100644 --- a/e2e/react-start/website/package.json +++ b/e2e/react-start/website/package.json @@ -19,7 +19,7 @@ "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", "vinxi": "0.5.3", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/solid-router/basic-esbuild-file-based/package.json b/e2e/solid-router/basic-esbuild-file-based/package.json index a7aeccf1d1..5640e6b59e 100644 --- a/e2e/solid-router/basic-esbuild-file-based/package.json +++ b/e2e/solid-router/basic-esbuild-file-based/package.json @@ -16,7 +16,7 @@ "@tanstack/zod-adapter": "workspace:^", "redaxios": "^0.5.1", "solid-js": "^1.9.5", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/solid-router/basic-file-based-code-splitting/package.json b/e2e/solid-router/basic-file-based-code-splitting/package.json index 4e04434c8e..ba4a9e2940 100644 --- a/e2e/solid-router/basic-file-based-code-splitting/package.json +++ b/e2e/solid-router/basic-file-based-code-splitting/package.json @@ -18,7 +18,7 @@ "postcss": "^8.5.1", "solid-js": "^1.9.5", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/solid-router/basic-file-based/package.json b/e2e/solid-router/basic-file-based/package.json index 3ddacc3ed5..9bfd059a6d 100644 --- a/e2e/solid-router/basic-file-based/package.json +++ b/e2e/solid-router/basic-file-based/package.json @@ -20,7 +20,7 @@ "solid-js": "^1.9.5", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/solid-router/basic-solid-query-file-based/package.json b/e2e/solid-router/basic-solid-query-file-based/package.json index 7823b343ed..5a27e959de 100644 --- a/e2e/solid-router/basic-solid-query-file-based/package.json +++ b/e2e/solid-router/basic-solid-query-file-based/package.json @@ -21,7 +21,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/solid-router/basic-virtual-file-based/package.json b/e2e/solid-router/basic-virtual-file-based/package.json index 41f35da25a..3d302dee67 100644 --- a/e2e/solid-router/basic-virtual-file-based/package.json +++ b/e2e/solid-router/basic-virtual-file-based/package.json @@ -20,7 +20,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/solid-router/basic-virtual-named-export-config-file-based/package.json b/e2e/solid-router/basic-virtual-named-export-config-file-based/package.json index a1cc90c747..b79d571fb7 100644 --- a/e2e/solid-router/basic-virtual-named-export-config-file-based/package.json +++ b/e2e/solid-router/basic-virtual-named-export-config-file-based/package.json @@ -20,7 +20,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/solid-router/scroll-restoration-sandbox-vite/package.json b/e2e/solid-router/scroll-restoration-sandbox-vite/package.json index 77c0254c6e..936a4a3214 100644 --- a/e2e/solid-router/scroll-restoration-sandbox-vite/package.json +++ b/e2e/solid-router/scroll-restoration-sandbox-vite/package.json @@ -23,7 +23,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/examples/react/authenticated-routes/package.json b/examples/react/authenticated-routes/package.json index 3c4aa5423d..f3ec72458e 100644 --- a/examples/react/authenticated-routes/package.json +++ b/examples/react/authenticated-routes/package.json @@ -18,7 +18,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/basic-default-search-params/package.json b/examples/react/basic-default-search-params/package.json index 05001f5062..f6f3b9fc6a 100644 --- a/examples/react/basic-default-search-params/package.json +++ b/examples/react/basic-default-search-params/package.json @@ -18,7 +18,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/basic-file-based/package.json b/examples/react/basic-file-based/package.json index 5715990a0e..206bd690fe 100644 --- a/examples/react/basic-file-based/package.json +++ b/examples/react/basic-file-based/package.json @@ -18,7 +18,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/basic-react-query-file-based/package.json b/examples/react/basic-react-query-file-based/package.json index 23bef46869..28f2079938 100644 --- a/examples/react/basic-react-query-file-based/package.json +++ b/examples/react/basic-react-query-file-based/package.json @@ -20,7 +20,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/basic-virtual-file-based/package.json b/examples/react/basic-virtual-file-based/package.json index 30cf054889..32ab8c9d92 100644 --- a/examples/react/basic-virtual-file-based/package.json +++ b/examples/react/basic-virtual-file-based/package.json @@ -19,7 +19,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/basic-virtual-inside-file-based/package.json b/examples/react/basic-virtual-inside-file-based/package.json index 316c2d3cc9..8bd6ec4b1a 100644 --- a/examples/react/basic-virtual-inside-file-based/package.json +++ b/examples/react/basic-virtual-inside-file-based/package.json @@ -19,7 +19,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/deferred-data/package.json b/examples/react/deferred-data/package.json index dec0d13a7c..17b18a43d7 100644 --- a/examples/react/deferred-data/package.json +++ b/examples/react/deferred-data/package.json @@ -17,7 +17,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/kitchen-sink-file-based/package.json b/examples/react/kitchen-sink-file-based/package.json index 876f5114cf..4a1f15a38b 100644 --- a/examples/react/kitchen-sink-file-based/package.json +++ b/examples/react/kitchen-sink-file-based/package.json @@ -19,7 +19,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", 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 7068118239..1a9ea69dcf 100644 --- a/examples/react/kitchen-sink-react-query-file-based/package.json +++ b/examples/react/kitchen-sink-react-query-file-based/package.json @@ -21,7 +21,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/kitchen-sink-react-query/package.json b/examples/react/kitchen-sink-react-query/package.json index ef1df060d8..4e24fc4ead 100644 --- a/examples/react/kitchen-sink-react-query/package.json +++ b/examples/react/kitchen-sink-react-query/package.json @@ -20,7 +20,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/kitchen-sink/package.json b/examples/react/kitchen-sink/package.json index 5d6df05178..1439c258c6 100644 --- a/examples/react/kitchen-sink/package.json +++ b/examples/react/kitchen-sink/package.json @@ -18,7 +18,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/large-file-based/package.json b/examples/react/large-file-based/package.json index b6a0123905..07c8ed2672 100644 --- a/examples/react/large-file-based/package.json +++ b/examples/react/large-file-based/package.json @@ -21,7 +21,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/quickstart-esbuild-file-based/package.json b/examples/react/quickstart-esbuild-file-based/package.json index d1016dbb27..7e5701bdb7 100644 --- a/examples/react/quickstart-esbuild-file-based/package.json +++ b/examples/react/quickstart-esbuild-file-based/package.json @@ -15,7 +15,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/quickstart-file-based/package.json b/examples/react/quickstart-file-based/package.json index e19f91f570..7f1ba0dabc 100644 --- a/examples/react/quickstart-file-based/package.json +++ b/examples/react/quickstart-file-based/package.json @@ -18,7 +18,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", 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 25b2a759a4..1ea8a36e06 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 @@ -10,7 +10,7 @@ "dependencies": { "@tanstack/react-query": "^5.66.0", "redaxios": "^0.5.1", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@vitejs/plugin-react": "^4.3.4", 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 6729579003..b2f51ca976 100644 --- a/examples/react/router-monorepo-react-query/packages/router/package.json +++ b/examples/react/router-monorepo-react-query/packages/router/package.json @@ -14,7 +14,7 @@ "@tanstack/router-plugin": "^1.114.3", "@router-mono-react-query/post-query": "workspace:*", "redaxios": "^0.5.1", - "zod": "^3.24.1", + "zod": "^3.24.2", "react": "^19.0.0", "react-dom": "^19.0.0" }, 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 726cbf056c..2fd2e228bc 100644 --- a/examples/react/router-monorepo-simple-lazy/packages/router/package.json +++ b/examples/react/router-monorepo-simple-lazy/packages/router/package.json @@ -12,7 +12,7 @@ "@tanstack/react-router": "^1.114.3", "@tanstack/router-plugin": "^1.114.3", "redaxios": "^0.5.1", - "zod": "^3.24.1", + "zod": "^3.24.2", "react": "^19.0.0", "react-dom": "^19.0.0" }, diff --git a/examples/react/router-monorepo-simple/packages/router/package.json b/examples/react/router-monorepo-simple/packages/router/package.json index 0a0ab9a0bc..2a455a1bf3 100644 --- a/examples/react/router-monorepo-simple/packages/router/package.json +++ b/examples/react/router-monorepo-simple/packages/router/package.json @@ -12,7 +12,7 @@ "@tanstack/react-router": "^1.114.3", "@tanstack/router-plugin": "^1.114.3", "redaxios": "^0.5.1", - "zod": "^3.24.1", + "zod": "^3.24.2", "react": "^19.0.0", "react-dom": "^19.0.0" }, diff --git a/examples/react/search-validator-adapters/package.json b/examples/react/search-validator-adapters/package.json index 8995bf1e8a..68c2a877a3 100644 --- a/examples/react/search-validator-adapters/package.json +++ b/examples/react/search-validator-adapters/package.json @@ -24,7 +24,7 @@ "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", "valibot": "1.0.0-beta.15", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@testing-library/jest-dom": "^6.6.3", diff --git a/examples/react/start-bare/package.json b/examples/react/start-bare/package.json index fb44cff494..b0762950f3 100644 --- a/examples/react/start-bare/package.json +++ b/examples/react/start-bare/package.json @@ -15,7 +15,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "vinxi": "0.5.3", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@tailwindcss/vite": "^4.0.8", diff --git a/examples/react/start-convex-trellaux/package.json b/examples/react/start-convex-trellaux/package.json index aca031b727..793d370a72 100644 --- a/examples/react/start-convex-trellaux/package.json +++ b/examples/react/start-convex-trellaux/package.json @@ -29,7 +29,7 @@ "tailwind-merge": "^2.6.0", "tiny-invariant": "^1.3.3", "vinxi": "0.5.3", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/start-trellaux/package.json b/examples/react/start-trellaux/package.json index db2d2f851d..04211214bf 100644 --- a/examples/react/start-trellaux/package.json +++ b/examples/react/start-trellaux/package.json @@ -24,7 +24,7 @@ "tailwind-merge": "^2.6.0", "tiny-invariant": "^1.3.3", "vinxi": "0.5.3", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/with-framer-motion/package.json b/examples/react/with-framer-motion/package.json index a97679fee8..0bc9030b86 100644 --- a/examples/react/with-framer-motion/package.json +++ b/examples/react/with-framer-motion/package.json @@ -18,7 +18,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/with-trpc-react-query/package.json b/examples/react/with-trpc-react-query/package.json index 6c533c6240..549b022de7 100644 --- a/examples/react/with-trpc-react-query/package.json +++ b/examples/react/with-trpc-react-query/package.json @@ -24,7 +24,7 @@ "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", "vinxi": "0.5.3", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/with-trpc/package.json b/examples/react/with-trpc/package.json index 05679b5cc7..31fc08a2ed 100644 --- a/examples/react/with-trpc/package.json +++ b/examples/react/with-trpc/package.json @@ -21,7 +21,7 @@ "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", "vinxi": "0.5.3", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/solid/kitchen-sink-file-based/package.json b/examples/solid/kitchen-sink-file-based/package.json index d8fa559e12..575cbbab4a 100644 --- a/examples/solid/kitchen-sink-file-based/package.json +++ b/examples/solid/kitchen-sink-file-based/package.json @@ -17,7 +17,7 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@tanstack/router-plugin": "^1.114.3", diff --git a/packages/create-start/package.json b/packages/create-start/package.json index 4f49aeaa09..6aaf61475c 100644 --- a/packages/create-start/package.json +++ b/packages/create-start/package.json @@ -54,7 +54,7 @@ "tiny-invariant": "^1.3.3", "validate-npm-package-name": "^6.0.0", "yocto-spinner": "^0.2.0", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "devDependencies": { "@inquirer/type": "^3.0.4", diff --git a/packages/react-router/package.json b/packages/react-router/package.json index 4328a768f2..06de277d9c 100644 --- a/packages/react-router/package.json +++ b/packages/react-router/package.json @@ -81,7 +81,7 @@ "combinate": "^1.1.11", "react": "^19.0.0", "react-dom": "^19.0.0", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "peerDependencies": { "react": ">=18.0.0 || >=19.0.0", diff --git a/packages/react-start-plugin/src/schema.ts b/packages/react-start-plugin/src/schema.ts index e0882a17d4..ecc939ec63 100644 --- a/packages/react-start-plugin/src/schema.ts +++ b/packages/react-start-plugin/src/schema.ts @@ -142,4 +142,4 @@ export type TanStackStartInputConfig = z.input< > export type TanStackStartOutputConfig = ReturnType< typeof getTanStackStartOptions -> +> \ No newline at end of file diff --git a/packages/router-generator/package.json b/packages/router-generator/package.json index 5f83478650..c84a9182b2 100644 --- a/packages/router-generator/package.json +++ b/packages/router-generator/package.json @@ -68,7 +68,7 @@ "@tanstack/virtual-file-routes": "workspace:^", "tsx": "^4.19.2", "prettier": "^3.5.0", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "peerDependencies": { "@tanstack/react-router": "workspace:^" diff --git a/packages/router-plugin/package.json b/packages/router-plugin/package.json index 843261f09b..d00ff42ccd 100644 --- a/packages/router-plugin/package.json +++ b/packages/router-plugin/package.json @@ -120,7 +120,7 @@ "babel-dead-code-elimination": "^1.0.9", "chokidar": "^3.6.0", "unplugin": "^2.1.2", - "zod": "^3.24.1" + "zod": "^3.24.2" }, "peerDependencies": { "@rsbuild/core": ">=1.0.2", diff --git a/packages/zod-adapter/package.json b/packages/zod-adapter/package.json index be7141fb00..80aef210a4 100644 --- a/packages/zod-adapter/package.json +++ b/packages/zod-adapter/package.json @@ -67,7 +67,7 @@ "@testing-library/jest-dom": "^6.6.3", "@testing-library/react": "^16.2.0", "@tanstack/react-router": "workspace:^", - "zod": "^3.24.1", + "zod": "^3.24.2", "react": "^19.0.0", "react-dom": "^19.0.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index de497a11c1..66f4bd092d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -212,8 +212,8 @@ importers: specifier: ^0.5.1 version: 0.5.1 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -264,8 +264,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -316,8 +316,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -426,8 +426,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -530,8 +530,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -585,8 +585,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -747,8 +747,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -851,8 +851,8 @@ importers: specifier: 0.5.3 version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -1211,8 +1211,8 @@ importers: specifier: 0.5.3 version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -1281,8 +1281,8 @@ importers: specifier: 0.5.3 version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -1351,8 +1351,8 @@ importers: specifier: 0.5.3 version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -1446,8 +1446,8 @@ importers: specifier: ^1.9.5 version: 1.9.5 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -1492,8 +1492,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -1535,8 +1535,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -1667,8 +1667,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -1713,8 +1713,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -1759,8 +1759,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -1900,8 +1900,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -2212,8 +2212,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -2359,8 +2359,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -2454,8 +2454,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -2601,8 +2601,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -2796,8 +2796,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -2848,8 +2848,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -2894,8 +2894,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -2943,8 +2943,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -2995,8 +2995,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -3050,8 +3050,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -3108,8 +3108,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -3160,8 +3160,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -3335,8 +3335,8 @@ importers: specifier: ^0.5.1 version: 0.5.1 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -3378,8 +3378,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -3630,8 +3630,8 @@ importers: specifier: ^0.5.1 version: 0.5.1 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@vitejs/plugin-react': specifier: ^4.3.4 @@ -3670,8 +3670,8 @@ importers: specifier: ^0.5.1 version: 0.5.1 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -3879,8 +3879,8 @@ importers: specifier: ^0.5.1 version: 0.5.1 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -3999,8 +3999,8 @@ importers: specifier: ^0.5.1 version: 0.5.1 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -4109,8 +4109,8 @@ importers: specifier: 1.0.0-beta.15 version: 1.0.0-beta.15(typescript@5.8.2) zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@testing-library/jest-dom': specifier: ^6.6.3 @@ -4155,8 +4155,8 @@ importers: specifier: 0.5.3 version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@tailwindcss/vite': specifier: ^4.0.8 @@ -4567,8 +4567,8 @@ importers: specifier: 0.5.3 version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -4839,8 +4839,8 @@ importers: specifier: 0.5.3 version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -4894,8 +4894,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -4955,8 +4955,8 @@ importers: specifier: 0.5.3 version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -5019,8 +5019,8 @@ importers: specifier: 0.5.3 version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -5302,8 +5302,8 @@ importers: specifier: ^3.4.17 version: 3.4.17 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@tanstack/router-plugin': specifier: workspace:* @@ -5588,8 +5588,8 @@ importers: specifier: ^0.2.0 version: 0.2.0 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 devDependencies: '@inquirer/type': specifier: ^3.0.4 @@ -5717,8 +5717,8 @@ importers: specifier: ^19.0.0 version: 19.0.0(react@19.0.0) zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 packages/react-router-devtools: dependencies: @@ -6228,8 +6228,8 @@ importers: specifier: ^4.19.2 version: 4.19.2 zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 packages/router-plugin: dependencies: @@ -6297,8 +6297,8 @@ importers: specifier: '>=5.92.0' version: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0) zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 packages/router-utils: dependencies: @@ -6872,8 +6872,8 @@ importers: specifier: ^19.0.0 version: 19.0.0(react@19.0.0) zod: - specifier: ^3.24.1 - version: 3.24.1 + specifier: ^3.24.2 + version: 3.24.2 packages: @@ -23582,7 +23582,7 @@ snapshots: unenv: 1.10.0 unstorage: 1.14.4(db0@0.2.3)(ioredis@5.4.2) vite: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - zod: 3.24.1 + zod: 3.24.2 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -23661,7 +23661,7 @@ snapshots: unenv: 1.10.0 unstorage: 1.14.4(db0@0.2.3)(ioredis@5.4.2) vite: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - zod: 3.24.1 + zod: 3.24.2 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' From 0087d6badfb3190566b84881eacebf48080131ca Mon Sep 17 00:00:00 2001 From: "autofix-ci[bot]" <114827586+autofix-ci[bot]@users.noreply.github.com> Date: Wed, 26 Feb 2025 00:01:31 +0000 Subject: [PATCH 016/155] ci: apply automated fixes --- packages/react-start-plugin/src/schema.ts | 2 +- packages/react-start/src/plugin.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/react-start-plugin/src/schema.ts b/packages/react-start-plugin/src/schema.ts index ecc939ec63..e0882a17d4 100644 --- a/packages/react-start-plugin/src/schema.ts +++ b/packages/react-start-plugin/src/schema.ts @@ -142,4 +142,4 @@ export type TanStackStartInputConfig = z.input< > export type TanStackStartOutputConfig = ReturnType< typeof getTanStackStartOptions -> \ No newline at end of file +> diff --git a/packages/react-start/src/plugin.ts b/packages/react-start/src/plugin.ts index f2f0c6372d..d991c3b71c 100644 --- a/packages/react-start/src/plugin.ts +++ b/packages/react-start/src/plugin.ts @@ -1 +1 @@ -export * from '@tanstack/react-start-plugin' \ No newline at end of file +export * from '@tanstack/react-start-plugin' From e33bd0bef027e04bb63c8fe405c2be026cca7f6a Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Wed, 26 Feb 2025 17:27:32 -0700 Subject: [PATCH 017/155] Remove "vinxi" from vocab, make dev html response work --- .prettierignore | 1 - .../framework/react/guide/tanstack-start.md | 15 +- .../framework/react/build-from-scratch.md | 15 +- .../start/framework/react/learn-the-basics.md | 6 +- e2e/create-start/utils/setup.ts | 2 +- e2e/react-start/basic-auth/.gitignore | 2 - e2e/react-start/basic-auth/app/client.tsx | 1 - e2e/react-start/basic-auth/package.json | 11 +- e2e/react-start/basic-react-query/.gitignore | 6 +- .../basic-react-query/app/client.tsx | 1 - .../basic-react-query/package.json | 11 +- e2e/react-start/basic-rsc/.gitignore | 6 +- e2e/react-start/basic-rsc/app/client.tsx | 1 - e2e/react-start/basic-rsc/package.json | 9 +- e2e/react-start/basic-tsr-config/.gitignore | 6 +- e2e/react-start/basic-tsr-config/package.json | 11 +- .../basic-tsr-config/src/app/client.tsx | 1 - .../basic-tsr-config/src/app/ssr.tsx | 1 - e2e/react-start/basic/.gitignore | 2 - e2e/react-start/basic/app/client.tsx | 1 - e2e/react-start/basic/package.json | 9 +- e2e/react-start/clerk-basic/.gitignore | 6 +- e2e/react-start/clerk-basic/app/client.tsx | 1 - e2e/react-start/clerk-basic/package.json | 11 +- e2e/react-start/scroll-restoration/.gitignore | 6 +- .../scroll-restoration/app/client.tsx | 1 - .../scroll-restoration/package.json | 9 +- e2e/react-start/server-functions/.gitignore | 6 +- .../server-functions/app/client.tsx | 1 - e2e/react-start/server-functions/package.json | 9 +- e2e/react-start/website/.gitignore | 6 +- e2e/react-start/website/app/client.tsx | 1 - e2e/react-start/website/app/ssr.tsx | 1 - e2e/react-start/website/package.json | 9 +- examples/react/start-bare/app/client.tsx | 1 - examples/react/start-bare/package.json | 7 +- examples/react/start-basic-auth/.gitignore | 6 +- .../react/start-basic-auth/app/client.tsx | 1 - examples/react/start-basic-auth/app/ssr.tsx | 1 - examples/react/start-basic-auth/package.json | 9 +- .../react/start-basic-react-query/.gitignore | 6 +- .../start-basic-react-query/app/client.tsx | 1 - .../react/start-basic-react-query/app/ssr.tsx | 1 - .../start-basic-react-query/package.json | 9 +- examples/react/start-basic-rsc/.gitignore | 6 +- examples/react/start-basic-rsc/app/client.tsx | 1 - examples/react/start-basic-rsc/app/ssr.tsx | 1 - examples/react/start-basic-rsc/package.json | 9 +- examples/react/start-basic-static/.gitignore | 6 +- .../react/start-basic-static/app/client.tsx | 1 - examples/react/start-basic-static/app/ssr.tsx | 1 - .../react/start-basic-static/package.json | 9 +- examples/react/start-basic/.gitignore | 6 +- examples/react/start-basic/app/client.tsx | 1 - examples/react/start-basic/app/ssr.tsx | 1 - examples/react/start-basic/vite.config.ts | 2 +- examples/react/start-clerk-basic/.gitignore | 6 +- .../react/start-clerk-basic/app/client.tsx | 1 - examples/react/start-clerk-basic/app/ssr.tsx | 1 - examples/react/start-clerk-basic/package.json | 9 +- .../react/start-convex-trellaux/.gitignore | 6 +- .../react/start-convex-trellaux/.stackblitzrc | 2 +- .../start-convex-trellaux/app/client.tsx | 1 - .../react/start-convex-trellaux/app/ssr.tsx | 1 - .../react/start-convex-trellaux/package.json | 7 +- examples/react/start-counter/.gitignore | 6 +- examples/react/start-counter/app/client.tsx | 1 - examples/react/start-counter/app/ssr.tsx | 1 - examples/react/start-counter/package.json | 9 +- examples/react/start-large/.gitignore | 5 +- examples/react/start-large/app/client.tsx | 2 +- examples/react/start-large/app/ssr.tsx | 2 +- examples/react/start-large/package.json | 9 +- .../react/start-supabase-basic/.gitignore | 6 +- .../react/start-supabase-basic/app/client.tsx | 2 +- .../react/start-supabase-basic/app/ssr.tsx | 2 +- .../react/start-supabase-basic/package.json | 9 +- examples/react/start-trellaux/.gitignore | 6 +- examples/react/start-trellaux/app/client.tsx | 1 - examples/react/start-trellaux/app/ssr.tsx | 1 - examples/react/start-trellaux/package.json | 7 +- .../react/with-trpc-react-query/.gitignore | 6 +- .../react/with-trpc-react-query/app.config.js | 6 +- .../react/with-trpc-react-query/app/main.tsx | 2 - .../with-trpc-react-query/app/router.tsx | 2 +- .../react/with-trpc-react-query/package.json | 7 +- examples/react/with-trpc/.gitignore | 6 +- examples/react/with-trpc/app.config.js | 6 +- examples/react/with-trpc/app/main.tsx | 2 - examples/react/with-trpc/app/trpc.ts | 2 +- examples/react/with-trpc/package.json | 7 +- .../templates/core/_dot_gitignore | 4 +- packages/create-start/package.json | 4 - .../create-start/src/modules/core/index.ts | 8 +- .../src/modules/core/template/app/client.tsx | 1 - .../src/modules/core/template/app/ssr.tsx | 1 - .../tests/e2e/templates/barebones.test.ts | 8 +- .../directive-functions-plugin/src/index.ts | 2 - .../tests/compiler.test.ts | 2 - packages/react-start-api-routes/package.json | 3 +- packages/react-start-api-routes/src/index.ts | 19 +- packages/react-start-client/package.json | 3 +- packages/react-start-client/src/index.tsx | 1 - packages/react-start-client/src/renderRSC.tsx | 2 - packages/react-start-plugin/src/index.ts | 59 ++--- .../src/nitro/nitro-plugin.ts | 100 +++------ .../src/nitro/plugins/dev-server-plugin.ts | 12 +- .../src/nitro/vite-plugin-nitro.ts | 0 .../react-start-router-manifest/package.json | 3 +- .../react-start-router-manifest/src/index.ts | 32 ++- .../src/index.ts | 4 +- packages/react-start/vite.config.ts | 2 + .../useStateDestructure@component.tsx | 4 +- .../useStateDestructure@errorComponent.tsx | 2 +- .../useStateDestructure@notFoundComponent.tsx | 2 +- .../useStateDestructure@pendingComponent.tsx | 2 +- .../useStateDestructure@component.tsx | 4 +- .../useStateDestructure@errorComponent.tsx | 2 +- .../useStateDestructure@notFoundComponent.tsx | 2 +- .../useStateDestructure@pendingComponent.tsx | 2 +- ...--notFoundComponent---pendingComponent.tsx | 4 +- .../useStateDestructure@loader.tsx | 2 +- ...--notFoundComponent---pendingComponent.tsx | 4 +- .../production/useStateDestructure@loader.tsx | 2 +- ...--notFoundComponent---pendingComponent.tsx | 4 +- .../useStateDestructure@errorComponent.tsx | 2 +- ...--notFoundComponent---pendingComponent.tsx | 4 +- .../useStateDestructure@errorComponent.tsx | 2 +- .../test-files/react/useStateDestructure.tsx | 6 +- pnpm-lock.yaml | 201 ++---------------- 130 files changed, 272 insertions(+), 669 deletions(-) delete mode 100644 packages/react-start-plugin/src/nitro/vite-plugin-nitro.ts diff --git a/.prettierignore b/.prettierignore index d285f8937d..25c93015ed 100644 --- a/.prettierignore +++ b/.prettierignore @@ -7,7 +7,6 @@ pnpm-lock.yaml **/snapshots **/.vercel -**/.vinxi **/.output **/node_modules node_modules diff --git a/docs/router/framework/react/guide/tanstack-start.md b/docs/router/framework/react/guide/tanstack-start.md index 99db736a7c..900ed67df2 100644 --- a/docs/router/framework/react/guide/tanstack-start.md +++ b/docs/router/framework/react/guide/tanstack-start.md @@ -47,15 +47,12 @@ TanStack Start is powered by the following packages and need to be installed as - [@tanstack/start](https://github.com/tanstack/start) - [@tanstack/react-router](https://tanstack.com/router) -- [Vinxi](https://vinxi.vercel.app/) - -> [!NOTE] -> Vinxi is a temporary dependency that will be replaced by a simple vite plugin or a dedicated Start CLI. +- [Vite](https://vite.dev/) To install them, run: ```shell -npm i @tanstack/start @tanstack/react-router vinxi +npm i @tanstack/start @tanstack/react-router vite ``` You'll also need React and the Vite React plugin, so install their dependencies as well: @@ -72,16 +69,16 @@ npm i -D typescript @types/react @types/react-dom # Update Configuration Files -We'll then update our `package.json` to use Vinxi's CLI and set `"type": "module"`: +We'll then update our `package.json` to use Vite's CLI and set `"type": "module"`: ```jsonc { // ... "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start", + "dev": "vite dev", + "build": "vite build", + "start": "vite start", }, } ``` diff --git a/docs/start/framework/react/build-from-scratch.md b/docs/start/framework/react/build-from-scratch.md index 66eecc1e98..a09e7ff678 100644 --- a/docs/start/framework/react/build-from-scratch.md +++ b/docs/start/framework/react/build-from-scratch.md @@ -47,14 +47,12 @@ We highly recommend using TypeScript with TanStack Start. Create a `tsconfig.jso ## Install Dependencies -TanStack Start is (currently\*) powered by [Vinxi](https://vinxi.vercel.app/) and [TanStack Router](https://tanstack.com/router) and requires them as dependencies. - -> [!NOTE] > \*Vinxi will be removed before version 1.0.0 is released and TanStack will rely only on Vite and Nitro. The commands and APIs that use Vinxi will likely be replaced with a Vite plugin or dedicated TanStack Start CLI. +TanStack Start is (currently\*) powered by [Vite](https://vite.dev/) and [TanStack Router](https://tanstack.com/router) and requires them as dependencies. To install them, run: ```shell -npm i @tanstack/react-start @tanstack/react-router vinxi +npm i @tanstack/react-start @tanstack/react-router vite ``` You'll also need React and the Vite React plugin, so install them too: @@ -72,16 +70,16 @@ npm i -D typescript @types/react @types/react-dom ## Update Configuration Files -We'll then update our `package.json` to use Vinxi's CLI and set `"type": "module"`: +We'll then update our `package.json` to set `"type": "module"`: ```json { // ... "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" + "dev": "vite dev", + "build": "vite build", + "start": "vite start" } } ``` @@ -189,7 +187,6 @@ router information to our client entry point: ```tsx // app/client.tsx -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/docs/start/framework/react/learn-the-basics.md b/docs/start/framework/react/learn-the-basics.md index 4703259c5a..95ac917a6c 100644 --- a/docs/start/framework/react/learn-the-basics.md +++ b/docs/start/framework/react/learn-the-basics.md @@ -7,13 +7,11 @@ This guide will help you learn the basics behind how TanStack Start works, regar ## Dependencies -TanStack Start is (currently\*) powered by [Vinxi](https://vinxi.vercel.app/), [Nitro](https://nitro.unjs.io/) and [TanStack Router](https://tanstack.com/router). +TanStack Start is powered by [Vite](https://vite.dev/), [Nitro](https://nitro.unjs.io/) and [TanStack Router](https://tanstack.com/router). - **TanStack Router**: A router for building web applications. - **Nitro**: A framework for building server applications. -- **Vinxi**: A server framework for building web applications. - -> [!NOTE] Vinxi will be removed before version 1.0.0 is released and TanStack will rely only on Vite and Nitro. The commands and APIs that use Vinxi will likely be replaced with a Vite plugin. +- **Vite**: A build tool for bundling your application. ## It all "Starts" with the Router diff --git a/e2e/create-start/utils/setup.ts b/e2e/create-start/utils/setup.ts index bfb4c1fd53..5f0af79fee 100644 --- a/e2e/create-start/utils/setup.ts +++ b/e2e/create-start/utils/setup.ts @@ -15,7 +15,7 @@ async function _setup( const ADDR = `http://localhost:${port}` const childProcess = exec( - `VITE_SERVER_PORT=${port} pnpm vinxi dev --port ${port}`, + `VITE_SERVER_PORT=${port} pnpm vite dev --port ${port}`, { cwd: projectPath, }, diff --git a/e2e/react-start/basic-auth/.gitignore b/e2e/react-start/basic-auth/.gitignore index b15fed94e2..75a469e80c 100644 --- a/e2e/react-start/basic-auth/.gitignore +++ b/e2e/react-start/basic-auth/.gitignore @@ -7,13 +7,11 @@ yarn.lock .cache .vercel .output -.vinxi /build/ /api/ /server/build /public/build -.vinxi # Sentry Config File .env.sentry-build-plugin /test-results/ diff --git a/e2e/react-start/basic-auth/app/client.tsx b/e2e/react-start/basic-auth/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/e2e/react-start/basic-auth/app/client.tsx +++ b/e2e/react-start/basic-auth/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/e2e/react-start/basic-auth/package.json b/e2e/react-start/basic-auth/package.json index bb04401e02..f0223cf4a1 100644 --- a/e2e/react-start/basic-auth/package.json +++ b/e2e/react-start/basic-auth/package.json @@ -4,10 +4,10 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev --port 3000", - "dev:e2e": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start", + "dev": "vite dev --port 3000", + "dev:e2e": "vite dev", + "build": "vite build", + "start": "vite start", "prisma-generate": "prisma generate", "test:e2e": "exit 0; pnpm run prisma-generate && playwright test --project=chromium" }, @@ -20,8 +20,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", - "tailwind-merge": "^2.6.0", - "vinxi": "0.5.3" + "tailwind-merge": "^2.6.0" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/react-start/basic-react-query/.gitignore b/e2e/react-start/basic-react-query/.gitignore index be342025da..ca63f49885 100644 --- a/e2e/react-start/basic-react-query/.gitignore +++ b/e2e/react-start/basic-react-query/.gitignore @@ -7,14 +7,10 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/e2e/react-start/basic-react-query/app/client.tsx b/e2e/react-start/basic-react-query/app/client.tsx index 31385f57f1..9fb62bd3c2 100644 --- a/e2e/react-start/basic-react-query/app/client.tsx +++ b/e2e/react-start/basic-react-query/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/e2e/react-start/basic-react-query/package.json b/e2e/react-start/basic-react-query/package.json index 4cc7162526..c7d7424af0 100644 --- a/e2e/react-start/basic-react-query/package.json +++ b/e2e/react-start/basic-react-query/package.json @@ -4,10 +4,10 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev --port 3000", - "dev:e2e": "vinxi dev", - "build": "vinxi build && tsc --noEmit", - "start": "vinxi start", + "dev": "vite dev --port 3000", + "dev:e2e": "vite dev", + "build": "vite build && tsc --noEmit", + "start": "vite start", "test:e2e": "playwright test --project=chromium" }, "dependencies": { @@ -20,8 +20,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", - "tailwind-merge": "^2.6.0", - "vinxi": "0.5.3" + "tailwind-merge": "^2.6.0" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/react-start/basic-rsc/.gitignore b/e2e/react-start/basic-rsc/.gitignore index d3387e00cd..3c8e6870b3 100644 --- a/e2e/react-start/basic-rsc/.gitignore +++ b/e2e/react-start/basic-rsc/.gitignore @@ -7,12 +7,8 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin diff --git a/e2e/react-start/basic-rsc/app/client.tsx b/e2e/react-start/basic-rsc/app/client.tsx index 31385f57f1..9fb62bd3c2 100644 --- a/e2e/react-start/basic-rsc/app/client.tsx +++ b/e2e/react-start/basic-rsc/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/e2e/react-start/basic-rsc/package.json b/e2e/react-start/basic-rsc/package.json index c93361fa88..fc2369d466 100644 --- a/e2e/react-start/basic-rsc/package.json +++ b/e2e/react-start/basic-rsc/package.json @@ -4,9 +4,9 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" + "dev": "vite dev", + "build": "vite build", + "start": "vite start" }, "dependencies": { "@babel/plugin-syntax-typescript": "^7.25.9", @@ -16,8 +16,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", - "tailwind-merge": "^2.6.0", - "vinxi": "0.5.3" + "tailwind-merge": "^2.6.0" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/e2e/react-start/basic-tsr-config/.gitignore b/e2e/react-start/basic-tsr-config/.gitignore index 2b76174be5..08eba9e706 100644 --- a/e2e/react-start/basic-tsr-config/.gitignore +++ b/e2e/react-start/basic-tsr-config/.gitignore @@ -7,14 +7,10 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/e2e/react-start/basic-tsr-config/package.json b/e2e/react-start/basic-tsr-config/package.json index cd697d2bfb..78fa63c5fc 100644 --- a/e2e/react-start/basic-tsr-config/package.json +++ b/e2e/react-start/basic-tsr-config/package.json @@ -4,18 +4,17 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev --port 3000", - "dev:e2e": "vinxi dev", - "build": "rimraf ./count.txt && vinxi build && tsc --noEmit", - "start": "vinxi start", + "dev": "vite dev --port 3000", + "dev:e2e": "vite dev", + "build": "rimraf ./count.txt && vite build && tsc --noEmit", + "start": "vite start", "test:e2e": "playwright test --project=chromium" }, "dependencies": { "@tanstack/react-router": "workspace:^", "@tanstack/react-start": "workspace:^", "react": "^19.0.0", - "react-dom": "^19.0.0", - "vinxi": "0.5.3" + "react-dom": "^19.0.0" }, "devDependencies": { "@tanstack/router-e2e-utils": "workspace:^", diff --git a/e2e/react-start/basic-tsr-config/src/app/client.tsx b/e2e/react-start/basic-tsr-config/src/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/e2e/react-start/basic-tsr-config/src/app/client.tsx +++ b/e2e/react-start/basic-tsr-config/src/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/e2e/react-start/basic-tsr-config/src/app/ssr.tsx b/e2e/react-start/basic-tsr-config/src/app/ssr.tsx index 8981a9a338..65a580f25e 100644 --- a/e2e/react-start/basic-tsr-config/src/app/ssr.tsx +++ b/e2e/react-start/basic-tsr-config/src/app/ssr.tsx @@ -1,4 +1,3 @@ -/// import { createStartHandler, defaultStreamHandler, diff --git a/e2e/react-start/basic/.gitignore b/e2e/react-start/basic/.gitignore index be342025da..a79d5cf129 100644 --- a/e2e/react-start/basic/.gitignore +++ b/e2e/react-start/basic/.gitignore @@ -7,13 +7,11 @@ yarn.lock .env .vercel .output -.vinxi /build/ /api/ /server/build /public/build -.vinxi # Sentry Config File .env.sentry-build-plugin /test-results/ diff --git a/e2e/react-start/basic/app/client.tsx b/e2e/react-start/basic/app/client.tsx index b14d8aac68..ffee5f382c 100644 --- a/e2e/react-start/basic/app/client.tsx +++ b/e2e/react-start/basic/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/start' import { createRouter } from './router' diff --git a/e2e/react-start/basic/package.json b/e2e/react-start/basic/package.json index 2046e82f17..8f0fd1fb2f 100644 --- a/e2e/react-start/basic/package.json +++ b/e2e/react-start/basic/package.json @@ -4,10 +4,10 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev --port 3000", - "dev:e2e": "vinxi dev", - "build": "vinxi build && tsc --noEmit", - "start": "vinxi start", + "dev": "vite dev --port 3000", + "dev:e2e": "vite dev", + "build": "vite build && tsc --noEmit", + "start": "vite start", "test:e2e": "playwright test --project=chromium" }, "dependencies": { @@ -18,7 +18,6 @@ "react-dom": "^19.0.0", "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", - "vinxi": "0.5.3", "zod": "^3.24.2" }, "devDependencies": { diff --git a/e2e/react-start/clerk-basic/.gitignore b/e2e/react-start/clerk-basic/.gitignore index b15fed94e2..2818549158 100644 --- a/e2e/react-start/clerk-basic/.gitignore +++ b/e2e/react-start/clerk-basic/.gitignore @@ -7,14 +7,10 @@ yarn.lock .cache .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/e2e/react-start/clerk-basic/app/client.tsx b/e2e/react-start/clerk-basic/app/client.tsx index 31385f57f1..9fb62bd3c2 100644 --- a/e2e/react-start/clerk-basic/app/client.tsx +++ b/e2e/react-start/clerk-basic/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/e2e/react-start/clerk-basic/package.json b/e2e/react-start/clerk-basic/package.json index 2f517dce0d..3bd0300ca5 100644 --- a/e2e/react-start/clerk-basic/package.json +++ b/e2e/react-start/clerk-basic/package.json @@ -4,10 +4,10 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev --port 3000", - "dev:e2e": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start", + "dev": "vite dev --port 3000", + "dev:e2e": "vite dev", + "build": "vite build", + "start": "vite start", "test:e2e": "exit 0; playwright test --project=chromium" }, "dependencies": { @@ -18,8 +18,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", - "tailwind-merge": "^2.6.0", - "vinxi": "0.5.3" + "tailwind-merge": "^2.6.0" }, "devDependencies": { "@playwright/test": "^1.50.1", diff --git a/e2e/react-start/scroll-restoration/.gitignore b/e2e/react-start/scroll-restoration/.gitignore index be342025da..ca63f49885 100644 --- a/e2e/react-start/scroll-restoration/.gitignore +++ b/e2e/react-start/scroll-restoration/.gitignore @@ -7,14 +7,10 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/e2e/react-start/scroll-restoration/app/client.tsx b/e2e/react-start/scroll-restoration/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/e2e/react-start/scroll-restoration/app/client.tsx +++ b/e2e/react-start/scroll-restoration/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/e2e/react-start/scroll-restoration/package.json b/e2e/react-start/scroll-restoration/package.json index 73a72f7300..de9d765fad 100644 --- a/e2e/react-start/scroll-restoration/package.json +++ b/e2e/react-start/scroll-restoration/package.json @@ -4,10 +4,10 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev --port 3000", - "dev:e2e": "vinxi dev", - "build": "vinxi build && tsc --noEmit", - "start": "vinxi start", + "dev": "vite dev --port 3000", + "dev:e2e": "vite dev", + "build": "vite build && tsc --noEmit", + "start": "vite start", "test:e2e": "playwright test --project=chromium" }, "dependencies": { @@ -19,7 +19,6 @@ "react-dom": "^19.0.0", "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", - "vinxi": "0.5.3", "zod": "^3.24.2" }, "devDependencies": { diff --git a/e2e/react-start/server-functions/.gitignore b/e2e/react-start/server-functions/.gitignore index be342025da..ca63f49885 100644 --- a/e2e/react-start/server-functions/.gitignore +++ b/e2e/react-start/server-functions/.gitignore @@ -7,14 +7,10 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/e2e/react-start/server-functions/app/client.tsx b/e2e/react-start/server-functions/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/e2e/react-start/server-functions/app/client.tsx +++ b/e2e/react-start/server-functions/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/e2e/react-start/server-functions/package.json b/e2e/react-start/server-functions/package.json index 2107818357..4d48b8f7da 100644 --- a/e2e/react-start/server-functions/package.json +++ b/e2e/react-start/server-functions/package.json @@ -4,10 +4,10 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev --port 3000", - "dev:e2e": "vinxi dev", - "build": "vinxi build && tsc --noEmit", - "start": "vinxi start", + "dev": "vite dev --port 3000", + "dev:e2e": "vite dev", + "build": "vite build && tsc --noEmit", + "start": "vite start", "test:e2e": "playwright test --project=chromium" }, "dependencies": { @@ -19,7 +19,6 @@ "react-dom": "^19.0.0", "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", - "vinxi": "0.5.3", "zod": "^3.24.2" }, "devDependencies": { diff --git a/e2e/react-start/website/.gitignore b/e2e/react-start/website/.gitignore index be342025da..ca63f49885 100644 --- a/e2e/react-start/website/.gitignore +++ b/e2e/react-start/website/.gitignore @@ -7,14 +7,10 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/e2e/react-start/website/app/client.tsx b/e2e/react-start/website/app/client.tsx index 31385f57f1..9fb62bd3c2 100644 --- a/e2e/react-start/website/app/client.tsx +++ b/e2e/react-start/website/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/e2e/react-start/website/app/ssr.tsx b/e2e/react-start/website/app/ssr.tsx index 8981a9a338..65a580f25e 100644 --- a/e2e/react-start/website/app/ssr.tsx +++ b/e2e/react-start/website/app/ssr.tsx @@ -1,4 +1,3 @@ -/// import { createStartHandler, defaultStreamHandler, diff --git a/e2e/react-start/website/package.json b/e2e/react-start/website/package.json index e69c2b3ffa..980aa9ca51 100644 --- a/e2e/react-start/website/package.json +++ b/e2e/react-start/website/package.json @@ -4,10 +4,10 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev --port 3000", - "dev:e2e": "vinxi dev", - "build": "vinxi build && tsc --noEmit", - "start": "vinxi start", + "dev": "vite dev --port 3000", + "dev:e2e": "vite dev", + "build": "vite build && tsc --noEmit", + "start": "vite start", "test:e2e": "playwright test --project=chromium" }, "dependencies": { @@ -18,7 +18,6 @@ "react-dom": "^19.0.0", "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", - "vinxi": "0.5.3", "zod": "^3.24.2" }, "devDependencies": { diff --git a/examples/react/start-bare/app/client.tsx b/examples/react/start-bare/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/examples/react/start-bare/app/client.tsx +++ b/examples/react/start-bare/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/examples/react/start-bare/package.json b/examples/react/start-bare/package.json index b0762950f3..ba8e8796a8 100644 --- a/examples/react/start-bare/package.json +++ b/examples/react/start-bare/package.json @@ -4,9 +4,9 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" + "dev": "vite dev", + "build": "vite build", + "start": "vite start" }, "dependencies": { "@tanstack/react-router": "^1.114.3", @@ -14,7 +14,6 @@ "@tanstack/react-start": "^1.114.3", "react": "^19.0.0", "react-dom": "^19.0.0", - "vinxi": "0.5.3", "zod": "^3.24.2" }, "devDependencies": { diff --git a/examples/react/start-basic-auth/.gitignore b/examples/react/start-basic-auth/.gitignore index b15fed94e2..2818549158 100644 --- a/examples/react/start-basic-auth/.gitignore +++ b/examples/react/start-basic-auth/.gitignore @@ -7,14 +7,10 @@ yarn.lock .cache .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/examples/react/start-basic-auth/app/client.tsx b/examples/react/start-basic-auth/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/examples/react/start-basic-auth/app/client.tsx +++ b/examples/react/start-basic-auth/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/examples/react/start-basic-auth/app/ssr.tsx b/examples/react/start-basic-auth/app/ssr.tsx index 8981a9a338..65a580f25e 100644 --- a/examples/react/start-basic-auth/app/ssr.tsx +++ b/examples/react/start-basic-auth/app/ssr.tsx @@ -1,4 +1,3 @@ -/// import { createStartHandler, defaultStreamHandler, diff --git a/examples/react/start-basic-auth/package.json b/examples/react/start-basic-auth/package.json index 7a6fcba0f1..a868ef024f 100644 --- a/examples/react/start-basic-auth/package.json +++ b/examples/react/start-basic-auth/package.json @@ -4,9 +4,9 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start", + "dev": "vite dev", + "build": "vite build", + "start": "vite start", "prisma-generate": "prisma generate" }, "dependencies": { @@ -18,8 +18,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", - "tailwind-merge": "^2.6.0", - "vinxi": "0.5.3" + "tailwind-merge": "^2.6.0" }, "devDependencies": { "@types/node": "^22.5.4", diff --git a/examples/react/start-basic-react-query/.gitignore b/examples/react/start-basic-react-query/.gitignore index be342025da..ca63f49885 100644 --- a/examples/react/start-basic-react-query/.gitignore +++ b/examples/react/start-basic-react-query/.gitignore @@ -7,14 +7,10 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/examples/react/start-basic-react-query/app/client.tsx b/examples/react/start-basic-react-query/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/examples/react/start-basic-react-query/app/client.tsx +++ b/examples/react/start-basic-react-query/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/examples/react/start-basic-react-query/app/ssr.tsx b/examples/react/start-basic-react-query/app/ssr.tsx index 8981a9a338..65a580f25e 100644 --- a/examples/react/start-basic-react-query/app/ssr.tsx +++ b/examples/react/start-basic-react-query/app/ssr.tsx @@ -1,4 +1,3 @@ -/// import { createStartHandler, defaultStreamHandler, diff --git a/examples/react/start-basic-react-query/package.json b/examples/react/start-basic-react-query/package.json index 31e4737373..6832b69457 100644 --- a/examples/react/start-basic-react-query/package.json +++ b/examples/react/start-basic-react-query/package.json @@ -4,9 +4,9 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" + "dev": "vite dev", + "build": "vite build", + "start": "vite start" }, "dependencies": { "@tanstack/react-query": "^5.66.0", @@ -18,8 +18,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", - "tailwind-merge": "^2.6.0", - "vinxi": "0.5.3" + "tailwind-merge": "^2.6.0" }, "devDependencies": { "@types/node": "^22.5.4", diff --git a/examples/react/start-basic-rsc/.gitignore b/examples/react/start-basic-rsc/.gitignore index d3387e00cd..3c8e6870b3 100644 --- a/examples/react/start-basic-rsc/.gitignore +++ b/examples/react/start-basic-rsc/.gitignore @@ -7,12 +7,8 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin diff --git a/examples/react/start-basic-rsc/app/client.tsx b/examples/react/start-basic-rsc/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/examples/react/start-basic-rsc/app/client.tsx +++ b/examples/react/start-basic-rsc/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/examples/react/start-basic-rsc/app/ssr.tsx b/examples/react/start-basic-rsc/app/ssr.tsx index 8981a9a338..65a580f25e 100644 --- a/examples/react/start-basic-rsc/app/ssr.tsx +++ b/examples/react/start-basic-rsc/app/ssr.tsx @@ -1,4 +1,3 @@ -/// import { createStartHandler, defaultStreamHandler, diff --git a/examples/react/start-basic-rsc/package.json b/examples/react/start-basic-rsc/package.json index 3450e46e66..a7a543c641 100644 --- a/examples/react/start-basic-rsc/package.json +++ b/examples/react/start-basic-rsc/package.json @@ -4,9 +4,9 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" + "dev": "vite dev", + "build": "vite build", + "start": "vite start" }, "dependencies": { "@babel/plugin-syntax-typescript": "^7.25.9", @@ -16,8 +16,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", - "tailwind-merge": "^2.6.0", - "vinxi": "0.5.3" + "tailwind-merge": "^2.6.0" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/start-basic-static/.gitignore b/examples/react/start-basic-static/.gitignore index be342025da..ca63f49885 100644 --- a/examples/react/start-basic-static/.gitignore +++ b/examples/react/start-basic-static/.gitignore @@ -7,14 +7,10 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/examples/react/start-basic-static/app/client.tsx b/examples/react/start-basic-static/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/examples/react/start-basic-static/app/client.tsx +++ b/examples/react/start-basic-static/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/examples/react/start-basic-static/app/ssr.tsx b/examples/react/start-basic-static/app/ssr.tsx index 8981a9a338..65a580f25e 100644 --- a/examples/react/start-basic-static/app/ssr.tsx +++ b/examples/react/start-basic-static/app/ssr.tsx @@ -1,4 +1,3 @@ -/// import { createStartHandler, defaultStreamHandler, diff --git a/examples/react/start-basic-static/package.json b/examples/react/start-basic-static/package.json index 83f461bb75..a3dce14b35 100644 --- a/examples/react/start-basic-static/package.json +++ b/examples/react/start-basic-static/package.json @@ -4,9 +4,9 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" + "dev": "vite dev", + "build": "vite build", + "start": "vite start" }, "dependencies": { "@tanstack/react-router": "^1.114.3", @@ -15,8 +15,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", - "tailwind-merge": "^2.5.5", - "vinxi": "0.5.1" + "tailwind-merge": "^2.5.5" }, "devDependencies": { "@types/node": "^22.5.4", diff --git a/examples/react/start-basic/.gitignore b/examples/react/start-basic/.gitignore index be342025da..ca63f49885 100644 --- a/examples/react/start-basic/.gitignore +++ b/examples/react/start-basic/.gitignore @@ -7,14 +7,10 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/examples/react/start-basic/app/client.tsx b/examples/react/start-basic/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/examples/react/start-basic/app/client.tsx +++ b/examples/react/start-basic/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/examples/react/start-basic/app/ssr.tsx b/examples/react/start-basic/app/ssr.tsx index 8981a9a338..65a580f25e 100644 --- a/examples/react/start-basic/app/ssr.tsx +++ b/examples/react/start-basic/app/ssr.tsx @@ -1,4 +1,3 @@ -/// import { createStartHandler, defaultStreamHandler, diff --git a/examples/react/start-basic/vite.config.ts b/examples/react/start-basic/vite.config.ts index 1bf4c44472..47532c5353 100644 --- a/examples/react/start-basic/vite.config.ts +++ b/examples/react/start-basic/vite.config.ts @@ -1,6 +1,6 @@ import { defineConfig } from 'vite' import tsConfigPaths from 'vite-tsconfig-paths' -import { TanStackStartVitePlugin } from '@tanstack/start/plugin' +import { TanStackStartVitePlugin } from '@tanstack/react-start/plugin' export default defineConfig({ server: { diff --git a/examples/react/start-clerk-basic/.gitignore b/examples/react/start-clerk-basic/.gitignore index b15fed94e2..2818549158 100644 --- a/examples/react/start-clerk-basic/.gitignore +++ b/examples/react/start-clerk-basic/.gitignore @@ -7,14 +7,10 @@ yarn.lock .cache .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/examples/react/start-clerk-basic/app/client.tsx b/examples/react/start-clerk-basic/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/examples/react/start-clerk-basic/app/client.tsx +++ b/examples/react/start-clerk-basic/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/examples/react/start-clerk-basic/app/ssr.tsx b/examples/react/start-clerk-basic/app/ssr.tsx index 363e47546d..ef5ba0bc95 100644 --- a/examples/react/start-clerk-basic/app/ssr.tsx +++ b/examples/react/start-clerk-basic/app/ssr.tsx @@ -1,4 +1,3 @@ -/// import { createStartHandler, defaultStreamHandler, diff --git a/examples/react/start-clerk-basic/package.json b/examples/react/start-clerk-basic/package.json index 3c6eeed6cd..a5430fc385 100644 --- a/examples/react/start-clerk-basic/package.json +++ b/examples/react/start-clerk-basic/package.json @@ -4,9 +4,9 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" + "dev": "vite dev", + "build": "vite build", + "start": "vite start" }, "dependencies": { "@clerk/tanstack-start": "0.11.0", @@ -16,8 +16,7 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "redaxios": "^0.5.1", - "tailwind-merge": "^2.6.0", - "vinxi": "0.5.3" + "tailwind-merge": "^2.6.0" }, "devDependencies": { "@types/node": "^22.5.4", diff --git a/examples/react/start-convex-trellaux/.gitignore b/examples/react/start-convex-trellaux/.gitignore index 30518e7416..ba7dbddfbe 100644 --- a/examples/react/start-convex-trellaux/.gitignore +++ b/examples/react/start-convex-trellaux/.gitignore @@ -7,14 +7,10 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin .env.local diff --git a/examples/react/start-convex-trellaux/.stackblitzrc b/examples/react/start-convex-trellaux/.stackblitzrc index 2f76846e62..e616ee3a78 100644 --- a/examples/react/start-convex-trellaux/.stackblitzrc +++ b/examples/react/start-convex-trellaux/.stackblitzrc @@ -1,3 +1,3 @@ { - "startCommand": "cp .env.local.example .env.local && npx vinxi dev" + "startCommand": "cp .env.local.example .env.local && npx vite dev" } diff --git a/examples/react/start-convex-trellaux/app/client.tsx b/examples/react/start-convex-trellaux/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/examples/react/start-convex-trellaux/app/client.tsx +++ b/examples/react/start-convex-trellaux/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/examples/react/start-convex-trellaux/app/ssr.tsx b/examples/react/start-convex-trellaux/app/ssr.tsx index 8981a9a338..65a580f25e 100644 --- a/examples/react/start-convex-trellaux/app/ssr.tsx +++ b/examples/react/start-convex-trellaux/app/ssr.tsx @@ -1,4 +1,3 @@ -/// import { createStartHandler, defaultStreamHandler, diff --git a/examples/react/start-convex-trellaux/package.json b/examples/react/start-convex-trellaux/package.json index 793d370a72..cab72fe6fe 100644 --- a/examples/react/start-convex-trellaux/package.json +++ b/examples/react/start-convex-trellaux/package.json @@ -5,10 +5,10 @@ "type": "module", "scripts": { "dev": "npx convex dev --once && concurrently -r npm:dev:web npm:dev:db", - "dev:web": "vinxi dev", + "dev:web": "vite dev", "dev:db": "convex dev --run board:seed", - "build": "vinxi build", - "start": "vinxi start" + "build": "vite build", + "start": "vite start" }, "dependencies": { "@convex-dev/react-query": "0.0.0-alpha.8", @@ -28,7 +28,6 @@ "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", "tiny-invariant": "^1.3.3", - "vinxi": "0.5.3", "zod": "^3.24.2" }, "devDependencies": { diff --git a/examples/react/start-counter/.gitignore b/examples/react/start-counter/.gitignore index 2b76174be5..08eba9e706 100644 --- a/examples/react/start-counter/.gitignore +++ b/examples/react/start-counter/.gitignore @@ -7,14 +7,10 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/examples/react/start-counter/app/client.tsx b/examples/react/start-counter/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/examples/react/start-counter/app/client.tsx +++ b/examples/react/start-counter/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/examples/react/start-counter/app/ssr.tsx b/examples/react/start-counter/app/ssr.tsx index 8981a9a338..65a580f25e 100644 --- a/examples/react/start-counter/app/ssr.tsx +++ b/examples/react/start-counter/app/ssr.tsx @@ -1,4 +1,3 @@ -/// import { createStartHandler, defaultStreamHandler, diff --git a/examples/react/start-counter/package.json b/examples/react/start-counter/package.json index ca30ed9dc1..6946b37a39 100644 --- a/examples/react/start-counter/package.json +++ b/examples/react/start-counter/package.json @@ -4,17 +4,16 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" + "dev": "vite dev", + "build": "vite build", + "start": "vite start" }, "dependencies": { "@tanstack/react-router": "^1.114.3", "@tanstack/react-router-devtools": "^1.114.3", "@tanstack/react-start": "^1.114.3", "react": "^19.0.0", - "react-dom": "^19.0.0", - "vinxi": "0.5.3" + "react-dom": "^19.0.0" }, "devDependencies": { "@types/node": "^22.5.4", diff --git a/examples/react/start-large/.gitignore b/examples/react/start-large/.gitignore index cb9991202d..ca4ef70bc0 100644 --- a/examples/react/start-large/.gitignore +++ b/examples/react/start-large/.gitignore @@ -13,10 +13,7 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi \ No newline at end of file +/public/build \ No newline at end of file diff --git a/examples/react/start-large/app/client.tsx b/examples/react/start-large/app/client.tsx index c9080c9132..6ef47afdd4 100644 --- a/examples/react/start-large/app/client.tsx +++ b/examples/react/start-large/app/client.tsx @@ -1,5 +1,5 @@ // app/client.tsx -/// + import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/examples/react/start-large/app/ssr.tsx b/examples/react/start-large/app/ssr.tsx index c3bb4cc868..b25c3c5648 100644 --- a/examples/react/start-large/app/ssr.tsx +++ b/examples/react/start-large/app/ssr.tsx @@ -1,5 +1,5 @@ // app/ssr.tsx -/// + import { createStartHandler, defaultStreamHandler, diff --git a/examples/react/start-large/package.json b/examples/react/start-large/package.json index 9f4dda61fb..0541ff343b 100644 --- a/examples/react/start-large/package.json +++ b/examples/react/start-large/package.json @@ -4,9 +4,9 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start", + "dev": "vite dev", + "build": "vite build", + "start": "vite start", "gen": "node ./app/createRoutes.mjs", "test:types": "tsc --extendedDiagnostics" }, @@ -19,8 +19,7 @@ "react-dom": "^19.0.0", "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", - "valibot": "^1.0.0-beta.15", - "vinxi": "0.5.3" + "valibot": "^1.0.0-beta.15" }, "devDependencies": { "@types/node": "^22.5.4", diff --git a/examples/react/start-supabase-basic/.gitignore b/examples/react/start-supabase-basic/.gitignore index 5578fb7487..8293849e8d 100644 --- a/examples/react/start-supabase-basic/.gitignore +++ b/examples/react/start-supabase-basic/.gitignore @@ -9,14 +9,10 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/examples/react/start-supabase-basic/app/client.tsx b/examples/react/start-supabase-basic/app/client.tsx index c9080c9132..6ef47afdd4 100644 --- a/examples/react/start-supabase-basic/app/client.tsx +++ b/examples/react/start-supabase-basic/app/client.tsx @@ -1,5 +1,5 @@ // app/client.tsx -/// + import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/examples/react/start-supabase-basic/app/ssr.tsx b/examples/react/start-supabase-basic/app/ssr.tsx index c3bb4cc868..b25c3c5648 100644 --- a/examples/react/start-supabase-basic/app/ssr.tsx +++ b/examples/react/start-supabase-basic/app/ssr.tsx @@ -1,5 +1,5 @@ // app/ssr.tsx -/// + import { createStartHandler, defaultStreamHandler, diff --git a/examples/react/start-supabase-basic/package.json b/examples/react/start-supabase-basic/package.json index de512d98ad..6f7bcdd827 100644 --- a/examples/react/start-supabase-basic/package.json +++ b/examples/react/start-supabase-basic/package.json @@ -5,9 +5,9 @@ "main": "index.js", "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" + "dev": "vite dev", + "build": "vite build", + "start": "vite start" }, "keywords": [], "author": "", @@ -19,8 +19,7 @@ "@tanstack/react-router-devtools": "^1.114.3", "@tanstack/react-start": "^1.114.3", "react": "^19.0.0", - "react-dom": "^19.0.0", - "vinxi": "0.5.3" + "react-dom": "^19.0.0" }, "devDependencies": { "@types/react": "^19.0.8", diff --git a/examples/react/start-trellaux/.gitignore b/examples/react/start-trellaux/.gitignore index d3387e00cd..3c8e6870b3 100644 --- a/examples/react/start-trellaux/.gitignore +++ b/examples/react/start-trellaux/.gitignore @@ -7,12 +7,8 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin diff --git a/examples/react/start-trellaux/app/client.tsx b/examples/react/start-trellaux/app/client.tsx index 1593d1b3c7..c5fbaa3c67 100644 --- a/examples/react/start-trellaux/app/client.tsx +++ b/examples/react/start-trellaux/app/client.tsx @@ -1,4 +1,3 @@ -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/examples/react/start-trellaux/app/ssr.tsx b/examples/react/start-trellaux/app/ssr.tsx index 8981a9a338..65a580f25e 100644 --- a/examples/react/start-trellaux/app/ssr.tsx +++ b/examples/react/start-trellaux/app/ssr.tsx @@ -1,4 +1,3 @@ -/// import { createStartHandler, defaultStreamHandler, diff --git a/examples/react/start-trellaux/package.json b/examples/react/start-trellaux/package.json index 04211214bf..0bd9f6253a 100644 --- a/examples/react/start-trellaux/package.json +++ b/examples/react/start-trellaux/package.json @@ -4,9 +4,9 @@ "sideEffects": false, "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" + "dev": "vite dev", + "build": "vite build", + "start": "vite start" }, "dependencies": { "@tanstack/react-query": "^5.66.0", @@ -23,7 +23,6 @@ "redaxios": "^0.5.1", "tailwind-merge": "^2.6.0", "tiny-invariant": "^1.3.3", - "vinxi": "0.5.3", "zod": "^3.24.2" }, "devDependencies": { diff --git a/examples/react/with-trpc-react-query/.gitignore b/examples/react/with-trpc-react-query/.gitignore index be342025da..ca63f49885 100644 --- a/examples/react/with-trpc-react-query/.gitignore +++ b/examples/react/with-trpc-react-query/.gitignore @@ -7,14 +7,10 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/examples/react/with-trpc-react-query/app.config.js b/examples/react/with-trpc-react-query/app.config.js index 1598094be8..c4847edca0 100644 --- a/examples/react/with-trpc-react-query/app.config.js +++ b/examples/react/with-trpc-react-query/app.config.js @@ -1,8 +1,10 @@ -import { createApp } from 'vinxi' +import { defineConfig } from 'vite' import reactRefresh from '@vitejs/plugin-react' import { TanStackRouterVite } from '@tanstack/router-plugin/vite' -export default createApp({ +// TODO: Need to migrate this to vite and the new TanStack Start plugin + +export default defineConfig({ server: { preset: 'node-server', // change to 'netlify' or 'bun' or anyof the supported presets for nitro (nitro.unjs.io) experimental: { diff --git a/examples/react/with-trpc-react-query/app/main.tsx b/examples/react/with-trpc-react-query/app/main.tsx index 4cc69baaac..bda5f47256 100644 --- a/examples/react/with-trpc-react-query/app/main.tsx +++ b/examples/react/with-trpc-react-query/app/main.tsx @@ -1,5 +1,3 @@ -/// - import React from 'react' import ReactDOM from 'react-dom/client' import { RouterProvider } from '@tanstack/react-router' diff --git a/examples/react/with-trpc-react-query/app/router.tsx b/examples/react/with-trpc-react-query/app/router.tsx index 1dfd9c4131..0d9dd5c4e4 100644 --- a/examples/react/with-trpc-react-query/app/router.tsx +++ b/examples/react/with-trpc-react-query/app/router.tsx @@ -15,7 +15,7 @@ export const trpc = createTRPCOptionsProxy({ client: createTRPCClient({ links: [ httpBatchLink({ - // since we are using Vinxi, the server is running on the same port, + // since we are using Vite, the server is running on the same port, // this means in dev the url is `http://localhost:3000/trpc` // and since its from the same origin, we don't need to explicitly set the full URL url: '/trpc', diff --git a/examples/react/with-trpc-react-query/package.json b/examples/react/with-trpc-react-query/package.json index 549b022de7..f8bc34bf8e 100644 --- a/examples/react/with-trpc-react-query/package.json +++ b/examples/react/with-trpc-react-query/package.json @@ -3,9 +3,9 @@ "private": true, "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" + "dev": "vite dev", + "build": "vite build", + "start": "vite start" }, "dependencies": { "@tanstack/react-query": "^5.66.0", @@ -23,7 +23,6 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "vinxi": "0.5.3", "zod": "^3.24.2" }, "devDependencies": { diff --git a/examples/react/with-trpc/.gitignore b/examples/react/with-trpc/.gitignore index be342025da..ca63f49885 100644 --- a/examples/react/with-trpc/.gitignore +++ b/examples/react/with-trpc/.gitignore @@ -7,14 +7,10 @@ yarn.lock .env .vercel .output -.vinxi - /build/ /api/ /server/build -/public/build -.vinxi -# Sentry Config File +/public/build# Sentry Config File .env.sentry-build-plugin /test-results/ /playwright-report/ diff --git a/examples/react/with-trpc/app.config.js b/examples/react/with-trpc/app.config.js index 1598094be8..c4847edca0 100644 --- a/examples/react/with-trpc/app.config.js +++ b/examples/react/with-trpc/app.config.js @@ -1,8 +1,10 @@ -import { createApp } from 'vinxi' +import { defineConfig } from 'vite' import reactRefresh from '@vitejs/plugin-react' import { TanStackRouterVite } from '@tanstack/router-plugin/vite' -export default createApp({ +// TODO: Need to migrate this to vite and the new TanStack Start plugin + +export default defineConfig({ server: { preset: 'node-server', // change to 'netlify' or 'bun' or anyof the supported presets for nitro (nitro.unjs.io) experimental: { diff --git a/examples/react/with-trpc/app/main.tsx b/examples/react/with-trpc/app/main.tsx index 3cff783e4b..ff5d7de693 100644 --- a/examples/react/with-trpc/app/main.tsx +++ b/examples/react/with-trpc/app/main.tsx @@ -1,5 +1,3 @@ -/// - import React from 'react' import ReactDOM from 'react-dom/client' import { RouterProvider, createRouter } from '@tanstack/react-router' diff --git a/examples/react/with-trpc/app/trpc.ts b/examples/react/with-trpc/app/trpc.ts index 243e4a6f5e..2320dcdfb6 100644 --- a/examples/react/with-trpc/app/trpc.ts +++ b/examples/react/with-trpc/app/trpc.ts @@ -4,7 +4,7 @@ import type { AppRouter } from '../trpc-server.handler' export const trpc = createTRPCClient({ links: [ httpBatchLink({ - // since we are using Vinxi, the server is running on the same port, + // since we are using Vite, the server is running on the same port, // this means in dev the url is `http://localhost:3000/trpc` // and since its from the same origin, we don't need to explicitly set the full URL url: '/trpc', diff --git a/examples/react/with-trpc/package.json b/examples/react/with-trpc/package.json index 31fc08a2ed..be90fae1bc 100644 --- a/examples/react/with-trpc/package.json +++ b/examples/react/with-trpc/package.json @@ -3,9 +3,9 @@ "private": true, "type": "module", "scripts": { - "dev": "vinxi dev", - "build": "vinxi build", - "start": "vinxi start" + "dev": "vite dev", + "build": "vite build", + "start": "vite start" }, "dependencies": { "@tanstack/react-router": "^1.114.3", @@ -20,7 +20,6 @@ "postcss": "^8.5.1", "autoprefixer": "^10.4.20", "tailwindcss": "^3.4.17", - "vinxi": "0.5.3", "zod": "^3.24.2" }, "devDependencies": { diff --git a/packages/create-router/templates/core/_dot_gitignore b/packages/create-router/templates/core/_dot_gitignore index ed335a7bdc..bfcf92b4fd 100644 --- a/packages/create-router/templates/core/_dot_gitignore +++ b/packages/create-router/templates/core/_dot_gitignore @@ -5,9 +5,7 @@ # Dist node_modules -dist/ -.vinxi -.output +dist/.output .vercel .netlify .wrangler diff --git a/packages/create-start/package.json b/packages/create-start/package.json index 6aaf61475c..63034d0bf7 100644 --- a/packages/create-start/package.json +++ b/packages/create-start/package.json @@ -70,7 +70,6 @@ "@types/react-dom": "^19.0.3", "react": "^19.0.0", "react-dom": "^19.0.0", - "vinxi": "0.5.1", "vite": "^6.0.3" }, "peerDependenciesMeta": { @@ -98,9 +97,6 @@ "react-dom": { "optional": true }, - "vinxi": { - "optional": true - }, "vite": { "optional": true } diff --git a/packages/create-start/src/modules/core/index.ts b/packages/create-start/src/modules/core/index.ts index 79aaf2e8b1..effeb1d66a 100644 --- a/packages/create-start/src/modules/core/index.ts +++ b/packages/create-start/src/modules/core/index.ts @@ -68,21 +68,21 @@ export const coreModule = createModule( '@tanstack/react-start', 'react', 'react-dom', - 'vinxi', + 'vite', ]), devDependencies: await deps(['@types/react', '@types/react']), scripts: [ { name: 'dev', - script: 'vinxi dev', + script: 'vite dev', }, { name: 'build', - script: 'vinxi build', + script: 'vite build', }, { name: 'start', - script: 'vinxi start', + script: 'vite start', }, ], ...vals.packageJson, diff --git a/packages/create-start/src/modules/core/template/app/client.tsx b/packages/create-start/src/modules/core/template/app/client.tsx index 64f18c113f..f675b9c39d 100644 --- a/packages/create-start/src/modules/core/template/app/client.tsx +++ b/packages/create-start/src/modules/core/template/app/client.tsx @@ -1,6 +1,5 @@ // @ts-nocheck -/// import { hydrateRoot } from 'react-dom/client' import { StartClient } from '@tanstack/react-start' import { createRouter } from './router' diff --git a/packages/create-start/src/modules/core/template/app/ssr.tsx b/packages/create-start/src/modules/core/template/app/ssr.tsx index 4ab0e48d6f..017f4efa21 100644 --- a/packages/create-start/src/modules/core/template/app/ssr.tsx +++ b/packages/create-start/src/modules/core/template/app/ssr.tsx @@ -1,6 +1,5 @@ // @ts-nocheck -/// import { createStartHandler, defaultStreamHandler, diff --git a/packages/create-start/tests/e2e/templates/barebones.test.ts b/packages/create-start/tests/e2e/templates/barebones.test.ts index f509937d32..35107d3069 100644 --- a/packages/create-start/tests/e2e/templates/barebones.test.ts +++ b/packages/create-start/tests/e2e/templates/barebones.test.ts @@ -65,15 +65,15 @@ describe('barebones template e2e', () => { expect(pkgJson.dependencies['@tanstack/react-start']).toBeDefined() expect(pkgJson.dependencies['react']).toBeDefined() expect(pkgJson.dependencies['react-dom']).toBeDefined() - expect(pkgJson.dependencies['vinxi']).toBeDefined() + expect(pkgJson.dependencies['vite']).toBeDefined() expect(pkgJson.devDependencies).toBeDefined() expect(pkgJson.devDependencies['@types/react']).toBeDefined() expect(pkgJson.scripts).toBeDefined() - expect(pkgJson.scripts.dev).toBe('vinxi dev') - expect(pkgJson.scripts.build).toBe('vinxi build') - expect(pkgJson.scripts.start).toBe('vinxi start') + expect(pkgJson.scripts.dev).toBe('vite dev') + expect(pkgJson.scripts.build).toBe('vite build') + expect(pkgJson.scripts.start).toBe('vite start') }) }) }) diff --git a/packages/directive-functions-plugin/src/index.ts b/packages/directive-functions-plugin/src/index.ts index 25ed1df746..5907545538 100644 --- a/packages/directive-functions-plugin/src/index.ts +++ b/packages/directive-functions-plugin/src/index.ts @@ -57,8 +57,6 @@ export function TanStackDirectiveFunctionsPlugin( code, root: ROOT, filename: id, - // globalThis.app currently refers to Vinxi's app instance. In the future, it can just be the - // vite dev server instance we get from Nitro. }) opts.onDirectiveFnsById?.(directiveFnsById) diff --git a/packages/directive-functions-plugin/tests/compiler.test.ts b/packages/directive-functions-plugin/tests/compiler.test.ts index a7ff05be97..e88114a8ef 100644 --- a/packages/directive-functions-plugin/tests/compiler.test.ts +++ b/packages/directive-functions-plugin/tests/compiler.test.ts @@ -697,8 +697,6 @@ describe('server function compilation', () => { .extractedFilename, }) - console.log(ssr.directiveFnsById) - expect(client.compiledResult.code).toMatchInlineSnapshot(` "'use server'; diff --git a/packages/react-start-api-routes/package.json b/packages/react-start-api-routes/package.json index cfff1fd6f1..8189bdea63 100644 --- a/packages/react-start-api-routes/package.json +++ b/packages/react-start-api-routes/package.json @@ -63,8 +63,7 @@ }, "dependencies": { "@tanstack/router-core": "workspace:^", - "@tanstack/react-start-server": "workspace:^", - "vinxi": "0.5.3" + "@tanstack/react-start-server": "workspace:^" }, "devDependencies": { "typescript": "^5.7.2" diff --git a/packages/react-start-api-routes/src/index.ts b/packages/react-start-api-routes/src/index.ts index 9ee1fc8ac1..ad9cb44821 100644 --- a/packages/react-start-api-routes/src/index.ts +++ b/packages/react-start-api-routes/src/index.ts @@ -1,5 +1,4 @@ import { eventHandler, toWebRequest } from '@tanstack/react-start-server' -import vinxiFileRoutes from 'vinxi/routes' import type { ResolveParams } from '@tanstack/router-core' export type StartAPIHandlerCallback = (ctx: { @@ -229,9 +228,9 @@ interface CustomizedVinxiFileRoute { /** * This is populated by the work done in the config file using the tsrFileRouter */ -const vinxiRoutes = ( - vinxiFileRoutes as unknown as Array -).filter((route) => route['$APIRoute']) +// const vinxiRoutes = ( +// vinxiFileRoutes as unknown as Array +// ).filter((route) => route['$APIRoute']) /** * This function takes the vinxi routes and interpolates them into a format that can be worked with in the API handler @@ -313,16 +312,20 @@ function toTSRFileBasedRoutes( export const defaultAPIFileRouteHandler: StartAPIHandlerCallback = async ({ request, }) => { - // Simple early abort if there are no routes - if (!vinxiRoutes.length) { - return new Response('No routes found', { status: 404 }) + // TODO: We need to reimplement api file routes without vinx-i + if (Math.random()) { + throw new Error('Not implemented') } + // Simple early abort if there are no routes + // if (!vinxiRoutes.length) { + // return new Response('No routes found', { status: 404 }) + // } if (!HTTP_API_METHODS.includes(request.method as HTTP_API_METHOD)) { return new Response('Method not allowed', { status: 405 }) } - const routes = toTSRFileBasedRoutes(vinxiRoutes) + const routes = toTSRFileBasedRoutes([]) const url = new URL(request.url, 'http://localhost:3000') diff --git a/packages/react-start-client/package.json b/packages/react-start-client/package.json index 8b59146167..612f71d792 100644 --- a/packages/react-start-client/package.json +++ b/packages/react-start-client/package.json @@ -68,8 +68,7 @@ "cookie-es": "^1.2.2", "jsesc": "^3.1.0", "tiny-invariant": "^1.3.3", - "tiny-warning": "^1.0.3", - "vinxi": "^0.5.3" + "tiny-warning": "^1.0.3" }, "devDependencies": { "@testing-library/react": "^16.2.0", diff --git a/packages/react-start-client/src/index.tsx b/packages/react-start-client/src/index.tsx index bc97adc78e..00dc9d8996 100644 --- a/packages/react-start-client/src/index.tsx +++ b/packages/react-start-client/src/index.tsx @@ -1,4 +1,3 @@ -/// export { createIsomorphicFn, type IsomorphicFn, diff --git a/packages/react-start-client/src/renderRSC.tsx b/packages/react-start-client/src/renderRSC.tsx index 6201bfa476..4832f074b6 100644 --- a/packages/react-start-client/src/renderRSC.tsx +++ b/packages/react-start-client/src/renderRSC.tsx @@ -1,6 +1,4 @@ // TODO: RSCs -// // @ts-expect-error -// import * as reactDom from '@vinxi/react-server-dom/client' import { isValidElement } from 'react' import invariant from 'tiny-invariant' import type React from 'react' diff --git a/packages/react-start-plugin/src/index.ts b/packages/react-start-plugin/src/index.ts index a649b905f2..076820022e 100644 --- a/packages/react-start-plugin/src/index.ts +++ b/packages/react-start-plugin/src/index.ts @@ -1,8 +1,3 @@ -// import { importMetaResolve } from 'import-meta-resolve' -// // @ts-expect-error -// import { serverComponents } from '@vinxi/server-components/plugin' - -// import { tanstackStartVinxiFileRouter } from './vinxi-file-router.js' import path from 'node:path' import { createTanStackServerFnPlugin } from '@tanstack/server-functions-plugin' import { mergeConfig, perEnvironmentPlugin } from 'vite' @@ -32,19 +27,19 @@ export function TanStackStartVitePlugin( manifestVirtualImportId: 'tsr:server-fn-manifest', client: { getRuntimeCode: () => - `import { createClientRpc } from '@tanstack/start/server-functions-client'`, + `import { createClientRpc } from '@tanstack/react-start/server-functions-client'`, replacer: (d) => `createClientRpc('${d.functionId}', '${options.routers.server.base}')`, }, ssr: { getRuntimeCode: () => - `import { createSsrRpc } from '@tanstack/start/server-functions-ssr'`, + `import { createSsrRpc } from '@tanstack/react-start/server-functions-ssr'`, replacer: (d) => `createSsrRpc('${d.functionId}', '${options.routers.server.base}')`, }, server: { getRuntimeCode: () => - `import { createServerRpc } from '@tanstack/start/server-functions-server'`, + `import { createServerRpc } from '@tanstack/react-start/server-functions-server'`, replacer: (d) => `createServerRpc('${d.functionId}', '${options.routers.server.base}', ${d.fn})`, }, @@ -135,15 +130,20 @@ export function TanStackStartVitePlugin( ? TanStackServerFnsPlugin.client : TanStackServerFnsPlugin.server, ), - perEnvironmentPlugin( - 'tanstack-router-manifest-plugin', - (environment) => - environment.name === 'ssr' && - tsrRoutesManifestPlugin({ - clientBase: options.routers.client.base, - tsrConfig: options.tsr, - }), - ), + // perEnvironmentPlugin( + // 'tanstack-router-manifest-plugin', + // (environment) => + // environment.name === 'ssr' && + // tsrRoutesManifestPlugin({ + // clientBase: options.routers.client.base, + // tsrConfig: options.tsr, + // }), + // ), + // TODO: Should this only be loaded for ssr? like above? + tsrRoutesManifestPlugin({ + clientBase: options.routers.client.base, + tsrConfig: options.tsr, + }), nitroPlugin({ ...options, server: { @@ -172,31 +172,6 @@ export function TanStackStartVitePlugin( ] } -// // Because Vinxi doesn't use the normal nitro dev server, it doesn't -// // supply $fetch during dev. We need to hook into the dev server creation, -// // nab the proper utils from the custom nitro instance that is used -// // during dev and supply the $fetch to app. -// // Hopefully and likely, this will just get removed when we move to -// // Nitro directly. -// vinxiApp.hooks.hook('app:dev:nitro:config', (devServer) => { -// vinxiApp.hooks.hook( -// 'app:dev:server:created', -// ({ devApp: { localFetch } }) => { -// const $fetch = createFetch({ -// fetch: localFetch, -// defaults: { -// baseURL: devServer.nitro.options.runtimeConfig.app.baseURL, -// }, -// }) - -// // @ts-expect-error -// globalThis.$fetch = $fetch -// }, -// ) -// }) - -// return vinxiApp - function injectDefineEnv( key: TKey, value: TValue, diff --git a/packages/react-start-plugin/src/nitro/nitro-plugin.ts b/packages/react-start-plugin/src/nitro/nitro-plugin.ts index f620a9fff6..18c073ce9e 100644 --- a/packages/react-start-plugin/src/nitro/nitro-plugin.ts +++ b/packages/react-start-plugin/src/nitro/nitro-plugin.ts @@ -1,8 +1,6 @@ import { dirname, resolve } from 'node:path' -import { writeFileSync } from 'node:fs' import { platform } from 'node:os' import { fileURLToPath } from 'node:url' -import { build, createDevServer, createNitro } from 'nitropack' import { normalizePath } from 'vite' import { buildServer } from './build-server.js' @@ -96,50 +94,6 @@ export function nitroPlugin( '#start/ssr': options.ssrEntryPath, } - if (isBuild) { - nitroConfig.publicAssets = [{ dir: clientOutputPath }] - nitroConfig.serverAssets = [ - { - baseName: 'public', - dir: clientOutputPath, - }, - ] - nitroConfig.renderer = rendererEntry - - if (ssrBuild) { - if (isWindows) { - // Write out the renderer manually because - // Windows doesn't resolve the aliases - // correctly in its native environment - writeFileSync( - normalizePath(rendererEntry.replace(filePrefix, '')), - ` - /** - * This file is shipped as ESM for Windows support, - * as it won't resolve the renderer.ts file correctly in node. - */ - import ssrEntry from '${options.ssrEntryPath}'; - export default ssrEntry - `, - ) - - nitroConfig.externals = { - inline: ['std-env'], - } - } - - nitroConfig = { - ...nitroConfig, - externals: { - ...nitroConfig.externals, - external: ['node-fetch-native/dist/polyfill'], - }, - // moduleSideEffects: [], - handlers: [], - } - } - } - return { environments: { ssr: { @@ -155,6 +109,7 @@ export function nitroPlugin( builder: { sharedPlugins: true, buildApp: async (builder) => { + console.log('tanner buildApp', builder) environmentBuild = true if (!builder.environments['client']) { @@ -190,32 +145,33 @@ export function nitroPlugin( } }, async configureServer(viteServer: ViteDevServer) { - if (isServe && !isTest) { - const nitro = await createNitro({ - dev: true, - ...nitroConfig, - }) - const server = createDevServer(nitro) - - await build(nitro) - - // viteServer.middlewares.use( - // apiBase, - // toNodeListener(server.app as unknown as App), - // ) - - viteServer.httpServer?.once('listening', () => { - process.env['START_HOST'] = !viteServer.config.server.host - ? 'localhost' - : (viteServer.config.server.host as string) - process.env['START_PORT'] = `${viteServer.config.server.port}` - }) - - // handle upgrades if websockets are enabled - if (nitroConfig.experimental?.websocket) { - viteServer.httpServer?.on('upgrade', server.upgrade) - } - } + return // TODO: We'll remove this when we're ready for non-entry routes + // if (isServe && !isTest) { + // const nitro = await createNitro({ + // dev: true, + // ...nitroConfig, + // }) + + // const server = createDevServer(nitro) + // await build(nitro) + + // // viteServer.middlewares.use( + // // apiBase, + // // toNodeListener(server.app as unknown as App), + // // ) + + // viteServer.httpServer?.once('listening', () => { + // process.env['START_HOST'] = !viteServer.config.server.host + // ? 'localhost' + // : (viteServer.config.server.host as string) + // process.env['START_PORT'] = `${viteServer.config.server.port}` + // }) + + // // handle upgrades if websockets are enabled + // if (nitroConfig.experimental?.websocket) { + // viteServer.httpServer?.on('upgrade', server.upgrade) + // } + // } }, async closeBundle() { // Skip when build is triggered by the Environment API diff --git a/packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts b/packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts index 912361c336..5781f4979a 100644 --- a/packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts +++ b/packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts @@ -16,6 +16,7 @@ export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { config(userConfig, { mode }) { // config = userConfig isTest = isTest ? isTest : mode === 'test' + return { resolve: { alias: { @@ -34,20 +35,11 @@ export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { registerDevServerMiddleware(options.root, viteServer) viteServer.middlewares.use(async (req, res) => { - const template = await viteServer.transformIndexHtml( - req.originalUrl as string, - ` - - - `, - ) - - console.log('template, maybe use?', template) - try { const serverEntry = ( await viteServer.ssrLoadModule('~start/ssr-entry') )['default'] + const event = createEvent(req, res) const result: string | Response = await serverEntry(event) diff --git a/packages/react-start-plugin/src/nitro/vite-plugin-nitro.ts b/packages/react-start-plugin/src/nitro/vite-plugin-nitro.ts deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/packages/react-start-router-manifest/package.json b/packages/react-start-router-manifest/package.json index 23f2ab74c5..758b86367d 100644 --- a/packages/react-start-router-manifest/package.json +++ b/packages/react-start-router-manifest/package.json @@ -59,8 +59,7 @@ }, "dependencies": { "@tanstack/router-core": "workspace:^", - "tiny-invariant": "^1.3.3", - "vinxi": "0.5.3" + "tiny-invariant": "^1.3.3" }, "devDependencies": { "typescript": "^5.7.2" diff --git a/packages/react-start-router-manifest/src/index.ts b/packages/react-start-router-manifest/src/index.ts index 3f0a37f609..c6749527d5 100644 --- a/packages/react-start-router-manifest/src/index.ts +++ b/packages/react-start-router-manifest/src/index.ts @@ -1,7 +1,5 @@ // @ts-expect-error import tsrGetManifest from 'tsr:routes-manifest' -import { getManifest } from 'vinxi/manifest' -import { default as invariant } from 'tiny-invariant' import type { Manifest } from '@tanstack/router-core' function sanitizeBase(base: string) { @@ -39,23 +37,23 @@ export function getFullRouterManifest() { } // Get the entry for the client from vinxi - const vinxiClientManifest = getManifest('client') + // const vinxiClientManifest = getManifest('client') - const importPath = - vinxiClientManifest.inputs[vinxiClientManifest.handler]?.output.path - if (!importPath) { - invariant(importPath, 'Could not find client entry in vinxi manifest') - } + // const importPath = + // vinxiClientManifest.inputs[vinxiClientManifest.handler]?.output.path + // if (!importPath) { + // invariant(importPath, 'Could not find client entry in vinxi manifest') + // } - rootRoute.assets.push({ - tag: 'script', - attrs: { - type: 'module', - suppressHydrationWarning: true, - async: true, - }, - children: `${script}import("${importPath}")`, - }) + // rootRoute.assets.push({ + // tag: 'script', + // attrs: { + // type: 'module', + // suppressHydrationWarning: true, + // async: true, + // }, + // children: `${script}import("${importPath}")`, + // }) return routerManifest } diff --git a/packages/react-start-server-functions-handler/src/index.ts b/packages/react-start-server-functions-handler/src/index.ts index c2b039a7b3..4139afcd22 100644 --- a/packages/react-start-server-functions-handler/src/index.ts +++ b/packages/react-start-server-functions-handler/src/index.ts @@ -208,11 +208,11 @@ async function handleServerRequest({ // return result.result // } - // TODO: RSCs + // TODO: RSCs Where are we getting this package? // if (isValidElement(result)) { // const { renderToPipeableStream } = await import( // // @ts-expect-error - // '@vinxi/react-server-dom/server' + // 'react-server-dom/server' // ) // const pipeableStream = renderToPipeableStream(result) diff --git a/packages/react-start/vite.config.ts b/packages/react-start/vite.config.ts index dd8d715d1d..8e960afd50 100644 --- a/packages/react-start/vite.config.ts +++ b/packages/react-start/vite.config.ts @@ -17,6 +17,7 @@ export default mergeConfig( entry: [ './src/client.tsx', './src/server.tsx', + './src/plugin.ts', './src/router-manifest.tsx', './src/server-functions-client.tsx', './src/server-functions-server.tsx', @@ -26,6 +27,7 @@ export default mergeConfig( externalDeps: [ '@tanstack/react-start-client', '@tanstack/react-start-server', + '@tanstack/react-start-plugin', '@tanstack/react-start-router-manifest', '@tanstack/react-start-server-functions-client', '@tanstack/start-server-functions-server', diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@component.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@component.tsx index 94fb102889..8e73632781 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@component.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@component.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

@@ -502,7 +502,7 @@ const SplitComponent = function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@errorComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@errorComponent.tsx index 0a4fcf7cd8..ebd0862514 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@errorComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@errorComponent.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@notFoundComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@notFoundComponent.tsx index 0a4fcf7cd8..ebd0862514 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@notFoundComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@notFoundComponent.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@pendingComponent.tsx index 0a4fcf7cd8..ebd0862514 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@pendingComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/development/useStateDestructure@pendingComponent.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@component.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@component.tsx index 94fb102889..8e73632781 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@component.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@component.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

@@ -502,7 +502,7 @@ const SplitComponent = function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@errorComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@errorComponent.tsx index 0a4fcf7cd8..ebd0862514 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@errorComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@errorComponent.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@notFoundComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@notFoundComponent.tsx index 0a4fcf7cd8..ebd0862514 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@notFoundComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@notFoundComponent.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@pendingComponent.tsx index 0a4fcf7cd8..ebd0862514 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@pendingComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/1-default/production/useStateDestructure@pendingComponent.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/development/useStateDestructure@component---errorComponent---notFoundComponent---pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/development/useStateDestructure@component---errorComponent---notFoundComponent---pendingComponent.tsx index 94fb102889..8e73632781 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/development/useStateDestructure@component---errorComponent---notFoundComponent---pendingComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/development/useStateDestructure@component---errorComponent---notFoundComponent---pendingComponent.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

@@ -502,7 +502,7 @@ const SplitComponent = function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/development/useStateDestructure@loader.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/development/useStateDestructure@loader.tsx index 0a4fcf7cd8..ebd0862514 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/development/useStateDestructure@loader.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/development/useStateDestructure@loader.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/production/useStateDestructure@component---errorComponent---notFoundComponent---pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/production/useStateDestructure@component---errorComponent---notFoundComponent---pendingComponent.tsx index 94fb102889..8e73632781 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/production/useStateDestructure@component---errorComponent---notFoundComponent---pendingComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/production/useStateDestructure@component---errorComponent---notFoundComponent---pendingComponent.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

@@ -502,7 +502,7 @@ const SplitComponent = function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/production/useStateDestructure@loader.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/production/useStateDestructure@loader.tsx index 0a4fcf7cd8..ebd0862514 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/production/useStateDestructure@loader.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/2-components-combined-loader-separate/production/useStateDestructure@loader.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/development/useStateDestructure@component---loader---notFoundComponent---pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/development/useStateDestructure@component---loader---notFoundComponent---pendingComponent.tsx index 94fb102889..8e73632781 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/development/useStateDestructure@component---loader---notFoundComponent---pendingComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/development/useStateDestructure@component---loader---notFoundComponent---pendingComponent.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

@@ -502,7 +502,7 @@ const SplitComponent = function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/development/useStateDestructure@errorComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/development/useStateDestructure@errorComponent.tsx index 0a4fcf7cd8..ebd0862514 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/development/useStateDestructure@errorComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/development/useStateDestructure@errorComponent.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/production/useStateDestructure@component---loader---notFoundComponent---pendingComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/production/useStateDestructure@component---loader---notFoundComponent---pendingComponent.tsx index 94fb102889..8e73632781 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/production/useStateDestructure@component---loader---notFoundComponent---pendingComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/production/useStateDestructure@component---loader---notFoundComponent---pendingComponent.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

@@ -502,7 +502,7 @@ const SplitComponent = function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/production/useStateDestructure@errorComponent.tsx b/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/production/useStateDestructure@errorComponent.tsx index 0a4fcf7cd8..ebd0862514 100644 --- a/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/production/useStateDestructure@errorComponent.tsx +++ b/packages/router-plugin/tests/code-splitter/snapshots/react/3-all-combined-errorComponent-separate/production/useStateDestructure@errorComponent.tsx @@ -108,7 +108,7 @@ export default function VersionIndex() {

Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} + powered by TanStack Router, {' '} Nitro and Vite. Ready to deploy to your favorite hosting provider.

diff --git a/packages/router-plugin/tests/code-splitter/test-files/react/useStateDestructure.tsx b/packages/router-plugin/tests/code-splitter/test-files/react/useStateDestructure.tsx index 6a1a086eaf..8f79e69bf0 100644 --- a/packages/router-plugin/tests/code-splitter/test-files/react/useStateDestructure.tsx +++ b/packages/router-plugin/tests/code-splitter/test-files/react/useStateDestructure.tsx @@ -159,9 +159,9 @@ export default function VersionIndex() { lg:text-xl lg:max-w-[600px]" > Full-document SSR, Streaming, Server Functions, bundling and more, - powered by TanStack Router, Vinxi,{' '} - Nitro and Vite. Ready to deploy to - your favorite hosting provider. + powered by TanStack Router, Nitro{' '} + and Vite. Ready to deploy to your favorite hosting + provider.

diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 66f4bd092d..70a55473e2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -847,9 +847,6 @@ importers: tailwind-merge: specifier: ^2.6.0 version: 2.6.0 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.2 version: 3.24.2 @@ -920,9 +917,6 @@ importers: tailwind-merge: specifier: ^2.6.0 version: 2.6.0 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -990,9 +984,6 @@ importers: tailwind-merge: specifier: ^2.6.0 version: 2.6.0 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -1054,9 +1045,6 @@ importers: tailwind-merge: specifier: ^2.6.0 version: 2.6.0 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@types/react': specifier: ^19.0.8 @@ -1097,9 +1085,6 @@ importers: react-dom: specifier: ^19.0.0 version: 19.0.0(react@19.0.0) - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@tanstack/router-e2e-utils': specifier: workspace:^ @@ -1143,9 +1128,6 @@ importers: tailwind-merge: specifier: ^2.6.0 version: 2.6.0 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -1207,9 +1189,6 @@ importers: tailwind-merge: specifier: ^2.6.0 version: 2.6.0 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.2 version: 3.24.2 @@ -1277,9 +1256,6 @@ importers: tailwind-merge: specifier: ^2.6.0 version: 2.6.0 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.2 version: 3.24.2 @@ -1347,9 +1323,6 @@ importers: tailwind-merge: specifier: ^2.6.0 version: 2.6.0 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.2 version: 3.24.2 @@ -3469,10 +3442,10 @@ importers: version: 19.0.3(@types/react@19.0.8) html-webpack-plugin: specifier: ^5.6.3 - version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) + version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1) swc-loader: specifier: ^0.2.6 - version: 0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) + version: 0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1) typescript: specifier: ^5.7.2 version: 5.8.2 @@ -4151,9 +4124,6 @@ importers: react-dom: specifier: ^19.0.0 version: 19.0.0(react@19.0.0) - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.2 version: 3.24.2 @@ -4261,9 +4231,6 @@ importers: tailwind-merge: specifier: ^2.6.0 version: 2.6.0 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@types/node': specifier: ^22.5.4 @@ -4322,9 +4289,6 @@ importers: tailwind-merge: specifier: ^2.6.0 version: 2.6.0 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@types/node': specifier: ^22.5.4 @@ -4377,9 +4341,6 @@ importers: tailwind-merge: specifier: ^2.6.0 version: 2.6.0 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@types/react': specifier: ^19.0.8 @@ -4426,9 +4387,6 @@ importers: tailwind-merge: specifier: ^2.5.5 version: 2.6.0 - vinxi: - specifier: 0.5.1 - version: 0.5.1(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@types/node': specifier: ^22.5.4 @@ -4481,9 +4439,6 @@ importers: tailwind-merge: specifier: ^2.6.0 version: 2.6.0 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@types/node': specifier: ^22.5.4 @@ -4563,9 +4518,6 @@ importers: tiny-invariant: specifier: ^1.3.3 version: 1.3.3 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.2 version: 3.24.2 @@ -4609,9 +4561,6 @@ importers: react-dom: specifier: ^19.0.0 version: 19.0.0(react@19.0.0) - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@types/node': specifier: ^22.5.4 @@ -4654,10 +4603,7 @@ importers: version: 2.6.0 valibot: specifier: ^1.0.0-beta.15 - version: 1.0.0-beta.15(typescript@5.8.2) - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) + version: 1.0.0-beta.15(typescript@5.7.3) devDependencies: '@types/node': specifier: ^22.5.4 @@ -4765,9 +4711,6 @@ importers: react-dom: specifier: ^19.0.0 version: 19.0.0(react@19.0.0) - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@types/react': specifier: ^19.0.8 @@ -4835,9 +4778,6 @@ importers: tiny-invariant: specifier: ^1.3.3 version: 1.3.3 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.2 version: 3.24.2 @@ -4951,9 +4891,6 @@ importers: tailwindcss: specifier: ^3.4.17 version: 3.4.17 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.2 version: 3.24.2 @@ -5015,9 +4952,6 @@ importers: tailwindcss: specifier: ^3.4.17 version: 3.4.17 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.2 version: 3.24.2 @@ -5468,7 +5402,7 @@ importers: version: 7.0.6 html-webpack-plugin: specifier: ^5.6.0 - version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) + version: 5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1) picocolors: specifier: ^1.1.1 version: 1.1.1 @@ -5480,7 +5414,7 @@ importers: version: 19.0.0(react@19.0.0) swc-loader: specifier: ^0.2.6 - version: 0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) + version: 0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1) tinyglobby: specifier: ^0.2.10 version: 0.2.12 @@ -5578,9 +5512,6 @@ importers: validate-npm-package-name: specifier: ^6.0.0 version: 6.0.0 - vinxi: - specifier: 0.5.1 - version: 0.5.1(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) vite: specifier: 6.1.0 version: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) @@ -5808,9 +5739,6 @@ importers: '@tanstack/router-core': specifier: workspace:* version: link:../router-core - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: typescript: specifier: ^5.7.2 @@ -5842,9 +5770,6 @@ importers: tiny-warning: specifier: ^1.0.3 version: 1.0.3 - vinxi: - specifier: ^0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: '@testing-library/react': specifier: ^16.2.0 @@ -5990,9 +5915,6 @@ importers: tiny-invariant: specifier: ^1.3.3 version: 1.3.3 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: typescript: specifier: ^5.7.2 @@ -14715,10 +14637,6 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} - vinxi@0.5.1: - resolution: {integrity: sha512-jvl2hJ0fyWwfDVQdDDHCJiVxqU4k0A6kFAnljS0kIjrGfhdTvKEWIoj0bcJgMyrKhxNMoZZGmHZsstQgjDIL3g==} - hasBin: true - vinxi@0.5.3: resolution: {integrity: sha512-4sL2SMrRzdzClapP44oXdGjCE1oq7/DagsbjY5A09EibmoIO4LP8ScRVdh03lfXxKRk7nCWK7n7dqKvm+fp/9w==} hasBin: true @@ -18742,17 +18660,17 @@ snapshots: '@webassemblyjs/ast': 1.14.1 '@xtuc/long': 4.2.2 - '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4))': + '@webpack-cli/configtest@2.1.1(webpack-cli@5.1.4)(webpack@5.97.1)': dependencies: webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1) - '@webpack-cli/info@2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4))': + '@webpack-cli/info@2.0.2(webpack-cli@5.1.4)(webpack@5.97.1)': dependencies: webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1) - '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack-dev-server@5.2.0(webpack-cli@5.1.4)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4))': + '@webpack-cli/serve@2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.2.0)(webpack@5.97.1)': dependencies: webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4) webpack-cli: 5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1) @@ -20719,7 +20637,7 @@ snapshots: html-tags@3.3.1: {} - html-webpack-plugin@5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)): + html-webpack-plugin@5.6.3(@rspack/core@1.2.2(@swc/helpers@0.5.15))(webpack@5.97.1): dependencies: '@types/html-minifier-terser': 6.1.0 html-minifier-terser: 6.1.0 @@ -23016,7 +22934,7 @@ snapshots: csso: 5.0.5 picocolors: 1.1.1 - swc-loader@0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)): + swc-loader@0.2.6(@swc/core@1.10.15(@swc/helpers@0.5.15))(webpack@5.97.1): dependencies: '@swc/core': 1.10.15(@swc/helpers@0.5.15) '@swc/counter': 0.1.3 @@ -23106,26 +23024,26 @@ snapshots: type-fest: 2.19.0 unique-string: 3.0.0 - terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)): + terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.37.0 - webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4) + webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0) optionalDependencies: '@swc/core': 1.10.15(@swc/helpers@0.5.15) esbuild: 0.25.0 - terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)): + terser-webpack-plugin@5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack@5.97.1): dependencies: '@jridgewell/trace-mapping': 0.3.25 jest-worker: 27.5.1 schema-utils: 4.3.0 serialize-javascript: 6.0.2 terser: 5.37.0 - webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0) + webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4) optionalDependencies: '@swc/core': 1.10.15(@swc/helpers@0.5.15) esbuild: 0.25.0 @@ -23547,85 +23465,6 @@ snapshots: vary@1.1.2: {} - vinxi@0.5.1(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0): - dependencies: - '@babel/core': 7.26.8 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.8) - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.8) - '@types/micromatch': 4.0.9 - '@vinxi/listhen': 1.5.6 - boxen: 7.1.1 - chokidar: 3.6.0 - citty: 0.1.6 - consola: 3.4.0 - crossws: 0.3.3 - dax-sh: 0.39.2 - defu: 6.1.4 - es-module-lexer: 1.6.0 - esbuild: 0.20.2 - fast-glob: 3.3.3 - get-port-please: 3.1.2 - h3: 1.13.0 - hookable: 5.5.3 - http-proxy: 1.18.1 - micromatch: 4.0.8 - nitropack: 2.10.4(typescript@5.8.2) - node-fetch-native: 1.6.6 - path-to-regexp: 6.3.0 - pathe: 1.1.2 - radix3: 1.1.2 - resolve: 1.22.10 - serve-placeholder: 2.0.2 - serve-static: 1.16.2 - ufo: 1.5.4 - unctx: 2.4.1 - unenv: 1.10.0 - unstorage: 1.14.4(db0@0.2.3)(ioredis@5.4.2) - vite: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - zod: 3.24.2 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@electric-sql/pglite' - - '@libsql/client' - - '@netlify/blobs' - - '@planetscale/database' - - '@types/node' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/kv' - - aws4fetch - - better-sqlite3 - - db0 - - debug - - drizzle-orm - - encoding - - idb-keyval - - ioredis - - jiti - - less - - lightningcss - - mysql2 - - rolldown - - sass - - sass-embedded - - sqlite3 - - stylus - - sugarss - - supports-color - - terser - - tsx - - typescript - - uploadthing - - xml2js - - yaml - vinxi@0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0): dependencies: '@babel/core': 7.26.8 @@ -23994,9 +23833,9 @@ snapshots: webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1): dependencies: '@discoveryjs/json-ext': 0.5.7 - '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) - '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) - '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4(webpack-dev-server@5.2.0)(webpack@5.97.1))(webpack-dev-server@5.2.0(webpack-cli@5.1.4)(webpack@5.97.1))(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) + '@webpack-cli/configtest': 2.1.1(webpack-cli@5.1.4)(webpack@5.97.1) + '@webpack-cli/info': 2.0.2(webpack-cli@5.1.4)(webpack@5.97.1) + '@webpack-cli/serve': 2.0.5(webpack-cli@5.1.4)(webpack-dev-server@5.2.0)(webpack@5.97.1) colorette: 2.0.20 commander: 10.0.1 cross-spawn: 7.0.6 @@ -24010,7 +23849,7 @@ snapshots: optionalDependencies: webpack-dev-server: 5.2.0(webpack-cli@5.1.4)(webpack@5.97.1) - webpack-dev-middleware@7.4.2(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)): + webpack-dev-middleware@7.4.2(webpack@5.97.1): dependencies: colorette: 2.0.20 memfs: 4.17.0 @@ -24048,7 +23887,7 @@ snapshots: serve-index: 1.9.1 sockjs: 0.3.24 spdy: 4.0.2 - webpack-dev-middleware: 7.4.2(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) + webpack-dev-middleware: 7.4.2(webpack@5.97.1) ws: 8.18.0 optionalDependencies: webpack: 5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4) @@ -24123,7 +23962,7 @@ snapshots: neo-async: 2.6.2 schema-utils: 3.3.0 tapable: 2.2.1 - terser-webpack-plugin: 5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack@5.97.1(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack-cli@5.1.4)) + terser-webpack-plugin: 5.3.11(@swc/core@1.10.15(@swc/helpers@0.5.15))(esbuild@0.25.0)(webpack@5.97.1) watchpack: 2.4.2 webpack-sources: 3.2.3 optionalDependencies: From 64c76dd277a163542f47a406b925ad035e33a2b5 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Fri, 7 Mar 2025 01:30:03 -0700 Subject: [PATCH 018/155] checkpoint --- .github/labeler.yml | 2 - e2e/react-start/basic/app/ssr.tsx | 13 +- examples/react/start-basic/app/ssr.tsx | 16 +- examples/react/start-basic/vite.config.ts | 2 +- package.json | 2 - .../src/compilers.ts | 4 + .../directive-functions-plugin/src/index.ts | 144 ++++- packages/react-router/src/fileRoute.ts | 40 +- packages/react-start-plugin/package.json | 1 + packages/react-start-plugin/src/compilers.ts | 7 +- packages/react-start-plugin/src/index.ts | 157 ++---- .../src/nitro/nitro-plugin.ts | 159 +----- .../src/nitro/plugins/dev-server-plugin.ts | 82 ++- .../src/nitro/utils/load-esm.ts | 27 - .../nitro/utils/register-dev-middleware.ts | 25 - .../src/routesManifestPlugin.ts | 12 +- packages/react-start-plugin/src/server-fns.ts | 178 ------- .../src/start-compiler-plugin.ts | 150 ++++++ packages/react-start-plugin/vite.config.ts | 1 + .../react-start-router-manifest/README.md | 33 -- .../eslint.config.js | 31 -- .../react-start-router-manifest/package.json | 67 --- .../react-start-router-manifest/tsconfig.json | 10 - .../vite.config.ts | 22 - .../README.md | 33 -- .../eslint.config.js | 31 -- .../package.json | 80 --- .../tsconfig.json | 7 - .../vite.config.ts | 23 - .../src/createStartHandler.ts | 21 +- packages/react-start-server/src/h3.ts | 498 +++++++++++++++++ packages/react-start-server/src/index.tsx | 503 +----------------- .../src/router-manifest.ts} | 60 +-- .../src/server-functions-handler.ts} | 20 +- packages/react-start-server/tsconfig.json | 7 +- packages/react-start-server/vite.config.ts | 1 + packages/react-start/package.json | 22 - packages/react-start/src/router-manifest.tsx | 1 - .../src/server-functions-handler.tsx | 1 - packages/react-start/vite.config.ts | 2 - .../src/core/code-splitter/compilers.ts | 3 + .../src/core/router-code-splitter-plugin.ts | 7 +- packages/router-utils/src/ast.ts | 8 - packages/server-functions-plugin/src/index.ts | 159 +++++- packages/start-plugin/package.json | 1 + .../package.json | 3 +- packages/start/package.json | 22 - packages/start/src/router-manifest.tsx | 4 - .../start/src/server-functions-handler.tsx | 4 - packages/start/vite.config.ts | 2 - pnpm-lock.yaml | 74 +-- scripts/publish.js | 8 - 52 files changed, 1206 insertions(+), 1584 deletions(-) delete mode 100644 packages/react-start-plugin/src/nitro/utils/load-esm.ts delete mode 100644 packages/react-start-plugin/src/nitro/utils/register-dev-middleware.ts delete mode 100644 packages/react-start-plugin/src/server-fns.ts create mode 100644 packages/react-start-plugin/src/start-compiler-plugin.ts delete mode 100644 packages/react-start-router-manifest/README.md delete mode 100644 packages/react-start-router-manifest/eslint.config.js delete mode 100644 packages/react-start-router-manifest/package.json delete mode 100644 packages/react-start-router-manifest/tsconfig.json delete mode 100644 packages/react-start-router-manifest/vite.config.ts delete mode 100644 packages/react-start-server-functions-handler/README.md delete mode 100644 packages/react-start-server-functions-handler/eslint.config.js delete mode 100644 packages/react-start-server-functions-handler/package.json delete mode 100644 packages/react-start-server-functions-handler/tsconfig.json delete mode 100644 packages/react-start-server-functions-handler/vite.config.ts create mode 100644 packages/react-start-server/src/h3.ts rename packages/{react-start-router-manifest/src/index.ts => react-start-server/src/router-manifest.ts} (63%) rename packages/{react-start-server-functions-handler/src/index.ts => react-start-server/src/server-functions-handler.ts} (95%) delete mode 100644 packages/react-start/src/router-manifest.tsx delete mode 100644 packages/react-start/src/server-functions-handler.tsx create mode 100644 packages/start-plugin/package.json delete mode 100644 packages/start/src/router-manifest.tsx delete mode 100644 packages/start/src/server-functions-handler.tsx diff --git a/.github/labeler.yml b/.github/labeler.yml index 7b5316ac2a..25014dccc5 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -32,8 +32,6 @@ - 'packages/react-start-server-functions-client/**/*' 'package: react-start-server-functions-fetcher': - 'packages/react-start-server-functions-fetcher/**/*' -'package: react-start-server-functions-handler': - - 'packages/react-start-server-functions-handler/**/*' 'package: react-start-server-functions-ssr': - 'packages/react-start-server-functions-ssr/**/*' 'package: router-cli': diff --git a/e2e/react-start/basic/app/ssr.tsx b/e2e/react-start/basic/app/ssr.tsx index 62572579ac..de2ca15a47 100644 --- a/e2e/react-start/basic/app/ssr.tsx +++ b/e2e/react-start/basic/app/ssr.tsx @@ -1,12 +1,17 @@ import { createStartHandler, defaultStreamHandler, + defineEventHandler, } from '@tanstack/start/server' import { getRouterManifest } from '@tanstack/start/router-manifest' import { createRouter } from './router' -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) +export default defineEventHandler((event) => { + const startHandler = createStartHandler({ + createRouter, + getRouterManifest, + })(defaultStreamHandler) + + return startHandler(event) +}) diff --git a/examples/react/start-basic/app/ssr.tsx b/examples/react/start-basic/app/ssr.tsx index 65a580f25e..07b04f617d 100644 --- a/examples/react/start-basic/app/ssr.tsx +++ b/examples/react/start-basic/app/ssr.tsx @@ -1,12 +1,18 @@ import { createStartHandler, defaultStreamHandler, + defineEventHandler, + getWebRequest, } from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' import { createRouter } from './router' -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) +export default defineEventHandler((event) => { + console.log(getWebRequest(event)?.url) + + const startHandler = createStartHandler({ + createRouter, + })(defaultStreamHandler) + + return startHandler(event) +}) diff --git a/examples/react/start-basic/vite.config.ts b/examples/react/start-basic/vite.config.ts index 47532c5353..698e4856da 100644 --- a/examples/react/start-basic/vite.config.ts +++ b/examples/react/start-basic/vite.config.ts @@ -10,6 +10,6 @@ export default defineConfig({ tsConfigPaths({ projects: ['./tsconfig.json'], }), - TanStackStartVitePlugin({}), + TanStackStartVitePlugin(), ], }) diff --git a/package.json b/package.json index 2fb22d4277..be79181ddc 100644 --- a/package.json +++ b/package.json @@ -98,11 +98,9 @@ "@tanstack/react-start-server": "workspace:*", "@tanstack/react-start-api-routes": "workspace:*", "@tanstack/react-start-server-functions-fetcher": "workspace:*", - "@tanstack/react-start-server-functions-handler": "workspace:*", "@tanstack/react-start-server-functions-client": "workspace:*", "@tanstack/react-start-server-functions-ssr": "workspace:*", "@tanstack/start-server-functions-server": "workspace:*", - "@tanstack/react-start-router-manifest": "workspace:*", "@tanstack/react-start-plugin": "workspace:*", "@tanstack/eslint-plugin-router": "workspace:*", "@tanstack/server-functions-plugin": "workspace:*", diff --git a/packages/directive-functions-plugin/src/compilers.ts b/packages/directive-functions-plugin/src/compilers.ts index da0fe941bc..332a40b415 100644 --- a/packages/directive-functions-plugin/src/compilers.ts +++ b/packages/directive-functions-plugin/src/compilers.ts @@ -40,6 +40,8 @@ export type CompileDirectivesOpts = ParseAstOptions & { }) => string replacer: ReplacerFn // devSplitImporter: string + filename: string + root: string } function buildDirectiveSplitParam(opts: CompileDirectivesOpts) { @@ -230,6 +232,8 @@ export function findDirectives( directiveLabel: string replacer?: ReplacerFn directiveSplitParam: string + filename: string + root: string }, ): Record { const directiveFnsById: Record = {} diff --git a/packages/directive-functions-plugin/src/index.ts b/packages/directive-functions-plugin/src/index.ts index 5907545538..be124822d4 100644 --- a/packages/directive-functions-plugin/src/index.ts +++ b/packages/directive-functions-plugin/src/index.ts @@ -15,23 +15,28 @@ export type { ReplacerFn, } from './compilers' -export type DirectiveFunctionsViteOptions = Pick< +export type DirectiveFunctionsViteEnvOptions = Pick< CompileDirectivesOpts, - 'directive' | 'directiveLabel' | 'getRuntimeCode' | 'replacer' - // | 'devSplitImporter' + 'getRuntimeCode' | 'replacer' > & { envLabel: string } +export type DirectiveFunctionsViteOptions = Pick< + CompileDirectivesOpts, + 'directive' | 'directiveLabel' +> & + DirectiveFunctionsViteEnvOptions & { + onDirectiveFnsById?: (directiveFnsById: Record) => void + } + const createDirectiveRx = (directive: string) => new RegExp(`"${directive}"|'${directive}'`, 'gm') export function TanStackDirectiveFunctionsPlugin( - opts: DirectiveFunctionsViteOptions & { - onDirectiveFnsById?: (directiveFnsById: Record) => void - }, + opts: DirectiveFunctionsViteOptions, ): Plugin { - let ROOT: string = process.cwd() + let root: string = process.cwd() const directiveRx = createDirectiveRx(opts.directive) @@ -39,34 +44,123 @@ export function TanStackDirectiveFunctionsPlugin( name: 'tanstack-start-directive-vite-plugin', enforce: 'pre', configResolved: (config) => { - ROOT = config.root + root = config.root }, transform(code, id) { - const url = pathToFileURL(id) - url.searchParams.delete('v') - id = fileURLToPath(url).replace(/\\/g, '/') + return transformCode({ ...opts, code, id, directiveRx, root }) + }, + } +} - if (!code.match(directiveRx)) { - return null - } +export type DirectiveFunctionsVitePluginEnvOptions = Pick< + CompileDirectivesOpts, + 'directive' | 'directiveLabel' +> & { + environments: { + client: DirectiveFunctionsViteEnvOptions & { envName?: string } + server: DirectiveFunctionsViteEnvOptions & { envName?: string } + } + onDirectiveFnsById?: (directiveFnsById: Record) => void +} + +export function TanStackDirectiveFunctionsPluginEnv( + opts: DirectiveFunctionsVitePluginEnvOptions, +): Plugin { + opts = { + ...opts, + environments: { + client: { + envName: 'client', + ...opts.environments.client, + }, + server: { + envName: 'server', + ...opts.environments.server, + }, + }, + } + + let root: string = process.cwd() - if (debug) console.info(`${opts.envLabel}: Compiling Directives: `, id) + const directiveRx = createDirectiveRx(opts.directive) + + return { + name: 'tanstack-start-directive-vite-plugin', + enforce: 'pre', + buildStart() { + root = this.environment.config.root + }, + applyToEnvironment(env) { + return [ + opts.environments.client.envName, + opts.environments.server.envName, + ].includes(env.name) + }, + transform(code, id) { + const envOptions = [ + opts.environments.client, + opts.environments.server, + ].find((e) => e.envName === this.environment.name) + + if (!envOptions) { + throw new Error(`Environment ${this.environment.name} not found`) + } - const { compiledResult, directiveFnsById } = compileDirectives({ + return transformCode({ ...opts, + ...envOptions, code, - root: ROOT, - filename: id, + id, + directiveRx, + root, }) + }, + } +} - opts.onDirectiveFnsById?.(directiveFnsById) +function transformCode({ + code, + id, + directiveRx, + envLabel, + directive, + directiveLabel, + getRuntimeCode, + replacer, + onDirectiveFnsById, + root, +}: DirectiveFunctionsViteOptions & { + code: string + id: string + directiveRx: RegExp + root: string +}) { + const url = pathToFileURL(id) + url.searchParams.delete('v') + id = fileURLToPath(url).replace(/\\/g, '/') - if (debug) { - logDiff(code, compiledResult.code) - console.log('Output:\n', compiledResult.code + '\n\n') - } + if (!code.match(directiveRx)) { + return null + } - return compiledResult - }, + if (debug) console.info(`${envLabel}: Compiling Directives: `, id) + + const { compiledResult, directiveFnsById } = compileDirectives({ + directive, + directiveLabel, + getRuntimeCode, + replacer, + code, + root, + filename: id, + }) + + onDirectiveFnsById?.(directiveFnsById) + + if (debug) { + logDiff(code, compiledResult.code) + console.log('Output:\n', compiledResult.code + '\n\n') } + + return compiledResult } diff --git a/packages/react-router/src/fileRoute.ts b/packages/react-router/src/fileRoute.ts index d645cc840d..c72e45ca15 100644 --- a/packages/react-router/src/fileRoute.ts +++ b/packages/react-router/src/fileRoute.ts @@ -33,19 +33,33 @@ import type { UseLoaderDepsRoute } from './useLoaderDeps' import type { UseLoaderDataRoute } from './useLoaderData' import type { UseRouteContextRoute } from './useRouteContext' -export function createFileRoute< - TFilePath extends keyof FileRoutesByPath, - TParentRoute extends AnyRoute = FileRoutesByPath[TFilePath]['parentRoute'], - TId extends RouteConstraints['TId'] = FileRoutesByPath[TFilePath]['id'], - TPath extends RouteConstraints['TPath'] = FileRoutesByPath[TFilePath]['path'], - TFullPath extends - RouteConstraints['TFullPath'] = FileRoutesByPath[TFilePath]['fullPath'], ->( - path: TFilePath, -): FileRoute['createRoute'] { - return new FileRoute(path, { - silent: true, - }).createRoute +type RouteInfo = { + parentRoute: AnyRoute + id: RouteConstraints['TId'] + path: keyof FileRoutesByPath + fullPath: RouteConstraints['TFullPath'] +} + +export function createFileRoute(): FileRoute< + TRouteInfo['path'], + TRouteInfo['parentRoute'], + TRouteInfo['id'], + TRouteInfo['path'], + TRouteInfo['fullPath'] +>['createRoute'] { + return new FileRoute< + TRouteInfo['path'], + TRouteInfo['parentRoute'], + TRouteInfo['id'], + TRouteInfo['path'], + TRouteInfo['fullPath'] + >( + // @ts-expect-error + undefined, + { + silent: true, + }, + ).createRoute } /** diff --git a/packages/react-start-plugin/package.json b/packages/react-start-plugin/package.json index 7d2e2977aa..a27265e674 100644 --- a/packages/react-start-plugin/package.json +++ b/packages/react-start-plugin/package.json @@ -85,6 +85,7 @@ "babel-dead-code-elimination": "^1.0.9", "fast-glob": "^3.3.3", "h3": "1.13.0", + "import-meta-resolve": "^4.1.0", "nitropack": "^2.10.4", "tiny-invariant": "^1.3.3", "vite": "6.1.0", diff --git a/packages/react-start-plugin/src/compilers.ts b/packages/react-start-plugin/src/compilers.ts index ca806fc991..6cd7cb55ae 100644 --- a/packages/react-start-plugin/src/compilers.ts +++ b/packages/react-start-plugin/src/compilers.ts @@ -17,6 +17,7 @@ const handleClientOnlyCallExpression = type CompileOptions = ParseAstOptions & { env: 'server' | 'client' | 'ssr' dce?: boolean + filename: string } type IdentifierConfig = { @@ -187,7 +188,7 @@ export function compileStartOutput(opts: CompileOptions): GeneratorResult { function handleCreateServerFnCallExpression( path: babel.NodePath, - opts: ParseAstOptions, + opts: CompileOptions, ) { // The function is the 'fn' property of the object passed to createServerFn @@ -352,7 +353,7 @@ function handleCreateServerFnCallExpression( function handleCreateMiddlewareCallExpression( path: babel.NodePath, - opts: ParseAstOptions, + opts: CompileOptions, ) { const rootCallExpression = getRootCallExpression(path) @@ -427,7 +428,7 @@ function handleCreateMiddlewareCallExpression( function buildEnvOnlyCallExpressionHandler(env: 'client' | 'server') { return function envOnlyCallExpressionHandler( path: babel.NodePath, - opts: ParseAstOptions, + opts: CompileOptions, ) { // if (debug) // console.info(`Handling ${env}Only call expression:`, path.toString()) diff --git a/packages/react-start-plugin/src/index.ts b/packages/react-start-plugin/src/index.ts index 076820022e..ca475b351e 100644 --- a/packages/react-start-plugin/src/index.ts +++ b/packages/react-start-plugin/src/index.ts @@ -1,13 +1,12 @@ -import path from 'node:path' -import { createTanStackServerFnPlugin } from '@tanstack/server-functions-plugin' -import { mergeConfig, perEnvironmentPlugin } from 'vite' -import viteReact from '@vitejs/plugin-react' +import { TanStackServerFnPluginEnv } from '@tanstack/server-functions-plugin' import { createNitro } from 'nitropack' import { TanStackRouterVite } from '@tanstack/router-plugin/vite' -import { createTanStackStartPlugin } from './server-fns.js' +import viteReact from '@vitejs/plugin-react' +import { mergeConfig } from 'vite' import { getTanStackStartOptions } from './schema.js' import { nitroPlugin } from './nitro/nitro-plugin.js' -import { tsrRoutesManifestPlugin } from './routesManifestPlugin.js' +import { tsrManifestPlugin } from './routesManifestPlugin.js' +import { TanStackStartCompilerPlugin } from './start-compiler-plugin.js' import type { PluginOption } from 'vite' import type { TanStackStartInputConfig } from './schema.js' @@ -21,39 +20,11 @@ export function TanStackStartVitePlugin( ): Array { const options = getTanStackStartOptions(opts) - const TanStackServerFnsPlugin = createTanStackServerFnPlugin({ - // This is the ID that will be available to look up and import - // our server function manifest and resolve its module - manifestVirtualImportId: 'tsr:server-fn-manifest', - client: { - getRuntimeCode: () => - `import { createClientRpc } from '@tanstack/react-start/server-functions-client'`, - replacer: (d) => - `createClientRpc('${d.functionId}', '${options.routers.server.base}')`, - }, - ssr: { - getRuntimeCode: () => - `import { createSsrRpc } from '@tanstack/react-start/server-functions-ssr'`, - replacer: (d) => - `createSsrRpc('${d.functionId}', '${options.routers.server.base}')`, - }, - server: { - getRuntimeCode: () => - `import { createServerRpc } from '@tanstack/react-start/server-functions-server'`, - replacer: (d) => - `createServerRpc('${d.functionId}', '${options.routers.server.base}', ${d.fn})`, - }, - }) - - const TanStackStartPlugin = createTanStackStartPlugin({ - globalMiddlewareEntry: options.routers.server.globalMiddlewareEntry, - }) - - const globalPlugins: Array = [ + return [ { name: 'tss-vite-config-client', ...options.vite, - async config() { + async config(config) { // Create a dummy nitro app to get the resolved public output path const dummyNitroApp = await createNitro({ preset: options.server.preset, @@ -63,7 +34,14 @@ export function TanStackStartVitePlugin( const nitroOutputPublicDir = dummyNitroApp.options.output.publicDir await dummyNitroApp.close() - return { + config.environments = { + ...(config.environments ?? {}), + server: { + ...(config.environments?.server ?? {}), + }, + } + + return mergeConfig(config, { resolve: { noExternal: [ '@tanstack/start', @@ -71,7 +49,6 @@ export function TanStackStartVitePlugin( '@tanstack/start-client', '@tanstack/start-server', '@tanstack/start-server-functions-fetcher', - '@tanstack/start-server-functions-handler', '@tanstack/start-server-functions-client', '@tanstack/start-server-functions-ssr', '@tanstack/start-server-functions-server', @@ -79,7 +56,7 @@ export function TanStackStartVitePlugin( '@tanstack/start-config', '@tanstack/start-api-routes', '@tanstack/server-functions-plugin', - 'tsr:routes-manifest', + 'tsr:start-manifest', 'tsr:server-fn-manifest', ], }, @@ -87,88 +64,66 @@ export function TanStackStartVitePlugin( entries: [], ...(options.vite?.optimizeDeps || {}), }, + /* prettier-ignore */ define: { ...(options.vite?.define || {}), ...injectDefineEnv('TSS_PUBLIC_BASE', options.routers.public.base), ...injectDefineEnv('TSS_CLIENT_BASE', options.routers.client.base), - ...injectDefineEnv('TSS_API_BASE', options.routers.server.base), + ...injectDefineEnv('TSS_CLIENT_ENTRY', options.clientEntryPath), + ...injectDefineEnv('TSS_SERVER_FN_BASE', options.routers.server.base), ...injectDefineEnv('TSS_OUTPUT_PUBLIC_DIR', nitroOutputPublicDir), }, - } + }) }, configEnvironment(env, config) { - if (env === 'client') { - return mergeConfig(config, options.routers.client.vite || {}) - } + if (env === 'server') { + config = mergeConfig(config, { + plugins: [], + }) - if (env === 'ssr') { - return mergeConfig(config, options.routers.ssr.vite || {}) + config = mergeConfig( + mergeConfig(config, options.vite || {}), + options.routers.server.vite || {}, + ) + } else { + config = mergeConfig( + mergeConfig(config, options.vite || {}), + options.routers.client.vite || {}, + ) } return config }, }, + TanStackStartCompilerPlugin(), + TanStackServerFnPluginEnv({ + // This is the ID that will be available to look up and import + // our server function manifest and resolve its module + manifestVirtualImportId: 'tsr:server-fn-manifest', + client: { + getRuntimeCode: () => + `import { createClientRpc } from '@tanstack/react-start/server-functions-client'`, + replacer: (d) => + `createClientRpc('${d.functionId}', '${options.routers.server.base}')`, + }, + server: { + getRuntimeCode: () => + `import { createServerRpc } from '@tanstack/react-start/server-functions-server'`, + replacer: (d) => + `createServerRpc('${d.functionId}', '${options.routers.server.base}', ${d.fn})`, + }, + }), + tsrManifestPlugin({ + clientBase: options.routers.client.base, + tsrConfig: options.tsr, + }), TanStackRouterVite({ ...options.tsr, enableRouteGeneration: true, autoCodeSplitting: true, }), viteReact(options.react), - ] - - return [ - perEnvironmentPlugin('tanstack-start-plugin-client', (environment) => - environment.name === 'client' - ? TanStackStartPlugin.client - : TanStackStartPlugin.server, - ), - ...globalPlugins, - perEnvironmentPlugin( - 'tanstack-server-fns-plugin-client-server', - (environment) => - environment.name === 'client' - ? TanStackServerFnsPlugin.client - : TanStackServerFnsPlugin.server, - ), - // perEnvironmentPlugin( - // 'tanstack-router-manifest-plugin', - // (environment) => - // environment.name === 'ssr' && - // tsrRoutesManifestPlugin({ - // clientBase: options.routers.client.base, - // tsrConfig: options.tsr, - // }), - // ), - // TODO: Should this only be loaded for ssr? like above? - tsrRoutesManifestPlugin({ - clientBase: options.routers.client.base, - tsrConfig: options.tsr, - }), - nitroPlugin({ - ...options, - server: { - ...options.server, - handlers: [ - ...(options.hasApiEntry - ? [ - { - route: options.routers.api.base, - handler: path.join( - options.root, - options.tsr.appDirectory, - options.routers.api.entry, - ), - }, - ] - : []), - ], - }, - plugins: [ - TanStackStartPlugin.server, - ...globalPlugins, - TanStackServerFnsPlugin.server, - ], - }), + nitroPlugin(options), ] } diff --git a/packages/react-start-plugin/src/nitro/nitro-plugin.ts b/packages/react-start-plugin/src/nitro/nitro-plugin.ts index 18c073ce9e..7b198e80e8 100644 --- a/packages/react-start-plugin/src/nitro/nitro-plugin.ts +++ b/packages/react-start-plugin/src/nitro/nitro-plugin.ts @@ -1,16 +1,15 @@ -import { dirname, resolve } from 'node:path' +import { resolve } from 'node:path' import { platform } from 'node:os' -import { fileURLToPath } from 'node:url' import { normalizePath } from 'vite' +import { getRollupConfig } from 'nitropack/rollup' -import { buildServer } from './build-server.js' -import { buildSSRApp } from './build-ssr.js' +import { createNitro } from 'nitropack' import { buildSitemap } from './build-sitemap.js' import { devServerPlugin } from './plugins/dev-server-plugin.js' -import type { TanStackStartOutputConfig } from '../schema.js' import type { NitroConfig } from 'nitropack' +import type { TanStackStartOutputConfig } from '../schema.js' -import type { PluginOption, UserConfig, ViteDevServer } from 'vite' +import type { PluginOption } from 'vite' export type { TanStackStartInputConfig, @@ -19,113 +18,63 @@ export type { const isWindows = platform() === 'win32' const filePrefix = isWindows ? 'file:///' : '' -let clientOutputPath = '' - -const __filename = fileURLToPath( - // @ts-ignore Cannot figure out for the life of me why tsconfig.json won't let me fix this. Only shows up during build, not in editor. - import.meta.url, -) -const __dirname = dirname(__filename) export function nitroPlugin( - options: TanStackStartOutputConfig & { - plugins: Array - }, + options: TanStackStartOutputConfig, ): Array { - let isTest = process.env['NODE_ENV'] === 'test' || !!process.env['VITEST'] - - let isBuild = false - let isServe = false - let ssrBuild = false - let config: UserConfig - let nitroConfig: NitroConfig - let environmentBuild = false - return [ devServerPlugin(options), { name: 'tanstack-vite-plugin-nitro', - config(userConfig, { mode, command }) { - isServe = command === 'serve' - isBuild = command === 'build' - ssrBuild = userConfig.build?.ssr === true - config = userConfig - isTest = isTest ? isTest : mode === 'test' - + async config() { const buildPreset = process.env['BUILD_PRESET'] ?? (options.server.preset as string | undefined) - const rendererEntry = - filePrefix + normalizePath(options.routers.ssr.entry) - - nitroConfig = { + const nitroConfig: NitroConfig = { ...options.server, preset: buildPreset, compatibilityDate: '2024-11-19', logLevel: options.server.logLevel || 0, srcDir: normalizePath(options.tsr.appDirectory), + renderer: filePrefix + normalizePath(options.ssrEntryPath), + } + + const nitro = await createNitro({ + dev: false, + ...nitroConfig, typescript: { generateTsConfig: false, }, - rollupConfig: { - onwarn(warning) { - if ( - warning.message.includes('empty chunk') && - warning.message.endsWith('.server') - ) { - return - } - }, - plugins: options.plugins, - }, - handlers: [], - } - - if (!ssrBuild && !isTest) { - // store the client output path for the SSR build config - clientOutputPath = resolve( - options.root, - config.build?.outDir || 'dist/client', - ) - } + }) - nitroConfig.alias = { - '#start/ssr': options.ssrEntryPath, - } + const nitroRollupOptions = getRollupConfig(nitro) return { environments: { - ssr: { + server: { build: { ssr: true, rollupOptions: { - input: options.ssrEntryPath, + ...nitroRollupOptions, + plugins: nitroRollupOptions.plugins as Array, }, - outDir: resolve(options.root, 'dist/ssr'), }, }, }, builder: { sharedPlugins: true, buildApp: async (builder) => { - console.log('tanner buildApp', builder) - environmentBuild = true - if (!builder.environments['client']) { throw new Error('Client environment not found') } - if (!builder.environments['ssr']) { + if (!builder.environments['server']) { throw new Error('SSR environment not found') } - await Promise.all([ - builder.build(builder.environments['client']), - builder.build(builder.environments['ssr']), - ]) - - await buildServer(nitroConfig) + await builder.build(builder.environments['client']) + await builder.build(builder.environments['server']) if (nitroConfig.prerender?.routes?.length && options.sitemap) { console.log('Building Sitemap...') @@ -144,70 +93,6 @@ export function nitroPlugin( }, } }, - async configureServer(viteServer: ViteDevServer) { - return // TODO: We'll remove this when we're ready for non-entry routes - // if (isServe && !isTest) { - // const nitro = await createNitro({ - // dev: true, - // ...nitroConfig, - // }) - - // const server = createDevServer(nitro) - // await build(nitro) - - // // viteServer.middlewares.use( - // // apiBase, - // // toNodeListener(server.app as unknown as App), - // // ) - - // viteServer.httpServer?.once('listening', () => { - // process.env['START_HOST'] = !viteServer.config.server.host - // ? 'localhost' - // : (viteServer.config.server.host as string) - // process.env['START_PORT'] = `${viteServer.config.server.port}` - // }) - - // // handle upgrades if websockets are enabled - // if (nitroConfig.experimental?.websocket) { - // viteServer.httpServer?.on('upgrade', server.upgrade) - // } - // } - }, - async closeBundle() { - // Skip when build is triggered by the Environment API - if (environmentBuild) { - return - } - - if (ssrBuild) { - return - } - - if (isBuild) { - console.log('Building SSR application...') - await buildSSRApp({ - root: options.root, - ssrEntry: options.ssrEntryPath, - viteConfig: config, - }) - - if (options.sitemap) { - console.log('Building Sitemap...') - // sitemap needs to be built after all directories are built - await buildSitemap({ - host: options.sitemap.host, - routes: nitroConfig.prerender?.routes || [], // TODO: Can we get these routes from the final crawled routes from prerender? - outputDir: resolve(options.root, 'dist/public'), - }) - } - - await buildServer(nitroConfig) - - console.log( - `\n\nThe 'tanstack-platform' server has been successfully built.`, - ) - } - }, }, ] } diff --git a/packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts b/packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts index 5781f4979a..995a9b7a0a 100644 --- a/packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts +++ b/packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts @@ -1,10 +1,9 @@ // SSR dev server, middleware and error page source modified from // https://github.com/solidjs/solid-start/blob/main/packages/start/dev/server.js -import { createEvent, sendWebResponse } from 'h3' - -import { registerDevServerMiddleware } from '../utils/register-dev-middleware.js' -import type { Connect, Plugin, ViteDevServer } from 'vite' +import { createEvent, getHeader, sendWebResponse } from 'h3' +import { isRunnableDevEnvironment } from 'vite' +import type { Connect, Environment, Plugin, ViteDevServer } from 'vite' import type { TanStackStartOutputConfig } from '../../schema.js' export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { @@ -25,34 +24,66 @@ export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { }, } }, - configureServer(viteServer) { + configureServer(viteDevServer) { if (isTest) { return } + ;(globalThis as any).viteDevServer = viteDevServer + return () => { - remove_html_middlewares(viteServer.middlewares) - registerDevServerMiddleware(options.root, viteServer) + remove_html_middlewares(viteDevServer.middlewares) + + viteDevServer.middlewares.use(async (req, res) => { + const event = createEvent(req, res) + const serverEnv = viteDevServer.environments['server'] as Environment - viteServer.middlewares.use(async (req, res) => { try { - const serverEntry = ( - await viteServer.ssrLoadModule('~start/ssr-entry') - )['default'] + if (!isRunnableDevEnvironment(serverEnv)) { + throw new Error('Server environment not found') + } - const event = createEvent(req, res) - const result: string | Response = await serverEntry(event) + const serverEntry = + await serverEnv.runner.import('~start/ssr-entry') - if (result instanceof Response) { - sendWebResponse(event, result) - return - } - res.setHeader('Content-Type', 'text/html') - res.end(result) + const response = await serverEntry['default'](event) + + sendWebResponse(event, response) } catch (e) { - viteServer.ssrFixStacktrace(e as Error) - res.statusCode = 500 - res.end(` + console.error(e) + viteDevServer.ssrFixStacktrace(e as Error) + + if ( + getHeader(event, 'content-type')?.includes('application/json') + ) { + return sendWebResponse( + event, + new Response( + JSON.stringify( + { + status: 500, + error: 'Internal Server Error', + message: + 'An unexpected error occurred. Please try again later.', + timestamp: new Date().toISOString(), + }, + null, + 2, + ), + { + status: 500, + headers: { + 'Content-Type': 'application/json', + }, + }, + ), + ) + } + + sendWebResponse( + event, + new Response( + ` @@ -68,7 +99,12 @@ export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { - `) + `, + { + status: 500, + }, + ), + ) } }) } diff --git a/packages/react-start-plugin/src/nitro/utils/load-esm.ts b/packages/react-start-plugin/src/nitro/utils/load-esm.ts deleted file mode 100644 index 78e8049184..0000000000 --- a/packages/react-start-plugin/src/nitro/utils/load-esm.ts +++ /dev/null @@ -1,27 +0,0 @@ -/** - * @license - * Copyright Google LLC All Rights Reserved. - * - * Use of this source code is governed by an MIT-style license that can be - * found in the LICENSE file at https://angular.dev/license - */ - -import { URL } from 'node:url' - -/** - * This uses a dynamic import to load a module which may be ESM. - * CommonJS code can load ESM code via a dynamic import. Unfortunately, TypeScript - * will currently, unconditionally downlevel dynamic import into a require call. - * require calls cannot load ESM code and will result in a runtime error. To workaround - * this, a Function constructor is used to prevent TypeScript from changing the dynamic import. - * Once TypeScript provides support for keeping the dynamic import this workaround can - * be dropped. - * - * @param modulePath The path of the module to load. - * @returns A Promise that resolves to the dynamically imported module. - */ -export function loadEsmModule(modulePath: string | URL): Promise { - return new Function('modulePath', `return import(modulePath);`)( - modulePath, - ) as Promise -} diff --git a/packages/react-start-plugin/src/nitro/utils/register-dev-middleware.ts b/packages/react-start-plugin/src/nitro/utils/register-dev-middleware.ts deleted file mode 100644 index 78d1389515..0000000000 --- a/packages/react-start-plugin/src/nitro/utils/register-dev-middleware.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { createEvent } from 'h3' -import fg from 'fast-glob' -import type { ViteDevServer } from 'vite' -import type { EventHandler } from 'h3' - -export function registerDevServerMiddleware( - root: string, - viteServer: ViteDevServer, -) { - const middlewareFiles = fg.sync([`${root}/src/server/middleware/**/*.ts`]) - - middlewareFiles.forEach((file) => { - viteServer.middlewares.use(async (req, res, next) => { - const middlewareHandler: EventHandler = await viteServer - .ssrLoadModule(file) - .then((m: unknown) => (m as { default: EventHandler }).default) - - const result = await middlewareHandler(createEvent(req, res)) - - if (!result) { - next() - } - }) - }) -} diff --git a/packages/react-start-plugin/src/routesManifestPlugin.ts b/packages/react-start-plugin/src/routesManifestPlugin.ts index 0fde46ec3c..be94ff2405 100644 --- a/packages/react-start-plugin/src/routesManifestPlugin.ts +++ b/packages/react-start-plugin/src/routesManifestPlugin.ts @@ -5,7 +5,7 @@ import type { PluginOption, ResolvedConfig } from 'vite' import type { z } from 'zod' import type { Manifest } from '@tanstack/react-router' -export function tsrRoutesManifestPlugin(opts: { +export function tsrManifestPlugin(opts: { tsrConfig: z.infer clientBase: string }): PluginOption { @@ -13,21 +13,27 @@ export function tsrRoutesManifestPlugin(opts: { return { name: 'tsr-routes-manifest', + enforce: 'pre', + configResolved(resolvedConfig) { config = resolvedConfig }, + // configEnvironment(env, envConfig) { + // config = envConfig. + // }, resolveId(id) { - if (id === 'tsr:routes-manifest') { + if (id === 'tsr:start-manifest') { return id } return }, load(id) { - if (id === 'tsr:routes-manifest') { + if (id === 'tsr:start-manifest') { // If we're in development, return a dummy manifest if (config.command === 'serve') { return `export default () => ({ + entry: "$${process.env.TSS_CLIENT_BASE}/", routes: {} })` } diff --git a/packages/react-start-plugin/src/server-fns.ts b/packages/react-start-plugin/src/server-fns.ts deleted file mode 100644 index 4d08a9d165..0000000000 --- a/packages/react-start-plugin/src/server-fns.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { fileURLToPath, pathToFileURL } from 'node:url' -import path from 'node:path' -import { logDiff } from '@tanstack/router-utils' -import { compileStartOutput } from './compilers' - -import type { Plugin } from 'vite' - -const debug = - process.env.TSR_VITE_DEBUG && - ['true', 'start-plugin'].includes(process.env.TSR_VITE_DEBUG) - -export type TanStackStartViteOptions = { - globalMiddlewareEntry: string -} - -const transformFuncs = [ - 'createServerFn', - 'createMiddleware', - 'serverOnly', - 'clientOnly', - 'createIsomorphicFn', -] -const tokenRegex = new RegExp(transformFuncs.join('|')) -// const eitherFuncRegex = new RegExp( -// `(function ${transformFuncs.join('|function ')})`, -// ) - -export function createTanStackStartPlugin(opts: TanStackStartViteOptions): { - client: Array - ssr: Array - server: Array -} { - return { - client: [ - (() => { - let entry: string | null = null - let ROOT: string = process.cwd() - return { - name: 'vite-plugin-tanstack-start-server-entry-client', - enforce: 'pre', - configResolved: (config) => { - ROOT = config.root - entry = path.resolve(ROOT, (config as any).router.handler) - - if (!entry) { - throw new Error('@tanstack/start-plugin: No server entry found!') - } - }, - transform(code, id) { - if (entry && id.includes(entry)) { - return { - code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, - map: null, - } - } - return null - }, - } - })(), - TanStackStartServerFnsAndMiddleware({ ...opts, env: 'client' }), - ], - ssr: [ - (() => { - let entry: string | null = null - let ROOT: string = process.cwd() - return { - name: 'vite-plugin-tanstack-start-server-entry-ssr', - enforce: 'pre', - configResolved: (config) => { - ROOT = config.root - entry = path.resolve(ROOT, (config as any).router.handler) - - if (!entry) { - throw new Error('@tanstack/start-plugin: No server entry found!') - } - }, - transform(code, id) { - if (entry && id.includes(entry)) { - return { - code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, - map: null, - } - } - return null - }, - } - })(), - TanStackStartServerFnsAndMiddleware({ ...opts, env: 'ssr' }), - ], - server: [ - (() => { - let entry: string | null = null - let ROOT: string = process.cwd() - return { - name: 'vite-plugin-tanstack-start-server-entry-server', - enforce: 'pre', - configResolved: (config) => { - ROOT = config.root - entry = path.resolve(ROOT, (config as any).router.handler) - - if (!entry) { - throw new Error('@tanstack/start-plugin: No server entry found!') - } - }, - transform(code, id) { - if (entry && id.includes(entry)) { - return { - code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, - map: null, - } - } - return null - }, - } - })(), - TanStackStartServerFnsAndMiddleware({ ...opts, env: 'server' }), - ], - } -} - -export function TanStackStartServerFnsAndMiddleware(opts: { - env: 'server' | 'ssr' | 'client' -}): Plugin { - let ROOT: string = process.cwd() - - return { - name: 'vite-plugin-tanstack-start-create-server-fn', - enforce: 'pre', - configResolved: (config) => { - ROOT = config.root - }, - transform(code, id) { - const url = pathToFileURL(id) - url.searchParams.delete('v') - id = fileURLToPath(url).replace(/\\/g, '/') - - const includesToken = tokenRegex.test(code) - // const includesEitherFunc = eitherFuncRegex.test(code) - - if ( - !includesToken - // includesEitherFunc - // /node_modules/.test(id) - ) { - return null - } - - if (code.includes('@react-refresh')) { - throw new Error( - `We detected that the '@vitejs/plugin-react' was passed before '@tanstack/start-plugin'. Please make sure that '@tanstack/router-vite-plugin' is passed before '@vitejs/plugin-react' and try again: -e.g. - -plugins: [ - TanStackStartVite(), // Place this before viteReact() - viteReact(), -] -`, - ) - } - - if (debug) console.info(`${opts.env} Compiling Start: `, id) - - const compiled = compileStartOutput({ - code, - root: ROOT, - filename: id, - env: opts.env, - }) - - if (debug) { - logDiff(code, compiled.code) - console.log('Output:\n', compiled.code + '\n\n') - } - - return compiled - }, - } -} diff --git a/packages/react-start-plugin/src/start-compiler-plugin.ts b/packages/react-start-plugin/src/start-compiler-plugin.ts new file mode 100644 index 0000000000..2c42234c10 --- /dev/null +++ b/packages/react-start-plugin/src/start-compiler-plugin.ts @@ -0,0 +1,150 @@ +import { fileURLToPath, pathToFileURL } from 'node:url' +import { logDiff } from '@tanstack/router-utils' +import { compileStartOutput } from './compilers' + +import type { Plugin } from 'vite' + +const debug = + process.env.TSR_VITE_DEBUG && + ['true', 'start-plugin'].includes(process.env.TSR_VITE_DEBUG) + +export type TanStackStartViteOptions = { + globalMiddlewareEntry: string +} + +const transformFuncs = [ + 'createServerFn', + 'createMiddleware', + 'serverOnly', + 'clientOnly', + 'createIsomorphicFn', +] +const tokenRegex = new RegExp(transformFuncs.join('|')) +// const eitherFuncRegex = new RegExp( +// `(function ${transformFuncs.join('|function ')})`, +// ) + +// TODO: Bring these back +// (() => { +// let entry: string | null = null +// let ROOT: string = process.cwd() +// return { +// name: 'vite-plugin-tanstack-start-server-entry-client', +// enforce: 'pre', +// configResolved: (config) => { +// ROOT = config.root +// entry = path.resolve(ROOT, (config as any).router.handler) + +// if (!entry) { +// throw new Error('@tanstack/start-plugin: No server entry found!') +// } +// }, +// transform(code, id) { +// if (entry && id.includes(entry)) { +// return { +// code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, +// map: null, +// } +// } +// return null +// }, +// } +// })(), + +export function TanStackStartCompilerPlugin(opts?: { + client?: { + envName?: string + } + server?: { + envName?: string + } +}): Plugin { + opts = { + client: { + envName: 'client', + ...opts?.client, + }, + server: { + envName: 'server', + ...opts?.server, + }, + } + + return { + name: 'vite-plugin-tanstack-start-create-server-fn', + enforce: 'pre', + applyToEnvironment(env) { + return [opts.client?.envName, opts.server?.envName].includes(env.name) + }, + transform(code, id) { + const env = + this.environment.name === opts.client?.envName + ? 'client' + : this.environment.name === opts.server?.envName + ? 'server' + : (() => { + throw new Error( + `Environment ${this.environment.name} not configured`, + ) + })() + + return transformCode({ + code, + id, + env, + }) + }, + } +} + +function transformCode(opts: { + code: string + id: string + env: 'server' | 'client' +}) { + const { code, env } = opts + let { id } = opts + + const url = pathToFileURL(id) + url.searchParams.delete('v') + id = fileURLToPath(url).replace(/\\/g, '/') + + const includesToken = tokenRegex.test(code) + // const includesEitherFunc = eitherFuncRegex.test(code) + + if ( + !includesToken + // includesEitherFunc + // /node_modules/.test(id) + ) { + return null + } + + if (code.includes('@react-refresh')) { + throw new Error( + `We detected that the '@vitejs/plugin-react' was passed before '@tanstack/start-plugin'. Please make sure that '@tanstack/router-vite-plugin' is passed before '@vitejs/plugin-react' and try again: + e.g. + + plugins: [ + TanStackStartVite(), // Place this before viteReact() + viteReact(), + ] + `, + ) + } + + if (debug) console.info(`${env} Compiling Start: `, id) + + const compiled = compileStartOutput({ + code, + filename: id, + env, + }) + + if (debug) { + logDiff(code, compiled.code) + console.log('Output:\n', compiled.code + '\n\n') + } + + return compiled +} diff --git a/packages/react-start-plugin/vite.config.ts b/packages/react-start-plugin/vite.config.ts index 5389f0f739..2c711fd181 100644 --- a/packages/react-start-plugin/vite.config.ts +++ b/packages/react-start-plugin/vite.config.ts @@ -16,5 +16,6 @@ export default mergeConfig( tanstackViteConfig({ entry: './src/index.ts', srcDir: './src', + outDir: './dist', }), ) diff --git a/packages/react-start-router-manifest/README.md b/packages/react-start-router-manifest/README.md deleted file mode 100644 index bb009b0c87..0000000000 --- a/packages/react-start-router-manifest/README.md +++ /dev/null @@ -1,33 +0,0 @@ -> 🤫 we're cooking up something special! - - - -# TanStack Start - -![TanStack Router Header](https://github.com/tanstack/router/raw/main/media/header.png) - -🤖 Type-safe router w/ built-in caching & URL state management for React! - - - #TanStack - - - - - - - - semantic-release - - Join the discussion on Github -Best of JS - - - - - - - -Enjoy this library? Try the entire [TanStack](https://tanstack.com)! [React Query](https://github.com/tannerlinsley/react-query), [React Table](https://github.com/tanstack/react-table), [React Charts](https://github.com/tannerlinsley/react-charts), [React Virtual](https://github.com/tannerlinsley/react-virtual) - -## Visit [tanstack.com/router](https://tanstack.com/router) for docs, guides, API and more! diff --git a/packages/react-start-router-manifest/eslint.config.js b/packages/react-start-router-manifest/eslint.config.js deleted file mode 100644 index 931f0ec774..0000000000 --- a/packages/react-start-router-manifest/eslint.config.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check - -import pluginReact from '@eslint-react/eslint-plugin' -import pluginReactHooks from 'eslint-plugin-react-hooks' -import rootConfig from '../../eslint.config.js' - -export default [ - ...rootConfig, - { - ...pluginReact.configs.recommended, - files: ['**/*.{ts,tsx}'], - }, - { - plugins: { - 'react-hooks': pluginReactHooks, - }, - rules: { - '@eslint-react/no-unstable-context-value': 'off', - '@eslint-react/no-unstable-default-props': 'off', - '@eslint-react/dom/no-missing-button-type': 'off', - 'react-hooks/exhaustive-deps': 'error', - 'react-hooks/rules-of-hooks': 'error', - }, - }, - { - files: ['**/__tests__/**'], - rules: { - '@typescript-eslint/no-unnecessary-condition': 'off', - }, - }, -] diff --git a/packages/react-start-router-manifest/package.json b/packages/react-start-router-manifest/package.json deleted file mode 100644 index 758b86367d..0000000000 --- a/packages/react-start-router-manifest/package.json +++ /dev/null @@ -1,67 +0,0 @@ -{ - "name": "@tanstack/react-start-router-manifest", - "version": "1.114.3", - "description": "Modern and scalable routing for React applications", - "author": "Tanner Linsley", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/TanStack/router.git", - "directory": "packages/react-start-router-manifest" - }, - "homepage": "https://tanstack.com/start", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "keywords": [ - "react", - "location", - "router", - "routing", - "async", - "async router", - "typescript" - ], - "scripts": { - "clean": "rimraf ./dist && rimraf ./coverage", - "test": "pnpm test:eslint && pnpm test:types && pnpm test:build && pnpm test:unit", - "test:unit": "exit 0; vitest", - "test:eslint": "eslint ./src", - "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"", - "test:types:ts53": "node ../../node_modules/typescript53/lib/tsc.js", - "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": "tsc", - "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .", - "build": "tsc" - }, - "type": "module", - "types": "dist/esm/index.d.ts", - "exports": { - ".": { - "import": { - "types": "./dist/esm/index.d.ts", - "default": "./dist/esm/index.js" - } - }, - "./package.json": "./package.json" - }, - "sideEffects": false, - "files": [ - "dist", - "src" - ], - "engines": { - "node": ">=12" - }, - "dependencies": { - "@tanstack/router-core": "workspace:^", - "tiny-invariant": "^1.3.3" - }, - "devDependencies": { - "typescript": "^5.7.2" - } -} diff --git a/packages/react-start-router-manifest/tsconfig.json b/packages/react-start-router-manifest/tsconfig.json deleted file mode 100644 index 940a9cce0a..0000000000 --- a/packages/react-start-router-manifest/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "include": ["src/index.ts"], - "compilerOptions": { - "rootDir": "src", - "outDir": "dist/esm", - "target": "esnext", - "noEmit": false - } -} diff --git a/packages/react-start-router-manifest/vite.config.ts b/packages/react-start-router-manifest/vite.config.ts deleted file mode 100644 index d6472068fb..0000000000 --- a/packages/react-start-router-manifest/vite.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' -import packageJson from './package.json' -import type { ViteUserConfig } from 'vitest/config' - -const config = defineConfig({ - plugins: [] as ViteUserConfig['plugins'], - test: { - name: packageJson.name, - watch: false, - environment: 'jsdom', - }, -}) - -export default mergeConfig( - config, - tanstackViteConfig({ - entry: './src/index.ts', - srcDir: './src', - externalDeps: ['tsr:routes-manifest'], - }), -) diff --git a/packages/react-start-server-functions-handler/README.md b/packages/react-start-server-functions-handler/README.md deleted file mode 100644 index bb009b0c87..0000000000 --- a/packages/react-start-server-functions-handler/README.md +++ /dev/null @@ -1,33 +0,0 @@ -> 🤫 we're cooking up something special! - - - -# TanStack Start - -![TanStack Router Header](https://github.com/tanstack/router/raw/main/media/header.png) - -🤖 Type-safe router w/ built-in caching & URL state management for React! - - - #TanStack - - - - - - - - semantic-release - - Join the discussion on Github -Best of JS - - - - - - - -Enjoy this library? Try the entire [TanStack](https://tanstack.com)! [React Query](https://github.com/tannerlinsley/react-query), [React Table](https://github.com/tanstack/react-table), [React Charts](https://github.com/tannerlinsley/react-charts), [React Virtual](https://github.com/tannerlinsley/react-virtual) - -## Visit [tanstack.com/router](https://tanstack.com/router) for docs, guides, API and more! diff --git a/packages/react-start-server-functions-handler/eslint.config.js b/packages/react-start-server-functions-handler/eslint.config.js deleted file mode 100644 index 931f0ec774..0000000000 --- a/packages/react-start-server-functions-handler/eslint.config.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check - -import pluginReact from '@eslint-react/eslint-plugin' -import pluginReactHooks from 'eslint-plugin-react-hooks' -import rootConfig from '../../eslint.config.js' - -export default [ - ...rootConfig, - { - ...pluginReact.configs.recommended, - files: ['**/*.{ts,tsx}'], - }, - { - plugins: { - 'react-hooks': pluginReactHooks, - }, - rules: { - '@eslint-react/no-unstable-context-value': 'off', - '@eslint-react/no-unstable-default-props': 'off', - '@eslint-react/dom/no-missing-button-type': 'off', - 'react-hooks/exhaustive-deps': 'error', - 'react-hooks/rules-of-hooks': 'error', - }, - }, - { - files: ['**/__tests__/**'], - rules: { - '@typescript-eslint/no-unnecessary-condition': 'off', - }, - }, -] diff --git a/packages/react-start-server-functions-handler/package.json b/packages/react-start-server-functions-handler/package.json deleted file mode 100644 index a34bf04530..0000000000 --- a/packages/react-start-server-functions-handler/package.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "name": "@tanstack/react-start-server-functions-handler", - "version": "1.114.3", - "description": "Modern and scalable routing for React applications", - "author": "Tanner Linsley", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/TanStack/router.git", - "directory": "packages/react-start-server-functions-handler" - }, - "homepage": "https://tanstack.com/start", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "keywords": [ - "react", - "location", - "router", - "routing", - "async", - "async router", - "typescript" - ], - "scripts": { - "clean": "rimraf ./dist && rimraf ./coverage", - "test": "pnpm test:eslint && pnpm test:types && pnpm test:build && pnpm test:unit", - "test:unit": "exit 0; vitest", - "test:eslint": "eslint ./src", - "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"", - "test:types:ts53": "node ../../node_modules/typescript53/lib/tsc.js", - "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": "tsc", - "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .", - "build": "vite build" - }, - "type": "module", - "types": "dist/esm/index.d.ts", - "exports": { - ".": { - "import": { - "types": "./dist/esm/index.d.ts", - "default": "./dist/esm/index.js" - }, - "require": { - "types": "./dist/cjs/index.d.cts", - "default": "./dist/cjs/index.cjs" - } - }, - "./package.json": "./package.json" - }, - "sideEffects": false, - "files": [ - "dist", - "src" - ], - "engines": { - "node": ">=12" - }, - "dependencies": { - "@tanstack/react-router": "workspace:^", - "@tanstack/react-start-client": "workspace:^", - "@tanstack/react-start-server": "workspace:^", - "tiny-invariant": "^1.3.3" - }, - "devDependencies": { - "@vitejs/plugin-react": "^4.3.4", - "react": "^19.0.0", - "react-dom": "^19.0.0", - "typescript": "^5.7.2" - }, - "peerDependencies": { - "react": ">=18.0.0 || >=19.0.0", - "react-dom": ">=18.0.0 || >=19.0.0" - } -} diff --git a/packages/react-start-server-functions-handler/tsconfig.json b/packages/react-start-server-functions-handler/tsconfig.json deleted file mode 100644 index 0484835e6b..0000000000 --- a/packages/react-start-server-functions-handler/tsconfig.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "compilerOptions": { - "module": "esnext" - }, - "include": ["src", "vite.config.ts"] -} diff --git a/packages/react-start-server-functions-handler/vite.config.ts b/packages/react-start-server-functions-handler/vite.config.ts deleted file mode 100644 index 09a96c3c0a..0000000000 --- a/packages/react-start-server-functions-handler/vite.config.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' -import react from '@vitejs/plugin-react' -import packageJson from './package.json' -import type { ViteUserConfig } from 'vitest/config' - -const config = defineConfig({ - plugins: [react()] as ViteUserConfig['plugins'], - test: { - name: packageJson.name, - watch: false, - environment: 'jsdom', - }, -}) - -export default mergeConfig( - config, - tanstackViteConfig({ - entry: './src/index.ts', - srcDir: './src', - externalDeps: ['tsr:server-fn-manifest'], - }), -) diff --git a/packages/react-start-server/src/createStartHandler.ts b/packages/react-start-server/src/createStartHandler.ts index fcd381c492..90172fe71e 100644 --- a/packages/react-start-server/src/createStartHandler.ts +++ b/packages/react-start-server/src/createStartHandler.ts @@ -1,10 +1,13 @@ +import path from 'node:path' import { createMemoryHistory } from '@tanstack/history' import { mergeHeaders } from '@tanstack/react-start-client' import { eventHandler, getResponseHeaders, toWebRequest } from 'h3' import { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server' +import serverFunctionsHandler from './server-functions-handler' +import { getStartManifest } from './router-manifest' import type { HandlerCallback } from './handlerCallback' import type { EventHandlerResponse, H3Event } from 'h3' -import type { AnyRouter, Manifest } from '@tanstack/router-core' +import type { AnyRouter } from '@tanstack/router-core' export type CustomizeStartHandler< TRouter extends AnyRouter, @@ -16,10 +19,8 @@ export function createStartHandler< TResponse extends EventHandlerResponse = EventHandlerResponse, >({ createRouter, - getRouterManifest, }: { createRouter: () => TRouter - getRouterManifest?: () => Manifest | Promise }): CustomizeStartHandler { return (cb) => { return eventHandler(async (event) => { @@ -28,6 +29,18 @@ export function createStartHandler< const url = new URL(request.url) const href = url.href.replace(url.origin, '') + if (!process.env.TSS_SERVER_FN_BASE) { + throw new Error( + 'tanstack/react-start-server: TSS_SERVER_FN_BASE must be defined in your environment for createStartHandler()', + ) + } + + if ( + href.startsWith(path.join('/', process.env.TSS_SERVER_FN_BASE, '/')) + ) { + return await serverFunctionsHandler(event) + } + // Create a history for the router const history = createMemoryHistory({ initialEntries: [href], @@ -35,7 +48,7 @@ export function createStartHandler< const router = createRouter() - attachRouterServerSsrUtils(router, await getRouterManifest?.()) + attachRouterServerSsrUtils(router, getStartManifest()) // Update the router with the history and context router.update({ diff --git a/packages/react-start-server/src/h3.ts b/packages/react-start-server/src/h3.ts new file mode 100644 index 0000000000..406cb93871 --- /dev/null +++ b/packages/react-start-server/src/h3.ts @@ -0,0 +1,498 @@ +import { AsyncLocalStorage } from 'node:async_hooks' +import { + H3Event, + appendCorsHeaders as _appendCorsHeaders, + appendCorsPreflightHeaders as _appendCorsPreflightHeaders, + appendHeader as _appendHeader, + appendHeaders as _appendHeaders, + appendResponseHeader as _appendResponseHeader, + appendResponseHeaders as _appendResponseHeaders, + assertMethod as _assertMethod, + clearResponseHeaders as _clearResponseHeaders, + clearSession as _clearSession, + defaultContentType as _defaultContentType, + deleteCookie as _deleteCookie, + fetchWithEvent as _fetchWithEvent, + getCookie as _getCookie, + getHeader as _getHeader, + getHeaders as _getHeaders, + getProxyRequestHeaders as _getProxyRequestHeaders, + getQuery as _getQuery, + getRequestFingerprint as _getRequestFingerprint, + getRequestHeader as _getRequestHeader, + getRequestHeaders as _getRequestHeaders, + getRequestHost as _getRequestHost, + getRequestIP as _getRequestIP, + getRequestProtocol as _getRequestProtocol, + getRequestURL as _getRequestURL, + getRequestWebStream as _getRequestWebStream, + getResponseHeader as _getResponseHeader, + getResponseHeaders as _getResponseHeaders, + getResponseStatus as _getResponseStatus, + getResponseStatusText as _getResponseStatusText, + getRouterParam as _getRouterParam, + getRouterParams as _getRouterParams, + getSession as _getSession, + getValidatedQuery as _getValidatedQuery, + getValidatedRouterParams as _getValidatedRouterParams, + handleCacheHeaders as _handleCacheHeaders, + handleCors as _handleCors, + isMethod as _isMethod, + isPreflightRequest as _isPreflightRequest, + parseCookies as _parseCookies, + proxyRequest as _proxyRequest, + readBody as _readBody, + readFormData as _readFormData, + readMultipartFormData as _readMultipartFormData, + readRawBody as _readRawBody, + readValidatedBody as _readValidatedBody, + removeResponseHeader as _removeResponseHeader, + sealSession as _sealSession, + send as _send, + sendError as _sendError, + sendNoContent as _sendNoContent, + sendProxy as _sendProxy, + sendRedirect as _sendRedirect, + sendStream as _sendStream, + sendWebResponse as _sendWebResponse, + setCookie as _setCookie, + setHeader as _setHeader, + setHeaders as _setHeaders, + setResponseHeader as _setResponseHeader, + setResponseHeaders as _setResponseHeaders, + setResponseStatus as _setResponseStatus, + unsealSession as _unsealSession, + updateSession as _updateSession, + useSession as _useSession, + writeEarlyHints as _writeEarlyHints, +} from 'h3' + +import { getContext as getUnctxContext } from 'unctx' + +import type { + Encoding, + HTTPHeaderName, + InferEventInput, + _RequestMiddleware, + _ResponseMiddleware, +} from 'h3' + +function _setContext(event: H3Event, key: string, value: any) { + event.context[key] = value +} + +function _getContext(event: H3Event, key: string) { + return event.context[key] +} + +export function defineMiddleware(options: { + onRequest?: _RequestMiddleware | Array<_RequestMiddleware> + onBeforeResponse?: _ResponseMiddleware | Array<_ResponseMiddleware> +}) { + return options +} + +function toWebRequestH3(event: H3Event) { + /** + * @type {ReadableStream | undefined} + */ + let readableStream: ReadableStream | undefined + + const url = getRequestURL(event) + const base = { + // @ts-ignore Undici option + duplex: 'half', + method: event.method, + headers: event.headers, + } + + if ((event.node.req as any).body instanceof ArrayBuffer) { + return new Request(url, { + ...base, + body: (event.node.req as any).body, + }) + } + + return new Request(url, { + ...base, + get body() { + if (readableStream) { + return readableStream + } + readableStream = getRequestWebStream(event) + return readableStream + }, + }) +} + +export function toWebRequest(event: H3Event) { + event.web ??= { + request: toWebRequestH3(event), + url: getRequestURL(event), + } + return event.web.request +} + +export { + H3Error, + H3Event, + MIMES, + callNodeListener, + createApp, + createAppEventHandler, + createEvent, + createRouter, + defineEventHandler, + defineLazyEventHandler, + defineNodeListener, + defineNodeMiddleware, + defineRequestMiddleware, + defineResponseMiddleware, + dynamicEventHandler, + defineWebSocket, + eventHandler, + splitCookiesString, + fromNodeMiddleware, + fromPlainHandler, + fromWebHandler, + isError, + isEventHandler, + isWebResponse, + lazyEventHandler, + promisifyNodeListener, + serveStatic, + toEventHandler, + toNodeListener, + toPlainHandler, + toWebHandler, + isCorsOriginAllowed, + isStream, + createError, + sanitizeStatusCode, + sanitizeStatusMessage, + useBase, + type AddRouteShortcuts, + type App, + type AppOptions, + type AppUse, + type CacheConditions, + type CreateRouterOptions, + type Duplex, + type DynamicEventHandler, + type Encoding, + type EventHandler, + type EventHandlerObject, + type EventHandlerRequest, + type EventHandlerResponse, + type H3CorsOptions, + type H3EventContext, + type HTTPHeaderName, + type HTTPMethod, + type InferEventInput, + type InputLayer, + type InputStack, + type Layer, + type LazyEventHandler, + type Matcher, + type MultiPartData, + type NodeEventContext, + type NodeListener, + type NodeMiddleware, + type NodePromisifiedHandler, + type PlainHandler, + type PlainRequest, + type PlainResponse, + type ProxyOptions, + type RequestFingerprintOptions, + type RequestHeaders, + type RouteNode, + type Router, + type RouterMethod, + type RouterUse, + type ServeStaticOptions, + type Session, + type SessionConfig, + type SessionData, + type Stack, + type StaticAssetMeta, + type ValidateFunction, + type ValidateResult, + type WebEventContext, + type WebHandler, + type _RequestMiddleware, + type _ResponseMiddleware, +} from 'h3' + +function getHTTPEvent() { + return getEvent() +} + +export function getEvent() { + const event = (getNitroAsyncContext().use() as any).event as + | H3Event + | undefined + if (!event) { + throw new Error( + `No HTTPEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`, + ) + } + return event +} + +function getNitroAsyncContext() { + const nitroAsyncContext = getUnctxContext('nitro-app', { + asyncContext: true, + AsyncLocalStorage, + }) + + return nitroAsyncContext +} + +export const HTTPEventSymbol = Symbol('$HTTPEvent') + +export function isEvent( + obj: any, +): obj is H3Event | { [HTTPEventSymbol]: H3Event } { + return ( + typeof obj === 'object' && + (obj instanceof H3Event || + obj?.[HTTPEventSymbol] instanceof H3Event || + obj?.__is_event__ === true) + ) + // Implement logic to check if obj is an H3Event +} + +type Tail = T extends [any, ...infer U] ? U : never + +type PrependOverload< + TOriginal extends (...args: Array) => any, + TOverload extends (...args: Array) => any, +> = TOverload & TOriginal + +// add an overload to the function without the event argument +type WrapFunction) => any> = PrependOverload< + TFn, + ( + ...args: Parameters extends [H3Event, ...infer TArgs] + ? TArgs + : Parameters + ) => ReturnType +> + +function createWrapperFunction) => any>( + h3Function: TFn, +): WrapFunction { + return function (...args: Array) { + const event = args[0] + if (!isEvent(event)) { + if (!(globalThis as any).app.config.server.experimental?.asyncContext) { + throw new Error( + 'AsyncLocalStorage was not enabled. Use the `server.experimental.asyncContext: true` option in your app configuration to enable it. Or, pass the instance of HTTPEvent that you have as the first argument to the function.', + ) + } + args.unshift(getHTTPEvent()) + } else { + args[0] = + event instanceof H3Event || (event as any).__is_event__ + ? event + : event[HTTPEventSymbol] + } + + return (h3Function as any)(...args) + } as any +} + +// Creating wrappers for each utility and exporting them with their original names +type WrappedReadRawBody = ( + ...args: Tail>> +) => ReturnType> +export const readRawBody: PrependOverload< + typeof _readRawBody, + WrappedReadRawBody +> = createWrapperFunction(_readRawBody) +type WrappedReadBody = >( + ...args: Tail>> +) => ReturnType> +export const readBody: PrependOverload = + createWrapperFunction(_readBody) +type WrappedGetQuery = < + T, + TEventInput = Exclude, undefined>, +>( + ...args: Tail>> +) => ReturnType> +export const getQuery: PrependOverload = + createWrapperFunction(_getQuery) +export const isMethod = createWrapperFunction(_isMethod) +export const isPreflightRequest = createWrapperFunction(_isPreflightRequest) +type WrappedGetValidatedQuery = < + T, + TEventInput = InferEventInput<'query', H3Event, T>, +>( + ...args: Tail>> +) => ReturnType> +export const getValidatedQuery: PrependOverload< + typeof _getValidatedQuery, + WrappedGetValidatedQuery +> = createWrapperFunction(_getValidatedQuery) +export const getRouterParams = createWrapperFunction(_getRouterParams) +export const getRouterParam = createWrapperFunction(_getRouterParam) +type WrappedGetValidatedRouterParams = < + T, + TEventInput = InferEventInput<'routerParams', H3Event, T>, +>( + ...args: Tail< + Parameters> + > +) => ReturnType> +export const getValidatedRouterParams: PrependOverload< + typeof _getValidatedRouterParams, + WrappedGetValidatedRouterParams +> = createWrapperFunction(_getValidatedRouterParams) +export const assertMethod = createWrapperFunction(_assertMethod) +export const getRequestHeaders = createWrapperFunction(_getRequestHeaders) +export const getRequestHeader = createWrapperFunction(_getRequestHeader) +export const getRequestURL = createWrapperFunction(_getRequestURL) +export const getRequestHost = createWrapperFunction(_getRequestHost) +export const getRequestProtocol = createWrapperFunction(_getRequestProtocol) +export const getRequestIP = createWrapperFunction(_getRequestIP) +export const send = createWrapperFunction(_send) +export const sendNoContent = createWrapperFunction(_sendNoContent) +export const setResponseStatus = createWrapperFunction(_setResponseStatus) +export const getResponseStatus = createWrapperFunction(_getResponseStatus) +export const getResponseStatusText = createWrapperFunction( + _getResponseStatusText, +) +export const getResponseHeaders = createWrapperFunction(_getResponseHeaders) +export const getResponseHeader = createWrapperFunction(_getResponseHeader) +export const setResponseHeaders = createWrapperFunction(_setResponseHeaders) +type WrappedSetResponseHeader = ( + ...args: Tail>> +) => ReturnType> +export const setResponseHeader: PrependOverload< + typeof _setResponseHeader, + WrappedSetResponseHeader +> = createWrapperFunction(_setResponseHeader) +export const appendResponseHeaders = createWrapperFunction( + _appendResponseHeaders, +) +type WrappedAppendResponseHeader = ( + ...args: Tail>> +) => ReturnType> +export const appendResponseHeader: PrependOverload< + typeof _appendResponseHeader, + WrappedAppendResponseHeader +> = createWrapperFunction(_appendResponseHeader) +export const defaultContentType = createWrapperFunction(_defaultContentType) +export const sendRedirect = createWrapperFunction(_sendRedirect) +export const sendStream = createWrapperFunction(_sendStream) +export const writeEarlyHints = createWrapperFunction(_writeEarlyHints) +export const sendError = createWrapperFunction(_sendError) +export const sendProxy = createWrapperFunction(_sendProxy) +export const proxyRequest = createWrapperFunction(_proxyRequest) +type WrappedFetchWithEvent = < + T = unknown, + TResponse = any, + TFetch extends (req: RequestInfo | URL, opts?: any) => any = typeof fetch, +>( + ...args: Tail>> +) => ReturnType> +export const fetchWithEvent: PrependOverload< + typeof _fetchWithEvent, + WrappedFetchWithEvent +> = createWrapperFunction(_fetchWithEvent) +export const getProxyRequestHeaders = createWrapperFunction( + _getProxyRequestHeaders, +) + +export const parseCookies = createWrapperFunction(_parseCookies) +export const getCookie = createWrapperFunction(_getCookie) +export const setCookie = createWrapperFunction(_setCookie) +export const deleteCookie = createWrapperFunction(_deleteCookie) +// not exported :( +type SessionDataT = Record +type WrappedUseSession = ( + ...args: Tail>> +) => ReturnType> +// we need to `as` these because the WrapFunction doesn't work for them +// because they also accept CompatEvent instead of H3Event +export const useSession = createWrapperFunction(_useSession) as PrependOverload< + typeof _useSession, + WrappedUseSession +> +type WrappedGetSession = ( + ...args: Tail>> +) => ReturnType> +export const getSession = createWrapperFunction(_getSession) as PrependOverload< + typeof _getSession, + WrappedGetSession +> +type WrappedUpdateSession = ( + ...args: Tail>> +) => ReturnType> +export const updateSession: PrependOverload< + typeof _updateSession, + WrappedUpdateSession +> = createWrapperFunction(_updateSession) +type WrappedSealSession = ( + ...args: Tail>> +) => ReturnType> +export const sealSession = createWrapperFunction( + _sealSession, +) as PrependOverload +export const unsealSession = createWrapperFunction(_unsealSession) +export const clearSession = createWrapperFunction(_clearSession) +export const handleCacheHeaders = createWrapperFunction(_handleCacheHeaders) +export const handleCors = createWrapperFunction(_handleCors) +export const appendCorsHeaders = createWrapperFunction(_appendCorsHeaders) +export const appendCorsPreflightHeaders = createWrapperFunction( + _appendCorsPreflightHeaders, +) +export const sendWebResponse = createWrapperFunction(_sendWebResponse) +type WrappedAppendHeader = ( + ...args: Tail>> +) => ReturnType> +export const appendHeader: PrependOverload< + typeof _appendHeader, + WrappedAppendHeader +> = createWrapperFunction(_appendHeader) +export const appendHeaders = createWrapperFunction(_appendHeaders) +type WrappedSetHeader = ( + ...args: Tail>> +) => ReturnType> +export const setHeader: PrependOverload = + createWrapperFunction(_setHeader) +export const setHeaders = createWrapperFunction(_setHeaders) +export const getHeader = createWrapperFunction(_getHeader) +export const getHeaders = createWrapperFunction(_getHeaders) +export const getRequestFingerprint = createWrapperFunction( + _getRequestFingerprint, +) +export const getRequestWebStream = createWrapperFunction(_getRequestWebStream) +export const readFormData = createWrapperFunction(_readFormData) +export const readMultipartFormData = createWrapperFunction( + _readMultipartFormData, +) +type WrappedReadValidatedBody = < + T, + TEventInput = InferEventInput<'body', H3Event, T>, +>( + ...args: Tail>> +) => ReturnType> +export const readValidatedBody: PrependOverload< + typeof _readValidatedBody, + WrappedReadValidatedBody +> = createWrapperFunction(_readValidatedBody) +export const removeResponseHeader = createWrapperFunction(_removeResponseHeader) +export const getContext = createWrapperFunction(_getContext) +export const setContext = createWrapperFunction(_setContext) + +export const clearResponseHeaders = createWrapperFunction(_clearResponseHeaders) + +export const getWebRequest = createWrapperFunction(toWebRequest) + +export { createApp as createServer } from 'h3' + +export async function handleHTTPEvent(event: H3Event) { + return await (globalThis as any).$handle(event) +} diff --git a/packages/react-start-server/src/index.tsx b/packages/react-start-server/src/index.tsx index d23e477dd7..de6dca17c9 100644 --- a/packages/react-start-server/src/index.tsx +++ b/packages/react-start-server/src/index.tsx @@ -1,508 +1,9 @@ -import { AsyncLocalStorage } from 'node:async_hooks' -import { - H3Event, - appendCorsHeaders as _appendCorsHeaders, - appendCorsPreflightHeaders as _appendCorsPreflightHeaders, - appendHeader as _appendHeader, - appendHeaders as _appendHeaders, - appendResponseHeader as _appendResponseHeader, - appendResponseHeaders as _appendResponseHeaders, - assertMethod as _assertMethod, - clearResponseHeaders as _clearResponseHeaders, - clearSession as _clearSession, - defaultContentType as _defaultContentType, - deleteCookie as _deleteCookie, - fetchWithEvent as _fetchWithEvent, - getCookie as _getCookie, - getHeader as _getHeader, - getHeaders as _getHeaders, - getProxyRequestHeaders as _getProxyRequestHeaders, - getQuery as _getQuery, - getRequestFingerprint as _getRequestFingerprint, - getRequestHeader as _getRequestHeader, - getRequestHeaders as _getRequestHeaders, - getRequestHost as _getRequestHost, - getRequestIP as _getRequestIP, - getRequestProtocol as _getRequestProtocol, - getRequestURL as _getRequestURL, - getRequestWebStream as _getRequestWebStream, - getResponseHeader as _getResponseHeader, - getResponseHeaders as _getResponseHeaders, - getResponseStatus as _getResponseStatus, - getResponseStatusText as _getResponseStatusText, - getRouterParam as _getRouterParam, - getRouterParams as _getRouterParams, - getSession as _getSession, - getValidatedQuery as _getValidatedQuery, - getValidatedRouterParams as _getValidatedRouterParams, - handleCacheHeaders as _handleCacheHeaders, - handleCors as _handleCors, - isMethod as _isMethod, - isPreflightRequest as _isPreflightRequest, - parseCookies as _parseCookies, - proxyRequest as _proxyRequest, - readBody as _readBody, - readFormData as _readFormData, - readMultipartFormData as _readMultipartFormData, - readRawBody as _readRawBody, - readValidatedBody as _readValidatedBody, - removeResponseHeader as _removeResponseHeader, - sealSession as _sealSession, - send as _send, - sendError as _sendError, - sendNoContent as _sendNoContent, - sendProxy as _sendProxy, - sendRedirect as _sendRedirect, - sendStream as _sendStream, - sendWebResponse as _sendWebResponse, - setCookie as _setCookie, - setHeader as _setHeader, - setHeaders as _setHeaders, - setResponseHeader as _setResponseHeader, - setResponseHeaders as _setResponseHeaders, - setResponseStatus as _setResponseStatus, - unsealSession as _unsealSession, - updateSession as _updateSession, - useSession as _useSession, - writeEarlyHints as _writeEarlyHints, -} from 'h3' -import { getContext as getUnctxContext } from 'unctx' -import type { - Encoding, - HTTPHeaderName, - InferEventInput, - _RequestMiddleware, - _ResponseMiddleware, -} from 'h3' - export { StartServer } from './StartServer' export { createStartHandler } from './createStartHandler' export { createRequestHandler } from './createRequestHandler' export { defaultStreamHandler } from './defaultStreamHandler' export { defaultRenderHandler } from './defaultRenderHandler' - -function _setContext(event: H3Event, key: string, value: any) { - event.context[key] = value -} - -function _getContext(event: H3Event, key: string) { - return event.context[key] -} - -export function defineMiddleware(options: { - onRequest?: _RequestMiddleware | Array<_RequestMiddleware> - onBeforeResponse?: _ResponseMiddleware | Array<_ResponseMiddleware> -}) { - return options -} - -function toWebRequestH3(event: H3Event) { - /** - * @type {ReadableStream | undefined} - */ - let readableStream: ReadableStream | undefined - - const url = getRequestURL(event) - const base = { - // @ts-ignore Undici option - duplex: 'half', - method: event.method, - headers: event.headers, - } - - if ((event.node.req as any).body instanceof ArrayBuffer) { - return new Request(url, { - ...base, - body: (event.node.req as any).body, - }) - } - - return new Request(url, { - ...base, - get body() { - if (readableStream) { - return readableStream - } - readableStream = getRequestWebStream(event) - return readableStream - }, - }) -} - -export function toWebRequest(event: H3Event) { - event.web ??= { - request: toWebRequestH3(event), - url: getRequestURL(event), - } - return event.web.request -} - -export { - H3Error, - H3Event, - MIMES, - callNodeListener, - createApp, - createAppEventHandler, - createEvent, - createRouter, - defineEventHandler, - defineLazyEventHandler, - defineNodeListener, - defineNodeMiddleware, - defineRequestMiddleware, - defineResponseMiddleware, - dynamicEventHandler, - defineWebSocket, - eventHandler, - splitCookiesString, - fromNodeMiddleware, - fromPlainHandler, - fromWebHandler, - isError, - isEventHandler, - isWebResponse, - lazyEventHandler, - promisifyNodeListener, - serveStatic, - toEventHandler, - toNodeListener, - toPlainHandler, - toWebHandler, - isCorsOriginAllowed, - isStream, - createError, - sanitizeStatusCode, - sanitizeStatusMessage, - useBase, - type AddRouteShortcuts, - type App, - type AppOptions, - type AppUse, - type CacheConditions, - type CreateRouterOptions, - type Duplex, - type DynamicEventHandler, - type Encoding, - type EventHandler, - type EventHandlerObject, - type EventHandlerRequest, - type EventHandlerResponse, - type H3CorsOptions, - type H3EventContext, - type HTTPHeaderName, - type HTTPMethod, - type InferEventInput, - type InputLayer, - type InputStack, - type Layer, - type LazyEventHandler, - type Matcher, - type MultiPartData, - type NodeEventContext, - type NodeListener, - type NodeMiddleware, - type NodePromisifiedHandler, - type PlainHandler, - type PlainRequest, - type PlainResponse, - type ProxyOptions, - type RequestFingerprintOptions, - type RequestHeaders, - type RouteNode, - type Router, - type RouterMethod, - type RouterUse, - type ServeStaticOptions, - type Session, - type SessionConfig, - type SessionData, - type Stack, - type StaticAssetMeta, - type ValidateFunction, - type ValidateResult, - type WebEventContext, - type WebHandler, - type _RequestMiddleware, - type _ResponseMiddleware, -} from 'h3' - -function getHTTPEvent() { - return getEvent() -} - -export const HTTPEventSymbol = Symbol('$HTTPEvent') - -export function isEvent( - obj: any, -): obj is H3Event | { [HTTPEventSymbol]: H3Event } { - return ( - typeof obj === 'object' && - (obj instanceof H3Event || - obj?.[HTTPEventSymbol] instanceof H3Event || - obj?.__is_event__ === true) - ) - // Implement logic to check if obj is an H3Event -} - -type Tail = T extends [any, ...infer U] ? U : never - -type PrependOverload< - TOriginal extends (...args: Array) => any, - TOverload extends (...args: Array) => any, -> = TOverload & TOriginal - -// add an overload to the function without the event argument -type WrapFunction) => any> = PrependOverload< - TFn, - ( - ...args: Parameters extends [H3Event, ...infer TArgs] - ? TArgs - : Parameters - ) => ReturnType -> - -function createWrapperFunction) => any>( - h3Function: TFn, -): WrapFunction { - return function (...args: Array) { - const event = args[0] - if (!isEvent(event)) { - if (!(globalThis as any).app.config.server.experimental?.asyncContext) { - throw new Error( - 'AsyncLocalStorage was not enabled. Use the `server.experimental.asyncContext: true` option in your app configuration to enable it. Or, pass the instance of HTTPEvent that you have as the first argument to the function.', - ) - } - args.unshift(getHTTPEvent()) - } else { - args[0] = - event instanceof H3Event || (event as any).__is_event__ - ? event - : event[HTTPEventSymbol] - } - - return (h3Function as any)(...args) - } as any -} - -// Creating wrappers for each utility and exporting them with their original names -type WrappedReadRawBody = ( - ...args: Tail>> -) => ReturnType> -export const readRawBody: PrependOverload< - typeof _readRawBody, - WrappedReadRawBody -> = createWrapperFunction(_readRawBody) -type WrappedReadBody = >( - ...args: Tail>> -) => ReturnType> -export const readBody: PrependOverload = - createWrapperFunction(_readBody) -type WrappedGetQuery = < - T, - TEventInput = Exclude, undefined>, ->( - ...args: Tail>> -) => ReturnType> -export const getQuery: PrependOverload = - createWrapperFunction(_getQuery) -export const isMethod = createWrapperFunction(_isMethod) -export const isPreflightRequest = createWrapperFunction(_isPreflightRequest) -type WrappedGetValidatedQuery = < - T, - TEventInput = InferEventInput<'query', H3Event, T>, ->( - ...args: Tail>> -) => ReturnType> -export const getValidatedQuery: PrependOverload< - typeof _getValidatedQuery, - WrappedGetValidatedQuery -> = createWrapperFunction(_getValidatedQuery) -export const getRouterParams = createWrapperFunction(_getRouterParams) -export const getRouterParam = createWrapperFunction(_getRouterParam) -type WrappedGetValidatedRouterParams = < - T, - TEventInput = InferEventInput<'routerParams', H3Event, T>, ->( - ...args: Tail< - Parameters> - > -) => ReturnType> -export const getValidatedRouterParams: PrependOverload< - typeof _getValidatedRouterParams, - WrappedGetValidatedRouterParams -> = createWrapperFunction(_getValidatedRouterParams) -export const assertMethod = createWrapperFunction(_assertMethod) -export const getRequestHeaders = createWrapperFunction(_getRequestHeaders) -export const getRequestHeader = createWrapperFunction(_getRequestHeader) -export const getRequestURL = createWrapperFunction(_getRequestURL) -export const getRequestHost = createWrapperFunction(_getRequestHost) -export const getRequestProtocol = createWrapperFunction(_getRequestProtocol) -export const getRequestIP = createWrapperFunction(_getRequestIP) -export const send = createWrapperFunction(_send) -export const sendNoContent = createWrapperFunction(_sendNoContent) -export const setResponseStatus = createWrapperFunction(_setResponseStatus) -export const getResponseStatus = createWrapperFunction(_getResponseStatus) -export const getResponseStatusText = createWrapperFunction( - _getResponseStatusText, -) -export const getResponseHeaders = createWrapperFunction(_getResponseHeaders) -export const getResponseHeader = createWrapperFunction(_getResponseHeader) -export const setResponseHeaders = createWrapperFunction(_setResponseHeaders) -type WrappedSetResponseHeader = ( - ...args: Tail>> -) => ReturnType> -export const setResponseHeader: PrependOverload< - typeof _setResponseHeader, - WrappedSetResponseHeader -> = createWrapperFunction(_setResponseHeader) -export const appendResponseHeaders = createWrapperFunction( - _appendResponseHeaders, -) -type WrappedAppendResponseHeader = ( - ...args: Tail>> -) => ReturnType> -export const appendResponseHeader: PrependOverload< - typeof _appendResponseHeader, - WrappedAppendResponseHeader -> = createWrapperFunction(_appendResponseHeader) -export const defaultContentType = createWrapperFunction(_defaultContentType) -export const sendRedirect = createWrapperFunction(_sendRedirect) -export const sendStream = createWrapperFunction(_sendStream) -export const writeEarlyHints = createWrapperFunction(_writeEarlyHints) -export const sendError = createWrapperFunction(_sendError) -export const sendProxy = createWrapperFunction(_sendProxy) -export const proxyRequest = createWrapperFunction(_proxyRequest) -type WrappedFetchWithEvent = < - T = unknown, - TResponse = any, - TFetch extends (req: RequestInfo | URL, opts?: any) => any = typeof fetch, ->( - ...args: Tail>> -) => ReturnType> -export const fetchWithEvent: PrependOverload< - typeof _fetchWithEvent, - WrappedFetchWithEvent -> = createWrapperFunction(_fetchWithEvent) -export const getProxyRequestHeaders = createWrapperFunction( - _getProxyRequestHeaders, -) - -export const parseCookies = createWrapperFunction(_parseCookies) -export const getCookie = createWrapperFunction(_getCookie) -export const setCookie = createWrapperFunction(_setCookie) -export const deleteCookie = createWrapperFunction(_deleteCookie) -// not exported :( -type SessionDataT = Record -type WrappedUseSession = ( - ...args: Tail>> -) => ReturnType> -// we need to `as` these because the WrapFunction doesn't work for them -// because they also accept CompatEvent instead of H3Event -export const useSession = createWrapperFunction(_useSession) as PrependOverload< - typeof _useSession, - WrappedUseSession -> -type WrappedGetSession = ( - ...args: Tail>> -) => ReturnType> -export const getSession = createWrapperFunction(_getSession) as PrependOverload< - typeof _getSession, - WrappedGetSession -> -type WrappedUpdateSession = ( - ...args: Tail>> -) => ReturnType> -export const updateSession: PrependOverload< - typeof _updateSession, - WrappedUpdateSession -> = createWrapperFunction(_updateSession) -type WrappedSealSession = ( - ...args: Tail>> -) => ReturnType> -export const sealSession = createWrapperFunction( - _sealSession, -) as PrependOverload -export const unsealSession = createWrapperFunction(_unsealSession) -export const clearSession = createWrapperFunction(_clearSession) -export const handleCacheHeaders = createWrapperFunction(_handleCacheHeaders) -export const handleCors = createWrapperFunction(_handleCors) -export const appendCorsHeaders = createWrapperFunction(_appendCorsHeaders) -export const appendCorsPreflightHeaders = createWrapperFunction( - _appendCorsPreflightHeaders, -) -export const sendWebResponse = createWrapperFunction(_sendWebResponse) -type WrappedAppendHeader = ( - ...args: Tail>> -) => ReturnType> -export const appendHeader: PrependOverload< - typeof _appendHeader, - WrappedAppendHeader -> = createWrapperFunction(_appendHeader) -export const appendHeaders = createWrapperFunction(_appendHeaders) -type WrappedSetHeader = ( - ...args: Tail>> -) => ReturnType> -export const setHeader: PrependOverload = - createWrapperFunction(_setHeader) -export const setHeaders = createWrapperFunction(_setHeaders) -export const getHeader = createWrapperFunction(_getHeader) -export const getHeaders = createWrapperFunction(_getHeaders) -export const getRequestFingerprint = createWrapperFunction( - _getRequestFingerprint, -) -export const getRequestWebStream = createWrapperFunction(_getRequestWebStream) -export const readFormData = createWrapperFunction(_readFormData) -export const readMultipartFormData = createWrapperFunction( - _readMultipartFormData, -) -type WrappedReadValidatedBody = < - T, - TEventInput = InferEventInput<'body', H3Event, T>, ->( - ...args: Tail>> -) => ReturnType> -export const readValidatedBody: PrependOverload< - typeof _readValidatedBody, - WrappedReadValidatedBody -> = createWrapperFunction(_readValidatedBody) -export const removeResponseHeader = createWrapperFunction(_removeResponseHeader) -export const getContext = createWrapperFunction(_getContext) -export const setContext = createWrapperFunction(_setContext) - -export const clearResponseHeaders = createWrapperFunction(_clearResponseHeaders) - -export const getWebRequest = createWrapperFunction(toWebRequest) - -export { createApp as createServer } from 'h3' - -function getNitroAsyncContext() { - const nitroAsyncContext = getUnctxContext('nitro-app', { - asyncContext: (globalThis as any).app.config.server.experimental - ?.asyncContext - ? true - : false, - AsyncLocalStorage, - }) - - return nitroAsyncContext -} - -export function getEvent() { - const event = (getNitroAsyncContext().use() as any).event as - | H3Event - | undefined - if (!event) { - throw new Error( - `No HTTPEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`, - ) - } - return event -} - -export async function handleHTTPEvent(event: H3Event) { - return await (globalThis as any).$handle(event) -} - export { defineHandlerCallback } from './handlerCallback' export type { HandlerCallback } from './handlerCallback' +// Yes its a barrel file, sue me. +export * from './h3' diff --git a/packages/react-start-router-manifest/src/index.ts b/packages/react-start-server/src/router-manifest.ts similarity index 63% rename from packages/react-start-router-manifest/src/index.ts rename to packages/react-start-server/src/router-manifest.ts index c6749527d5..03c4f3fb2a 100644 --- a/packages/react-start-router-manifest/src/index.ts +++ b/packages/react-start-server/src/router-manifest.ts @@ -1,5 +1,6 @@ +import path from 'node:path' // @ts-expect-error -import tsrGetManifest from 'tsr:routes-manifest' +import tsrStartManifest from 'tsr:start-manifest' import type { Manifest } from '@tanstack/router-core' function sanitizeBase(base: string) { @@ -7,15 +8,16 @@ function sanitizeBase(base: string) { } /** - * @description Returns the full, unfiltered router manifest. This includes relationships - * between routes, assets, and preloads and is NOT what you want to serialize and - * send to the client. + * @description Returns the router manifest that should be sent to the client. + * This includes only the assets and preloads for the current route and any + * special assets that are needed for the client. It does not include relationships + * between routes or any other data that is not needed for the client. */ -export function getFullRouterManifest() { - const routerManifest = tsrGetManifest() as Manifest +export function getStartManifest() { + const startManifest = tsrStartManifest() as Manifest - const rootRoute = (routerManifest.routes.__root__ = - routerManifest.routes.__root__ || {}) + const rootRoute = (startManifest.routes.__root__ = + startManifest.routes.__root__ || {}) rootRoute.assets = rootRoute.assets || [] @@ -29,7 +31,7 @@ export function getFullRouterManifest() { 'tanstack/start-router-manifest: TSS_CLIENT_BASE must be defined in your environment for getFullRouterManifest()', ) } - script = `import RefreshRuntime from "/${CLIENT_BASE}/@react-refresh"; + script = `import RefreshRuntime from "${path.join('/', '@react-refresh')}"; RefreshRuntime.injectIntoGlobalHook(window) window.$RefreshReg$ = () => {} window.$RefreshSig$ = () => (type) => type @@ -45,33 +47,29 @@ export function getFullRouterManifest() { // invariant(importPath, 'Could not find client entry in vinxi manifest') // } - // rootRoute.assets.push({ - // tag: 'script', - // attrs: { - // type: 'module', - // suppressHydrationWarning: true, - // async: true, - // }, - // children: `${script}import("${importPath}")`, - // }) - - return routerManifest -} + if (!process.env.TSS_CLIENT_ENTRY) { + throw new Error( + 'tanstack/start-router-manifest: TSS_CLIENT_ENTRY must be defined in your environment for getStartManifest()', + ) + } -/** - * @description Returns the router manifest that should be sent to the client. - * This includes only the assets and preloads for the current route and any - * special assets that are needed for the client. It does not include relationships - * between routes or any other data that is not needed for the client. - */ -export function getRouterManifest() { - const routerManifest = getFullRouterManifest() + rootRoute.assets.push({ + tag: 'script', + attrs: { + type: 'module', + suppressHydrationWarning: true, + async: true, + }, + children: `${script};\nimport(${JSON.stringify( + path.join('/', process.env.TSS_CLIENT_ENTRY), + )})`, + }) // Strip out anything that isn't needed for the client return { - ...routerManifest, + ...startManifest, routes: Object.fromEntries( - Object.entries(routerManifest.routes).map(([k, v]: any) => { + Object.entries(startManifest.routes).map(([k, v]: any) => { const { preloads, assets } = v return [ k, diff --git a/packages/react-start-server-functions-handler/src/index.ts b/packages/react-start-server/src/server-functions-handler.ts similarity index 95% rename from packages/react-start-server-functions-handler/src/index.ts rename to packages/react-start-server/src/server-functions-handler.ts index 4139afcd22..9f54774f05 100644 --- a/packages/react-start-server-functions-handler/src/index.ts +++ b/packages/react-start-server/src/server-functions-handler.ts @@ -1,19 +1,13 @@ -import { isNotFound, isRedirect } from '@tanstack/react-router' -import invariant from 'tiny-invariant' -import { - eventHandler, - getEvent, - getResponseStatus, - toWebRequest, -} from '@tanstack/react-start-server' +import { invariant, isNotFound, isRedirect } from '@tanstack/react-router' import { startSerializer } from '@tanstack/react-start-client' // @ts-expect-error import _serverFnManifest from 'tsr:server-fn-manifest' -import type { H3Event } from '@tanstack/react-start-server' +import { eventHandler, getEvent, getResponseStatus, toWebRequest } from './h3' +import type { H3Event } from './h3' // NOTE: This is a dummy export to silence warnings about // only having a default export. -export const dummy = 1 +export const dummy = 2 export default eventHandler(handleServerAction) @@ -94,9 +88,9 @@ async function handleServerRequest({ let fnModule: undefined | { [key: string]: any } if (process.env.NODE_ENV === 'development') { - fnModule = await (globalThis as any).app - .getRouter('server') - .internals.devServer.ssrLoadModule(serverFnInfo.extractedFilename) + fnModule = await (globalThis as any).viteDevServer.ssrLoadModule( + serverFnInfo.extractedFilename, + ) } else { fnModule = await serverFnInfo.importer() } diff --git a/packages/react-start-server/tsconfig.json b/packages/react-start-server/tsconfig.json index 134e51f065..108c78712f 100644 --- a/packages/react-start-server/tsconfig.json +++ b/packages/react-start-server/tsconfig.json @@ -4,10 +4,5 @@ "jsx": "react-jsx", "module": "esnext" }, - "include": [ - "src", - "tests", - "vite.config.ts", - "../start-client/src/tsrScript.ts" - ] + "include": ["src", "tests", "vite.config.ts"] } diff --git a/packages/react-start-server/vite.config.ts b/packages/react-start-server/vite.config.ts index e05e5cc394..983ae16f57 100644 --- a/packages/react-start-server/vite.config.ts +++ b/packages/react-start-server/vite.config.ts @@ -19,5 +19,6 @@ export default mergeConfig( tanstackViteConfig({ srcDir: './src', entry: './src/index.tsx', + externalDeps: ['tsr:server-fn-manifest', 'tsr:start-manifest'], }), ) diff --git a/packages/react-start/package.json b/packages/react-start/package.json index 9acc663ba4..be241be369 100644 --- a/packages/react-start/package.json +++ b/packages/react-start/package.json @@ -82,16 +82,6 @@ "default": "./dist/cjs/api.cjs" } }, - "./router-manifest": { - "import": { - "types": "./dist/esm/router-manifest.d.ts", - "default": "./dist/esm/router-manifest.js" - }, - "require": { - "types": "./dist/cjs/router-manifest.d.cts", - "default": "./dist/cjs/router-manifest.cjs" - } - }, "./server-functions-client": { "import": { "types": "./dist/esm/server-functions-client.d.ts", @@ -112,16 +102,6 @@ "default": "./dist/cjs/server-functions-server.cjs" } }, - "./server-functions-handler": { - "import": { - "types": "./dist/esm/server-functions-handler.d.ts", - "default": "./dist/esm/server-functions-handler.js" - }, - "require": { - "types": "./dist/cjs/server-functions-handler.d.cts", - "default": "./dist/cjs/server-functions-handler.cjs" - } - }, "./server-functions-ssr": { "import": { "types": "./dist/esm/server-functions-ssr.d.ts", @@ -146,10 +126,8 @@ "@tanstack/react-start-client": "workspace:^", "@tanstack/react-start-server": "workspace:^", "@tanstack/react-start-plugin": "workspace:^", - "@tanstack/react-start-router-manifest": "workspace:^", "@tanstack/react-start-server-functions-client": "workspace:^", "@tanstack/start-server-functions-server": "workspace:^", - "@tanstack/react-start-server-functions-handler": "workspace:^", "@tanstack/react-start-server-functions-ssr": "workspace:^", "@tanstack/react-start-api-routes": "workspace:^" }, diff --git a/packages/react-start/src/router-manifest.tsx b/packages/react-start/src/router-manifest.tsx deleted file mode 100644 index ce430d7884..0000000000 --- a/packages/react-start/src/router-manifest.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from '@tanstack/react-start-router-manifest' diff --git a/packages/react-start/src/server-functions-handler.tsx b/packages/react-start/src/server-functions-handler.tsx deleted file mode 100644 index 26e58e19e4..0000000000 --- a/packages/react-start/src/server-functions-handler.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from '@tanstack/react-start-server-functions-handler' diff --git a/packages/react-start/vite.config.ts b/packages/react-start/vite.config.ts index 8e960afd50..5b74f25498 100644 --- a/packages/react-start/vite.config.ts +++ b/packages/react-start/vite.config.ts @@ -18,7 +18,6 @@ export default mergeConfig( './src/client.tsx', './src/server.tsx', './src/plugin.ts', - './src/router-manifest.tsx', './src/server-functions-client.tsx', './src/server-functions-server.tsx', './src/server-functions-ssr.tsx', @@ -28,7 +27,6 @@ export default mergeConfig( '@tanstack/react-start-client', '@tanstack/react-start-server', '@tanstack/react-start-plugin', - '@tanstack/react-start-router-manifest', '@tanstack/react-start-server-functions-client', '@tanstack/start-server-functions-server', '@tanstack/react-start-server-functions-ssr', diff --git a/packages/router-plugin/src/core/code-splitter/compilers.ts b/packages/router-plugin/src/core/code-splitter/compilers.ts index 6a4102ebc5..8646e4d779 100644 --- a/packages/router-plugin/src/core/code-splitter/compilers.ts +++ b/packages/router-plugin/src/core/code-splitter/compilers.ts @@ -117,6 +117,8 @@ export function compileCodeSplitReferenceRoute( runtimeEnv: 'dev' | 'prod' codeSplitGroupings: CodeSplitGroupings targetFramework: Config['target'] + filename: string + id: string }, ): GeneratorResult { const ast = parseAst(opts) @@ -406,6 +408,7 @@ export function compileCodeSplitReferenceRoute( export function compileCodeSplitVirtualRoute( opts: ParseAstOptions & { splitTargets: Array + filename: string }, ): GeneratorResult { const ast = parseAst(opts) diff --git a/packages/router-plugin/src/core/router-code-splitter-plugin.ts b/packages/router-plugin/src/core/router-code-splitter-plugin.ts index 7c1ecc17a8..6ad50650f5 100644 --- a/packages/router-plugin/src/core/router-code-splitter-plugin.ts +++ b/packages/router-plugin/src/core/router-code-splitter-plugin.ts @@ -104,8 +104,6 @@ export const unpluginRouterCodeSplitterFactory: UnpluginFactory< const fromCode = detectCodeSplitGroupingsFromRoute({ code, - root: ROOT, - filename: id, }) if (fromCode.groupings) { @@ -139,11 +137,11 @@ export const unpluginRouterCodeSplitterFactory: UnpluginFactory< const compiledReferenceRoute = compileCodeSplitReferenceRoute({ code, - root: ROOT, - filename: id, runtimeEnv: isProduction ? 'prod' : 'dev', codeSplitGroupings: splitGroupings, targetFramework: userConfig.target, + filename: id, + id, }) if (debug) { @@ -178,7 +176,6 @@ export const unpluginRouterCodeSplitterFactory: UnpluginFactory< const result = compileCodeSplitVirtualRoute({ code, - root: ROOT, filename: id, splitTargets: grouping, }) diff --git a/packages/router-utils/src/ast.ts b/packages/router-utils/src/ast.ts index fbf6d970d5..87f175d2a3 100644 --- a/packages/router-utils/src/ast.ts +++ b/packages/router-utils/src/ast.ts @@ -6,9 +6,6 @@ import type * as _babel_types from '@babel/types' export type ParseAstOptions = { code: string - filename: string - root: string - env?: 'server' | 'client' | 'ssr' } export function parseAst( @@ -17,11 +14,6 @@ export function parseAst( return parse(opts.code, { plugins: ['jsx', 'typescript'], sourceType: 'module', - ...{ - root: opts.root, - filename: opts.filename, - env: opts.env, - }, }) } diff --git a/packages/server-functions-plugin/src/index.ts b/packages/server-functions-plugin/src/index.ts index dfa8993b45..6f52ddda45 100644 --- a/packages/server-functions-plugin/src/index.ts +++ b/packages/server-functions-plugin/src/index.ts @@ -1,6 +1,9 @@ import { mkdirSync, readFileSync, writeFileSync } from 'node:fs' import path from 'node:path' -import { TanStackDirectiveFunctionsPlugin } from '@tanstack/directive-functions-plugin' +import { + TanStackDirectiveFunctionsPlugin, + TanStackDirectiveFunctionsPluginEnv, +} from '@tanstack/directive-functions-plugin' import type { Plugin } from 'vite' import type { DirectiveFn, @@ -79,7 +82,6 @@ export function createTanStackServerFnPlugin(opts: ServerFnPluginOpts): { getRuntimeCode: opts.client.getRuntimeCode, replacer: opts.client.replacer, onDirectiveFnsById, - // devSplitImporter: `(globalThis.app.getRouter('server').internals.devServer.ssrLoadModule)`, }), { // Now that we have the directiveFnsById, we need to create a new @@ -124,7 +126,6 @@ export function createTanStackServerFnPlugin(opts: ServerFnPluginOpts): { getRuntimeCode: opts.ssr.getRuntimeCode, replacer: opts.ssr.replacer, onDirectiveFnsById, - // devSplitImporter: `(globalThis.app.getRouter('server').internals.devServer.ssrLoadModule)`, }), ], server: [ @@ -185,3 +186,155 @@ export function createTanStackServerFnPlugin(opts: ServerFnPluginOpts): { ], } } + +export function TanStackServerFnPluginEnv(opts: { + manifestVirtualImportId: string + client: { + envName?: string + getRuntimeCode: () => string + replacer: ReplacerFn + } + server: { + envName?: string + getRuntimeCode: () => string + replacer: ReplacerFn + } +}): Array { + const root = process.cwd() + const manifestFilename = + 'node_modules/.tanstack-start/server-functions-manifest.json' + + globalThis.TSR_directiveFnsById = {} + + const onDirectiveFnsById = (d: Record) => { + // When directives are compiled, save them to our global variable + // This variable will be used both during development to incrementally + // look up server functions and during build/production to produce a + // static manifest that can be read by the server build + Object.assign( + globalThis.TSR_directiveFnsById, + Object.fromEntries( + Object.entries(d).map(([id, fn]) => [ + id, + { + ...fn, + // This importer is required for the development server to + // work. It's also required in production, but cannot be serialized + // into the manifest because it's a dynamic import. Instead, as you'll + // see below, we augment the manifest output with a code-generated importer + // that looks exactly like this. + importer: () => import(fn.extractedFilename), + }, + ]), + ), + ) + } + + const directive = 'use server' + const directiveLabel = 'Server Function' + + return [ + // client: [ + // The client plugin is used to compile the client directives + // and save them so we can create a manifest + TanStackDirectiveFunctionsPluginEnv({ + directive, + directiveLabel, + onDirectiveFnsById, + environments: { + client: { + envLabel: 'Client', + getRuntimeCode: opts.client.getRuntimeCode, + replacer: opts.client.replacer, + }, + server: { + envLabel: 'Server', + getRuntimeCode: opts.server.getRuntimeCode, + replacer: opts.server.replacer, + }, + }, + }), + { + // Now that we have the directiveFnsById, we need to create a new + // virtual module that can be used to import that manifest + name: 'tanstack-start-server-fn-vite-plugin-build-client', + applyToEnvironment(environment) { + return environment.name === opts.client.envName + }, + generateBundle() { + // In production, we create a manifest so we can + // access it later in the server build, which likely does not run in the + // same vite build environment. This is essentially a + // serialized state transfer from the client build to the server + // build. + + // Ensure the manifest directory exists + mkdirSync(path.dirname(manifestFilename), { recursive: true }) + + // Write the manifest to disk + writeFileSync( + path.join(root, manifestFilename), + JSON.stringify( + Object.fromEntries( + Object.entries(globalThis.TSR_directiveFnsById).map( + ([id, fn]) => [ + id, + { + functionName: fn.functionName, + extractedFilename: fn.extractedFilename, + }, + ], + ), + ), + ), + ) + }, + }, + { + // On the server, we need to be able to read the server-function manifest from the client build. + // This is likely used in the handler for server functions, so we can find the server function + // by its ID, import it, and call it. We can't do this in memory here because the builds happen in isolation, + // so the manifest is like a serialized state from the client build to the server build + name: 'tanstack-start-server-fn-vite-plugin-manifest-server', + enforce: 'pre', + // applyToEnvironment(environment) { + // return environment.name === opts.server.envName + // }, + resolveId: (id) => (id === opts.manifestVirtualImportId ? id : null), + load(id) { + if (id !== opts.manifestVirtualImportId) return null + + // In development, we **can** use the in-memory manifest, and we should + // since it will be incrementally updated as we use the app and dynamic + // imports are triggered. + if (process.env.NODE_ENV === 'development') { + return `export default globalThis.TSR_directiveFnsById` + } + + // In production, we need to read the manifest from the client build. + // The manifest at that point should contain the full set of server functions + // that were found in the client build. + const manifest = JSON.parse( + readFileSync(path.join(root, manifestFilename), 'utf-8'), + ) + + // The manifest has a lot of information, but for now we only need to + // provide the function ID for lookup and the importer for loading + // This should keep the manifest small for now. + const manifestWithImports = ` + export default {${Object.entries(manifest) + .map( + ([id, fn]: any) => + `'${id}': { + functionName: '${fn.functionName}', + importer: () => import(${JSON.stringify(fn.extractedFilename)}) + }`, + ) + .join(',')}}` + + return manifestWithImports + }, + }, + // ], + ] +} diff --git a/packages/start-plugin/package.json b/packages/start-plugin/package.json new file mode 100644 index 0000000000..0967ef424b --- /dev/null +++ b/packages/start-plugin/package.json @@ -0,0 +1 @@ +{} diff --git a/packages/start-server-functions-server/package.json b/packages/start-server-functions-server/package.json index 960bfbe322..be7b37de9b 100644 --- a/packages/start-server-functions-server/package.json +++ b/packages/start-server-functions-server/package.json @@ -63,7 +63,8 @@ }, "dependencies": { "@tanstack/server-functions-plugin": "workspace:^", - "tiny-invariant": "^1.3.3" + "tiny-invariant": "^1.3.3", + "vite": "6.1.0" }, "devDependencies": { "typescript": "^5.7.2" diff --git a/packages/start/package.json b/packages/start/package.json index 0457100311..72778d4b09 100644 --- a/packages/start/package.json +++ b/packages/start/package.json @@ -82,16 +82,6 @@ "default": "./dist/cjs/api.cjs" } }, - "./router-manifest": { - "import": { - "types": "./dist/esm/router-manifest.d.ts", - "default": "./dist/esm/router-manifest.js" - }, - "require": { - "types": "./dist/cjs/router-manifest.d.cts", - "default": "./dist/cjs/router-manifest.cjs" - } - }, "./server-functions-client": { "import": { "types": "./dist/esm/server-functions-client.d.ts", @@ -112,16 +102,6 @@ "default": "./dist/cjs/server-functions-server.cjs" } }, - "./server-functions-handler": { - "import": { - "types": "./dist/esm/server-functions-handler.d.ts", - "default": "./dist/esm/server-functions-handler.js" - }, - "require": { - "types": "./dist/cjs/server-functions-handler.d.cts", - "default": "./dist/cjs/server-functions-handler.cjs" - } - }, "./server-functions-ssr": { "import": { "types": "./dist/esm/server-functions-ssr.d.ts", @@ -146,10 +126,8 @@ "@tanstack/react-start-client": "workspace:^", "@tanstack/react-start-server": "workspace:^", "@tanstack/react-start-plugin": "workspace:^", - "@tanstack/react-start-router-manifest": "workspace:^", "@tanstack/react-start-server-functions-client": "workspace:^", "@tanstack/start-server-functions-server": "workspace:^", - "@tanstack/react-start-server-functions-handler": "workspace:^", "@tanstack/react-start-server-functions-ssr": "workspace:^", "@tanstack/react-start-api-routes": "workspace:^" } diff --git a/packages/start/src/router-manifest.tsx b/packages/start/src/router-manifest.tsx deleted file mode 100644 index 10e98ba06d..0000000000 --- a/packages/start/src/router-manifest.tsx +++ /dev/null @@ -1,4 +0,0 @@ -console.warn( - '[@tanstack/start] Warning: This package has moved to @tanstack/react-start. Please switch to the new package, as this package will be dropped soon.', -) -export * from '@tanstack/react-start-router-manifest' diff --git a/packages/start/src/server-functions-handler.tsx b/packages/start/src/server-functions-handler.tsx deleted file mode 100644 index 4ecd303e62..0000000000 --- a/packages/start/src/server-functions-handler.tsx +++ /dev/null @@ -1,4 +0,0 @@ -console.warn( - '[@tanstack/start] Warning: This package has moved to @tanstack/react-start. Please switch to the new package, as this package will be dropped soon.', -) -export * from '@tanstack/react-start-server-functions-handler' diff --git a/packages/start/vite.config.ts b/packages/start/vite.config.ts index 8c696b7b37..86e0f4a63b 100644 --- a/packages/start/vite.config.ts +++ b/packages/start/vite.config.ts @@ -18,7 +18,6 @@ export default mergeConfig( './src/client.tsx', './src/server.tsx', './src/plugin.tsx', - './src/router-manifest.tsx', './src/server-functions-client.tsx', './src/server-functions-server.tsx', './src/server-functions-ssr.tsx', @@ -28,7 +27,6 @@ export default mergeConfig( '@tanstack/react-start-client', '@tanstack/react-start-server', '@tanstack/react-start-plugin', - '@tanstack/react-start-router-manifest', '@tanstack/react-start-server-functions-client', '@tanstack/start-server-functions-server', '@tanstack/react-start-server-functions-ssr', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 70a55473e2..afcc287938 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -34,7 +34,6 @@ overrides: '@tanstack/react-start-server': workspace:* '@tanstack/react-start-api-routes': workspace:* '@tanstack/react-start-server-functions-fetcher': workspace:* - '@tanstack/react-start-server-functions-handler': workspace:* '@tanstack/react-start-server-functions-client': workspace:* '@tanstack/react-start-server-functions-ssr': workspace:* '@tanstack/start-server-functions-server': workspace:* @@ -5699,18 +5698,12 @@ importers: '@tanstack/react-start-plugin': specifier: workspace:* version: link:../react-start-plugin - '@tanstack/react-start-router-manifest': - specifier: workspace:* - version: link:../react-start-router-manifest '@tanstack/react-start-server': specifier: workspace:* version: link:../react-start-server '@tanstack/react-start-server-functions-client': specifier: workspace:* version: link:../react-start-server-functions-client - '@tanstack/react-start-server-functions-handler': - specifier: workspace:* - version: link:../react-start-server-functions-handler '@tanstack/react-start-server-functions-ssr': specifier: workspace:* version: link:../react-start-server-functions-ssr @@ -5891,6 +5884,9 @@ importers: h3: specifier: 1.13.0 version: 1.13.0 + import-meta-resolve: + specifier: ^4.1.0 + version: 4.1.0 nitropack: specifier: ^2.10.4 version: 2.10.4(typescript@5.7.3) @@ -5907,19 +5903,6 @@ importers: specifier: ^3.24.2 version: 3.24.2 - packages/react-start-router-manifest: - dependencies: - '@tanstack/router-core': - specifier: workspace:* - version: link:../router-core - tiny-invariant: - specifier: ^1.3.3 - version: 1.3.3 - devDependencies: - typescript: - specifier: ^5.7.2 - version: 5.8.2 - packages/react-start-server: dependencies: '@tanstack/history': @@ -6007,34 +5990,6 @@ importers: specifier: ^5.7.2 version: 5.8.2 - packages/react-start-server-functions-handler: - dependencies: - '@tanstack/react-router': - specifier: workspace:* - version: link:../react-router - '@tanstack/react-start-client': - specifier: workspace:* - version: link:../react-start-client - '@tanstack/react-start-server': - specifier: workspace:* - version: link:../react-start-server - tiny-invariant: - specifier: ^1.3.3 - version: 1.3.3 - devDependencies: - '@vitejs/plugin-react': - specifier: ^4.3.4 - version: 4.3.4(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) - react: - specifier: ^19.0.0 - version: 19.0.0 - react-dom: - specifier: ^19.0.0 - version: 19.0.0(react@19.0.0) - typescript: - specifier: ^5.7.2 - version: 5.8.2 - packages/react-start-server-functions-ssr: dependencies: '@tanstack/react-start-client': @@ -6355,7 +6310,7 @@ importers: version: 2.11.6(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) zod: specifier: ^3.23.8 - version: 3.24.1 + version: 3.24.2 packages/solid-router-devtools: dependencies: @@ -6721,18 +6676,12 @@ importers: '@tanstack/react-start-plugin': specifier: workspace:* version: link:../react-start-plugin - '@tanstack/react-start-router-manifest': - specifier: workspace:* - version: link:../react-start-router-manifest '@tanstack/react-start-server': specifier: workspace:* version: link:../react-start-server '@tanstack/react-start-server-functions-client': specifier: workspace:* version: link:../react-start-server-functions-client - '@tanstack/react-start-server-functions-handler': - specifier: workspace:* - version: link:../react-start-server-functions-handler '@tanstack/react-start-server-functions-ssr': specifier: workspace:* version: link:../react-start-server-functions-ssr @@ -6740,6 +6689,8 @@ importers: specifier: workspace:* version: link:../start-server-functions-server + packages/start-plugin: {} + packages/start-server-functions-server: dependencies: '@tanstack/server-functions-plugin': @@ -6748,6 +6699,9 @@ importers: tiny-invariant: specifier: ^1.3.3 version: 1.3.3 + vite: + specifier: 6.1.0 + version: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) devDependencies: typescript: specifier: ^5.7.2 @@ -12051,6 +12005,9 @@ packages: engines: {node: '>=8'} hasBin: true + import-meta-resolve@4.1.0: + resolution: {integrity: sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==} + imurmurhash@0.1.4: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} @@ -15028,9 +14985,6 @@ packages: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} engines: {node: '>= 14'} - zod@3.24.1: - resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} - zod@3.24.2: resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} @@ -20751,6 +20705,8 @@ snapshots: pkg-dir: 4.2.0 resolve-cwd: 3.0.0 + import-meta-resolve@4.1.0: {} + imurmurhash@0.1.4: {} indent-string@4.0.0: {} @@ -24112,6 +24068,4 @@ snapshots: compress-commons: 6.0.2 readable-stream: 4.7.0 - zod@3.24.1: {} - zod@3.24.2: {} diff --git a/scripts/publish.js b/scripts/publish.js index 8d825110f7..bc0313f510 100644 --- a/scripts/publish.js +++ b/scripts/publish.js @@ -164,10 +164,6 @@ await publish({ name: '@tanstack/react-start-server-functions-fetcher', packageDir: 'packages/react-start-server-functions-fetcher', }, - { - name: '@tanstack/react-start-server-functions-handler', - packageDir: 'packages/react-start-server-functions-handler', - }, { name: '@tanstack/react-start-server-functions-client', packageDir: 'packages/react-start-server-functions-client', @@ -180,10 +176,6 @@ await publish({ name: '@tanstack/start-server-functions-server', packageDir: 'packages/start-server-functions-server', }, - { - name: '@tanstack/react-start-router-manifest', - packageDir: 'packages/react-start-router-manifest', - }, { name: '@tanstack/start', packageDir: 'packages/start', From 12ee34a157e2f211b0bbbbc45bb3baff828819c2 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Fri, 7 Mar 2025 12:11:26 -0700 Subject: [PATCH 019/155] It's working! --- examples/react/start-basic/app/ssr.tsx | 3 -- .../directive-functions-plugin/src/index.ts | 12 ++--- .../react-start-plugin/src/nitro/build-ssr.ts | 25 ---------- packages/react-start-server/src/h3.ts | 48 +++++++------------ .../src/server-functions-handler.ts | 12 +++-- 5 files changed, 30 insertions(+), 70 deletions(-) delete mode 100644 packages/react-start-plugin/src/nitro/build-ssr.ts diff --git a/examples/react/start-basic/app/ssr.tsx b/examples/react/start-basic/app/ssr.tsx index 07b04f617d..3cce9272c4 100644 --- a/examples/react/start-basic/app/ssr.tsx +++ b/examples/react/start-basic/app/ssr.tsx @@ -2,14 +2,11 @@ import { createStartHandler, defaultStreamHandler, defineEventHandler, - getWebRequest, } from '@tanstack/react-start/server' import { createRouter } from './router' export default defineEventHandler((event) => { - console.log(getWebRequest(event)?.url) - const startHandler = createStartHandler({ createRouter, })(defaultStreamHandler) diff --git a/packages/directive-functions-plugin/src/index.ts b/packages/directive-functions-plugin/src/index.ts index be124822d4..d0fd8aee06 100644 --- a/packages/directive-functions-plugin/src/index.ts +++ b/packages/directive-functions-plugin/src/index.ts @@ -90,12 +90,12 @@ export function TanStackDirectiveFunctionsPluginEnv( buildStart() { root = this.environment.config.root }, - applyToEnvironment(env) { - return [ - opts.environments.client.envName, - opts.environments.server.envName, - ].includes(env.name) - }, + // applyToEnvironment(env) { + // return [ + // opts.environments.client.envName, + // opts.environments.server.envName, + // ].includes(env.name) + // }, transform(code, id) { const envOptions = [ opts.environments.client, diff --git a/packages/react-start-plugin/src/nitro/build-ssr.ts b/packages/react-start-plugin/src/nitro/build-ssr.ts deleted file mode 100644 index ff2a769437..0000000000 --- a/packages/react-start-plugin/src/nitro/build-ssr.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { resolve } from 'node:path' -import { build, mergeConfig } from 'vite' -import type { UserConfig } from 'vite' - -export async function buildSSRApp({ - root, - viteConfig, - ssrEntry, -}: { - root: string - viteConfig: UserConfig - ssrEntry: string -}) { - const ssrBuildConfig = mergeConfig(viteConfig, { - build: { - ssr: true, - rollupOptions: { - input: ssrEntry, - }, - outDir: resolve(root, 'dist/ssr'), - }, - }) - - await build(ssrBuildConfig) -} diff --git a/packages/react-start-server/src/h3.ts b/packages/react-start-server/src/h3.ts index 406cb93871..b58ba1e10a 100644 --- a/packages/react-start-server/src/h3.ts +++ b/packages/react-start-server/src/h3.ts @@ -11,6 +11,7 @@ import { clearResponseHeaders as _clearResponseHeaders, clearSession as _clearSession, defaultContentType as _defaultContentType, + defineEventHandler as _defineEventHandler, deleteCookie as _deleteCookie, fetchWithEvent as _fetchWithEvent, getCookie as _getCookie, @@ -67,16 +68,17 @@ import { writeEarlyHints as _writeEarlyHints, } from 'h3' -import { getContext as getUnctxContext } from 'unctx' - import type { Encoding, + EventHandler, HTTPHeaderName, InferEventInput, _RequestMiddleware, _ResponseMiddleware, } from 'h3' +const eventStorage = new AsyncLocalStorage() + function _setContext(event: H3Event, key: string, value: any) { event.context[key] = value } @@ -142,7 +144,6 @@ export { createAppEventHandler, createEvent, createRouter, - defineEventHandler, defineLazyEventHandler, defineNodeListener, defineNodeMiddleware, @@ -223,14 +224,21 @@ export { type _ResponseMiddleware, } from 'h3' -function getHTTPEvent() { - return getEvent() +export function defineEventHandler(handler: EventHandler) { + return _defineEventHandler((event) => { + return runWithEvent(event, () => handler(event)) + }) +} + +export async function runWithEvent( + event: H3Event, + fn: () => T | Promise, +): Promise { + return eventStorage.run(event, fn) } export function getEvent() { - const event = (getNitroAsyncContext().use() as any).event as - | H3Event - | undefined + const event = eventStorage.getStore() as H3Event | undefined if (!event) { throw new Error( `No HTTPEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`, @@ -239,15 +247,6 @@ export function getEvent() { return event } -function getNitroAsyncContext() { - const nitroAsyncContext = getUnctxContext('nitro-app', { - asyncContext: true, - AsyncLocalStorage, - }) - - return nitroAsyncContext -} - export const HTTPEventSymbol = Symbol('$HTTPEvent') export function isEvent( @@ -285,12 +284,7 @@ function createWrapperFunction) => any>( return function (...args: Array) { const event = args[0] if (!isEvent(event)) { - if (!(globalThis as any).app.config.server.experimental?.asyncContext) { - throw new Error( - 'AsyncLocalStorage was not enabled. Use the `server.experimental.asyncContext: true` option in your app configuration to enable it. Or, pass the instance of HTTPEvent that you have as the first argument to the function.', - ) - } - args.unshift(getHTTPEvent()) + args.unshift(getEvent()) } else { args[0] = event instanceof H3Event || (event as any).__is_event__ @@ -486,13 +480,5 @@ export const readValidatedBody: PrependOverload< export const removeResponseHeader = createWrapperFunction(_removeResponseHeader) export const getContext = createWrapperFunction(_getContext) export const setContext = createWrapperFunction(_setContext) - export const clearResponseHeaders = createWrapperFunction(_clearResponseHeaders) - export const getWebRequest = createWrapperFunction(toWebRequest) - -export { createApp as createServer } from 'h3' - -export async function handleHTTPEvent(event: H3Event) { - return await (globalThis as any).$handle(event) -} diff --git a/packages/react-start-server/src/server-functions-handler.ts b/packages/react-start-server/src/server-functions-handler.ts index 9f54774f05..87d8c51036 100644 --- a/packages/react-start-server/src/server-functions-handler.ts +++ b/packages/react-start-server/src/server-functions-handler.ts @@ -88,22 +88,24 @@ async function handleServerRequest({ let fnModule: undefined | { [key: string]: any } if (process.env.NODE_ENV === 'development') { - fnModule = await (globalThis as any).viteDevServer.ssrLoadModule( - serverFnInfo.extractedFilename, - ) + const serverEnv = (globalThis as any).viteDevServer.environments['server'] + if (!serverEnv) { + throw new Error(`'server' vite dev environment not found`) + } + fnModule = await serverEnv.runner.import(serverFnInfo.extractedFilename) } else { fnModule = await serverFnInfo.importer() } if (!fnModule) { - console.log('serverFnManifest', serverFnManifest) + console.log('serverFnInfo', serverFnInfo) throw new Error('Server function module not resolved for ' + serverFnId) } const action = fnModule[serverFnInfo.functionName] if (!action) { - console.log('serverFnManifest', serverFnManifest) + console.log('serverFnInfo', serverFnInfo) console.log('fnModule', fnModule) throw new Error( `Server function module export not resolved for serverFn ID: ${serverFnId}`, From 6fc0df9daf4d8d71367a00d67814d98a138c7837 Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sat, 8 Mar 2025 18:25:41 +1300 Subject: [PATCH 020/155] chore(root): regen lockfile --- pnpm-lock.yaml | 243 ++++--------------------------------------------- 1 file changed, 20 insertions(+), 223 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index afcc287938..40ae2d4843 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -37,7 +37,6 @@ overrides: '@tanstack/react-start-server-functions-client': workspace:* '@tanstack/react-start-server-functions-ssr': workspace:* '@tanstack/start-server-functions-server': workspace:* - '@tanstack/react-start-router-manifest': workspace:* '@tanstack/react-start-plugin': workspace:* '@tanstack/eslint-plugin-router': workspace:* '@tanstack/server-functions-plugin': workspace:* @@ -1105,7 +1104,7 @@ importers: dependencies: '@clerk/tanstack-start': specifier: ^0.11.0 - version: 0.11.0(@tanstack/react-router@packages+react-router)(@tanstack/react-start@packages+react-start)(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) + version: 0.11.0(@tanstack/react-router@packages+react-router)(@tanstack/react-start@packages+react-start)(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -1913,7 +1912,7 @@ importers: version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.1 - version: 3.24.1 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -2002,7 +2001,7 @@ importers: version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.1 - version: 3.24.1 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -2063,7 +2062,7 @@ importers: version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.1 - version: 3.24.1 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -2124,7 +2123,7 @@ importers: version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.1 - version: 3.24.1 + version: 3.24.2 devDependencies: '@playwright/test': specifier: ^1.50.1 @@ -2240,7 +2239,7 @@ importers: version: 3.4.17 zod: specifier: ^3.24.1 - version: 3.24.1 + version: 3.24.2 devDependencies: '@types/react': specifier: ^19.0.8 @@ -4416,7 +4415,7 @@ importers: dependencies: '@clerk/tanstack-start': specifier: 0.11.0 - version: 0.11.0(@tanstack/react-router@packages+react-router)(@tanstack/react-start@packages+react-start)(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) + version: 0.11.0(@tanstack/react-router@packages+react-router)(@tanstack/react-start@packages+react-start)(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -4602,7 +4601,7 @@ importers: version: 2.6.0 valibot: specifier: ^1.0.0-beta.15 - version: 1.0.0-beta.15(typescript@5.7.3) + version: 1.0.0-beta.15(typescript@5.8.2) devDependencies: '@types/node': specifier: ^22.5.4 @@ -4666,10 +4665,10 @@ importers: version: 19.0.0(react@19.0.0) vinxi: specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0) + version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.1 - version: 3.24.1 + version: 3.24.2 devDependencies: '@types/node': specifier: ^22.5.4 @@ -4682,10 +4681,10 @@ importers: version: 19.0.3(@types/react@19.0.8) typescript: specifier: ^5.7.2 - version: 5.7.3 + version: 5.8.2 vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.7.3)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) + version: 5.1.4(typescript@5.8.2)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) examples/react/start-supabase-basic: dependencies: @@ -5064,7 +5063,7 @@ importers: version: 3.4.17 zod: specifier: ^3.24.1 - version: 3.24.1 + version: 3.24.2 devDependencies: '@tanstack/router-plugin': specifier: workspace:* @@ -5193,7 +5192,7 @@ importers: version: 3.4.17 zod: specifier: ^3.24.1 - version: 3.24.1 + version: 3.24.2 devDependencies: '@tanstack/router-plugin': specifier: workspace:* @@ -5276,7 +5275,7 @@ importers: version: 3.4.17 zod: specifier: ^3.24.1 - version: 3.24.1 + version: 3.24.2 devDependencies: '@tanstack/router-plugin': specifier: workspace:* @@ -5316,7 +5315,7 @@ importers: version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.1 - version: 3.24.1 + version: 3.24.2 devDependencies: '@tailwindcss/vite': specifier: ^4.0.8 @@ -5889,7 +5888,7 @@ importers: version: 4.1.0 nitropack: specifier: ^2.10.4 - version: 2.10.4(typescript@5.7.3) + version: 2.10.4(typescript@5.8.2) tiny-invariant: specifier: ^1.3.3 version: 1.3.3 @@ -6467,7 +6466,7 @@ importers: version: 2.11.6(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) zod: specifier: ^3.24.1 - version: 3.24.1 + version: 3.24.2 packages/solid-start-plugin: dependencies: @@ -15306,7 +15305,7 @@ snapshots: react: 19.0.0 react-dom: 19.0.0(react@19.0.0) - '@clerk/tanstack-start@0.11.0(@tanstack/react-router@packages+react-router)(@tanstack/react-start@packages+react-start)(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0)': + '@clerk/tanstack-start@0.11.0(@tanstack/react-router@packages+react-router)(@tanstack/react-start@packages+react-start)(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0)': dependencies: '@clerk/backend': 1.24.3(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@clerk/clerk-react': 5.24.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -21402,104 +21401,6 @@ snapshots: neo-async@2.6.2: {} - nitropack@2.10.4(typescript@5.7.3): - dependencies: - '@cloudflare/kv-asset-handler': 0.3.4 - '@netlify/functions': 2.8.2 - '@rollup/plugin-alias': 5.1.1(rollup@4.34.0) - '@rollup/plugin-commonjs': 28.0.2(rollup@4.34.0) - '@rollup/plugin-inject': 5.0.5(rollup@4.34.0) - '@rollup/plugin-json': 6.1.0(rollup@4.34.0) - '@rollup/plugin-node-resolve': 15.3.1(rollup@4.34.0) - '@rollup/plugin-replace': 6.0.2(rollup@4.34.0) - '@rollup/plugin-terser': 0.4.4(rollup@4.34.0) - '@rollup/pluginutils': 5.1.4(rollup@4.34.0) - '@types/http-proxy': 1.17.15 - '@vercel/nft': 0.27.10(rollup@4.34.0) - archiver: 7.0.1 - c12: 2.0.1(magicast@0.3.5) - chokidar: 3.6.0 - citty: 0.1.6 - compatx: 0.1.8 - confbox: 0.1.8 - consola: 3.4.0 - cookie-es: 1.2.2 - croner: 9.0.0 - crossws: 0.3.3 - db0: 0.2.3 - defu: 6.1.4 - destr: 2.0.3 - dot-prop: 9.0.0 - esbuild: 0.24.2 - escape-string-regexp: 5.0.0 - etag: 1.8.1 - fs-extra: 11.3.0 - globby: 14.0.2 - gzip-size: 7.0.0 - h3: 1.13.0 - hookable: 5.5.3 - httpxy: 0.1.7 - ioredis: 5.4.2 - jiti: 2.4.2 - klona: 2.0.6 - knitwork: 1.2.0 - listhen: 1.9.0 - magic-string: 0.30.17 - magicast: 0.3.5 - mime: 4.0.6 - mlly: 1.7.4 - node-fetch-native: 1.6.6 - ofetch: 1.4.1 - ohash: 1.1.4 - openapi-typescript: 7.6.0(typescript@5.7.3) - pathe: 1.1.2 - perfect-debounce: 1.0.0 - pkg-types: 1.3.1 - pretty-bytes: 6.1.1 - radix3: 1.1.2 - rollup: 4.34.0 - rollup-plugin-visualizer: 5.14.0(rollup@4.34.0) - scule: 1.3.0 - semver: 7.7.0 - serve-placeholder: 2.0.2 - serve-static: 1.16.2 - std-env: 3.8.0 - ufo: 1.5.4 - uncrypto: 0.1.3 - unctx: 2.4.1 - unenv: 1.10.0 - unimport: 3.14.6(rollup@4.34.0) - unstorage: 1.14.4(db0@0.2.3)(ioredis@5.4.2) - untyped: 1.5.2 - unwasm: 0.3.9 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@electric-sql/pglite' - - '@libsql/client' - - '@netlify/blobs' - - '@planetscale/database' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/kv' - - aws4fetch - - better-sqlite3 - - drizzle-orm - - encoding - - idb-keyval - - mysql2 - - rolldown - - sqlite3 - - supports-color - - typescript - - uploadthing - nitropack@2.10.4(typescript@5.8.2): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 @@ -21774,16 +21675,6 @@ snapshots: is-docker: 2.2.1 is-wsl: 2.2.0 - openapi-typescript@7.6.0(typescript@5.7.3): - dependencies: - '@redocly/openapi-core': 1.28.0(supports-color@9.4.0) - ansi-colors: 4.1.3 - change-case: 5.4.4 - parse-json: 8.1.0 - supports-color: 9.4.0 - typescript: 5.7.3 - yargs-parser: 21.1.1 - openapi-typescript@7.6.0(typescript@5.8.2): dependencies: '@redocly/openapi-core': 1.28.0(supports-color@9.4.0) @@ -23115,10 +23006,6 @@ snapshots: ts-pattern@5.6.2: {} - tsconfck@3.1.4(typescript@5.7.3): - optionalDependencies: - typescript: 5.7.3 - tsconfck@3.1.4(typescript@5.8.2): optionalDependencies: typescript: 5.8.2 @@ -23421,85 +23308,6 @@ snapshots: vary@1.1.2: {} - vinxi@0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0): - dependencies: - '@babel/core': 7.26.8 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.8) - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.8) - '@types/micromatch': 4.0.9 - '@vinxi/listhen': 1.5.6 - boxen: 7.1.1 - chokidar: 3.6.0 - citty: 0.1.6 - consola: 3.4.0 - crossws: 0.3.3 - dax-sh: 0.39.2 - defu: 6.1.4 - es-module-lexer: 1.6.0 - esbuild: 0.20.2 - fast-glob: 3.3.3 - get-port-please: 3.1.2 - h3: 1.13.0 - hookable: 5.5.3 - http-proxy: 1.18.1 - micromatch: 4.0.8 - nitropack: 2.10.4(typescript@5.7.3) - node-fetch-native: 1.6.6 - path-to-regexp: 6.3.0 - pathe: 1.1.2 - radix3: 1.1.2 - resolve: 1.22.10 - serve-placeholder: 2.0.2 - serve-static: 1.16.2 - ufo: 1.5.4 - unctx: 2.4.1 - unenv: 1.10.0 - unstorage: 1.14.4(db0@0.2.3)(ioredis@5.4.2) - vite: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - zod: 3.24.2 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@electric-sql/pglite' - - '@libsql/client' - - '@netlify/blobs' - - '@planetscale/database' - - '@types/node' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/kv' - - aws4fetch - - better-sqlite3 - - db0 - - debug - - drizzle-orm - - encoding - - idb-keyval - - ioredis - - jiti - - less - - lightningcss - - mysql2 - - rolldown - - sass - - sass-embedded - - sqlite3 - - stylus - - sugarss - - supports-color - - terser - - tsx - - typescript - - uploadthing - - xml2js - - yaml - vinxi@0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0): dependencies: '@babel/core': 7.26.8 @@ -23535,7 +23343,7 @@ snapshots: unenv: 1.10.0 unstorage: 1.14.4(db0@0.2.3)(ioredis@5.4.2) vite: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - zod: 3.24.1 + zod: 3.24.2 transitivePeerDependencies: - '@azure/app-configuration' - '@azure/cosmos' @@ -23658,17 +23466,6 @@ snapshots: transitivePeerDependencies: - supports-color - vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)): - dependencies: - debug: 4.4.0(supports-color@9.4.0) - globrex: 0.1.2 - tsconfck: 3.1.4(typescript@5.7.3) - optionalDependencies: - vite: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - transitivePeerDependencies: - - supports-color - - typescript - vite-tsconfig-paths@5.1.4(typescript@5.8.2)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)): dependencies: debug: 4.4.0(supports-color@9.4.0) From 37812fcdede23a2844634ea65c74a7e4deea303b Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sat, 8 Mar 2025 18:33:17 +1300 Subject: [PATCH 021/155] fix(solid-start-plugin): build failures due to type mismatches --- packages/solid-start-plugin/src/compilers.ts | 7 ++++--- packages/solid-start-plugin/src/index.ts | 7 +++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/packages/solid-start-plugin/src/compilers.ts b/packages/solid-start-plugin/src/compilers.ts index 0fd65af65c..cc1d890c68 100644 --- a/packages/solid-start-plugin/src/compilers.ts +++ b/packages/solid-start-plugin/src/compilers.ts @@ -17,6 +17,7 @@ const handleClientOnlyCallExpression = type CompileOptions = ParseAstOptions & { env: 'server' | 'client' | 'ssr' dce?: boolean + filename: string } type IdentifierConfig = { @@ -187,7 +188,7 @@ export function compileStartOutput(opts: CompileOptions): GeneratorResult { function handleCreateServerFnCallExpression( path: babel.NodePath, - opts: ParseAstOptions, + opts: CompileOptions, ) { // The function is the 'fn' property of the object passed to createServerFn @@ -352,7 +353,7 @@ function handleCreateServerFnCallExpression( function handleCreateMiddlewareCallExpression( path: babel.NodePath, - opts: ParseAstOptions, + opts: CompileOptions, ) { const rootCallExpression = getRootCallExpression(path) @@ -427,7 +428,7 @@ function handleCreateMiddlewareCallExpression( function buildEnvOnlyCallExpressionHandler(env: 'client' | 'server') { return function envOnlyCallExpressionHandler( path: babel.NodePath, - opts: ParseAstOptions, + opts: CompileOptions, ) { // if (debug) // console.info(`Handling ${env}Only call expression:`, path.toString()) diff --git a/packages/solid-start-plugin/src/index.ts b/packages/solid-start-plugin/src/index.ts index f24f09d18a..1e856c0bda 100644 --- a/packages/solid-start-plugin/src/index.ts +++ b/packages/solid-start-plugin/src/index.ts @@ -86,13 +86,13 @@ export function createTanStackStartPlugin(opts: TanStackStartViteOptions): { export function TanStackStartServerFnsAndMiddleware(opts: { env: 'server' | 'ssr' | 'client' }): Plugin { - let ROOT: string = process.cwd() + // let ROOT: string = process.cwd() return { name: 'vite-plugin-tanstack-start-create-server-fn', enforce: 'pre', - configResolved: (config) => { - ROOT = config.root + configResolved: (_config) => { + // ROOT = config.root }, transform(code, id) { const url = pathToFileURL(id) @@ -114,7 +114,6 @@ export function TanStackStartServerFnsAndMiddleware(opts: { const compiled = compileStartOutput({ code, - root: ROOT, filename: id, env: opts.env, }) From 4713ebf1a65a5745e795ad74e41b7e63952f9fbb Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sat, 8 Mar 2025 18:36:29 +1300 Subject: [PATCH 022/155] chore(start-plugin): cleanup this doesn't exist anymore --- packages/start-plugin/package.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 packages/start-plugin/package.json diff --git a/packages/start-plugin/package.json b/packages/start-plugin/package.json deleted file mode 100644 index 0967ef424b..0000000000 --- a/packages/start-plugin/package.json +++ /dev/null @@ -1 +0,0 @@ -{} From 4bfb75b5567589d036ac88ec3d5c89fb8a2cceed Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sat, 8 Mar 2025 18:44:08 +1300 Subject: [PATCH 023/155] fix(react-start-plugin): use the `__enableAPIRoutesGeneration` flag --- packages/react-start-plugin/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-start-plugin/src/index.ts b/packages/react-start-plugin/src/index.ts index ca475b351e..a017bbff15 100644 --- a/packages/react-start-plugin/src/index.ts +++ b/packages/react-start-plugin/src/index.ts @@ -120,6 +120,7 @@ export function TanStackStartVitePlugin( TanStackRouterVite({ ...options.tsr, enableRouteGeneration: true, + __enableAPIRoutesGeneration: true, autoCodeSplitting: true, }), viteReact(options.react), From 0d1fb0626998cf5392fefd0003bb82c170a461af Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sat, 8 Mar 2025 18:48:23 +1300 Subject: [PATCH 024/155] chore(root): sync lockfile and labeler config --- .github/labeler.yml | 2 -- pnpm-lock.yaml | 2 -- 2 files changed, 4 deletions(-) diff --git a/.github/labeler.yml b/.github/labeler.yml index 25014dccc5..a4272bf152 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -24,8 +24,6 @@ - 'packages/react-start-client/**/*' 'package: react-start-plugin': - 'packages/react-start-plugin/**/*' -'package: react-start-router-manifest': - - 'packages/react-start-router-manifest/**/*' 'package: react-start-server': - 'packages/react-start-server/**/*' 'package: react-start-server-functions-client': diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 40ae2d4843..24f48cc818 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6688,8 +6688,6 @@ importers: specifier: workspace:* version: link:../start-server-functions-server - packages/start-plugin: {} - packages/start-server-functions-server: dependencies: '@tanstack/server-functions-plugin': From d4f0a6696641a85d026f5fa8af4b2d6d4221c246 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Fri, 7 Mar 2025 23:03:58 -0700 Subject: [PATCH 025/155] checkpoint --- .../framework/react/guide/tanstack-start.md | 55 +- .../framework/react/build-from-scratch.md | 52 +- .../start/framework/react/learn-the-basics.md | 18 +- docs/start/framework/react/path-aliases.md | 2 +- docs/start/framework/react/ssr.md | 4 +- e2e/react-start/basic-auth/app/client.tsx | 7 - .../basic-auth/tailwind.config.mjs | 2 +- .../basic-react-query/app/client.tsx | 7 - .../basic-react-query/tailwind.config.mjs | 2 +- e2e/react-start/basic-rsc/app/client.tsx | 7 - e2e/react-start/basic-rsc/tailwind.config.mjs | 2 +- .../basic-tsr-config/src/app/client.tsx | 7 - e2e/react-start/basic/app/client.tsx | 7 - e2e/react-start/basic/app/ssr.tsx | 17 - e2e/react-start/basic/tailwind.config.mjs | 2 +- e2e/react-start/clerk-basic/app/client.tsx | 7 - .../react-start/clerk-basic/app/server.tsx | 9 +- .../clerk-basic/tailwind.config.mjs | 2 +- .../scroll-restoration/app/client.tsx | 7 - .../scroll-restoration/tailwind.config.mjs | 2 +- .../server-functions/app/client.tsx | 7 - .../server-functions/tailwind.config.mjs | 2 +- .../server-functions/tsconfig.json | 2 +- e2e/react-start/website/app/client.tsx | 7 - e2e/react-start/website/tailwind.config.mjs | 2 +- examples/react/start-bare/app/client.tsx | 7 - .../react/start-bare/app/server.ts | 0 .../react/start-basic-auth/app/client.tsx | 7 - .../react/start-basic-auth/app/server.ts | 0 examples/react/start-basic-auth/app/ssr.tsx | 12 - .../start-basic-auth/tailwind.config.mjs | 2 +- .../start-basic-react-query/app/client.tsx | 7 - .../start-basic-react-query/app/server.ts | 0 .../react/start-basic-react-query/app/ssr.tsx | 12 - .../tailwind.config.mjs | 2 +- examples/react/start-basic-rsc/app/client.tsx | 7 - .../react/start-basic-rsc/app/server.ts | 0 examples/react/start-basic-rsc/app/ssr.tsx | 12 - .../react/start-basic-rsc/tailwind.config.mjs | 2 +- .../react/start-basic-static/app/client.tsx | 7 - .../react/start-basic-static/app/server.ts | 0 examples/react/start-basic-static/app/ssr.tsx | 12 - .../start-basic-static/tailwind.config.cjs | 2 +- examples/react/start-basic/app/api.ts | 6 - examples/react/start-basic/app/client.tsx | 7 - .../start-basic/app/global-middleware.ts | 6 - .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/components/PostError.tsx | 0 .../{app => src}/components/UserError.tsx | 0 .../react/start-basic/src/routeTree.gen.ts | 470 ++++++++++++++++++ .../react/start-basic/{app => src}/router.tsx | 0 .../react/start-basic/src/routes/__root.tsx | 139 ++++++ .../react/start-basic/src/routes/_layout.tsx | 16 + .../src/routes/_layout/_layout-2.tsx | 34 ++ .../src/routes/_layout/_layout-2/layout-a.tsx | 9 + .../src/routes/_layout/_layout-2/layout-b.tsx | 9 + .../{app => src}/routes/api/users.$id.ts | 0 .../{app => src}/routes/api/users.ts | 0 .../{app => src}/routes/deferred.tsx | 0 .../start-basic/{app => src}/routes/index.tsx | 0 .../{app => src}/routes/posts.$postId.tsx | 0 .../{app => src}/routes/posts.index.tsx | 0 .../react/start-basic/src/routes/posts.tsx | 38 ++ .../routes/posts_.$postId.deep.tsx | 0 .../{app => src}/routes/redirect.tsx | 0 .../{app => src}/routes/users.$userId.tsx | 0 .../{app => src}/routes/users.index.tsx | 0 .../react/start-basic/src/routes/users.tsx | 48 ++ .../start-basic/{app => src}/styles/app.css | 0 .../{app => src}/utils/loggingMiddleware.tsx | 0 .../start-basic/{app => src}/utils/posts.tsx | 0 .../start-basic/{app => src}/utils/seo.ts | 0 .../start-basic/{app => src}/utils/users.tsx | 0 .../react/start-basic/tailwind.config.mjs | 2 +- examples/react/start-basic/tsconfig.json | 2 +- .../react/start-clerk-basic/app/client.tsx | 7 - .../react/start-clerk-basic/app/server.ts | 0 examples/react/start-clerk-basic/app/ssr.tsx | 16 - .../start-clerk-basic/tailwind.config.mjs | 2 +- .../start-convex-trellaux/app/client.tsx | 7 - .../react/start-convex-trellaux/app/server.ts | 0 .../react/start-convex-trellaux/app/ssr.tsx | 12 - .../start-convex-trellaux/tailwind.config.mjs | 2 +- examples/react/start-counter/app/client.tsx | 7 - .../react/start-counter/app/server.ts | 0 examples/react/start-counter/app/ssr.tsx | 12 - examples/react/start-large/app/client.tsx | 9 - .../start-large/app/{ssr.tsx => server.ts} | 2 +- .../react/start-large/tailwind.config.mjs | 2 +- .../react/start-supabase-basic/app/client.tsx | 9 - .../app/{ssr.tsx => server.ts} | 2 +- .../start-supabase-basic/tailwind.config.mjs | 2 +- examples/react/start-trellaux/app/client.tsx | 7 - .../ssr.tsx => start-trellaux/app/server.ts} | 0 examples/react/start-trellaux/app/ssr.tsx | 12 - .../react/start-trellaux/tailwind.config.mjs | 2 +- .../with-trpc-react-query/tailwind.config.mjs | 2 +- examples/react/with-trpc/tailwind.config.mjs | 2 +- .../src/modules/core/template/app/ssr.tsx | 14 - packages/react-start-plugin/src/index.ts | 44 ++ .../nitro/{plugins => }/dev-server-plugin.ts | 6 +- .../src/nitro/nitro-plugin.ts | 6 +- packages/react-start-plugin/src/schema.ts | 61 +-- .../src/createStartHandler.ts | 9 + packages/react-start-server/src/h3.ts | 8 +- .../react-start-server/src/router-manifest.ts | 2 +- 107 files changed, 913 insertions(+), 468 deletions(-) delete mode 100644 e2e/react-start/basic-auth/app/client.tsx delete mode 100644 e2e/react-start/basic-react-query/app/client.tsx delete mode 100644 e2e/react-start/basic-rsc/app/client.tsx delete mode 100644 e2e/react-start/basic-tsr-config/src/app/client.tsx delete mode 100644 e2e/react-start/basic/app/client.tsx delete mode 100644 e2e/react-start/basic/app/ssr.tsx delete mode 100644 e2e/react-start/clerk-basic/app/client.tsx rename examples/react/start-basic/app/ssr.tsx => e2e/react-start/clerk-basic/app/server.tsx (58%) delete mode 100644 e2e/react-start/scroll-restoration/app/client.tsx delete mode 100644 e2e/react-start/server-functions/app/client.tsx delete mode 100644 e2e/react-start/website/app/client.tsx delete mode 100644 examples/react/start-bare/app/client.tsx rename e2e/react-start/basic-auth/app/ssr.tsx => examples/react/start-bare/app/server.ts (100%) delete mode 100644 examples/react/start-basic-auth/app/client.tsx rename e2e/react-start/basic-react-query/app/ssr.tsx => examples/react/start-basic-auth/app/server.ts (100%) delete mode 100644 examples/react/start-basic-auth/app/ssr.tsx delete mode 100644 examples/react/start-basic-react-query/app/client.tsx rename e2e/react-start/basic-rsc/app/ssr.tsx => examples/react/start-basic-react-query/app/server.ts (100%) delete mode 100644 examples/react/start-basic-react-query/app/ssr.tsx delete mode 100644 examples/react/start-basic-rsc/app/client.tsx rename e2e/react-start/basic-tsr-config/src/app/ssr.tsx => examples/react/start-basic-rsc/app/server.ts (100%) delete mode 100644 examples/react/start-basic-rsc/app/ssr.tsx delete mode 100644 examples/react/start-basic-static/app/client.tsx rename e2e/react-start/scroll-restoration/app/ssr.tsx => examples/react/start-basic-static/app/server.ts (100%) delete mode 100644 examples/react/start-basic-static/app/ssr.tsx delete mode 100644 examples/react/start-basic/app/api.ts delete mode 100644 examples/react/start-basic/app/client.tsx delete mode 100644 examples/react/start-basic/app/global-middleware.ts rename examples/react/start-basic/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename examples/react/start-basic/{app => src}/components/NotFound.tsx (100%) rename examples/react/start-basic/{app => src}/components/PostError.tsx (100%) rename examples/react/start-basic/{app => src}/components/UserError.tsx (100%) create mode 100644 examples/react/start-basic/src/routeTree.gen.ts rename examples/react/start-basic/{app => src}/router.tsx (100%) create mode 100644 examples/react/start-basic/src/routes/__root.tsx create mode 100644 examples/react/start-basic/src/routes/_layout.tsx create mode 100644 examples/react/start-basic/src/routes/_layout/_layout-2.tsx create mode 100644 examples/react/start-basic/src/routes/_layout/_layout-2/layout-a.tsx create mode 100644 examples/react/start-basic/src/routes/_layout/_layout-2/layout-b.tsx rename examples/react/start-basic/{app => src}/routes/api/users.$id.ts (100%) rename examples/react/start-basic/{app => src}/routes/api/users.ts (100%) rename examples/react/start-basic/{app => src}/routes/deferred.tsx (100%) rename examples/react/start-basic/{app => src}/routes/index.tsx (100%) rename examples/react/start-basic/{app => src}/routes/posts.$postId.tsx (100%) rename examples/react/start-basic/{app => src}/routes/posts.index.tsx (100%) create mode 100644 examples/react/start-basic/src/routes/posts.tsx rename examples/react/start-basic/{app => src}/routes/posts_.$postId.deep.tsx (100%) rename examples/react/start-basic/{app => src}/routes/redirect.tsx (100%) rename examples/react/start-basic/{app => src}/routes/users.$userId.tsx (100%) rename examples/react/start-basic/{app => src}/routes/users.index.tsx (100%) create mode 100644 examples/react/start-basic/src/routes/users.tsx rename examples/react/start-basic/{app => src}/styles/app.css (100%) rename examples/react/start-basic/{app => src}/utils/loggingMiddleware.tsx (100%) rename examples/react/start-basic/{app => src}/utils/posts.tsx (100%) rename examples/react/start-basic/{app => src}/utils/seo.ts (100%) rename examples/react/start-basic/{app => src}/utils/users.tsx (100%) delete mode 100644 examples/react/start-clerk-basic/app/client.tsx rename e2e/react-start/clerk-basic/app/ssr.tsx => examples/react/start-clerk-basic/app/server.ts (100%) delete mode 100644 examples/react/start-clerk-basic/app/ssr.tsx delete mode 100644 examples/react/start-convex-trellaux/app/client.tsx rename e2e/react-start/server-functions/app/ssr.tsx => examples/react/start-convex-trellaux/app/server.ts (100%) delete mode 100644 examples/react/start-convex-trellaux/app/ssr.tsx delete mode 100644 examples/react/start-counter/app/client.tsx rename e2e/react-start/website/app/ssr.tsx => examples/react/start-counter/app/server.ts (100%) delete mode 100644 examples/react/start-counter/app/ssr.tsx delete mode 100644 examples/react/start-large/app/client.tsx rename examples/react/start-large/app/{ssr.tsx => server.ts} (94%) delete mode 100644 examples/react/start-supabase-basic/app/client.tsx rename examples/react/start-supabase-basic/app/{ssr.tsx => server.ts} (94%) delete mode 100644 examples/react/start-trellaux/app/client.tsx rename examples/react/{start-bare/app/ssr.tsx => start-trellaux/app/server.ts} (100%) delete mode 100644 examples/react/start-trellaux/app/ssr.tsx delete mode 100644 packages/create-start/src/modules/core/template/app/ssr.tsx rename packages/react-start-plugin/src/nitro/{plugins => }/dev-server-plugin.ts (95%) diff --git a/docs/router/framework/react/guide/tanstack-start.md b/docs/router/framework/react/guide/tanstack-start.md index 900ed67df2..776cf10d80 100644 --- a/docs/router/framework/react/guide/tanstack-start.md +++ b/docs/router/framework/react/guide/tanstack-start.md @@ -94,12 +94,10 @@ export default defineConfig({}) # Add the Basic Templating -There are four required files for TanStack Start usage: +There are 2 required files for TanStack Start usage: 1. The router configuration -2. The server entry point -3. The client entry point -4. The root of your application +2. The root of your application Once configuration is done, we'll have a file tree that looks like the following: @@ -108,10 +106,8 @@ Once configuration is done, we'll have a file tree that looks like the following ├── app/ │ ├── routes/ │ │ └── `__root.tsx` -│ ├── `client.tsx` │ ├── `router.tsx` │ ├── `routeTree.gen.ts` -│ └── `ssr.tsx` ├── `.gitignore` ├── `app.config.ts` ├── `package.json` @@ -120,7 +116,7 @@ Once configuration is done, we'll have a file tree that looks like the following ## The Router Configuration -This is the file that will dictate the behavior of TanStack Router used within Start. Here, you can configure everything +This is the file that will dictate the behavior of TanStack Router used within Start for both the server and the client. Here, you can configure everything from the default [preloading functionality](./preloading.md) to [caching staleness](./data-loading.md). ```tsx @@ -146,52 +142,9 @@ declare module '@tanstack/react-router' { > `routeTree.gen.ts` is not a file you're expected to have at this point. > It will be generated when you run TanStack Start (via `npm run dev` or `npm run start`) for the first time. -## The Server Entry Point - -As TanStack Start is an [SSR](https://unicorn-utterances.com/posts/what-is-ssr-and-ssg) framework, we need to pipe this router -information to our server entry point: - -```tsx -// app/ssr.tsx -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) -``` - -This allows us to know what routes and loaders we need to execute when the user hits a given route. - -## The Client Entry Point - -Now we need a way to hydrate our client-side JavaScript once the route resolves to the client. We do this by piping the same -router information to our client entry point: - -```tsx -// app/client.tsx -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter({ - scrollRestoration: true, -}) - -hydrateRoot(document!, ) -``` - -This enables us to kick off client-side routing once the user's initial server request has fulfilled. - ## The Root of Your Application -Finally, we need to create the root of our application. This is the entry point for all other routes. The code in this file will wrap all other routes in the application. +Finally, we need to create the root of our application. This is the entry point for all application routes. The code in this file will wrap all other routes in the application. ```tsx // app/routes/__root.tsx diff --git a/docs/start/framework/react/build-from-scratch.md b/docs/start/framework/react/build-from-scratch.md index a09e7ff678..c6761297c1 100644 --- a/docs/start/framework/react/build-from-scratch.md +++ b/docs/start/framework/react/build-from-scratch.md @@ -104,12 +104,10 @@ export default defineConfig({ ## Add the Basic Templating -There are four required files for TanStack Start usage: +There are 2 required files for TanStack Start usage: 1. The router configuration -2. The server entry point -3. The client entry point -4. The root of your application +2. The root of your application Once configuration is done, we'll have a file tree that looks like the following: @@ -118,10 +116,8 @@ Once configuration is done, we'll have a file tree that looks like the following ├── app/ │ ├── routes/ │ │ └── `__root.tsx` -│ ├── `client.tsx` │ ├── `router.tsx` │ ├── `routeTree.gen.ts` -│ └── `ssr.tsx` ├── `.gitignore` ├── `app.config.ts` ├── `package.json` @@ -154,50 +150,6 @@ declare module '@tanstack/react-router' { } ``` -> `routeTree.gen.ts` is not a file you're expected to have at this point. -> It will be generated when you run TanStack Start (via `npm run dev` or `npm run start`) for the first time. - -## The Server Entry Point - -As TanStack Start is an [SSR](https://unicorn-utterances.com/posts/what-is-ssr-and-ssg) framework, we need to pipe this router -information to our server entry point: - -```tsx -// app/ssr.tsx -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) -``` - -This allows us to know what routes and loaders we need to execute when the user hits a given route. - -## The Client Entry Point - -Now we need a way to hydrate our client-side JavaScript once the route resolves to the client. We do this by piping the same -router information to our client entry point: - -```tsx -// app/client.tsx -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) -``` - -This enables us to kick off client-side routing once the user's initial server request has fulfilled. - ## The Root of Your Application Finally, we need to create the root of our application. This is the entry point for all other routes. The code in this file will wrap all other routes in the application. diff --git a/docs/start/framework/react/learn-the-basics.md b/docs/start/framework/react/learn-the-basics.md index 95ac917a6c..3df3844980 100644 --- a/docs/start/framework/react/learn-the-basics.md +++ b/docs/start/framework/react/learn-the-basics.md @@ -45,14 +45,15 @@ declare module '@tanstack/react-router' { The `routeTree.gen.ts` file is generated when you run TanStack Start (via `npm run dev` or `npm run start`) for the first time. This file contains the generated route tree and a handful of TS utilities that make TanStack Start fully type-safe. -## The Server Entry Point +## The Server Entry Point (Optional) -Although TanStack Start is designed with client-first APIs, it is by and large, a full-stack framework. This means that all use cases, including both dynamic and static rely on a server or build-time entry to render our application's initial HTML payload. +> [!NOTE] +> The server entry point is **optional** out of the box. If not provided, TanStack Start will automatically handle the server entry point for you using the below as a default. -This is done via the `app/ssr.tsx` file: +This is done via the `src/server.tsx` file: ```tsx -// app/ssr.tsx +// src/server.tsx import { createStartHandler, defaultStreamHandler, @@ -67,13 +68,16 @@ export default createStartHandler({ })(defaultStreamHandler) ``` -Whether we are statically generating our app or serving it dynamically, the `ssr.tsx` file is the entry point for doing all SSR-related work. +Whether we are statically generating our app or serving it dynamically, the `server.tsx` file is the entry point for doing all SSR-related work. - It's important that a new router is created for each request. This ensures that any data handled by the router is unique to the request. - The `getRouterManifest` function is used to generate the router manifest, which is used to determine many aspects of asset management and preloading for our application. - The `defaultStreamHandler` function is used to render our application to a stream, allowing us to take advantage of streaming HTML to the client. (This is the default handler, but you can also use other handlers like `defaultRenderHandler`, or even build your own) -## The Client Entry Point +## The Client Entry Point (Optional) + +> [!NOTE] +> The client entry point is **optional** out of the box. If not provided, TanStack Start will automatically handle the client entry point for you using the below as a default. Getting our html to the client is only half the battle. Once there, we need to hydrate our client-side JavaScript once the route resolves to the client. We do this by hydrating the root of our application with the `StartClient` component: @@ -92,7 +96,7 @@ This enables us to kick off client-side routing once the user's initial server r ## The Root of Your Application -Other than the client entry point, the `__root` route of your application is the entry point for your application. The code in this file will wrap all other routes in the app, including your home page. It behaves like a pathless layout route for your whole application. +Other than the client entry point (which is optional by default), the `__root` route of your application is the entry point for your application. The code in this file will wrap all other routes in the app, including your home page. It behaves like a pathless layout route for your whole application. Because it is **always rendered**, it is the perfect place to construct your application shell and take care of any global logic. diff --git a/docs/start/framework/react/path-aliases.md b/docs/start/framework/react/path-aliases.md index 28ecf7aa1a..ef65f4771b 100644 --- a/docs/start/framework/react/path-aliases.md +++ b/docs/start/framework/react/path-aliases.md @@ -12,7 +12,7 @@ By default, TanStack Start does not include path aliases. However, you can easil "compilerOptions": { "baseUrl": ".", "paths": { - "~/*": ["app/*"] + "~/*": ["src/*"] } } } diff --git a/docs/start/framework/react/ssr.md b/docs/start/framework/react/ssr.md index f509d47f72..b932548555 100644 --- a/docs/start/framework/react/ssr.md +++ b/docs/start/framework/react/ssr.md @@ -7,10 +7,10 @@ Server-side rendering (SSR) is the process of rendering your application on the ## SSR Basics -TanStack Start supports server-side rendering out of the box. To enable server-side rendering, create an `app/ssr.tsx` file in your project: +TanStack Start supports server-side rendering out of the box. To enable server-side rendering, create an `src/server.tsx` file in your project: ```tsx -// app/ssr.tsx +// src/server.tsx import { createStartHandler, diff --git a/e2e/react-start/basic-auth/app/client.tsx b/e2e/react-start/basic-auth/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/e2e/react-start/basic-auth/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/basic-auth/tailwind.config.mjs b/e2e/react-start/basic-auth/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/e2e/react-start/basic-auth/tailwind.config.mjs +++ b/e2e/react-start/basic-auth/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/e2e/react-start/basic-react-query/app/client.tsx b/e2e/react-start/basic-react-query/app/client.tsx deleted file mode 100644 index 9fb62bd3c2..0000000000 --- a/e2e/react-start/basic-react-query/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document!, ) diff --git a/e2e/react-start/basic-react-query/tailwind.config.mjs b/e2e/react-start/basic-react-query/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/e2e/react-start/basic-react-query/tailwind.config.mjs +++ b/e2e/react-start/basic-react-query/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/e2e/react-start/basic-rsc/app/client.tsx b/e2e/react-start/basic-rsc/app/client.tsx deleted file mode 100644 index 9fb62bd3c2..0000000000 --- a/e2e/react-start/basic-rsc/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document!, ) diff --git a/e2e/react-start/basic-rsc/tailwind.config.mjs b/e2e/react-start/basic-rsc/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/e2e/react-start/basic-rsc/tailwind.config.mjs +++ b/e2e/react-start/basic-rsc/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/e2e/react-start/basic-tsr-config/src/app/client.tsx b/e2e/react-start/basic-tsr-config/src/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/e2e/react-start/basic-tsr-config/src/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/basic/app/client.tsx b/e2e/react-start/basic/app/client.tsx deleted file mode 100644 index ffee5f382c..0000000000 --- a/e2e/react-start/basic/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/basic/app/ssr.tsx b/e2e/react-start/basic/app/ssr.tsx deleted file mode 100644 index de2ca15a47..0000000000 --- a/e2e/react-start/basic/app/ssr.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, - defineEventHandler, -} from '@tanstack/start/server' -import { getRouterManifest } from '@tanstack/start/router-manifest' - -import { createRouter } from './router' - -export default defineEventHandler((event) => { - const startHandler = createStartHandler({ - createRouter, - getRouterManifest, - })(defaultStreamHandler) - - return startHandler(event) -}) diff --git a/e2e/react-start/basic/tailwind.config.mjs b/e2e/react-start/basic/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/e2e/react-start/basic/tailwind.config.mjs +++ b/e2e/react-start/basic/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/e2e/react-start/clerk-basic/app/client.tsx b/e2e/react-start/clerk-basic/app/client.tsx deleted file mode 100644 index 9fb62bd3c2..0000000000 --- a/e2e/react-start/clerk-basic/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document!, ) diff --git a/examples/react/start-basic/app/ssr.tsx b/e2e/react-start/clerk-basic/app/server.tsx similarity index 58% rename from examples/react/start-basic/app/ssr.tsx rename to e2e/react-start/clerk-basic/app/server.tsx index 3cce9272c4..3283a1ba85 100644 --- a/examples/react/start-basic/app/ssr.tsx +++ b/e2e/react-start/clerk-basic/app/server.tsx @@ -3,13 +3,16 @@ import { defaultStreamHandler, defineEventHandler, } from '@tanstack/react-start/server' - +import { createClerkHandler } from '@clerk/tanstack-start/server' import { createRouter } from './router' export default defineEventHandler((event) => { const startHandler = createStartHandler({ createRouter, - })(defaultStreamHandler) + }) + + const withClerkHandler = + createClerkHandler(startHandler)(defaultStreamHandler) - return startHandler(event) + return withClerkHandler(event) }) diff --git a/e2e/react-start/clerk-basic/tailwind.config.mjs b/e2e/react-start/clerk-basic/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/e2e/react-start/clerk-basic/tailwind.config.mjs +++ b/e2e/react-start/clerk-basic/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/e2e/react-start/scroll-restoration/app/client.tsx b/e2e/react-start/scroll-restoration/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/e2e/react-start/scroll-restoration/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/scroll-restoration/tailwind.config.mjs b/e2e/react-start/scroll-restoration/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/e2e/react-start/scroll-restoration/tailwind.config.mjs +++ b/e2e/react-start/scroll-restoration/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/e2e/react-start/server-functions/app/client.tsx b/e2e/react-start/server-functions/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/e2e/react-start/server-functions/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/server-functions/tailwind.config.mjs b/e2e/react-start/server-functions/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/e2e/react-start/server-functions/tailwind.config.mjs +++ b/e2e/react-start/server-functions/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/e2e/react-start/server-functions/tsconfig.json b/e2e/react-start/server-functions/tsconfig.json index 15d0654dae..2c6f205688 100644 --- a/e2e/react-start/server-functions/tsconfig.json +++ b/e2e/react-start/server-functions/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": "", "paths": { - "~/*": ["app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/e2e/react-start/website/app/client.tsx b/e2e/react-start/website/app/client.tsx deleted file mode 100644 index 9fb62bd3c2..0000000000 --- a/e2e/react-start/website/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document!, ) diff --git a/e2e/react-start/website/tailwind.config.mjs b/e2e/react-start/website/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/e2e/react-start/website/tailwind.config.mjs +++ b/e2e/react-start/website/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/examples/react/start-bare/app/client.tsx b/examples/react/start-bare/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/examples/react/start-bare/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/basic-auth/app/ssr.tsx b/examples/react/start-bare/app/server.ts similarity index 100% rename from e2e/react-start/basic-auth/app/ssr.tsx rename to examples/react/start-bare/app/server.ts diff --git a/examples/react/start-basic-auth/app/client.tsx b/examples/react/start-basic-auth/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/examples/react/start-basic-auth/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/basic-react-query/app/ssr.tsx b/examples/react/start-basic-auth/app/server.ts similarity index 100% rename from e2e/react-start/basic-react-query/app/ssr.tsx rename to examples/react/start-basic-auth/app/server.ts diff --git a/examples/react/start-basic-auth/app/ssr.tsx b/examples/react/start-basic-auth/app/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/examples/react/start-basic-auth/app/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/examples/react/start-basic-auth/tailwind.config.mjs b/examples/react/start-basic-auth/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/examples/react/start-basic-auth/tailwind.config.mjs +++ b/examples/react/start-basic-auth/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/examples/react/start-basic-react-query/app/client.tsx b/examples/react/start-basic-react-query/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/examples/react/start-basic-react-query/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/basic-rsc/app/ssr.tsx b/examples/react/start-basic-react-query/app/server.ts similarity index 100% rename from e2e/react-start/basic-rsc/app/ssr.tsx rename to examples/react/start-basic-react-query/app/server.ts diff --git a/examples/react/start-basic-react-query/app/ssr.tsx b/examples/react/start-basic-react-query/app/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/examples/react/start-basic-react-query/app/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/examples/react/start-basic-react-query/tailwind.config.mjs b/examples/react/start-basic-react-query/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/examples/react/start-basic-react-query/tailwind.config.mjs +++ b/examples/react/start-basic-react-query/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/examples/react/start-basic-rsc/app/client.tsx b/examples/react/start-basic-rsc/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/examples/react/start-basic-rsc/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/basic-tsr-config/src/app/ssr.tsx b/examples/react/start-basic-rsc/app/server.ts similarity index 100% rename from e2e/react-start/basic-tsr-config/src/app/ssr.tsx rename to examples/react/start-basic-rsc/app/server.ts diff --git a/examples/react/start-basic-rsc/app/ssr.tsx b/examples/react/start-basic-rsc/app/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/examples/react/start-basic-rsc/app/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/examples/react/start-basic-rsc/tailwind.config.mjs b/examples/react/start-basic-rsc/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/examples/react/start-basic-rsc/tailwind.config.mjs +++ b/examples/react/start-basic-rsc/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/examples/react/start-basic-static/app/client.tsx b/examples/react/start-basic-static/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/examples/react/start-basic-static/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/scroll-restoration/app/ssr.tsx b/examples/react/start-basic-static/app/server.ts similarity index 100% rename from e2e/react-start/scroll-restoration/app/ssr.tsx rename to examples/react/start-basic-static/app/server.ts diff --git a/examples/react/start-basic-static/app/ssr.tsx b/examples/react/start-basic-static/app/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/examples/react/start-basic-static/app/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/examples/react/start-basic-static/tailwind.config.cjs b/examples/react/start-basic-static/tailwind.config.cjs index 75fe25dbf7..10c9224f8c 100644 --- a/examples/react/start-basic-static/tailwind.config.cjs +++ b/examples/react/start-basic-static/tailwind.config.cjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ module.exports = { - content: ['./app/**/*.{js,ts,jsx,tsx}'], + content: ['./src/**/*.{js,ts,jsx,tsx}'], } diff --git a/examples/react/start-basic/app/api.ts b/examples/react/start-basic/app/api.ts deleted file mode 100644 index 8b9fef1667..0000000000 --- a/examples/react/start-basic/app/api.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { - createStartAPIHandler, - defaultAPIFileRouteHandler, -} from '@tanstack/react-start/api' - -export default createStartAPIHandler(defaultAPIFileRouteHandler) diff --git a/examples/react/start-basic/app/client.tsx b/examples/react/start-basic/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/examples/react/start-basic/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/examples/react/start-basic/app/global-middleware.ts b/examples/react/start-basic/app/global-middleware.ts deleted file mode 100644 index c7e7af599f..0000000000 --- a/examples/react/start-basic/app/global-middleware.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { registerGlobalMiddleware } from '@tanstack/react-start' -import { logMiddleware } from './utils/loggingMiddleware' - -registerGlobalMiddleware({ - middleware: [logMiddleware], -}) diff --git a/examples/react/start-basic/app/components/DefaultCatchBoundary.tsx b/examples/react/start-basic/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from examples/react/start-basic/app/components/DefaultCatchBoundary.tsx rename to examples/react/start-basic/src/components/DefaultCatchBoundary.tsx diff --git a/examples/react/start-basic/app/components/NotFound.tsx b/examples/react/start-basic/src/components/NotFound.tsx similarity index 100% rename from examples/react/start-basic/app/components/NotFound.tsx rename to examples/react/start-basic/src/components/NotFound.tsx diff --git a/examples/react/start-basic/app/components/PostError.tsx b/examples/react/start-basic/src/components/PostError.tsx similarity index 100% rename from examples/react/start-basic/app/components/PostError.tsx rename to examples/react/start-basic/src/components/PostError.tsx diff --git a/examples/react/start-basic/app/components/UserError.tsx b/examples/react/start-basic/src/components/UserError.tsx similarity index 100% rename from examples/react/start-basic/app/components/UserError.tsx rename to examples/react/start-basic/src/components/UserError.tsx diff --git a/examples/react/start-basic/src/routeTree.gen.ts b/examples/react/start-basic/src/routeTree.gen.ts new file mode 100644 index 0000000000..9f7ab8107b --- /dev/null +++ b/examples/react/start-basic/src/routeTree.gen.ts @@ -0,0 +1,470 @@ +/* eslint-disable */ + +// @ts-nocheck + +// noinspection JSUnusedGlobalSymbols + +// This file was automatically generated by TanStack Router. +// You should NOT make any changes in this file as it will be overwritten. +// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. + +// Import Routes + +import { Route as rootRoute } from './routes/__root' +import { Route as UsersImport } from './routes/users' +import { Route as RedirectImport } from './routes/redirect' +import { Route as PostsImport } from './routes/posts' +import { Route as DeferredImport } from './routes/deferred' +import { Route as LayoutImport } from './routes/_layout' +import { Route as IndexImport } from './routes/index' +import { Route as UsersIndexImport } from './routes/users.index' +import { Route as PostsIndexImport } from './routes/posts.index' +import { Route as UsersUserIdImport } from './routes/users.$userId' +import { Route as PostsPostIdImport } from './routes/posts.$postId' +import { Route as LayoutLayout2Import } from './routes/_layout/_layout-2' +import { Route as PostsPostIdDeepImport } from './routes/posts_.$postId.deep' +import { Route as LayoutLayout2LayoutBImport } from './routes/_layout/_layout-2/layout-b' +import { Route as LayoutLayout2LayoutAImport } from './routes/_layout/_layout-2/layout-a' + +// Create/Update Routes + +const UsersRoute = UsersImport.update({ + id: '/users', + path: '/users', + getParentRoute: () => rootRoute, +} as any) + +const RedirectRoute = RedirectImport.update({ + id: '/redirect', + path: '/redirect', + getParentRoute: () => rootRoute, +} as any) + +const PostsRoute = PostsImport.update({ + id: '/posts', + path: '/posts', + getParentRoute: () => rootRoute, +} as any) + +const DeferredRoute = DeferredImport.update({ + id: '/deferred', + path: '/deferred', + getParentRoute: () => rootRoute, +} as any) + +const LayoutRoute = LayoutImport.update({ + id: '/_layout', + getParentRoute: () => rootRoute, +} as any) + +const IndexRoute = IndexImport.update({ + id: '/', + path: '/', + getParentRoute: () => rootRoute, +} as any) + +const UsersIndexRoute = UsersIndexImport.update({ + id: '/', + path: '/', + getParentRoute: () => UsersRoute, +} as any) + +const PostsIndexRoute = PostsIndexImport.update({ + id: '/', + path: '/', + getParentRoute: () => PostsRoute, +} as any) + +const UsersUserIdRoute = UsersUserIdImport.update({ + id: '/$userId', + path: '/$userId', + getParentRoute: () => UsersRoute, +} as any) + +const PostsPostIdRoute = PostsPostIdImport.update({ + id: '/$postId', + path: '/$postId', + getParentRoute: () => PostsRoute, +} as any) + +const LayoutLayout2Route = LayoutLayout2Import.update({ + id: '/_layout-2', + getParentRoute: () => LayoutRoute, +} as any) + +const PostsPostIdDeepRoute = PostsPostIdDeepImport.update({ + id: '/posts_/$postId/deep', + path: '/posts/$postId/deep', + getParentRoute: () => rootRoute, +} as any) + +const LayoutLayout2LayoutBRoute = LayoutLayout2LayoutBImport.update({ + id: '/layout-b', + path: '/layout-b', + getParentRoute: () => LayoutLayout2Route, +} as any) + +const LayoutLayout2LayoutARoute = LayoutLayout2LayoutAImport.update({ + id: '/layout-a', + path: '/layout-a', + getParentRoute: () => LayoutLayout2Route, +} as any) + +// Populate the FileRoutesByPath interface + +declare module '@tanstack/react-router' { + interface FileRoutesByPath { + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexImport + parentRoute: typeof rootRoute + } + '/_layout': { + id: '/_layout' + path: '' + fullPath: '' + preLoaderRoute: typeof LayoutImport + parentRoute: typeof rootRoute + } + '/deferred': { + id: '/deferred' + path: '/deferred' + fullPath: '/deferred' + preLoaderRoute: typeof DeferredImport + parentRoute: typeof rootRoute + } + '/posts': { + id: '/posts' + path: '/posts' + fullPath: '/posts' + preLoaderRoute: typeof PostsImport + parentRoute: typeof rootRoute + } + '/redirect': { + id: '/redirect' + path: '/redirect' + fullPath: '/redirect' + preLoaderRoute: typeof RedirectImport + parentRoute: typeof rootRoute + } + '/users': { + id: '/users' + path: '/users' + fullPath: '/users' + preLoaderRoute: typeof UsersImport + parentRoute: typeof rootRoute + } + '/_layout/_layout-2': { + id: '/_layout/_layout-2' + path: '' + fullPath: '' + preLoaderRoute: typeof LayoutLayout2Import + parentRoute: typeof LayoutImport + } + '/posts/$postId': { + id: '/posts/$postId' + path: '/$postId' + fullPath: '/posts/$postId' + preLoaderRoute: typeof PostsPostIdImport + parentRoute: typeof PostsImport + } + '/users/$userId': { + id: '/users/$userId' + path: '/$userId' + fullPath: '/users/$userId' + preLoaderRoute: typeof UsersUserIdImport + parentRoute: typeof UsersImport + } + '/posts/': { + id: '/posts/' + path: '/' + fullPath: '/posts/' + preLoaderRoute: typeof PostsIndexImport + parentRoute: typeof PostsImport + } + '/users/': { + id: '/users/' + path: '/' + fullPath: '/users/' + preLoaderRoute: typeof UsersIndexImport + parentRoute: typeof UsersImport + } + '/_layout/_layout-2/layout-a': { + id: '/_layout/_layout-2/layout-a' + path: '/layout-a' + fullPath: '/layout-a' + preLoaderRoute: typeof LayoutLayout2LayoutAImport + parentRoute: typeof LayoutLayout2Import + } + '/_layout/_layout-2/layout-b': { + id: '/_layout/_layout-2/layout-b' + path: '/layout-b' + fullPath: '/layout-b' + preLoaderRoute: typeof LayoutLayout2LayoutBImport + parentRoute: typeof LayoutLayout2Import + } + '/posts_/$postId/deep': { + id: '/posts_/$postId/deep' + path: '/posts/$postId/deep' + fullPath: '/posts/$postId/deep' + preLoaderRoute: typeof PostsPostIdDeepImport + parentRoute: typeof rootRoute + } + } +} + +// Create and export the route tree + +interface LayoutLayout2RouteChildren { + LayoutLayout2LayoutARoute: typeof LayoutLayout2LayoutARoute + LayoutLayout2LayoutBRoute: typeof LayoutLayout2LayoutBRoute +} + +const LayoutLayout2RouteChildren: LayoutLayout2RouteChildren = { + LayoutLayout2LayoutARoute: LayoutLayout2LayoutARoute, + LayoutLayout2LayoutBRoute: LayoutLayout2LayoutBRoute, +} + +const LayoutLayout2RouteWithChildren = LayoutLayout2Route._addFileChildren( + LayoutLayout2RouteChildren, +) + +interface LayoutRouteChildren { + LayoutLayout2Route: typeof LayoutLayout2RouteWithChildren +} + +const LayoutRouteChildren: LayoutRouteChildren = { + LayoutLayout2Route: LayoutLayout2RouteWithChildren, +} + +const LayoutRouteWithChildren = + LayoutRoute._addFileChildren(LayoutRouteChildren) + +interface PostsRouteChildren { + PostsPostIdRoute: typeof PostsPostIdRoute + PostsIndexRoute: typeof PostsIndexRoute +} + +const PostsRouteChildren: PostsRouteChildren = { + PostsPostIdRoute: PostsPostIdRoute, + PostsIndexRoute: PostsIndexRoute, +} + +const PostsRouteWithChildren = PostsRoute._addFileChildren(PostsRouteChildren) + +interface UsersRouteChildren { + UsersUserIdRoute: typeof UsersUserIdRoute + UsersIndexRoute: typeof UsersIndexRoute +} + +const UsersRouteChildren: UsersRouteChildren = { + UsersUserIdRoute: UsersUserIdRoute, + UsersIndexRoute: UsersIndexRoute, +} + +const UsersRouteWithChildren = UsersRoute._addFileChildren(UsersRouteChildren) + +export interface FileRoutesByFullPath { + '/': typeof IndexRoute + '': typeof LayoutLayout2RouteWithChildren + '/deferred': typeof DeferredRoute + '/posts': typeof PostsRouteWithChildren + '/redirect': typeof RedirectRoute + '/users': typeof UsersRouteWithChildren + '/posts/$postId': typeof PostsPostIdRoute + '/users/$userId': typeof UsersUserIdRoute + '/posts/': typeof PostsIndexRoute + '/users/': typeof UsersIndexRoute + '/layout-a': typeof LayoutLayout2LayoutARoute + '/layout-b': typeof LayoutLayout2LayoutBRoute + '/posts/$postId/deep': typeof PostsPostIdDeepRoute +} + +export interface FileRoutesByTo { + '/': typeof IndexRoute + '': typeof LayoutLayout2RouteWithChildren + '/deferred': typeof DeferredRoute + '/redirect': typeof RedirectRoute + '/posts/$postId': typeof PostsPostIdRoute + '/users/$userId': typeof UsersUserIdRoute + '/posts': typeof PostsIndexRoute + '/users': typeof UsersIndexRoute + '/layout-a': typeof LayoutLayout2LayoutARoute + '/layout-b': typeof LayoutLayout2LayoutBRoute + '/posts/$postId/deep': typeof PostsPostIdDeepRoute +} + +export interface FileRoutesById { + __root__: typeof rootRoute + '/': typeof IndexRoute + '/_layout': typeof LayoutRouteWithChildren + '/deferred': typeof DeferredRoute + '/posts': typeof PostsRouteWithChildren + '/redirect': typeof RedirectRoute + '/users': typeof UsersRouteWithChildren + '/_layout/_layout-2': typeof LayoutLayout2RouteWithChildren + '/posts/$postId': typeof PostsPostIdRoute + '/users/$userId': typeof UsersUserIdRoute + '/posts/': typeof PostsIndexRoute + '/users/': typeof UsersIndexRoute + '/_layout/_layout-2/layout-a': typeof LayoutLayout2LayoutARoute + '/_layout/_layout-2/layout-b': typeof LayoutLayout2LayoutBRoute + '/posts_/$postId/deep': typeof PostsPostIdDeepRoute +} + +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: + | '/' + | '' + | '/deferred' + | '/posts' + | '/redirect' + | '/users' + | '/posts/$postId' + | '/users/$userId' + | '/posts/' + | '/users/' + | '/layout-a' + | '/layout-b' + | '/posts/$postId/deep' + fileRoutesByTo: FileRoutesByTo + to: + | '/' + | '' + | '/deferred' + | '/redirect' + | '/posts/$postId' + | '/users/$userId' + | '/posts' + | '/users' + | '/layout-a' + | '/layout-b' + | '/posts/$postId/deep' + id: + | '__root__' + | '/' + | '/_layout' + | '/deferred' + | '/posts' + | '/redirect' + | '/users' + | '/_layout/_layout-2' + | '/posts/$postId' + | '/users/$userId' + | '/posts/' + | '/users/' + | '/_layout/_layout-2/layout-a' + | '/_layout/_layout-2/layout-b' + | '/posts_/$postId/deep' + fileRoutesById: FileRoutesById +} + +export interface RootRouteChildren { + IndexRoute: typeof IndexRoute + LayoutRoute: typeof LayoutRouteWithChildren + DeferredRoute: typeof DeferredRoute + PostsRoute: typeof PostsRouteWithChildren + RedirectRoute: typeof RedirectRoute + UsersRoute: typeof UsersRouteWithChildren + PostsPostIdDeepRoute: typeof PostsPostIdDeepRoute +} + +const rootRouteChildren: RootRouteChildren = { + IndexRoute: IndexRoute, + LayoutRoute: LayoutRouteWithChildren, + DeferredRoute: DeferredRoute, + PostsRoute: PostsRouteWithChildren, + RedirectRoute: RedirectRoute, + UsersRoute: UsersRouteWithChildren, + PostsPostIdDeepRoute: PostsPostIdDeepRoute, +} + +export const routeTree = rootRoute + ._addFileChildren(rootRouteChildren) + ._addFileTypes() + +/* ROUTE_MANIFEST_START +{ + "routes": { + "__root__": { + "filePath": "__root.tsx", + "children": [ + "/", + "/_layout", + "/deferred", + "/posts", + "/redirect", + "/users", + "/posts_/$postId/deep" + ] + }, + "/": { + "filePath": "index.tsx" + }, + "/_layout": { + "filePath": "_layout.tsx", + "children": [ + "/_layout/_layout-2" + ] + }, + "/deferred": { + "filePath": "deferred.tsx" + }, + "/posts": { + "filePath": "posts.tsx", + "children": [ + "/posts/$postId", + "/posts/" + ] + }, + "/redirect": { + "filePath": "redirect.tsx" + }, + "/users": { + "filePath": "users.tsx", + "children": [ + "/users/$userId", + "/users/" + ] + }, + "/_layout/_layout-2": { + "filePath": "_layout/_layout-2.tsx", + "parent": "/_layout", + "children": [ + "/_layout/_layout-2/layout-a", + "/_layout/_layout-2/layout-b" + ] + }, + "/posts/$postId": { + "filePath": "posts.$postId.tsx", + "parent": "/posts" + }, + "/users/$userId": { + "filePath": "users.$userId.tsx", + "parent": "/users" + }, + "/posts/": { + "filePath": "posts.index.tsx", + "parent": "/posts" + }, + "/users/": { + "filePath": "users.index.tsx", + "parent": "/users" + }, + "/_layout/_layout-2/layout-a": { + "filePath": "_layout/_layout-2/layout-a.tsx", + "parent": "/_layout/_layout-2" + }, + "/_layout/_layout-2/layout-b": { + "filePath": "_layout/_layout-2/layout-b.tsx", + "parent": "/_layout/_layout-2" + }, + "/posts_/$postId/deep": { + "filePath": "posts_.$postId.deep.tsx" + } + } +} +ROUTE_MANIFEST_END */ diff --git a/examples/react/start-basic/app/router.tsx b/examples/react/start-basic/src/router.tsx similarity index 100% rename from examples/react/start-basic/app/router.tsx rename to examples/react/start-basic/src/router.tsx diff --git a/examples/react/start-basic/src/routes/__root.tsx b/examples/react/start-basic/src/routes/__root.tsx new file mode 100644 index 0000000000..f6d8d8cf97 --- /dev/null +++ b/examples/react/start-basic/src/routes/__root.tsx @@ -0,0 +1,139 @@ +import { + HeadContent, + Link, + Outlet, + Scripts, + createRootRoute, +} from '@tanstack/react-router' +import { TanStackRouterDevtools } from '@tanstack/router-devtools' +import * as React from 'react' +import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' +import { NotFound } from 'src/components/NotFound' +import { seo } from 'src/utils/seo' +import appCss from '~/styles/app.css?url' + +export const Route = createRootRoute({ + head: () => ({ + meta: [ + { + charSet: 'utf-8', + }, + { + name: 'viewport', + content: 'width=device-width, initial-scale=1', + }, + ...seo({ + title: + 'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework', + description: `TanStack Start is a type-safe, client-first, full-stack React framework. `, + }), + ], + links: [ + { rel: 'stylesheet', href: appCss }, + { + rel: 'apple-touch-icon', + sizes: '180x180', + href: '/apple-touch-icon.png', + }, + { + rel: 'icon', + type: 'image/png', + sizes: '32x32', + href: '/favicon-32x32.png', + }, + { + rel: 'icon', + type: 'image/png', + sizes: '16x16', + href: '/favicon-16x16.png', + }, + { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' }, + { rel: 'icon', href: '/favicon.ico' }, + ], + }), + errorComponent: (props) => { + return ( + + + + ) + }, + notFoundComponent: () => , + component: RootComponent, +}) + +function RootComponent() { + return ( + + + + ) +} + +function RootDocument({ children }: { children: React.ReactNode }) { + return ( + + + + + +
+ + Home + {' '} + + Posts + {' '} + + Users + {' '} + + Layout + {' '} + + Deferred + {' '} + + This Route Does Not Exist + +
+
+ {children} + + + + + ) +} diff --git a/examples/react/start-basic/src/routes/_layout.tsx b/examples/react/start-basic/src/routes/_layout.tsx new file mode 100644 index 0000000000..02ddbb1cd9 --- /dev/null +++ b/examples/react/start-basic/src/routes/_layout.tsx @@ -0,0 +1,16 @@ +import { Outlet, createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/_layout')({ + component: LayoutComponent, +}) + +function LayoutComponent() { + return ( +
+
I'm a layout
+
+ +
+
+ ) +} diff --git a/examples/react/start-basic/src/routes/_layout/_layout-2.tsx b/examples/react/start-basic/src/routes/_layout/_layout-2.tsx new file mode 100644 index 0000000000..3b7dbf2903 --- /dev/null +++ b/examples/react/start-basic/src/routes/_layout/_layout-2.tsx @@ -0,0 +1,34 @@ +import { Link, Outlet, createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/_layout/_layout-2')({ + component: LayoutComponent, +}) + +function LayoutComponent() { + return ( +
+
I'm a nested layout
+
+ + Layout A + + + Layout B + +
+
+ +
+
+ ) +} diff --git a/examples/react/start-basic/src/routes/_layout/_layout-2/layout-a.tsx b/examples/react/start-basic/src/routes/_layout/_layout-2/layout-a.tsx new file mode 100644 index 0000000000..61e19b4d9f --- /dev/null +++ b/examples/react/start-basic/src/routes/_layout/_layout-2/layout-a.tsx @@ -0,0 +1,9 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/_layout/_layout-2/layout-a')({ + component: LayoutAComponent, +}) + +function LayoutAComponent() { + return
I'm layout A!
+} diff --git a/examples/react/start-basic/src/routes/_layout/_layout-2/layout-b.tsx b/examples/react/start-basic/src/routes/_layout/_layout-2/layout-b.tsx new file mode 100644 index 0000000000..cceed1fb9a --- /dev/null +++ b/examples/react/start-basic/src/routes/_layout/_layout-2/layout-b.tsx @@ -0,0 +1,9 @@ +import { createFileRoute } from '@tanstack/react-router' + +export const Route = createFileRoute('/_layout/_layout-2/layout-b')({ + component: LayoutBComponent, +}) + +function LayoutBComponent() { + return
I'm layout B!
+} diff --git a/examples/react/start-basic/app/routes/api/users.$id.ts b/examples/react/start-basic/src/routes/api/users.$id.ts similarity index 100% rename from examples/react/start-basic/app/routes/api/users.$id.ts rename to examples/react/start-basic/src/routes/api/users.$id.ts diff --git a/examples/react/start-basic/app/routes/api/users.ts b/examples/react/start-basic/src/routes/api/users.ts similarity index 100% rename from examples/react/start-basic/app/routes/api/users.ts rename to examples/react/start-basic/src/routes/api/users.ts diff --git a/examples/react/start-basic/app/routes/deferred.tsx b/examples/react/start-basic/src/routes/deferred.tsx similarity index 100% rename from examples/react/start-basic/app/routes/deferred.tsx rename to examples/react/start-basic/src/routes/deferred.tsx diff --git a/examples/react/start-basic/app/routes/index.tsx b/examples/react/start-basic/src/routes/index.tsx similarity index 100% rename from examples/react/start-basic/app/routes/index.tsx rename to examples/react/start-basic/src/routes/index.tsx diff --git a/examples/react/start-basic/app/routes/posts.$postId.tsx b/examples/react/start-basic/src/routes/posts.$postId.tsx similarity index 100% rename from examples/react/start-basic/app/routes/posts.$postId.tsx rename to examples/react/start-basic/src/routes/posts.$postId.tsx diff --git a/examples/react/start-basic/app/routes/posts.index.tsx b/examples/react/start-basic/src/routes/posts.index.tsx similarity index 100% rename from examples/react/start-basic/app/routes/posts.index.tsx rename to examples/react/start-basic/src/routes/posts.index.tsx diff --git a/examples/react/start-basic/src/routes/posts.tsx b/examples/react/start-basic/src/routes/posts.tsx new file mode 100644 index 0000000000..ae49032459 --- /dev/null +++ b/examples/react/start-basic/src/routes/posts.tsx @@ -0,0 +1,38 @@ +import { Link, Outlet, createFileRoute } from '@tanstack/react-router' +import { fetchPosts } from '../utils/posts' + +export const Route = createFileRoute('/posts')({ + loader: async () => fetchPosts(), + component: PostsComponent, +}) + +function PostsComponent() { + const posts = Route.useLoaderData() + + return ( +
+
    + {[...posts, { id: 'i-do-not-exist', title: 'Non-existent Post' }].map( + (post) => { + return ( +
  • + +
    {post.title.substring(0, 20)}
    + +
  • + ) + }, + )} +
+
+ +
+ ) +} diff --git a/examples/react/start-basic/app/routes/posts_.$postId.deep.tsx b/examples/react/start-basic/src/routes/posts_.$postId.deep.tsx similarity index 100% rename from examples/react/start-basic/app/routes/posts_.$postId.deep.tsx rename to examples/react/start-basic/src/routes/posts_.$postId.deep.tsx diff --git a/examples/react/start-basic/app/routes/redirect.tsx b/examples/react/start-basic/src/routes/redirect.tsx similarity index 100% rename from examples/react/start-basic/app/routes/redirect.tsx rename to examples/react/start-basic/src/routes/redirect.tsx diff --git a/examples/react/start-basic/app/routes/users.$userId.tsx b/examples/react/start-basic/src/routes/users.$userId.tsx similarity index 100% rename from examples/react/start-basic/app/routes/users.$userId.tsx rename to examples/react/start-basic/src/routes/users.$userId.tsx diff --git a/examples/react/start-basic/app/routes/users.index.tsx b/examples/react/start-basic/src/routes/users.index.tsx similarity index 100% rename from examples/react/start-basic/app/routes/users.index.tsx rename to examples/react/start-basic/src/routes/users.index.tsx diff --git a/examples/react/start-basic/src/routes/users.tsx b/examples/react/start-basic/src/routes/users.tsx new file mode 100644 index 0000000000..1c51b659d9 --- /dev/null +++ b/examples/react/start-basic/src/routes/users.tsx @@ -0,0 +1,48 @@ +import { Link, Outlet, createFileRoute } from '@tanstack/react-router' +import axios from 'redaxios' +import { DEPLOY_URL } from '../utils/users' +import type { User } from '../utils/users' + +export const Route = createFileRoute('/users')({ + loader: async () => { + return await axios + .get>(DEPLOY_URL + '/api/users') + .then((r) => r.data) + .catch(() => { + throw new Error('Failed to fetch users') + }) + }, + component: UsersComponent, +}) + +function UsersComponent() { + const users = Route.useLoaderData() + + return ( +
+
    + {[ + ...users, + { id: 'i-do-not-exist', name: 'Non-existent User', email: '' }, + ].map((user) => { + return ( +
  • + +
    {user.name}
    + +
  • + ) + })} +
+
+ +
+ ) +} diff --git a/examples/react/start-basic/app/styles/app.css b/examples/react/start-basic/src/styles/app.css similarity index 100% rename from examples/react/start-basic/app/styles/app.css rename to examples/react/start-basic/src/styles/app.css diff --git a/examples/react/start-basic/app/utils/loggingMiddleware.tsx b/examples/react/start-basic/src/utils/loggingMiddleware.tsx similarity index 100% rename from examples/react/start-basic/app/utils/loggingMiddleware.tsx rename to examples/react/start-basic/src/utils/loggingMiddleware.tsx diff --git a/examples/react/start-basic/app/utils/posts.tsx b/examples/react/start-basic/src/utils/posts.tsx similarity index 100% rename from examples/react/start-basic/app/utils/posts.tsx rename to examples/react/start-basic/src/utils/posts.tsx diff --git a/examples/react/start-basic/app/utils/seo.ts b/examples/react/start-basic/src/utils/seo.ts similarity index 100% rename from examples/react/start-basic/app/utils/seo.ts rename to examples/react/start-basic/src/utils/seo.ts diff --git a/examples/react/start-basic/app/utils/users.tsx b/examples/react/start-basic/src/utils/users.tsx similarity index 100% rename from examples/react/start-basic/app/utils/users.tsx rename to examples/react/start-basic/src/utils/users.tsx diff --git a/examples/react/start-basic/tailwind.config.mjs b/examples/react/start-basic/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/examples/react/start-basic/tailwind.config.mjs +++ b/examples/react/start-basic/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/examples/react/start-basic/tsconfig.json b/examples/react/start-basic/tsconfig.json index d1b5b77660..9a7cf62c30 100644 --- a/examples/react/start-basic/tsconfig.json +++ b/examples/react/start-basic/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/examples/react/start-clerk-basic/app/client.tsx b/examples/react/start-clerk-basic/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/examples/react/start-clerk-basic/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/clerk-basic/app/ssr.tsx b/examples/react/start-clerk-basic/app/server.ts similarity index 100% rename from e2e/react-start/clerk-basic/app/ssr.tsx rename to examples/react/start-clerk-basic/app/server.ts diff --git a/examples/react/start-clerk-basic/app/ssr.tsx b/examples/react/start-clerk-basic/app/ssr.tsx deleted file mode 100644 index ef5ba0bc95..0000000000 --- a/examples/react/start-clerk-basic/app/ssr.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' -import { createClerkHandler } from '@clerk/tanstack-start/server' -import { createRouter } from './router' - -const handler = createStartHandler({ - createRouter, - getRouterManifest, -}) - -const clerkHandler = createClerkHandler(handler) - -export default clerkHandler(defaultStreamHandler) diff --git a/examples/react/start-clerk-basic/tailwind.config.mjs b/examples/react/start-clerk-basic/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/examples/react/start-clerk-basic/tailwind.config.mjs +++ b/examples/react/start-clerk-basic/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/examples/react/start-convex-trellaux/app/client.tsx b/examples/react/start-convex-trellaux/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/examples/react/start-convex-trellaux/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/server-functions/app/ssr.tsx b/examples/react/start-convex-trellaux/app/server.ts similarity index 100% rename from e2e/react-start/server-functions/app/ssr.tsx rename to examples/react/start-convex-trellaux/app/server.ts diff --git a/examples/react/start-convex-trellaux/app/ssr.tsx b/examples/react/start-convex-trellaux/app/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/examples/react/start-convex-trellaux/app/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/examples/react/start-convex-trellaux/tailwind.config.mjs b/examples/react/start-convex-trellaux/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/examples/react/start-convex-trellaux/tailwind.config.mjs +++ b/examples/react/start-convex-trellaux/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/examples/react/start-counter/app/client.tsx b/examples/react/start-counter/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/examples/react/start-counter/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/website/app/ssr.tsx b/examples/react/start-counter/app/server.ts similarity index 100% rename from e2e/react-start/website/app/ssr.tsx rename to examples/react/start-counter/app/server.ts diff --git a/examples/react/start-counter/app/ssr.tsx b/examples/react/start-counter/app/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/examples/react/start-counter/app/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/examples/react/start-large/app/client.tsx b/examples/react/start-large/app/client.tsx deleted file mode 100644 index 6ef47afdd4..0000000000 --- a/examples/react/start-large/app/client.tsx +++ /dev/null @@ -1,9 +0,0 @@ -// app/client.tsx - -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/examples/react/start-large/app/ssr.tsx b/examples/react/start-large/app/server.ts similarity index 94% rename from examples/react/start-large/app/ssr.tsx rename to examples/react/start-large/app/server.ts index b25c3c5648..cb5ab731aa 100644 --- a/examples/react/start-large/app/ssr.tsx +++ b/examples/react/start-large/app/server.ts @@ -1,4 +1,4 @@ -// app/ssr.tsx +// src/server.tsx import { createStartHandler, diff --git a/examples/react/start-large/tailwind.config.mjs b/examples/react/start-large/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/examples/react/start-large/tailwind.config.mjs +++ b/examples/react/start-large/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/examples/react/start-supabase-basic/app/client.tsx b/examples/react/start-supabase-basic/app/client.tsx deleted file mode 100644 index 6ef47afdd4..0000000000 --- a/examples/react/start-supabase-basic/app/client.tsx +++ /dev/null @@ -1,9 +0,0 @@ -// app/client.tsx - -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/examples/react/start-supabase-basic/app/ssr.tsx b/examples/react/start-supabase-basic/app/server.ts similarity index 94% rename from examples/react/start-supabase-basic/app/ssr.tsx rename to examples/react/start-supabase-basic/app/server.ts index b25c3c5648..cb5ab731aa 100644 --- a/examples/react/start-supabase-basic/app/ssr.tsx +++ b/examples/react/start-supabase-basic/app/server.ts @@ -1,4 +1,4 @@ -// app/ssr.tsx +// src/server.tsx import { createStartHandler, diff --git a/examples/react/start-supabase-basic/tailwind.config.mjs b/examples/react/start-supabase-basic/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/examples/react/start-supabase-basic/tailwind.config.mjs +++ b/examples/react/start-supabase-basic/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/examples/react/start-trellaux/app/client.tsx b/examples/react/start-trellaux/app/client.tsx deleted file mode 100644 index c5fbaa3c67..0000000000 --- a/examples/react/start-trellaux/app/client.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/examples/react/start-bare/app/ssr.tsx b/examples/react/start-trellaux/app/server.ts similarity index 100% rename from examples/react/start-bare/app/ssr.tsx rename to examples/react/start-trellaux/app/server.ts diff --git a/examples/react/start-trellaux/app/ssr.tsx b/examples/react/start-trellaux/app/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/examples/react/start-trellaux/app/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/examples/react/start-trellaux/tailwind.config.mjs b/examples/react/start-trellaux/tailwind.config.mjs index 07c3598bac..e49f4eb776 100644 --- a/examples/react/start-trellaux/tailwind.config.mjs +++ b/examples/react/start-trellaux/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}'], + content: ['./src/**/*.{js,jsx,ts,tsx}'], } diff --git a/examples/react/with-trpc-react-query/tailwind.config.mjs b/examples/react/with-trpc-react-query/tailwind.config.mjs index 1d2eca8aa7..4986094b9d 100644 --- a/examples/react/with-trpc-react-query/tailwind.config.mjs +++ b/examples/react/with-trpc-react-query/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}', './index.html'], + content: ['./src/**/*.{js,jsx,ts,tsx}', './index.html'], } diff --git a/examples/react/with-trpc/tailwind.config.mjs b/examples/react/with-trpc/tailwind.config.mjs index 1d2eca8aa7..4986094b9d 100644 --- a/examples/react/with-trpc/tailwind.config.mjs +++ b/examples/react/with-trpc/tailwind.config.mjs @@ -1,4 +1,4 @@ /** @type {import('tailwindcss').Config} */ export default { - content: ['./app/**/*.{js,jsx,ts,tsx}', './index.html'], + content: ['./src/**/*.{js,jsx,ts,tsx}', './index.html'], } diff --git a/packages/create-start/src/modules/core/template/app/ssr.tsx b/packages/create-start/src/modules/core/template/app/ssr.tsx deleted file mode 100644 index 017f4efa21..0000000000 --- a/packages/create-start/src/modules/core/template/app/ssr.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-nocheck - -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/packages/react-start-plugin/src/index.ts b/packages/react-start-plugin/src/index.ts index a017bbff15..3ab92a4701 100644 --- a/packages/react-start-plugin/src/index.ts +++ b/packages/react-start-plugin/src/index.ts @@ -1,3 +1,4 @@ +import path from 'node:path' import { TanStackServerFnPluginEnv } from '@tanstack/server-functions-plugin' import { createNitro } from 'nitropack' import { TanStackRouterVite } from '@tanstack/router-plugin/vite' @@ -94,6 +95,49 @@ export function TanStackStartVitePlugin( return config }, + resolveId(id) { + if ( + [ + '/~start/default-server-entry', + '/~start/default-client-entry', + ].includes(id) + ) { + return `${id}.tsx` + } + + return null + }, + load(id) { + const routerImportPath = JSON.stringify( + path.resolve(options.root, options.tsr.srcDirectory, 'router'), + ) + + if (id === '/~start/default-client-entry.tsx') { + return ` +import { hydrateRoot } from 'react-dom/client' +import { StartClient } from '@tanstack/react-start' +import { createRouter } from ${routerImportPath} + +const router = createRouter() + +hydrateRoot(document, ) +` + } + + if (id === '/~start/default-server-entry.tsx') { + console.log('routerImportPath', routerImportPath) + return ` +import { createStartHandler, defaultStreamHandler } from '@tanstack/react-start/server' +import { createRouter } from ${routerImportPath} + +export default createStartHandler({ + createRouter, +})(defaultStreamHandler) +` + } + + return null + }, }, TanStackStartCompilerPlugin(), TanStackServerFnPluginEnv({ diff --git a/packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts b/packages/react-start-plugin/src/nitro/dev-server-plugin.ts similarity index 95% rename from packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts rename to packages/react-start-plugin/src/nitro/dev-server-plugin.ts index 995a9b7a0a..9f6c156b45 100644 --- a/packages/react-start-plugin/src/nitro/plugins/dev-server-plugin.ts +++ b/packages/react-start-plugin/src/nitro/dev-server-plugin.ts @@ -4,7 +4,7 @@ import { createEvent, getHeader, sendWebResponse } from 'h3' import { isRunnableDevEnvironment } from 'vite' import type { Connect, Environment, Plugin, ViteDevServer } from 'vite' -import type { TanStackStartOutputConfig } from '../../schema.js' +import type { TanStackStartOutputConfig } from '../schema.js' export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { // let config: UserConfig @@ -19,7 +19,7 @@ export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { return { resolve: { alias: { - '~start/ssr-entry': options.ssrEntryPath, + '/~start/ssr-entry': options.serverEntryPath, }, }, } @@ -44,7 +44,7 @@ export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { } const serverEntry = - await serverEnv.runner.import('~start/ssr-entry') + await serverEnv.runner.import('/~start/ssr-entry') const response = await serverEntry['default'](event) diff --git a/packages/react-start-plugin/src/nitro/nitro-plugin.ts b/packages/react-start-plugin/src/nitro/nitro-plugin.ts index 7b198e80e8..13af417ecb 100644 --- a/packages/react-start-plugin/src/nitro/nitro-plugin.ts +++ b/packages/react-start-plugin/src/nitro/nitro-plugin.ts @@ -5,7 +5,7 @@ import { getRollupConfig } from 'nitropack/rollup' import { createNitro } from 'nitropack' import { buildSitemap } from './build-sitemap.js' -import { devServerPlugin } from './plugins/dev-server-plugin.js' +import { devServerPlugin } from './dev-server-plugin.js' import type { NitroConfig } from 'nitropack' import type { TanStackStartOutputConfig } from '../schema.js' @@ -36,8 +36,8 @@ export function nitroPlugin( preset: buildPreset, compatibilityDate: '2024-11-19', logLevel: options.server.logLevel || 0, - srcDir: normalizePath(options.tsr.appDirectory), - renderer: filePrefix + normalizePath(options.ssrEntryPath), + srcDir: normalizePath(options.tsr.srcDirectory), + // renderer: filePrefix + normalizePath(options.ssrEntryPath), } const nitro = await createNitro({ diff --git a/packages/react-start-plugin/src/schema.ts b/packages/react-start-plugin/src/schema.ts index e0882a17d4..ac120b642d 100644 --- a/packages/react-start-plugin/src/schema.ts +++ b/packages/react-start-plugin/src/schema.ts @@ -35,7 +35,7 @@ const viteReactSchema = z.custom() const routersSchema = z.object({ ssr: z .object({ - entry: z.string().optional().default('ssr.tsx'), + entry: z.string().optional(), // middleware: z.string().optional(), vite: viteSchema.optional(), }) @@ -43,7 +43,7 @@ const routersSchema = z.object({ .default({}), client: z .object({ - entry: z.string().optional().default('client.tsx'), + entry: z.string().optional(), base: z.string().optional().default('/_build'), vite: viteSchema.optional(), }) @@ -61,15 +61,6 @@ const routersSchema = z.object({ }) .optional() .default({}), - api: z - .object({ - base: z.string().optional().default('/api'), - entry: z.string().optional().default('api.ts'), - // middleware: z.string().optional(), - vite: viteSchema.optional(), - }) - .optional() - .default({}), public: z .object({ dir: z.string().optional().default('public'), @@ -84,8 +75,7 @@ const sitemapSchema = z.object({ }) const tsrConfig = configSchema.partial().extend({ - // Normally these are `./src/___`, but we're using `./app/___` for Start stuff - appDirectory: z.string().optional().default('app'), + srcDirectory: z.string().optional().default('src'), }) const TanStackStartOptionsSchema = z @@ -104,20 +94,38 @@ const TanStackStartOptionsSchema = z export function getTanStackStartOptions(opts?: TanStackStartInputConfig) { const options = TanStackStartOptionsSchema.parse(opts) - const appDirectory = options.tsr.appDirectory + const srcDirectory = options.tsr.srcDirectory + const routesDirectory = - options.tsr.routesDirectory ?? path.join(appDirectory, 'routes') + options.tsr.routesDirectory ?? path.join(srcDirectory, 'routes') + const generatedRouteTree = options.tsr.generatedRouteTree ?? - path.join(appDirectory, 'routeTree.gen.ts') - const clientEntryPath = path.join(appDirectory, options.routers.client.entry) - const ssrEntryPath = path.join(appDirectory, options.routers.ssr.entry) - const apiEntryPath = path.join(appDirectory, options.routers.api.entry) - const globalMiddlewareEntryPath = path.join( - appDirectory, - options.routers.server.globalMiddlewareEntry, - ) - const hasApiEntry = existsSync(apiEntryPath) + path.join(srcDirectory, 'routeTree.gen.ts') + + const clientEntryPath = (() => { + if (options.routers.client.entry) { + return path.join(srcDirectory, options.routers.client.entry) + } + + if (existsSync(path.join(srcDirectory, 'client.tsx'))) { + return path.join(srcDirectory, 'client.tsx') + } + + return '/~start/default-client-entry' + })() + + const serverEntryPath = (() => { + if (options.routers.ssr.entry) { + return path.join(srcDirectory, options.routers.ssr.entry) + } + + if (existsSync(path.join(srcDirectory, 'server.tsx'))) { + return path.join(srcDirectory, 'server.tsx') + } + + return '/~start/default-server-entry' + })() return { ...options, @@ -130,10 +138,7 @@ export function getTanStackStartOptions(opts?: TanStackStartInputConfig) { }), }, clientEntryPath, - ssrEntryPath, - apiEntryPath, - globalMiddlewareEntryPath, - hasApiEntry, + serverEntryPath, } } diff --git a/packages/react-start-server/src/createStartHandler.ts b/packages/react-start-server/src/createStartHandler.ts index 90172fe71e..60c6a28638 100644 --- a/packages/react-start-server/src/createStartHandler.ts +++ b/packages/react-start-server/src/createStartHandler.ts @@ -35,12 +35,21 @@ export function createStartHandler< ) } + // Handle server functions if ( href.startsWith(path.join('/', process.env.TSS_SERVER_FN_BASE, '/')) ) { return await serverFunctionsHandler(event) } + // Handle API routes + // handleApiRoutes(event) + // if (event.handled) { + // return + // } + + // If no API routes returned, then fallback to SSR on the router + // Create a history for the router const history = createMemoryHistory({ initialEntries: [href], diff --git a/packages/react-start-server/src/h3.ts b/packages/react-start-server/src/h3.ts index b58ba1e10a..8e7dbc049c 100644 --- a/packages/react-start-server/src/h3.ts +++ b/packages/react-start-server/src/h3.ts @@ -13,6 +13,7 @@ import { defaultContentType as _defaultContentType, defineEventHandler as _defineEventHandler, deleteCookie as _deleteCookie, + eventHandler as _eventHandler, fetchWithEvent as _fetchWithEvent, getCookie as _getCookie, getHeader as _getHeader, @@ -151,7 +152,6 @@ export { defineResponseMiddleware, dynamicEventHandler, defineWebSocket, - eventHandler, splitCookiesString, fromNodeMiddleware, fromPlainHandler, @@ -230,6 +230,12 @@ export function defineEventHandler(handler: EventHandler) { }) } +export function eventHandler(handler: EventHandler) { + return _eventHandler((event) => { + return runWithEvent(event, () => handler(event)) + }) +} + export async function runWithEvent( event: H3Event, fn: () => T | Promise, diff --git a/packages/react-start-server/src/router-manifest.ts b/packages/react-start-server/src/router-manifest.ts index 03c4f3fb2a..44e851527d 100644 --- a/packages/react-start-server/src/router-manifest.ts +++ b/packages/react-start-server/src/router-manifest.ts @@ -61,7 +61,7 @@ export function getStartManifest() { async: true, }, children: `${script};\nimport(${JSON.stringify( - path.join('/', process.env.TSS_CLIENT_ENTRY), + process.env.TSS_CLIENT_ENTRY, )})`, }) From 1c5acbbb782d716870d54f81764abb9b6a933416 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Fri, 7 Mar 2025 23:17:55 -0700 Subject: [PATCH 026/155] rename app to src --- .../{app => src}/components/Auth.tsx | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/Login.tsx | 2 +- .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/hooks/useMutation.ts | 0 .../basic-auth/{app => src}/routeTree.gen.ts | 0 .../basic-auth/{app => src}/router.tsx | 0 .../basic-auth/{app => src}/routes/__root.tsx | 8 +- .../{app => src}/routes/_authed.tsx | 6 +- .../src}/routes/_authed/posts.$postId.tsx | 4 +- .../routes/_authed/posts.index.tsx | 0 .../{app => src}/routes/_authed/posts.tsx | 2 +- .../basic-auth/{app => src}/routes/index.tsx | 0 .../basic-auth/{app => src}/routes/login.tsx | 2 +- .../basic-auth/{app => src}/routes/logout.tsx | 2 +- .../basic-auth/{app => src}/routes/signup.tsx | 8 +- .../basic-auth/{app => src}/styles/app.css | 0 .../basic-auth/{app => src}/utils/posts.ts | 0 .../basic-auth/{app => src}/utils/prisma.ts | 0 .../basic-auth/{app => src}/utils/seo.ts | 0 .../basic-auth/{app => src}/utils/session.ts | 0 e2e/react-start/basic-auth/tsconfig.json | 2 +- .../basic-react-query/{app => src}/api.ts | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/routeTree.gen.ts | 0 .../basic-react-query/{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 6 +- .../{app => src}/routes/_layout.tsx | 0 .../{app => src}/routes/_layout/_layout-2.tsx | 0 .../routes/_layout/_layout-2/layout-a.tsx | 0 .../routes/_layout/_layout-2/layout-b.tsx | 0 .../{app => src}/routes/api.users.ts | 0 .../{app => src}/routes/api/users.$id.ts | 0 .../{app => src}/routes/deferred.tsx | 0 .../{app => src}/routes/index.tsx | 0 .../{app => src}/routes/posts.$postId.tsx | 4 +- .../{app => src}/routes/posts.index.tsx | 0 .../{app => src}/routes/posts.tsx | 2 +- .../routes/posts_.$postId.deep.tsx | 0 .../{app => src}/routes/redirect.tsx | 0 .../{app => src}/routes/users.$userId.tsx | 4 +- .../{app => src}/routes/users.index.tsx | 0 .../{app => src}/routes/users.tsx | 2 +- .../{app => src}/styles/app.css | 0 .../{app => src}/utils/posts.tsx | 0 .../{app => src}/utils/seo.ts | 0 .../{app => src}/utils/users.tsx | 0 .../basic-react-query/tsconfig.json | 2 +- .../src/{app => }/routeTree.gen.ts | 0 .../basic-tsr-config/src/{app => }/router.tsx | 0 .../src/{app => }/routes/__root.tsx | 0 .../src/{app => }/routes/index.tsx | 0 e2e/react-start/basic/{app => src}/api.ts | 0 .../{app => src}/components/CustomMessage.tsx | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../components/RedirectOnClick.tsx | 0 .../{app => src}/components/throwRedirect.ts | 0 .../basic/{app => src}/routeTree.gen.ts | 0 e2e/react-start/basic/{app => src}/router.tsx | 0 .../basic/{app => src}/routes/__root.tsx | 6 +- .../basic/{app => src}/routes/_layout.tsx | 0 .../{app => src}/routes/_layout/_layout-2.tsx | 0 .../routes/_layout/_layout-2/layout-a.tsx | 0 .../routes/_layout/_layout-2/layout-b.tsx | 0 .../basic/{app => src}/routes/api.users.ts | 0 .../{app => src}/routes/api/users.$id.ts | 0 .../basic/{app => src}/routes/deferred.tsx | 0 .../basic/{app => src}/routes/index.tsx | 2 +- .../basic/{app => src}/routes/links.tsx | 0 .../{app => src}/routes/not-found/index.tsx | 0 .../{app => src}/routes/not-found/route.tsx | 0 .../routes/not-found/via-beforeLoad.tsx | 0 .../routes/not-found/via-loader.tsx | 0 .../{app => src}/routes/posts.$postId.tsx | 4 +- .../basic/{app => src}/routes/posts.index.tsx | 0 .../basic/{app => src}/routes/posts.tsx | 2 +- .../routes/posts_.$postId.deep.tsx | 0 .../{app => src}/routes/redirect/$target.tsx | 0 .../routes/redirect/$target/index.tsx | 0 .../redirect/$target/serverFn/index.tsx | 0 .../$target/serverFn/via-beforeLoad.tsx | 0 .../redirect/$target/serverFn/via-loader.tsx | 0 .../$target/serverFn/via-useServerFn.tsx | 0 .../redirect/$target/via-beforeLoad.tsx | 0 .../routes/redirect/$target/via-loader.tsx | 0 .../{app => src}/routes/redirect/index.tsx | 0 .../basic/{app => src}/routes/scripts.tsx | 0 .../{app => src}/routes/search-params.tsx | 0 .../basic/{app => src}/routes/stream.tsx | 0 .../{app => src}/routes/users.$userId.tsx | 6 +- .../basic/{app => src}/routes/users.index.tsx | 0 .../basic/{app => src}/routes/users.tsx | 4 +- .../basic/{app => src}/styles/app.css | 0 .../basic/{app => src}/utils/posts.tsx | 0 .../basic/{app => src}/utils/seo.ts | 0 .../basic/{app => src}/utils/users.tsx | 0 e2e/react-start/basic/tsconfig.json | 2 +- .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../clerk-basic/{app => src}/routeTree.gen.ts | 0 .../clerk-basic/{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 4 +- .../{app => src}/routes/_authed.tsx | 0 .../src}/routes/_authed/posts.$postId.tsx | 4 +- .../routes/_authed/posts.index.tsx | 0 .../{app => src}/routes/_authed/posts.tsx | 2 +- .../{app => src}/routes/_authed/profile.$.tsx | 2 +- .../clerk-basic/{app => src}/routes/index.tsx | 0 .../clerk-basic/{app => src}/server.tsx | 0 .../clerk-basic/{app => src}/styles/app.css | 0 .../clerk-basic/{app => src}/utils/posts.ts | 0 .../clerk-basic/{app => src}/utils/seo.ts | 0 e2e/react-start/clerk-basic/tsconfig.json | 2 +- .../scroll-restoration/{app => src}/api.ts | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/routeTree.gen.ts | 0 .../{app => src}/router.tsx | 0 .../routes/(tests)/normal-page.tsx | 0 .../routes/(tests)/with-loader.tsx | 2 +- .../routes/(tests)/with-search.tsx | 0 .../routes/-components/scroll-block.tsx | 0 .../{app => src}/routes/__root.tsx | 8 +- .../{app => src}/routes/index.tsx | 0 .../{app => src}/styles/app.css | 0 .../{app => src}/utils/posts.tsx | 0 .../{app => src}/utils/seo.ts | 0 .../{app => src}/utils/users.tsx | 0 .../scroll-restoration/tsconfig.json | 2 +- .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/routeTree.gen.ts | 0 .../server-functions/{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 0 .../{app => src}/routes/abort-signal.tsx | 0 .../{app => src}/routes/consistent.tsx | 0 .../{app => src}/routes/cookies/index.tsx | 0 .../{app => src}/routes/cookies/set.tsx | 0 .../routes/dead-code-preserve.tsx | 0 .../{app => src}/routes/env-only.tsx | 0 .../{app => src}/routes/headers.tsx | 0 .../{app => src}/routes/index.tsx | 0 .../{app => src}/routes/isomorphic-fns.tsx | 0 .../{app => src}/routes/multipart.tsx | 0 .../{app => src}/routes/raw-response.tsx | 0 .../{app => src}/routes/return-null.tsx | 0 .../routes/serialize-form-data.tsx | 0 .../{app => src}/routes/status.tsx | 0 .../routes/submit-post-formdata.tsx | 0 .../{app => src}/styles/app.css | 0 .../basic-tsr-config/src}/client.tsx | 2 +- .../src/{app => }/routeTree.gen.ts | 2 +- .../basic-tsr-config/src/{app => }/router.tsx | 2 +- .../src/{app => }/routes/__root.tsx | 0 .../src/{app => }/routes/index.tsx | 0 .../app => basic-tsr-config/src}/ssr.tsx | 2 +- .../scroll-restoration/{app => src}/api.ts | 0 .../app => scroll-restoration/src}/client.tsx | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/routeTree.gen.ts | 0 .../{app => src}/router.tsx | 0 .../routes/(tests)/normal-page.tsx | 0 .../routes/(tests)/with-loader.tsx | 0 .../routes/(tests)/with-search.tsx | 0 .../routes/-components/scroll-block.tsx | 0 .../{app => src}/routes/__root.tsx | 6 +- .../{app => src}/routes/index.tsx | 0 .../scroll-restoration/{app => src}/ssr.tsx | 0 .../{app => src}/styles/app.css | 0 .../{app => src}/utils/posts.tsx | 0 .../{app => src}/utils/seo.ts | 0 .../{app => src}/utils/users.tsx | 0 .../scroll-restoration/tsconfig.json | 2 +- .../app => server-functions/src}/client.tsx | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/routeTree.gen.ts | 0 .../server-functions/{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 4 +- .../{app => src}/routes/abort-signal.tsx | 0 .../{app => src}/routes/consistent.tsx | 0 .../{app => src}/routes/cookies/index.tsx | 0 .../{app => src}/routes/cookies/set.tsx | 0 .../routes/dead-code-preserve.tsx | 0 .../{app => src}/routes/env-only.tsx | 0 .../{app => src}/routes/headers.tsx | 0 .../{app => src}/routes/index.tsx | 0 .../{app => src}/routes/isomorphic-fns.tsx | 0 .../{app => src}/routes/multipart.tsx | 0 .../{app => src}/routes/raw-response.tsx | 0 .../{app => src}/routes/return-null.tsx | 0 .../routes/serialize-form-data.tsx | 0 .../{app => src}/routes/status.tsx | 0 .../routes/submit-post-formdata.tsx | 0 .../server-functions/{app => src}/ssr.tsx | 0 .../{app => src}/styles/app.css | 0 .../server-functions/tsconfig.json | 2 +- .../app => website/src}/client.tsx | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../website/{app => src}/routeTree.gen.ts | 0 .../website/{app => src}/router.tsx | 0 ...t.$version.docs.framework.$framework.$.tsx | 0 ...n.docs.framework.$framework.examples.$.tsx | 0 ...ersion.docs.framework.$framework.index.tsx | 0 ...ect.$version.docs.framework.$framework.tsx | 0 .../routes/$project.$version.docs.index.tsx | 0 .../{app => src}/routes/$project.index.tsx | 0 .../website/{app => src}/routes/__root.tsx | 4 +- .../_library.$project.$version.index.tsx | 0 .../{app => src}/routes/_library.$project.tsx | 4 +- .../{app => src}/routes/_library.index.tsx | 0 .../website/{app => src}/routes/_library.tsx | 2 +- .../website/{app => src}/server/document.tsx | 0 .../website/{app => src}/server/projects.tsx | 0 .../src/app => website/src}/ssr.tsx | 0 .../website/{app => src}/styles/app.css | 0 .../website/{app => src}/utils/seo.ts | 0 e2e/solid-start/website/tsconfig.json | 2 +- examples/react/start-bare/{app => src}/api.ts | 0 .../{app => src}/components/Counter.css | 0 .../{app => src}/components/Counter.tsx | 0 .../start-bare/{app => src}/routeTree.gen.ts | 0 .../react/start-bare/{app => src}/router.tsx | 0 .../start-bare/{app => src}/routes/__root.tsx | 0 .../start-bare/{app => src}/routes/about.tsx | 0 .../start-bare/{app => src}/routes/index.tsx | 2 +- .../start-bare/{app => src}/styles/app.css | 0 examples/react/start-bare/tsconfig.json | 2 +- .../{app => src}/components/Auth.tsx | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/Login.tsx | 2 +- .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/hooks/useMutation.ts | 0 .../{app => src}/routeTree.gen.ts | 0 .../start-basic-auth/{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 8 +- .../{app => src}/routes/_authed.tsx | 6 +- .../src}/routes/_authed/posts.$postId.tsx | 4 +- .../routes/_authed/posts.index.tsx | 0 .../routes/_authed/posts.route.tsx | 2 +- .../{app => src}/routes/index.tsx | 0 .../{app => src}/routes/login.tsx | 2 +- .../{app => src}/routes/logout.tsx | 2 +- .../{app => src}/routes/signup.tsx | 8 +- .../app => start-basic-auth/src}/server.ts | 0 .../{app => src}/styles/app.css | 0 .../{app => src}/utils/posts.ts | 0 .../{app => src}/utils/prisma.ts | 0 .../{app => src}/utils/seo.ts | 0 .../{app => src}/utils/session.ts | 0 examples/react/start-basic-auth/tsconfig.json | 2 +- .../{app => src}/api.ts | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/routeTree.gen.ts | 0 .../{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 0 .../{app => src}/routes/_pathlessLayout.tsx | 0 .../routes/_pathlessLayout/_nested-layout.tsx | 0 .../_nested-layout/route-a.tsx | 0 .../_nested-layout/route-b.tsx | 0 .../{app => src}/routes/api.users.ts | 0 .../{app => src}/routes/api/users.$id.ts | 0 .../{app => src}/routes/deferred.tsx | 0 .../{app => src}/routes/index.tsx | 0 .../{app => src}/routes/posts.$postId.tsx | 0 .../{app => src}/routes/posts.index.tsx | 0 .../{app => src}/routes/posts.route.tsx | 0 .../routes/posts_.$postId.deep.tsx | 0 .../{app => src}/routes/redirect.tsx | 0 .../{app => src}/routes/users.$userId.tsx | 0 .../{app => src}/routes/users.index.tsx | 0 .../{app => src}/routes/users.route.tsx | 0 .../src}/server.ts | 0 .../{app => src}/styles/app.css | 0 .../{app => src}/utils/posts.tsx | 0 .../{app => src}/utils/seo.ts | 0 .../{app => src}/utils/users.tsx | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/routeTree.gen.ts | 0 .../start-basic-rsc/{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 6 +- .../{app => src}/routes/_pathlessLayout.tsx | 0 .../routes/_pathlessLayout/_nested-layout.tsx | 0 .../_nested-layout/route-a.tsx | 0 .../_nested-layout/route-b.tsx | 0 .../{app => src}/routes/index.tsx | 0 .../{app => src}/routes/posts.$postId.tsx | 2 +- .../{app => src}/routes/posts.index.tsx | 0 .../{app => src}/routes/posts.tsx | 2 +- .../routes/posts_.$postId.deep.tsx | 0 .../app => start-basic-rsc/src}/server.ts | 0 .../{app => src}/styles/app.css | 0 .../{app => src}/utils/posts.tsx | 0 .../{app => src}/utils/renderPosts.tsx | 0 .../start-basic-rsc/{app => src}/utils/seo.ts | 0 examples/react/start-basic-rsc/tsconfig.json | 2 +- .../start-basic-static/app/routes/__root.tsx | 139 ----- .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/routeTree.gen.ts | 0 .../{app => src}/router.tsx | 0 .../src}/routes/__root.tsx | 6 +- .../{app => src}/routes/_pathlessLayout.tsx | 0 .../routes/_pathlessLayout/_nested-layout.tsx | 0 .../_nested-layout/route-a.tsx | 0 .../_nested-layout/route-b.tsx | 0 .../{app => src}/routes/deferred.tsx | 0 .../{app => src}/routes/index.tsx | 0 .../{app => src}/routes/posts.$postId.tsx | 2 +- .../{app => src}/routes/posts.index.tsx | 0 .../{app => src}/routes/posts.tsx | 0 .../routes/posts_.$postId.deep.tsx | 0 .../{app => src}/routes/redirect.tsx | 0 .../{app => src}/routes/users.$userId.tsx | 4 +- .../{app => src}/routes/users.index.tsx | 0 .../{app => src}/routes/users.tsx | 0 .../app => start-basic-static/src}/server.ts | 0 .../{app => src}/styles/app.css | 0 .../{app => src}/utils/loggingMiddleware.tsx | 0 .../{app => src}/utils/posts.tsx | 0 .../{app => src}/utils/seo.ts | 0 .../{app => src}/utils/users.tsx | 0 .../react/start-basic-static/tsconfig.json | 2 +- .../react/start-basic/app/routeTree.gen.ts | 479 ------------------ .../react/start-basic/src/routeTree.gen.ts | 270 ++++++---- .../react/start-basic/src/routes/__root.tsx | 10 +- .../src/routes/_layout/_layout-2.tsx | 34 -- .../src/routes/_layout/_layout-2/layout-a.tsx | 9 - .../src/routes/_layout/_layout-2/layout-b.tsx | 9 - .../{app => src}/routes/_pathlessLayout.tsx | 0 .../routes/_pathlessLayout/_nested-layout.tsx | 0 .../_nested-layout/route-a.tsx | 0 .../_nested-layout/route-b.tsx | 0 .../{app => src}/routes/posts.route.tsx | 0 .../{app => src}/routes/users.route.tsx | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/routeTree.gen.ts | 0 .../start-clerk-basic/{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 4 +- .../{app => src}/routes/_authed.tsx | 0 .../src}/routes/_authed/posts.$postId.tsx | 4 +- .../routes/_authed/posts.index.tsx | 0 .../{app => src}/routes/_authed/posts.tsx | 2 +- .../{app => src}/routes/_authed/profile.$.tsx | 2 +- .../{app => src}/routes/index.tsx | 0 .../start-clerk-basic/{app => src}/server.ts | 0 .../{app => src}/styles/app.css | 0 .../{app => src}/utils/posts.ts | 0 .../{app => src}/utils/seo.ts | 0 .../react/start-clerk-basic/tsconfig.json | 2 +- .../{app => src}/components/Board.tsx | 0 .../{app => src}/components/CancelButton.tsx | 0 .../{app => src}/components/Card.tsx | 0 .../{app => src}/components/Column.tsx | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/EditableText.tsx | 0 .../{app => src}/components/IconLink.tsx | 0 .../{app => src}/components/Loader.tsx | 0 .../{app => src}/components/NewCard.tsx | 0 .../{app => src}/components/NewColumn.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/components/SaveButton.tsx | 0 .../{app => src}/db/schema.ts | 0 .../hooks/useOfflineIndicator.tsx | 0 .../{app => src}/icons/icons.svg | 0 .../{app => src}/icons/icons.tsx | 0 .../{app => src}/queries.ts | 0 .../{app => src}/routeTree.gen.ts | 0 .../{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 0 .../{app => src}/routes/boards.$boardId.tsx | 0 .../{app => src}/routes/index.tsx | 0 .../src}/server.ts | 0 .../{app => src}/styles/app.css | 0 .../{app => src}/types.ts | 0 .../{app => src}/utils/posts.tsx | 0 .../{app => src}/utils/seo.ts | 0 .../{app => src}/routeTree.gen.ts | 0 .../start-counter/{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 0 .../{app => src}/routes/index.tsx | 0 .../app => start-counter/src}/server.ts | 0 .../start-large/{app => src}/createRoutes.mjs | 0 .../start-large/{app => src}/routeTree.gen.ts | 0 .../react/start-large/{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 0 .../{app => src}/routes/absolute.tsx | 0 .../start-large/{app => src}/routes/index.tsx | 0 .../{app => src}/routes/linkProps.tsx | 2 +- .../routes/params/$paramsPlaceholder.tsx | 0 .../{app => src}/routes/params/route.tsx | 0 .../{app => src}/routes/relative.tsx | 0 .../{app => src}/routes/search/route.tsx | 0 .../routes/search/searchPlaceholder.tsx | 0 .../react/start-large/{app => src}/server.ts | 0 .../react/start-large/{app => src}/styles.css | 0 .../{app => src}/typePrimitives.tsx | 0 examples/react/start-large/tsconfig.json | 2 +- .../start-material-ui/{app => src}/client.tsx | 0 .../{app => src}/components/Counter.tsx | 2 +- .../components/CustomButtonLink.tsx | 0 .../{app => src}/components/CustomLink.tsx | 0 .../{app => src}/components/Header.tsx | 0 .../{app => src}/routeTree.gen.ts | 0 .../start-material-ui/{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 4 +- .../{app => src}/routes/about.tsx | 0 .../{app => src}/routes/index.tsx | 2 +- .../{app => src}/setup/theme.ts | 0 .../start-material-ui/{app => src}/ssr.tsx | 0 .../react/start-material-ui/tsconfig.json | 2 +- .../{app => src}/components/Auth.tsx | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/Login.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/hooks/useMutation.ts | 0 .../{app => src}/routeTree.gen.ts | 0 .../{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 0 .../{app => src}/routes/_authed.tsx | 0 .../routes/_authed/posts.$postId.tsx | 4 +- .../routes/_authed/posts.index.tsx | 0 .../{app => src}/routes/_authed/posts.tsx | 0 .../{app => src}/routes/index.tsx | 0 .../{app => src}/routes/login.tsx | 0 .../{app => src}/routes/logout.tsx | 0 .../{app => src}/routes/signup.tsx | 0 .../{app => src}/server.ts | 0 .../{app => src}/styles/app.css | 0 .../{app => src}/utils/posts.ts | 0 .../{app => src}/utils/seo.ts | 0 .../{app => src}/utils/supabase.ts | 0 .../react/start-supabase-basic/tsconfig.json | 2 +- examples/react/start-trellaux/app/server.ts | 12 - .../{app => src}/assets/react.svg | 0 .../{app => src}/components/Board.tsx | 0 .../{app => src}/components/CancelButton.tsx | 0 .../{app => src}/components/Card.tsx | 0 .../{app => src}/components/Column.tsx | 0 .../components/DefaultCatchBoundary.tsx | 0 .../{app => src}/components/EditableText.tsx | 0 .../{app => src}/components/IconLink.tsx | 0 .../{app => src}/components/Loader.tsx | 0 .../{app => src}/components/NewCard.tsx | 0 .../{app => src}/components/NewColumn.tsx | 0 .../{app => src}/components/NotFound.tsx | 0 .../{app => src}/components/SaveButton.tsx | 0 .../start-trellaux/{app => src}/db/board.ts | 0 .../start-trellaux/{app => src}/db/schema.ts | 0 .../hooks/useOfflineIndicator.tsx | 0 .../{app => src}/icons/icons.svg | 0 .../{app => src}/icons/icons.tsx | 0 .../start-trellaux/{app => src}/queries.ts | 0 .../{app => src}/routeTree.gen.ts | 0 .../start-trellaux/{app => src}/router.tsx | 0 .../{app => src}/routes/__root.tsx | 0 .../{app => src}/routes/boards.$boardId.tsx | 0 .../{app => src}/routes/index.tsx | 0 .../app => start-trellaux/src}/server.ts | 0 .../{app => src}/styles/app.css | 0 .../start-trellaux/{app => src}/types.ts | 0 .../{app => src}/utils/posts.tsx | 0 .../start-trellaux/{app => src}/utils/seo.ts | 0 .../{app => src}/main.tsx | 0 .../{app => src}/routeTree.gen.ts | 0 .../{app => src}/router.tsx | 0 .../routes/-components/spinner.tsx | 0 .../{app => src}/routes/__root.tsx | 0 .../{app => src}/routes/dashboard.index.tsx | 0 .../routes/dashboard.posts.$postId.tsx | 0 .../routes/dashboard.posts.index.tsx | 0 .../{app => src}/routes/dashboard.posts.tsx | 0 .../{app => src}/routes/dashboard.tsx | 0 .../{app => src}/routes/index.tsx | 0 .../{app => src}/styles.css | 0 .../react/with-trpc/{app => src}/main.tsx | 0 .../with-trpc/{app => src}/routeTree.gen.ts | 0 .../routes/-components/spinner.tsx | 0 .../with-trpc/{app => src}/routes/__root.tsx | 0 .../{app => src}/routes/dashboard.index.tsx | 0 .../routes/dashboard.posts.$postId.tsx | 0 .../routes/dashboard.posts.index.tsx | 0 .../{app => src}/routes/dashboard.posts.tsx | 0 .../{app => src}/routes/dashboard.tsx | 0 .../with-trpc/{app => src}/routes/index.tsx | 0 .../react/with-trpc/{app => src}/styles.css | 0 examples/react/with-trpc/{app => src}/trpc.ts | 0 .../solid/start-bare/src}/client.tsx | 0 .../{app => src}/components/Counter.css | 0 .../{app => src}/components/Counter.tsx | 0 .../start-bare/{app => src}/routeTree.gen.ts | 0 .../solid/start-bare/{app => src}/router.tsx | 0 .../start-bare/{app => src}/routes/__root.tsx | 0 .../start-bare/{app => src}/routes/about.tsx | 0 .../start-bare/{app => src}/routes/index.tsx | 2 +- .../solid/start-bare/{app => src}/ssr.tsx | 0 .../start-bare/{app => src}/styles/app.css | 0 examples/solid/start-bare/tsconfig.json | 2 +- .../core/template/{app => src}/client.tsx | 0 .../core/template/{app => src}/router.tsx | 0 .../template/{app => src}/routes/__root.tsx | 0 508 files changed, 296 insertions(+), 912 deletions(-) rename e2e/react-start/basic-auth/{app => src}/components/Auth.tsx (100%) rename e2e/react-start/basic-auth/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename e2e/react-start/basic-auth/{app => src}/components/Login.tsx (97%) rename e2e/react-start/basic-auth/{app => src}/components/NotFound.tsx (100%) rename e2e/react-start/basic-auth/{app => src}/hooks/useMutation.ts (100%) rename e2e/react-start/basic-auth/{app => src}/routeTree.gen.ts (100%) rename e2e/react-start/basic-auth/{app => src}/router.tsx (100%) rename e2e/react-start/basic-auth/{app => src}/routes/__root.tsx (93%) rename e2e/react-start/basic-auth/{app => src}/routes/_authed.tsx (89%) rename e2e/react-start/{clerk-basic/app => basic-auth/src}/routes/_authed/posts.$postId.tsx (88%) rename e2e/react-start/basic-auth/{app => src}/routes/_authed/posts.index.tsx (100%) rename e2e/react-start/basic-auth/{app => src}/routes/_authed/posts.tsx (95%) rename e2e/react-start/basic-auth/{app => src}/routes/index.tsx (100%) rename e2e/react-start/basic-auth/{app => src}/routes/login.tsx (80%) rename e2e/react-start/basic-auth/{app => src}/routes/logout.tsx (88%) rename e2e/react-start/basic-auth/{app => src}/routes/signup.tsx (91%) rename e2e/react-start/basic-auth/{app => src}/styles/app.css (100%) rename e2e/react-start/basic-auth/{app => src}/utils/posts.ts (100%) rename e2e/react-start/basic-auth/{app => src}/utils/prisma.ts (100%) rename e2e/react-start/basic-auth/{app => src}/utils/seo.ts (100%) rename e2e/react-start/basic-auth/{app => src}/utils/session.ts (100%) rename e2e/react-start/basic-react-query/{app => src}/api.ts (100%) rename e2e/react-start/basic-react-query/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/components/NotFound.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/routeTree.gen.ts (100%) rename e2e/react-start/basic-react-query/{app => src}/router.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/routes/__root.tsx (95%) rename e2e/react-start/basic-react-query/{app => src}/routes/_layout.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/routes/_layout/_layout-2.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/routes/_layout/_layout-2/layout-a.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/routes/_layout/_layout-2/layout-b.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/routes/api.users.ts (100%) rename e2e/react-start/basic-react-query/{app => src}/routes/api/users.$id.ts (100%) rename e2e/react-start/basic-react-query/{app => src}/routes/deferred.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/routes/index.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/routes/posts.$postId.tsx (93%) rename e2e/react-start/basic-react-query/{app => src}/routes/posts.index.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/routes/posts.tsx (95%) rename e2e/react-start/basic-react-query/{app => src}/routes/posts_.$postId.deep.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/routes/redirect.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/routes/users.$userId.tsx (90%) rename e2e/react-start/basic-react-query/{app => src}/routes/users.index.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/routes/users.tsx (95%) rename e2e/react-start/basic-react-query/{app => src}/styles/app.css (100%) rename e2e/react-start/basic-react-query/{app => src}/utils/posts.tsx (100%) rename e2e/react-start/basic-react-query/{app => src}/utils/seo.ts (100%) rename e2e/react-start/basic-react-query/{app => src}/utils/users.tsx (100%) rename e2e/react-start/basic-tsr-config/src/{app => }/routeTree.gen.ts (100%) rename e2e/react-start/basic-tsr-config/src/{app => }/router.tsx (100%) rename e2e/react-start/basic-tsr-config/src/{app => }/routes/__root.tsx (100%) rename e2e/react-start/basic-tsr-config/src/{app => }/routes/index.tsx (100%) rename e2e/react-start/basic/{app => src}/api.ts (100%) rename e2e/react-start/basic/{app => src}/components/CustomMessage.tsx (100%) rename e2e/react-start/basic/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename e2e/react-start/basic/{app => src}/components/NotFound.tsx (100%) rename e2e/react-start/basic/{app => src}/components/RedirectOnClick.tsx (100%) rename e2e/react-start/basic/{app => src}/components/throwRedirect.ts (100%) rename e2e/react-start/basic/{app => src}/routeTree.gen.ts (100%) rename e2e/react-start/basic/{app => src}/router.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/__root.tsx (95%) rename e2e/react-start/basic/{app => src}/routes/_layout.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/_layout/_layout-2.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/_layout/_layout-2/layout-a.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/_layout/_layout-2/layout-b.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/api.users.ts (100%) rename e2e/react-start/basic/{app => src}/routes/api/users.$id.ts (100%) rename e2e/react-start/basic/{app => src}/routes/deferred.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/index.tsx (82%) rename e2e/react-start/basic/{app => src}/routes/links.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/not-found/index.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/not-found/route.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/not-found/via-beforeLoad.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/not-found/via-loader.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/posts.$postId.tsx (91%) rename e2e/react-start/basic/{app => src}/routes/posts.index.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/posts.tsx (96%) rename e2e/react-start/basic/{app => src}/routes/posts_.$postId.deep.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/redirect/$target.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/redirect/$target/index.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/redirect/$target/serverFn/index.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/redirect/$target/serverFn/via-beforeLoad.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/redirect/$target/serverFn/via-loader.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/redirect/$target/serverFn/via-useServerFn.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/redirect/$target/via-beforeLoad.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/redirect/$target/via-loader.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/redirect/index.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/scripts.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/search-params.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/stream.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/users.$userId.tsx (87%) rename e2e/react-start/basic/{app => src}/routes/users.index.tsx (100%) rename e2e/react-start/basic/{app => src}/routes/users.tsx (93%) rename e2e/react-start/basic/{app => src}/styles/app.css (100%) rename e2e/react-start/basic/{app => src}/utils/posts.tsx (100%) rename e2e/react-start/basic/{app => src}/utils/seo.ts (100%) rename e2e/react-start/basic/{app => src}/utils/users.tsx (100%) rename e2e/react-start/clerk-basic/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename e2e/react-start/clerk-basic/{app => src}/components/NotFound.tsx (100%) rename e2e/react-start/clerk-basic/{app => src}/routeTree.gen.ts (100%) rename e2e/react-start/clerk-basic/{app => src}/router.tsx (100%) rename e2e/react-start/clerk-basic/{app => src}/routes/__root.tsx (95%) rename e2e/react-start/clerk-basic/{app => src}/routes/_authed.tsx (100%) rename e2e/react-start/{basic-auth/app => clerk-basic/src}/routes/_authed/posts.$postId.tsx (88%) rename e2e/react-start/clerk-basic/{app => src}/routes/_authed/posts.index.tsx (100%) rename e2e/react-start/clerk-basic/{app => src}/routes/_authed/posts.tsx (95%) rename e2e/react-start/clerk-basic/{app => src}/routes/_authed/profile.$.tsx (95%) rename e2e/react-start/clerk-basic/{app => src}/routes/index.tsx (100%) rename e2e/react-start/clerk-basic/{app => src}/server.tsx (100%) rename e2e/react-start/clerk-basic/{app => src}/styles/app.css (100%) rename e2e/react-start/clerk-basic/{app => src}/utils/posts.ts (100%) rename e2e/react-start/clerk-basic/{app => src}/utils/seo.ts (100%) rename e2e/react-start/scroll-restoration/{app => src}/api.ts (100%) rename e2e/react-start/scroll-restoration/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename e2e/react-start/scroll-restoration/{app => src}/components/NotFound.tsx (100%) rename e2e/react-start/scroll-restoration/{app => src}/routeTree.gen.ts (100%) rename e2e/react-start/scroll-restoration/{app => src}/router.tsx (100%) rename e2e/react-start/scroll-restoration/{app => src}/routes/(tests)/normal-page.tsx (100%) rename e2e/react-start/scroll-restoration/{app => src}/routes/(tests)/with-loader.tsx (91%) rename e2e/react-start/scroll-restoration/{app => src}/routes/(tests)/with-search.tsx (100%) rename e2e/react-start/scroll-restoration/{app => src}/routes/-components/scroll-block.tsx (100%) rename e2e/react-start/scroll-restoration/{app => src}/routes/__root.tsx (90%) rename e2e/react-start/scroll-restoration/{app => src}/routes/index.tsx (100%) rename e2e/react-start/scroll-restoration/{app => src}/styles/app.css (100%) rename e2e/react-start/scroll-restoration/{app => src}/utils/posts.tsx (100%) rename e2e/react-start/scroll-restoration/{app => src}/utils/seo.ts (100%) rename e2e/react-start/scroll-restoration/{app => src}/utils/users.tsx (100%) rename e2e/react-start/server-functions/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename e2e/react-start/server-functions/{app => src}/components/NotFound.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routeTree.gen.ts (100%) rename e2e/react-start/server-functions/{app => src}/router.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/__root.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/abort-signal.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/consistent.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/cookies/index.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/cookies/set.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/dead-code-preserve.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/env-only.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/headers.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/index.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/isomorphic-fns.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/multipart.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/raw-response.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/return-null.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/serialize-form-data.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/status.tsx (100%) rename e2e/react-start/server-functions/{app => src}/routes/submit-post-formdata.tsx (100%) rename e2e/react-start/server-functions/{app => src}/styles/app.css (100%) rename {examples/solid/start-bare/app => e2e/solid-start/basic-tsr-config/src}/client.tsx (83%) rename e2e/solid-start/basic-tsr-config/src/{app => }/routeTree.gen.ts (96%) rename e2e/solid-start/basic-tsr-config/src/{app => }/router.tsx (87%) rename e2e/solid-start/basic-tsr-config/src/{app => }/routes/__root.tsx (100%) rename e2e/solid-start/basic-tsr-config/src/{app => }/routes/index.tsx (100%) rename e2e/solid-start/{website/app => basic-tsr-config/src}/ssr.tsx (87%) rename e2e/solid-start/scroll-restoration/{app => src}/api.ts (100%) rename e2e/solid-start/{basic-tsr-config/src/app => scroll-restoration/src}/client.tsx (100%) rename e2e/solid-start/scroll-restoration/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename e2e/solid-start/scroll-restoration/{app => src}/components/NotFound.tsx (100%) rename e2e/solid-start/scroll-restoration/{app => src}/routeTree.gen.ts (100%) rename e2e/solid-start/scroll-restoration/{app => src}/router.tsx (100%) rename e2e/solid-start/scroll-restoration/{app => src}/routes/(tests)/normal-page.tsx (100%) rename e2e/solid-start/scroll-restoration/{app => src}/routes/(tests)/with-loader.tsx (100%) rename e2e/solid-start/scroll-restoration/{app => src}/routes/(tests)/with-search.tsx (100%) rename e2e/solid-start/scroll-restoration/{app => src}/routes/-components/scroll-block.tsx (100%) rename e2e/solid-start/scroll-restoration/{app => src}/routes/__root.tsx (93%) rename e2e/solid-start/scroll-restoration/{app => src}/routes/index.tsx (100%) rename e2e/solid-start/scroll-restoration/{app => src}/ssr.tsx (100%) rename e2e/solid-start/scroll-restoration/{app => src}/styles/app.css (100%) rename e2e/solid-start/scroll-restoration/{app => src}/utils/posts.tsx (100%) rename e2e/solid-start/scroll-restoration/{app => src}/utils/seo.ts (100%) rename e2e/solid-start/scroll-restoration/{app => src}/utils/users.tsx (100%) rename e2e/solid-start/{scroll-restoration/app => server-functions/src}/client.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/components/NotFound.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routeTree.gen.ts (100%) rename e2e/solid-start/server-functions/{app => src}/router.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/__root.tsx (85%) rename e2e/solid-start/server-functions/{app => src}/routes/abort-signal.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/consistent.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/cookies/index.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/cookies/set.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/dead-code-preserve.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/env-only.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/headers.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/index.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/isomorphic-fns.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/multipart.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/raw-response.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/return-null.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/serialize-form-data.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/status.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/routes/submit-post-formdata.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/ssr.tsx (100%) rename e2e/solid-start/server-functions/{app => src}/styles/app.css (100%) rename e2e/solid-start/{server-functions/app => website/src}/client.tsx (100%) rename e2e/solid-start/website/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename e2e/solid-start/website/{app => src}/components/NotFound.tsx (100%) rename e2e/solid-start/website/{app => src}/routeTree.gen.ts (100%) rename e2e/solid-start/website/{app => src}/router.tsx (100%) rename e2e/solid-start/website/{app => src}/routes/$project.$version.docs.framework.$framework.$.tsx (100%) rename e2e/solid-start/website/{app => src}/routes/$project.$version.docs.framework.$framework.examples.$.tsx (100%) rename e2e/solid-start/website/{app => src}/routes/$project.$version.docs.framework.$framework.index.tsx (100%) rename e2e/solid-start/website/{app => src}/routes/$project.$version.docs.framework.$framework.tsx (100%) rename e2e/solid-start/website/{app => src}/routes/$project.$version.docs.index.tsx (100%) rename e2e/solid-start/website/{app => src}/routes/$project.index.tsx (100%) rename e2e/solid-start/website/{app => src}/routes/__root.tsx (93%) rename e2e/solid-start/website/{app => src}/routes/_library.$project.$version.index.tsx (100%) rename e2e/solid-start/website/{app => src}/routes/_library.$project.tsx (81%) rename e2e/solid-start/website/{app => src}/routes/_library.index.tsx (100%) rename e2e/solid-start/website/{app => src}/routes/_library.tsx (96%) rename e2e/solid-start/website/{app => src}/server/document.tsx (100%) rename e2e/solid-start/website/{app => src}/server/projects.tsx (100%) rename e2e/solid-start/{basic-tsr-config/src/app => website/src}/ssr.tsx (100%) rename e2e/solid-start/website/{app => src}/styles/app.css (100%) rename e2e/solid-start/website/{app => src}/utils/seo.ts (100%) rename examples/react/start-bare/{app => src}/api.ts (100%) rename examples/react/start-bare/{app => src}/components/Counter.css (100%) rename examples/react/start-bare/{app => src}/components/Counter.tsx (100%) rename examples/react/start-bare/{app => src}/routeTree.gen.ts (100%) rename examples/react/start-bare/{app => src}/router.tsx (100%) rename examples/react/start-bare/{app => src}/routes/__root.tsx (100%) rename examples/react/start-bare/{app => src}/routes/about.tsx (100%) rename examples/react/start-bare/{app => src}/routes/index.tsx (86%) rename examples/react/start-bare/{app => src}/styles/app.css (100%) rename examples/react/start-basic-auth/{app => src}/components/Auth.tsx (100%) rename examples/react/start-basic-auth/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename examples/react/start-basic-auth/{app => src}/components/Login.tsx (97%) rename examples/react/start-basic-auth/{app => src}/components/NotFound.tsx (100%) rename examples/react/start-basic-auth/{app => src}/hooks/useMutation.ts (100%) rename examples/react/start-basic-auth/{app => src}/routeTree.gen.ts (100%) rename examples/react/start-basic-auth/{app => src}/router.tsx (100%) rename examples/react/start-basic-auth/{app => src}/routes/__root.tsx (93%) rename examples/react/start-basic-auth/{app => src}/routes/_authed.tsx (88%) rename examples/react/{start-clerk-basic/app => start-basic-auth/src}/routes/_authed/posts.$postId.tsx (88%) rename examples/react/start-basic-auth/{app => src}/routes/_authed/posts.index.tsx (100%) rename examples/react/start-basic-auth/{app => src}/routes/_authed/posts.route.tsx (95%) rename examples/react/start-basic-auth/{app => src}/routes/index.tsx (100%) rename examples/react/start-basic-auth/{app => src}/routes/login.tsx (79%) rename examples/react/start-basic-auth/{app => src}/routes/logout.tsx (88%) rename examples/react/start-basic-auth/{app => src}/routes/signup.tsx (91%) rename examples/react/{start-bare/app => start-basic-auth/src}/server.ts (100%) rename examples/react/start-basic-auth/{app => src}/styles/app.css (100%) rename examples/react/start-basic-auth/{app => src}/utils/posts.ts (100%) rename examples/react/start-basic-auth/{app => src}/utils/prisma.ts (100%) rename examples/react/start-basic-auth/{app => src}/utils/seo.ts (100%) rename examples/react/start-basic-auth/{app => src}/utils/session.ts (100%) rename examples/react/start-basic-react-query/{app => src}/api.ts (100%) rename examples/react/start-basic-react-query/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/components/NotFound.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routeTree.gen.ts (100%) rename examples/react/start-basic-react-query/{app => src}/router.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/__root.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/_pathlessLayout.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/_pathlessLayout/_nested-layout.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/_pathlessLayout/_nested-layout/route-a.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/_pathlessLayout/_nested-layout/route-b.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/api.users.ts (100%) rename examples/react/start-basic-react-query/{app => src}/routes/api/users.$id.ts (100%) rename examples/react/start-basic-react-query/{app => src}/routes/deferred.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/index.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/posts.$postId.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/posts.index.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/posts.route.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/posts_.$postId.deep.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/redirect.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/users.$userId.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/users.index.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/routes/users.route.tsx (100%) rename examples/react/{start-basic-auth/app => start-basic-react-query/src}/server.ts (100%) rename examples/react/start-basic-react-query/{app => src}/styles/app.css (100%) rename examples/react/start-basic-react-query/{app => src}/utils/posts.tsx (100%) rename examples/react/start-basic-react-query/{app => src}/utils/seo.ts (100%) rename examples/react/start-basic-react-query/{app => src}/utils/users.tsx (100%) rename examples/react/start-basic-rsc/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename examples/react/start-basic-rsc/{app => src}/components/NotFound.tsx (100%) rename examples/react/start-basic-rsc/{app => src}/routeTree.gen.ts (100%) rename examples/react/start-basic-rsc/{app => src}/router.tsx (100%) rename examples/react/start-basic-rsc/{app => src}/routes/__root.tsx (94%) rename examples/react/start-basic-rsc/{app => src}/routes/_pathlessLayout.tsx (100%) rename examples/react/start-basic-rsc/{app => src}/routes/_pathlessLayout/_nested-layout.tsx (100%) rename examples/react/start-basic-rsc/{app => src}/routes/_pathlessLayout/_nested-layout/route-a.tsx (100%) rename examples/react/start-basic-rsc/{app => src}/routes/_pathlessLayout/_nested-layout/route-b.tsx (100%) rename examples/react/start-basic-rsc/{app => src}/routes/index.tsx (100%) rename examples/react/start-basic-rsc/{app => src}/routes/posts.$postId.tsx (96%) rename examples/react/start-basic-rsc/{app => src}/routes/posts.index.tsx (100%) rename examples/react/start-basic-rsc/{app => src}/routes/posts.tsx (88%) rename examples/react/start-basic-rsc/{app => src}/routes/posts_.$postId.deep.tsx (100%) rename examples/react/{start-basic-react-query/app => start-basic-rsc/src}/server.ts (100%) rename examples/react/start-basic-rsc/{app => src}/styles/app.css (100%) rename examples/react/start-basic-rsc/{app => src}/utils/posts.tsx (100%) rename examples/react/start-basic-rsc/{app => src}/utils/renderPosts.tsx (100%) rename examples/react/start-basic-rsc/{app => src}/utils/seo.ts (100%) delete mode 100644 examples/react/start-basic-static/app/routes/__root.tsx rename examples/react/start-basic-static/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename examples/react/start-basic-static/{app => src}/components/NotFound.tsx (100%) rename examples/react/start-basic-static/{app => src}/routeTree.gen.ts (100%) rename examples/react/start-basic-static/{app => src}/router.tsx (100%) rename examples/react/{start-basic/app => start-basic-static/src}/routes/__root.tsx (95%) rename examples/react/start-basic-static/{app => src}/routes/_pathlessLayout.tsx (100%) rename examples/react/start-basic-static/{app => src}/routes/_pathlessLayout/_nested-layout.tsx (100%) rename examples/react/start-basic-static/{app => src}/routes/_pathlessLayout/_nested-layout/route-a.tsx (100%) rename examples/react/start-basic-static/{app => src}/routes/_pathlessLayout/_nested-layout/route-b.tsx (100%) rename examples/react/start-basic-static/{app => src}/routes/deferred.tsx (100%) rename examples/react/start-basic-static/{app => src}/routes/index.tsx (100%) rename examples/react/start-basic-static/{app => src}/routes/posts.$postId.tsx (95%) rename examples/react/start-basic-static/{app => src}/routes/posts.index.tsx (100%) rename examples/react/start-basic-static/{app => src}/routes/posts.tsx (100%) rename examples/react/start-basic-static/{app => src}/routes/posts_.$postId.deep.tsx (100%) rename examples/react/start-basic-static/{app => src}/routes/redirect.tsx (100%) rename examples/react/start-basic-static/{app => src}/routes/users.$userId.tsx (93%) rename examples/react/start-basic-static/{app => src}/routes/users.index.tsx (100%) rename examples/react/start-basic-static/{app => src}/routes/users.tsx (100%) rename examples/react/{start-basic-rsc/app => start-basic-static/src}/server.ts (100%) rename examples/react/start-basic-static/{app => src}/styles/app.css (100%) rename examples/react/start-basic-static/{app => src}/utils/loggingMiddleware.tsx (100%) rename examples/react/start-basic-static/{app => src}/utils/posts.tsx (100%) rename examples/react/start-basic-static/{app => src}/utils/seo.ts (100%) rename examples/react/start-basic-static/{app => src}/utils/users.tsx (100%) delete mode 100644 examples/react/start-basic/app/routeTree.gen.ts delete mode 100644 examples/react/start-basic/src/routes/_layout/_layout-2.tsx delete mode 100644 examples/react/start-basic/src/routes/_layout/_layout-2/layout-a.tsx delete mode 100644 examples/react/start-basic/src/routes/_layout/_layout-2/layout-b.tsx rename examples/react/start-basic/{app => src}/routes/_pathlessLayout.tsx (100%) rename examples/react/start-basic/{app => src}/routes/_pathlessLayout/_nested-layout.tsx (100%) rename examples/react/start-basic/{app => src}/routes/_pathlessLayout/_nested-layout/route-a.tsx (100%) rename examples/react/start-basic/{app => src}/routes/_pathlessLayout/_nested-layout/route-b.tsx (100%) rename examples/react/start-basic/{app => src}/routes/posts.route.tsx (100%) rename examples/react/start-basic/{app => src}/routes/users.route.tsx (100%) rename examples/react/start-clerk-basic/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename examples/react/start-clerk-basic/{app => src}/components/NotFound.tsx (100%) rename examples/react/start-clerk-basic/{app => src}/routeTree.gen.ts (100%) rename examples/react/start-clerk-basic/{app => src}/router.tsx (100%) rename examples/react/start-clerk-basic/{app => src}/routes/__root.tsx (95%) rename examples/react/start-clerk-basic/{app => src}/routes/_authed.tsx (100%) rename examples/react/{start-basic-auth/app => start-clerk-basic/src}/routes/_authed/posts.$postId.tsx (88%) rename examples/react/start-clerk-basic/{app => src}/routes/_authed/posts.index.tsx (100%) rename examples/react/start-clerk-basic/{app => src}/routes/_authed/posts.tsx (95%) rename examples/react/start-clerk-basic/{app => src}/routes/_authed/profile.$.tsx (95%) rename examples/react/start-clerk-basic/{app => src}/routes/index.tsx (100%) rename examples/react/start-clerk-basic/{app => src}/server.ts (100%) rename examples/react/start-clerk-basic/{app => src}/styles/app.css (100%) rename examples/react/start-clerk-basic/{app => src}/utils/posts.ts (100%) rename examples/react/start-clerk-basic/{app => src}/utils/seo.ts (100%) rename examples/react/start-convex-trellaux/{app => src}/components/Board.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/components/CancelButton.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/components/Card.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/components/Column.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/components/EditableText.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/components/IconLink.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/components/Loader.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/components/NewCard.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/components/NewColumn.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/components/NotFound.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/components/SaveButton.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/db/schema.ts (100%) rename examples/react/start-convex-trellaux/{app => src}/hooks/useOfflineIndicator.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/icons/icons.svg (100%) rename examples/react/start-convex-trellaux/{app => src}/icons/icons.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/queries.ts (100%) rename examples/react/start-convex-trellaux/{app => src}/routeTree.gen.ts (100%) rename examples/react/start-convex-trellaux/{app => src}/router.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/routes/__root.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/routes/boards.$boardId.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/routes/index.tsx (100%) rename examples/react/{start-basic-static/app => start-convex-trellaux/src}/server.ts (100%) rename examples/react/start-convex-trellaux/{app => src}/styles/app.css (100%) rename examples/react/start-convex-trellaux/{app => src}/types.ts (100%) rename examples/react/start-convex-trellaux/{app => src}/utils/posts.tsx (100%) rename examples/react/start-convex-trellaux/{app => src}/utils/seo.ts (100%) rename examples/react/start-counter/{app => src}/routeTree.gen.ts (100%) rename examples/react/start-counter/{app => src}/router.tsx (100%) rename examples/react/start-counter/{app => src}/routes/__root.tsx (100%) rename examples/react/start-counter/{app => src}/routes/index.tsx (100%) rename examples/react/{start-convex-trellaux/app => start-counter/src}/server.ts (100%) rename examples/react/start-large/{app => src}/createRoutes.mjs (100%) rename examples/react/start-large/{app => src}/routeTree.gen.ts (100%) rename examples/react/start-large/{app => src}/router.tsx (100%) rename examples/react/start-large/{app => src}/routes/__root.tsx (100%) rename examples/react/start-large/{app => src}/routes/absolute.tsx (100%) rename examples/react/start-large/{app => src}/routes/index.tsx (100%) rename examples/react/start-large/{app => src}/routes/linkProps.tsx (98%) rename examples/react/start-large/{app => src}/routes/params/$paramsPlaceholder.tsx (100%) rename examples/react/start-large/{app => src}/routes/params/route.tsx (100%) rename examples/react/start-large/{app => src}/routes/relative.tsx (100%) rename examples/react/start-large/{app => src}/routes/search/route.tsx (100%) rename examples/react/start-large/{app => src}/routes/search/searchPlaceholder.tsx (100%) rename examples/react/start-large/{app => src}/server.ts (100%) rename examples/react/start-large/{app => src}/styles.css (100%) rename examples/react/start-large/{app => src}/typePrimitives.tsx (100%) rename examples/react/start-material-ui/{app => src}/client.tsx (100%) rename examples/react/start-material-ui/{app => src}/components/Counter.tsx (85%) rename examples/react/start-material-ui/{app => src}/components/CustomButtonLink.tsx (100%) rename examples/react/start-material-ui/{app => src}/components/CustomLink.tsx (100%) rename examples/react/start-material-ui/{app => src}/components/Header.tsx (100%) rename examples/react/start-material-ui/{app => src}/routeTree.gen.ts (100%) rename examples/react/start-material-ui/{app => src}/router.tsx (100%) rename examples/react/start-material-ui/{app => src}/routes/__root.tsx (94%) rename examples/react/start-material-ui/{app => src}/routes/about.tsx (100%) rename examples/react/start-material-ui/{app => src}/routes/index.tsx (90%) rename examples/react/start-material-ui/{app => src}/setup/theme.ts (100%) rename examples/react/start-material-ui/{app => src}/ssr.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/components/Auth.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/components/Login.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/components/NotFound.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/hooks/useMutation.ts (100%) rename examples/react/start-supabase-basic/{app => src}/routeTree.gen.ts (100%) rename examples/react/start-supabase-basic/{app => src}/router.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/routes/__root.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/routes/_authed.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/routes/_authed/posts.$postId.tsx (89%) rename examples/react/start-supabase-basic/{app => src}/routes/_authed/posts.index.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/routes/_authed/posts.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/routes/index.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/routes/login.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/routes/logout.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/routes/signup.tsx (100%) rename examples/react/start-supabase-basic/{app => src}/server.ts (100%) rename examples/react/start-supabase-basic/{app => src}/styles/app.css (100%) rename examples/react/start-supabase-basic/{app => src}/utils/posts.ts (100%) rename examples/react/start-supabase-basic/{app => src}/utils/seo.ts (100%) rename examples/react/start-supabase-basic/{app => src}/utils/supabase.ts (100%) delete mode 100644 examples/react/start-trellaux/app/server.ts rename examples/react/start-trellaux/{app => src}/assets/react.svg (100%) rename examples/react/start-trellaux/{app => src}/components/Board.tsx (100%) rename examples/react/start-trellaux/{app => src}/components/CancelButton.tsx (100%) rename examples/react/start-trellaux/{app => src}/components/Card.tsx (100%) rename examples/react/start-trellaux/{app => src}/components/Column.tsx (100%) rename examples/react/start-trellaux/{app => src}/components/DefaultCatchBoundary.tsx (100%) rename examples/react/start-trellaux/{app => src}/components/EditableText.tsx (100%) rename examples/react/start-trellaux/{app => src}/components/IconLink.tsx (100%) rename examples/react/start-trellaux/{app => src}/components/Loader.tsx (100%) rename examples/react/start-trellaux/{app => src}/components/NewCard.tsx (100%) rename examples/react/start-trellaux/{app => src}/components/NewColumn.tsx (100%) rename examples/react/start-trellaux/{app => src}/components/NotFound.tsx (100%) rename examples/react/start-trellaux/{app => src}/components/SaveButton.tsx (100%) rename examples/react/start-trellaux/{app => src}/db/board.ts (100%) rename examples/react/start-trellaux/{app => src}/db/schema.ts (100%) rename examples/react/start-trellaux/{app => src}/hooks/useOfflineIndicator.tsx (100%) rename examples/react/start-trellaux/{app => src}/icons/icons.svg (100%) rename examples/react/start-trellaux/{app => src}/icons/icons.tsx (100%) rename examples/react/start-trellaux/{app => src}/queries.ts (100%) rename examples/react/start-trellaux/{app => src}/routeTree.gen.ts (100%) rename examples/react/start-trellaux/{app => src}/router.tsx (100%) rename examples/react/start-trellaux/{app => src}/routes/__root.tsx (100%) rename examples/react/start-trellaux/{app => src}/routes/boards.$boardId.tsx (100%) rename examples/react/start-trellaux/{app => src}/routes/index.tsx (100%) rename examples/react/{start-counter/app => start-trellaux/src}/server.ts (100%) rename examples/react/start-trellaux/{app => src}/styles/app.css (100%) rename examples/react/start-trellaux/{app => src}/types.ts (100%) rename examples/react/start-trellaux/{app => src}/utils/posts.tsx (100%) rename examples/react/start-trellaux/{app => src}/utils/seo.ts (100%) rename examples/react/with-trpc-react-query/{app => src}/main.tsx (100%) rename examples/react/with-trpc-react-query/{app => src}/routeTree.gen.ts (100%) rename examples/react/with-trpc-react-query/{app => src}/router.tsx (100%) rename examples/react/with-trpc-react-query/{app => src}/routes/-components/spinner.tsx (100%) rename examples/react/with-trpc-react-query/{app => src}/routes/__root.tsx (100%) rename examples/react/with-trpc-react-query/{app => src}/routes/dashboard.index.tsx (100%) rename examples/react/with-trpc-react-query/{app => src}/routes/dashboard.posts.$postId.tsx (100%) rename examples/react/with-trpc-react-query/{app => src}/routes/dashboard.posts.index.tsx (100%) rename examples/react/with-trpc-react-query/{app => src}/routes/dashboard.posts.tsx (100%) rename examples/react/with-trpc-react-query/{app => src}/routes/dashboard.tsx (100%) rename examples/react/with-trpc-react-query/{app => src}/routes/index.tsx (100%) rename examples/react/with-trpc-react-query/{app => src}/styles.css (100%) rename examples/react/with-trpc/{app => src}/main.tsx (100%) rename examples/react/with-trpc/{app => src}/routeTree.gen.ts (100%) rename examples/react/with-trpc/{app => src}/routes/-components/spinner.tsx (100%) rename examples/react/with-trpc/{app => src}/routes/__root.tsx (100%) rename examples/react/with-trpc/{app => src}/routes/dashboard.index.tsx (100%) rename examples/react/with-trpc/{app => src}/routes/dashboard.posts.$postId.tsx (100%) rename examples/react/with-trpc/{app => src}/routes/dashboard.posts.index.tsx (100%) rename examples/react/with-trpc/{app => src}/routes/dashboard.posts.tsx (100%) rename examples/react/with-trpc/{app => src}/routes/dashboard.tsx (100%) rename examples/react/with-trpc/{app => src}/routes/index.tsx (100%) rename examples/react/with-trpc/{app => src}/styles.css (100%) rename examples/react/with-trpc/{app => src}/trpc.ts (100%) rename {e2e/solid-start/website/app => examples/solid/start-bare/src}/client.tsx (100%) rename examples/solid/start-bare/{app => src}/components/Counter.css (100%) rename examples/solid/start-bare/{app => src}/components/Counter.tsx (100%) rename examples/solid/start-bare/{app => src}/routeTree.gen.ts (100%) rename examples/solid/start-bare/{app => src}/router.tsx (100%) rename examples/solid/start-bare/{app => src}/routes/__root.tsx (100%) rename examples/solid/start-bare/{app => src}/routes/about.tsx (100%) rename examples/solid/start-bare/{app => src}/routes/index.tsx (86%) rename examples/solid/start-bare/{app => src}/ssr.tsx (100%) rename examples/solid/start-bare/{app => src}/styles/app.css (100%) rename packages/create-start/src/modules/core/template/{app => src}/client.tsx (100%) rename packages/create-start/src/modules/core/template/{app => src}/router.tsx (100%) rename packages/create-start/src/modules/core/template/{app => src}/routes/__root.tsx (100%) diff --git a/e2e/react-start/basic-auth/app/components/Auth.tsx b/e2e/react-start/basic-auth/src/components/Auth.tsx similarity index 100% rename from e2e/react-start/basic-auth/app/components/Auth.tsx rename to e2e/react-start/basic-auth/src/components/Auth.tsx diff --git a/e2e/react-start/basic-auth/app/components/DefaultCatchBoundary.tsx b/e2e/react-start/basic-auth/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from e2e/react-start/basic-auth/app/components/DefaultCatchBoundary.tsx rename to e2e/react-start/basic-auth/src/components/DefaultCatchBoundary.tsx diff --git a/e2e/react-start/basic-auth/app/components/Login.tsx b/e2e/react-start/basic-auth/src/components/Login.tsx similarity index 97% rename from e2e/react-start/basic-auth/app/components/Login.tsx rename to e2e/react-start/basic-auth/src/components/Login.tsx index b6b6da0c37..9ba6b8f019 100644 --- a/e2e/react-start/basic-auth/app/components/Login.tsx +++ b/e2e/react-start/basic-auth/src/components/Login.tsx @@ -3,7 +3,7 @@ import { useServerFn } from '@tanstack/react-start' import { useMutation } from '../hooks/useMutation' import { loginFn } from '../routes/_authed' import { Auth } from './Auth' -import { signupFn } from '~/routes/signup' +import { signupFn } from 'src/routes/signup' export function Login() { const router = useRouter() diff --git a/e2e/react-start/basic-auth/app/components/NotFound.tsx b/e2e/react-start/basic-auth/src/components/NotFound.tsx similarity index 100% rename from e2e/react-start/basic-auth/app/components/NotFound.tsx rename to e2e/react-start/basic-auth/src/components/NotFound.tsx diff --git a/e2e/react-start/basic-auth/app/hooks/useMutation.ts b/e2e/react-start/basic-auth/src/hooks/useMutation.ts similarity index 100% rename from e2e/react-start/basic-auth/app/hooks/useMutation.ts rename to e2e/react-start/basic-auth/src/hooks/useMutation.ts diff --git a/e2e/react-start/basic-auth/app/routeTree.gen.ts b/e2e/react-start/basic-auth/src/routeTree.gen.ts similarity index 100% rename from e2e/react-start/basic-auth/app/routeTree.gen.ts rename to e2e/react-start/basic-auth/src/routeTree.gen.ts diff --git a/e2e/react-start/basic-auth/app/router.tsx b/e2e/react-start/basic-auth/src/router.tsx similarity index 100% rename from e2e/react-start/basic-auth/app/router.tsx rename to e2e/react-start/basic-auth/src/router.tsx diff --git a/e2e/react-start/basic-auth/app/routes/__root.tsx b/e2e/react-start/basic-auth/src/routes/__root.tsx similarity index 93% rename from e2e/react-start/basic-auth/app/routes/__root.tsx rename to e2e/react-start/basic-auth/src/routes/__root.tsx index a3c8d1e872..3eeb03a93d 100644 --- a/e2e/react-start/basic-auth/app/routes/__root.tsx +++ b/e2e/react-start/basic-auth/src/routes/__root.tsx @@ -9,11 +9,11 @@ import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' import { createServerFn } from '@tanstack/react-start' import * as React from 'react' -import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary.js' -import { NotFound } from '~/components/NotFound.js' +import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary.js' +import { NotFound } from 'src/components/NotFound.js' import appCss from '~/styles/app.css?url' -import { seo } from '~/utils/seo.js' -import { useAppSession } from '~/utils/session.js' +import { seo } from 'src/utils/seo.js' +import { useAppSession } from 'src/utils/session.js' const fetchUser = createServerFn({ method: 'GET' }).handler(async () => { // We need to auth on the server so we have access to secure cookies diff --git a/e2e/react-start/basic-auth/app/routes/_authed.tsx b/e2e/react-start/basic-auth/src/routes/_authed.tsx similarity index 89% rename from e2e/react-start/basic-auth/app/routes/_authed.tsx rename to e2e/react-start/basic-auth/src/routes/_authed.tsx index c457cf5e57..b238afe63f 100644 --- a/e2e/react-start/basic-auth/app/routes/_authed.tsx +++ b/e2e/react-start/basic-auth/src/routes/_authed.tsx @@ -1,9 +1,9 @@ import { createFileRoute } from '@tanstack/react-router' import { createServerFn } from '@tanstack/react-start' -import { hashPassword, prismaClient } from '~/utils/prisma' -import { Login } from '~/components/Login' -import { useAppSession } from '~/utils/session' +import { hashPassword, prismaClient } from 'src/utils/prisma' +import { Login } from 'src/components/Login' +import { useAppSession } from 'src/utils/session' export const loginFn = createServerFn({ method: 'POST', diff --git a/e2e/react-start/clerk-basic/app/routes/_authed/posts.$postId.tsx b/e2e/react-start/basic-auth/src/routes/_authed/posts.$postId.tsx similarity index 88% rename from e2e/react-start/clerk-basic/app/routes/_authed/posts.$postId.tsx rename to e2e/react-start/basic-auth/src/routes/_authed/posts.$postId.tsx index 27296b9658..612394673b 100644 --- a/e2e/react-start/clerk-basic/app/routes/_authed/posts.$postId.tsx +++ b/e2e/react-start/basic-auth/src/routes/_authed/posts.$postId.tsx @@ -1,8 +1,8 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from '~/components/NotFound.js' -import { fetchPost } from '~/utils/posts.js' +import { NotFound } from 'src/components/NotFound.js' +import { fetchPost } from 'src/utils/posts.js' export const Route = createFileRoute('/_authed/posts/$postId')({ loader: ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/e2e/react-start/basic-auth/app/routes/_authed/posts.index.tsx b/e2e/react-start/basic-auth/src/routes/_authed/posts.index.tsx similarity index 100% rename from e2e/react-start/basic-auth/app/routes/_authed/posts.index.tsx rename to e2e/react-start/basic-auth/src/routes/_authed/posts.index.tsx diff --git a/e2e/react-start/basic-auth/app/routes/_authed/posts.tsx b/e2e/react-start/basic-auth/src/routes/_authed/posts.tsx similarity index 95% rename from e2e/react-start/basic-auth/app/routes/_authed/posts.tsx rename to e2e/react-start/basic-auth/src/routes/_authed/posts.tsx index c01f12c49a..d769f02b68 100644 --- a/e2e/react-start/basic-auth/app/routes/_authed/posts.tsx +++ b/e2e/react-start/basic-auth/src/routes/_authed/posts.tsx @@ -1,6 +1,6 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from '~/utils/posts.js' +import { fetchPosts } from 'src/utils/posts.js' export const Route = createFileRoute('/_authed/posts')({ loader: () => fetchPosts(), diff --git a/e2e/react-start/basic-auth/app/routes/index.tsx b/e2e/react-start/basic-auth/src/routes/index.tsx similarity index 100% rename from e2e/react-start/basic-auth/app/routes/index.tsx rename to e2e/react-start/basic-auth/src/routes/index.tsx diff --git a/e2e/react-start/basic-auth/app/routes/login.tsx b/e2e/react-start/basic-auth/src/routes/login.tsx similarity index 80% rename from e2e/react-start/basic-auth/app/routes/login.tsx rename to e2e/react-start/basic-auth/src/routes/login.tsx index 19dc34a439..ef419a72f7 100644 --- a/e2e/react-start/basic-auth/app/routes/login.tsx +++ b/e2e/react-start/basic-auth/src/routes/login.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/react-router' -import { Login } from '~/components/Login' +import { Login } from 'src/components/Login' export const Route = createFileRoute('/login')({ component: LoginComp, diff --git a/e2e/react-start/basic-auth/app/routes/logout.tsx b/e2e/react-start/basic-auth/src/routes/logout.tsx similarity index 88% rename from e2e/react-start/basic-auth/app/routes/logout.tsx rename to e2e/react-start/basic-auth/src/routes/logout.tsx index 43a14fa39a..0060780d11 100644 --- a/e2e/react-start/basic-auth/app/routes/logout.tsx +++ b/e2e/react-start/basic-auth/src/routes/logout.tsx @@ -1,7 +1,7 @@ import { createFileRoute, redirect } from '@tanstack/react-router' import { createServerFn } from '@tanstack/react-start' -import { useAppSession } from '~/utils/session' +import { useAppSession } from 'src/utils/session' const logoutFn = createServerFn({ method: 'POST' }).handler(async () => { const session = await useAppSession() diff --git a/e2e/react-start/basic-auth/app/routes/signup.tsx b/e2e/react-start/basic-auth/src/routes/signup.tsx similarity index 91% rename from e2e/react-start/basic-auth/app/routes/signup.tsx rename to e2e/react-start/basic-auth/src/routes/signup.tsx index 5edbb4993f..864ab0ab38 100644 --- a/e2e/react-start/basic-auth/app/routes/signup.tsx +++ b/e2e/react-start/basic-auth/src/routes/signup.tsx @@ -1,10 +1,10 @@ import { createFileRoute, redirect } from '@tanstack/react-router' import { createServerFn, useServerFn } from '@tanstack/react-start' -import { hashPassword, prismaClient } from '~/utils/prisma' -import { useMutation } from '~/hooks/useMutation' -import { Auth } from '~/components/Auth' -import { useAppSession } from '~/utils/session' +import { hashPassword, prismaClient } from 'src/utils/prisma' +import { useMutation } from 'src/hooks/useMutation' +import { Auth } from 'src/components/Auth' +import { useAppSession } from 'src/utils/session' export const signupFn = createServerFn({ method: 'POST', diff --git a/e2e/react-start/basic-auth/app/styles/app.css b/e2e/react-start/basic-auth/src/styles/app.css similarity index 100% rename from e2e/react-start/basic-auth/app/styles/app.css rename to e2e/react-start/basic-auth/src/styles/app.css diff --git a/e2e/react-start/basic-auth/app/utils/posts.ts b/e2e/react-start/basic-auth/src/utils/posts.ts similarity index 100% rename from e2e/react-start/basic-auth/app/utils/posts.ts rename to e2e/react-start/basic-auth/src/utils/posts.ts diff --git a/e2e/react-start/basic-auth/app/utils/prisma.ts b/e2e/react-start/basic-auth/src/utils/prisma.ts similarity index 100% rename from e2e/react-start/basic-auth/app/utils/prisma.ts rename to e2e/react-start/basic-auth/src/utils/prisma.ts diff --git a/e2e/react-start/basic-auth/app/utils/seo.ts b/e2e/react-start/basic-auth/src/utils/seo.ts similarity index 100% rename from e2e/react-start/basic-auth/app/utils/seo.ts rename to e2e/react-start/basic-auth/src/utils/seo.ts diff --git a/e2e/react-start/basic-auth/app/utils/session.ts b/e2e/react-start/basic-auth/src/utils/session.ts similarity index 100% rename from e2e/react-start/basic-auth/app/utils/session.ts rename to e2e/react-start/basic-auth/src/utils/session.ts diff --git a/e2e/react-start/basic-auth/tsconfig.json b/e2e/react-start/basic-auth/tsconfig.json index d1b5b77660..9a7cf62c30 100644 --- a/e2e/react-start/basic-auth/tsconfig.json +++ b/e2e/react-start/basic-auth/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/e2e/react-start/basic-react-query/app/api.ts b/e2e/react-start/basic-react-query/src/api.ts similarity index 100% rename from e2e/react-start/basic-react-query/app/api.ts rename to e2e/react-start/basic-react-query/src/api.ts diff --git a/e2e/react-start/basic-react-query/app/components/DefaultCatchBoundary.tsx b/e2e/react-start/basic-react-query/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/components/DefaultCatchBoundary.tsx rename to e2e/react-start/basic-react-query/src/components/DefaultCatchBoundary.tsx diff --git a/e2e/react-start/basic-react-query/app/components/NotFound.tsx b/e2e/react-start/basic-react-query/src/components/NotFound.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/components/NotFound.tsx rename to e2e/react-start/basic-react-query/src/components/NotFound.tsx diff --git a/e2e/react-start/basic-react-query/app/routeTree.gen.ts b/e2e/react-start/basic-react-query/src/routeTree.gen.ts similarity index 100% rename from e2e/react-start/basic-react-query/app/routeTree.gen.ts rename to e2e/react-start/basic-react-query/src/routeTree.gen.ts diff --git a/e2e/react-start/basic-react-query/app/router.tsx b/e2e/react-start/basic-react-query/src/router.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/router.tsx rename to e2e/react-start/basic-react-query/src/router.tsx diff --git a/e2e/react-start/basic-react-query/app/routes/__root.tsx b/e2e/react-start/basic-react-query/src/routes/__root.tsx similarity index 95% rename from e2e/react-start/basic-react-query/app/routes/__root.tsx rename to e2e/react-start/basic-react-query/src/routes/__root.tsx index 6bd9e76801..ff8b829c6a 100644 --- a/e2e/react-start/basic-react-query/app/routes/__root.tsx +++ b/e2e/react-start/basic-react-query/src/routes/__root.tsx @@ -9,10 +9,10 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools' import { TanStackRouterDevtoolsInProd } from '@tanstack/react-router-devtools' import * as React from 'react' import type { QueryClient } from '@tanstack/react-query' -import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' -import { NotFound } from '~/components/NotFound' +import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' +import { NotFound } from 'src/components/NotFound' import appCss from '~/styles/app.css?url' -import { seo } from '~/utils/seo' +import { seo } from 'src/utils/seo' export const Route = createRootRouteWithContext<{ queryClient: QueryClient diff --git a/e2e/react-start/basic-react-query/app/routes/_layout.tsx b/e2e/react-start/basic-react-query/src/routes/_layout.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/routes/_layout.tsx rename to e2e/react-start/basic-react-query/src/routes/_layout.tsx diff --git a/e2e/react-start/basic-react-query/app/routes/_layout/_layout-2.tsx b/e2e/react-start/basic-react-query/src/routes/_layout/_layout-2.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/routes/_layout/_layout-2.tsx rename to e2e/react-start/basic-react-query/src/routes/_layout/_layout-2.tsx diff --git a/e2e/react-start/basic-react-query/app/routes/_layout/_layout-2/layout-a.tsx b/e2e/react-start/basic-react-query/src/routes/_layout/_layout-2/layout-a.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/routes/_layout/_layout-2/layout-a.tsx rename to e2e/react-start/basic-react-query/src/routes/_layout/_layout-2/layout-a.tsx diff --git a/e2e/react-start/basic-react-query/app/routes/_layout/_layout-2/layout-b.tsx b/e2e/react-start/basic-react-query/src/routes/_layout/_layout-2/layout-b.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/routes/_layout/_layout-2/layout-b.tsx rename to e2e/react-start/basic-react-query/src/routes/_layout/_layout-2/layout-b.tsx diff --git a/e2e/react-start/basic-react-query/app/routes/api.users.ts b/e2e/react-start/basic-react-query/src/routes/api.users.ts similarity index 100% rename from e2e/react-start/basic-react-query/app/routes/api.users.ts rename to e2e/react-start/basic-react-query/src/routes/api.users.ts diff --git a/e2e/react-start/basic-react-query/app/routes/api/users.$id.ts b/e2e/react-start/basic-react-query/src/routes/api/users.$id.ts similarity index 100% rename from e2e/react-start/basic-react-query/app/routes/api/users.$id.ts rename to e2e/react-start/basic-react-query/src/routes/api/users.$id.ts diff --git a/e2e/react-start/basic-react-query/app/routes/deferred.tsx b/e2e/react-start/basic-react-query/src/routes/deferred.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/routes/deferred.tsx rename to e2e/react-start/basic-react-query/src/routes/deferred.tsx diff --git a/e2e/react-start/basic-react-query/app/routes/index.tsx b/e2e/react-start/basic-react-query/src/routes/index.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/routes/index.tsx rename to e2e/react-start/basic-react-query/src/routes/index.tsx diff --git a/e2e/react-start/basic-react-query/app/routes/posts.$postId.tsx b/e2e/react-start/basic-react-query/src/routes/posts.$postId.tsx similarity index 93% rename from e2e/react-start/basic-react-query/app/routes/posts.$postId.tsx rename to e2e/react-start/basic-react-query/src/routes/posts.$postId.tsx index 16a6bf29aa..688e23a674 100644 --- a/e2e/react-start/basic-react-query/app/routes/posts.$postId.tsx +++ b/e2e/react-start/basic-react-query/src/routes/posts.$postId.tsx @@ -2,8 +2,8 @@ import { ErrorComponent, Link, createFileRoute } from '@tanstack/react-router' import { useSuspenseQuery } from '@tanstack/react-query' import type { ErrorComponentProps } from '@tanstack/react-router' -import { postQueryOptions } from '~/utils/posts' -import { NotFound } from '~/components/NotFound' +import { postQueryOptions } from 'src/utils/posts' +import { NotFound } from 'src/components/NotFound' export const Route = createFileRoute('/posts/$postId')({ loader: async ({ params: { postId }, context }) => { diff --git a/e2e/react-start/basic-react-query/app/routes/posts.index.tsx b/e2e/react-start/basic-react-query/src/routes/posts.index.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/routes/posts.index.tsx rename to e2e/react-start/basic-react-query/src/routes/posts.index.tsx diff --git a/e2e/react-start/basic-react-query/app/routes/posts.tsx b/e2e/react-start/basic-react-query/src/routes/posts.tsx similarity index 95% rename from e2e/react-start/basic-react-query/app/routes/posts.tsx rename to e2e/react-start/basic-react-query/src/routes/posts.tsx index 3f678ed1f1..83919aafc9 100644 --- a/e2e/react-start/basic-react-query/app/routes/posts.tsx +++ b/e2e/react-start/basic-react-query/src/routes/posts.tsx @@ -1,7 +1,7 @@ import { useSuspenseQuery } from '@tanstack/react-query' import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { postsQueryOptions } from '~/utils/posts' +import { postsQueryOptions } from 'src/utils/posts' export const Route = createFileRoute('/posts')({ loader: async ({ context }) => { diff --git a/e2e/react-start/basic-react-query/app/routes/posts_.$postId.deep.tsx b/e2e/react-start/basic-react-query/src/routes/posts_.$postId.deep.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/routes/posts_.$postId.deep.tsx rename to e2e/react-start/basic-react-query/src/routes/posts_.$postId.deep.tsx diff --git a/e2e/react-start/basic-react-query/app/routes/redirect.tsx b/e2e/react-start/basic-react-query/src/routes/redirect.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/routes/redirect.tsx rename to e2e/react-start/basic-react-query/src/routes/redirect.tsx diff --git a/e2e/react-start/basic-react-query/app/routes/users.$userId.tsx b/e2e/react-start/basic-react-query/src/routes/users.$userId.tsx similarity index 90% rename from e2e/react-start/basic-react-query/app/routes/users.$userId.tsx rename to e2e/react-start/basic-react-query/src/routes/users.$userId.tsx index 656fb6dbb8..8db366a551 100644 --- a/e2e/react-start/basic-react-query/app/routes/users.$userId.tsx +++ b/e2e/react-start/basic-react-query/src/routes/users.$userId.tsx @@ -2,8 +2,8 @@ import { useSuspenseQuery } from '@tanstack/react-query' import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from '~/components/NotFound' -import { userQueryOptions } from '~/utils/users' +import { NotFound } from 'src/components/NotFound' +import { userQueryOptions } from 'src/utils/users' export const Route = createFileRoute('/users/$userId')({ loader: async ({ context, params: { userId } }) => { diff --git a/e2e/react-start/basic-react-query/app/routes/users.index.tsx b/e2e/react-start/basic-react-query/src/routes/users.index.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/routes/users.index.tsx rename to e2e/react-start/basic-react-query/src/routes/users.index.tsx diff --git a/e2e/react-start/basic-react-query/app/routes/users.tsx b/e2e/react-start/basic-react-query/src/routes/users.tsx similarity index 95% rename from e2e/react-start/basic-react-query/app/routes/users.tsx rename to e2e/react-start/basic-react-query/src/routes/users.tsx index 1b56bb9890..c0ad4349aa 100644 --- a/e2e/react-start/basic-react-query/app/routes/users.tsx +++ b/e2e/react-start/basic-react-query/src/routes/users.tsx @@ -1,7 +1,7 @@ import { useSuspenseQuery } from '@tanstack/react-query' import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { usersQueryOptions } from '~/utils/users' +import { usersQueryOptions } from 'src/utils/users' export const Route = createFileRoute('/users')({ loader: async ({ context }) => { diff --git a/e2e/react-start/basic-react-query/app/styles/app.css b/e2e/react-start/basic-react-query/src/styles/app.css similarity index 100% rename from e2e/react-start/basic-react-query/app/styles/app.css rename to e2e/react-start/basic-react-query/src/styles/app.css diff --git a/e2e/react-start/basic-react-query/app/utils/posts.tsx b/e2e/react-start/basic-react-query/src/utils/posts.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/utils/posts.tsx rename to e2e/react-start/basic-react-query/src/utils/posts.tsx diff --git a/e2e/react-start/basic-react-query/app/utils/seo.ts b/e2e/react-start/basic-react-query/src/utils/seo.ts similarity index 100% rename from e2e/react-start/basic-react-query/app/utils/seo.ts rename to e2e/react-start/basic-react-query/src/utils/seo.ts diff --git a/e2e/react-start/basic-react-query/app/utils/users.tsx b/e2e/react-start/basic-react-query/src/utils/users.tsx similarity index 100% rename from e2e/react-start/basic-react-query/app/utils/users.tsx rename to e2e/react-start/basic-react-query/src/utils/users.tsx diff --git a/e2e/react-start/basic-react-query/tsconfig.json b/e2e/react-start/basic-react-query/tsconfig.json index d1b5b77660..9a7cf62c30 100644 --- a/e2e/react-start/basic-react-query/tsconfig.json +++ b/e2e/react-start/basic-react-query/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/e2e/react-start/basic-tsr-config/src/app/routeTree.gen.ts b/e2e/react-start/basic-tsr-config/src/routeTree.gen.ts similarity index 100% rename from e2e/react-start/basic-tsr-config/src/app/routeTree.gen.ts rename to e2e/react-start/basic-tsr-config/src/routeTree.gen.ts diff --git a/e2e/react-start/basic-tsr-config/src/app/router.tsx b/e2e/react-start/basic-tsr-config/src/router.tsx similarity index 100% rename from e2e/react-start/basic-tsr-config/src/app/router.tsx rename to e2e/react-start/basic-tsr-config/src/router.tsx diff --git a/e2e/react-start/basic-tsr-config/src/app/routes/__root.tsx b/e2e/react-start/basic-tsr-config/src/routes/__root.tsx similarity index 100% rename from e2e/react-start/basic-tsr-config/src/app/routes/__root.tsx rename to e2e/react-start/basic-tsr-config/src/routes/__root.tsx diff --git a/e2e/react-start/basic-tsr-config/src/app/routes/index.tsx b/e2e/react-start/basic-tsr-config/src/routes/index.tsx similarity index 100% rename from e2e/react-start/basic-tsr-config/src/app/routes/index.tsx rename to e2e/react-start/basic-tsr-config/src/routes/index.tsx diff --git a/e2e/react-start/basic/app/api.ts b/e2e/react-start/basic/src/api.ts similarity index 100% rename from e2e/react-start/basic/app/api.ts rename to e2e/react-start/basic/src/api.ts diff --git a/e2e/react-start/basic/app/components/CustomMessage.tsx b/e2e/react-start/basic/src/components/CustomMessage.tsx similarity index 100% rename from e2e/react-start/basic/app/components/CustomMessage.tsx rename to e2e/react-start/basic/src/components/CustomMessage.tsx diff --git a/e2e/react-start/basic/app/components/DefaultCatchBoundary.tsx b/e2e/react-start/basic/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from e2e/react-start/basic/app/components/DefaultCatchBoundary.tsx rename to e2e/react-start/basic/src/components/DefaultCatchBoundary.tsx diff --git a/e2e/react-start/basic/app/components/NotFound.tsx b/e2e/react-start/basic/src/components/NotFound.tsx similarity index 100% rename from e2e/react-start/basic/app/components/NotFound.tsx rename to e2e/react-start/basic/src/components/NotFound.tsx diff --git a/e2e/react-start/basic/app/components/RedirectOnClick.tsx b/e2e/react-start/basic/src/components/RedirectOnClick.tsx similarity index 100% rename from e2e/react-start/basic/app/components/RedirectOnClick.tsx rename to e2e/react-start/basic/src/components/RedirectOnClick.tsx diff --git a/e2e/react-start/basic/app/components/throwRedirect.ts b/e2e/react-start/basic/src/components/throwRedirect.ts similarity index 100% rename from e2e/react-start/basic/app/components/throwRedirect.ts rename to e2e/react-start/basic/src/components/throwRedirect.ts diff --git a/e2e/react-start/basic/app/routeTree.gen.ts b/e2e/react-start/basic/src/routeTree.gen.ts similarity index 100% rename from e2e/react-start/basic/app/routeTree.gen.ts rename to e2e/react-start/basic/src/routeTree.gen.ts diff --git a/e2e/react-start/basic/app/router.tsx b/e2e/react-start/basic/src/router.tsx similarity index 100% rename from e2e/react-start/basic/app/router.tsx rename to e2e/react-start/basic/src/router.tsx diff --git a/e2e/react-start/basic/app/routes/__root.tsx b/e2e/react-start/basic/src/routes/__root.tsx similarity index 95% rename from e2e/react-start/basic/app/routes/__root.tsx rename to e2e/react-start/basic/src/routes/__root.tsx index 1b64b1c468..9c62771a63 100644 --- a/e2e/react-start/basic/app/routes/__root.tsx +++ b/e2e/react-start/basic/src/routes/__root.tsx @@ -7,10 +7,10 @@ import { createRootRoute, } from '@tanstack/react-router' -import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' -import { NotFound } from '~/components/NotFound' +import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' +import { NotFound } from 'src/components/NotFound' import appCss from '~/styles/app.css?url' -import { seo } from '~/utils/seo' +import { seo } from 'src/utils/seo' export const Route = createRootRoute({ head: () => ({ diff --git a/e2e/react-start/basic/app/routes/_layout.tsx b/e2e/react-start/basic/src/routes/_layout.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/_layout.tsx rename to e2e/react-start/basic/src/routes/_layout.tsx diff --git a/e2e/react-start/basic/app/routes/_layout/_layout-2.tsx b/e2e/react-start/basic/src/routes/_layout/_layout-2.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/_layout/_layout-2.tsx rename to e2e/react-start/basic/src/routes/_layout/_layout-2.tsx diff --git a/e2e/react-start/basic/app/routes/_layout/_layout-2/layout-a.tsx b/e2e/react-start/basic/src/routes/_layout/_layout-2/layout-a.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/_layout/_layout-2/layout-a.tsx rename to e2e/react-start/basic/src/routes/_layout/_layout-2/layout-a.tsx diff --git a/e2e/react-start/basic/app/routes/_layout/_layout-2/layout-b.tsx b/e2e/react-start/basic/src/routes/_layout/_layout-2/layout-b.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/_layout/_layout-2/layout-b.tsx rename to e2e/react-start/basic/src/routes/_layout/_layout-2/layout-b.tsx diff --git a/e2e/react-start/basic/app/routes/api.users.ts b/e2e/react-start/basic/src/routes/api.users.ts similarity index 100% rename from e2e/react-start/basic/app/routes/api.users.ts rename to e2e/react-start/basic/src/routes/api.users.ts diff --git a/e2e/react-start/basic/app/routes/api/users.$id.ts b/e2e/react-start/basic/src/routes/api/users.$id.ts similarity index 100% rename from e2e/react-start/basic/app/routes/api/users.$id.ts rename to e2e/react-start/basic/src/routes/api/users.$id.ts diff --git a/e2e/react-start/basic/app/routes/deferred.tsx b/e2e/react-start/basic/src/routes/deferred.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/deferred.tsx rename to e2e/react-start/basic/src/routes/deferred.tsx diff --git a/e2e/react-start/basic/app/routes/index.tsx b/e2e/react-start/basic/src/routes/index.tsx similarity index 82% rename from e2e/react-start/basic/app/routes/index.tsx rename to e2e/react-start/basic/src/routes/index.tsx index 37169a78b4..55e4693651 100644 --- a/e2e/react-start/basic/app/routes/index.tsx +++ b/e2e/react-start/basic/src/routes/index.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/react-router' -import { CustomMessage } from '~/components/CustomMessage' +import { CustomMessage } from 'src/components/CustomMessage' export const Route = createFileRoute('/')({ component: Home, diff --git a/e2e/react-start/basic/app/routes/links.tsx b/e2e/react-start/basic/src/routes/links.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/links.tsx rename to e2e/react-start/basic/src/routes/links.tsx diff --git a/e2e/react-start/basic/app/routes/not-found/index.tsx b/e2e/react-start/basic/src/routes/not-found/index.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/not-found/index.tsx rename to e2e/react-start/basic/src/routes/not-found/index.tsx diff --git a/e2e/react-start/basic/app/routes/not-found/route.tsx b/e2e/react-start/basic/src/routes/not-found/route.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/not-found/route.tsx rename to e2e/react-start/basic/src/routes/not-found/route.tsx diff --git a/e2e/react-start/basic/app/routes/not-found/via-beforeLoad.tsx b/e2e/react-start/basic/src/routes/not-found/via-beforeLoad.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/not-found/via-beforeLoad.tsx rename to e2e/react-start/basic/src/routes/not-found/via-beforeLoad.tsx diff --git a/e2e/react-start/basic/app/routes/not-found/via-loader.tsx b/e2e/react-start/basic/src/routes/not-found/via-loader.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/not-found/via-loader.tsx rename to e2e/react-start/basic/src/routes/not-found/via-loader.tsx diff --git a/e2e/react-start/basic/app/routes/posts.$postId.tsx b/e2e/react-start/basic/src/routes/posts.$postId.tsx similarity index 91% rename from e2e/react-start/basic/app/routes/posts.$postId.tsx rename to e2e/react-start/basic/src/routes/posts.$postId.tsx index 005228a0fe..368c1d3c1f 100644 --- a/e2e/react-start/basic/app/routes/posts.$postId.tsx +++ b/e2e/react-start/basic/src/routes/posts.$postId.tsx @@ -1,8 +1,8 @@ import { ErrorComponent, Link, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { fetchPost } from '~/utils/posts' -import { NotFound } from '~/components/NotFound' +import { fetchPost } from 'src/utils/posts' +import { NotFound } from 'src/components/NotFound' export const Route = createFileRoute('/posts/$postId')({ loader: async ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/e2e/react-start/basic/app/routes/posts.index.tsx b/e2e/react-start/basic/src/routes/posts.index.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/posts.index.tsx rename to e2e/react-start/basic/src/routes/posts.index.tsx diff --git a/e2e/react-start/basic/app/routes/posts.tsx b/e2e/react-start/basic/src/routes/posts.tsx similarity index 96% rename from e2e/react-start/basic/app/routes/posts.tsx rename to e2e/react-start/basic/src/routes/posts.tsx index 0f69c18341..60e9aa37c3 100644 --- a/e2e/react-start/basic/app/routes/posts.tsx +++ b/e2e/react-start/basic/src/routes/posts.tsx @@ -1,6 +1,6 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from '~/utils/posts' +import { fetchPosts } from 'src/utils/posts' export const Route = createFileRoute('/posts')({ head: () => ({ diff --git a/e2e/react-start/basic/app/routes/posts_.$postId.deep.tsx b/e2e/react-start/basic/src/routes/posts_.$postId.deep.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/posts_.$postId.deep.tsx rename to e2e/react-start/basic/src/routes/posts_.$postId.deep.tsx diff --git a/e2e/react-start/basic/app/routes/redirect/$target.tsx b/e2e/react-start/basic/src/routes/redirect/$target.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/redirect/$target.tsx rename to e2e/react-start/basic/src/routes/redirect/$target.tsx diff --git a/e2e/react-start/basic/app/routes/redirect/$target/index.tsx b/e2e/react-start/basic/src/routes/redirect/$target/index.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/redirect/$target/index.tsx rename to e2e/react-start/basic/src/routes/redirect/$target/index.tsx diff --git a/e2e/react-start/basic/app/routes/redirect/$target/serverFn/index.tsx b/e2e/react-start/basic/src/routes/redirect/$target/serverFn/index.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/redirect/$target/serverFn/index.tsx rename to e2e/react-start/basic/src/routes/redirect/$target/serverFn/index.tsx diff --git a/e2e/react-start/basic/app/routes/redirect/$target/serverFn/via-beforeLoad.tsx b/e2e/react-start/basic/src/routes/redirect/$target/serverFn/via-beforeLoad.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/redirect/$target/serverFn/via-beforeLoad.tsx rename to e2e/react-start/basic/src/routes/redirect/$target/serverFn/via-beforeLoad.tsx diff --git a/e2e/react-start/basic/app/routes/redirect/$target/serverFn/via-loader.tsx b/e2e/react-start/basic/src/routes/redirect/$target/serverFn/via-loader.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/redirect/$target/serverFn/via-loader.tsx rename to e2e/react-start/basic/src/routes/redirect/$target/serverFn/via-loader.tsx diff --git a/e2e/react-start/basic/app/routes/redirect/$target/serverFn/via-useServerFn.tsx b/e2e/react-start/basic/src/routes/redirect/$target/serverFn/via-useServerFn.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/redirect/$target/serverFn/via-useServerFn.tsx rename to e2e/react-start/basic/src/routes/redirect/$target/serverFn/via-useServerFn.tsx diff --git a/e2e/react-start/basic/app/routes/redirect/$target/via-beforeLoad.tsx b/e2e/react-start/basic/src/routes/redirect/$target/via-beforeLoad.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/redirect/$target/via-beforeLoad.tsx rename to e2e/react-start/basic/src/routes/redirect/$target/via-beforeLoad.tsx diff --git a/e2e/react-start/basic/app/routes/redirect/$target/via-loader.tsx b/e2e/react-start/basic/src/routes/redirect/$target/via-loader.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/redirect/$target/via-loader.tsx rename to e2e/react-start/basic/src/routes/redirect/$target/via-loader.tsx diff --git a/e2e/react-start/basic/app/routes/redirect/index.tsx b/e2e/react-start/basic/src/routes/redirect/index.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/redirect/index.tsx rename to e2e/react-start/basic/src/routes/redirect/index.tsx diff --git a/e2e/react-start/basic/app/routes/scripts.tsx b/e2e/react-start/basic/src/routes/scripts.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/scripts.tsx rename to e2e/react-start/basic/src/routes/scripts.tsx diff --git a/e2e/react-start/basic/app/routes/search-params.tsx b/e2e/react-start/basic/src/routes/search-params.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/search-params.tsx rename to e2e/react-start/basic/src/routes/search-params.tsx diff --git a/e2e/react-start/basic/app/routes/stream.tsx b/e2e/react-start/basic/src/routes/stream.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/stream.tsx rename to e2e/react-start/basic/src/routes/stream.tsx diff --git a/e2e/react-start/basic/app/routes/users.$userId.tsx b/e2e/react-start/basic/src/routes/users.$userId.tsx similarity index 87% rename from e2e/react-start/basic/app/routes/users.$userId.tsx rename to e2e/react-start/basic/src/routes/users.$userId.tsx index 1e2921411a..56f0a472da 100644 --- a/e2e/react-start/basic/app/routes/users.$userId.tsx +++ b/e2e/react-start/basic/src/routes/users.$userId.tsx @@ -2,9 +2,9 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import axios from 'redaxios' import type { ErrorComponentProps } from '@tanstack/react-router' -import type { User } from '~/utils/users' -import { DEPLOY_URL } from '~/utils/users' -import { NotFound } from '~/components/NotFound' +import type { User } from 'src/utils/users' +import { DEPLOY_URL } from 'src/utils/users' +import { NotFound } from 'src/components/NotFound' export const Route = createFileRoute('/users/$userId')({ loader: async ({ params: { userId } }) => { diff --git a/e2e/react-start/basic/app/routes/users.index.tsx b/e2e/react-start/basic/src/routes/users.index.tsx similarity index 100% rename from e2e/react-start/basic/app/routes/users.index.tsx rename to e2e/react-start/basic/src/routes/users.index.tsx diff --git a/e2e/react-start/basic/app/routes/users.tsx b/e2e/react-start/basic/src/routes/users.tsx similarity index 93% rename from e2e/react-start/basic/app/routes/users.tsx rename to e2e/react-start/basic/src/routes/users.tsx index 45e070657e..d4bdb8f53c 100644 --- a/e2e/react-start/basic/app/routes/users.tsx +++ b/e2e/react-start/basic/src/routes/users.tsx @@ -1,8 +1,8 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' import axios from 'redaxios' -import type { User } from '~/utils/users' -import { DEPLOY_URL } from '~/utils/users' +import type { User } from 'src/utils/users' +import { DEPLOY_URL } from 'src/utils/users' export const Route = createFileRoute('/users')({ loader: async () => { diff --git a/e2e/react-start/basic/app/styles/app.css b/e2e/react-start/basic/src/styles/app.css similarity index 100% rename from e2e/react-start/basic/app/styles/app.css rename to e2e/react-start/basic/src/styles/app.css diff --git a/e2e/react-start/basic/app/utils/posts.tsx b/e2e/react-start/basic/src/utils/posts.tsx similarity index 100% rename from e2e/react-start/basic/app/utils/posts.tsx rename to e2e/react-start/basic/src/utils/posts.tsx diff --git a/e2e/react-start/basic/app/utils/seo.ts b/e2e/react-start/basic/src/utils/seo.ts similarity index 100% rename from e2e/react-start/basic/app/utils/seo.ts rename to e2e/react-start/basic/src/utils/seo.ts diff --git a/e2e/react-start/basic/app/utils/users.tsx b/e2e/react-start/basic/src/utils/users.tsx similarity index 100% rename from e2e/react-start/basic/app/utils/users.tsx rename to e2e/react-start/basic/src/utils/users.tsx diff --git a/e2e/react-start/basic/tsconfig.json b/e2e/react-start/basic/tsconfig.json index a6747faec5..23f12840c3 100644 --- a/e2e/react-start/basic/tsconfig.json +++ b/e2e/react-start/basic/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/e2e/react-start/clerk-basic/app/components/DefaultCatchBoundary.tsx b/e2e/react-start/clerk-basic/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from e2e/react-start/clerk-basic/app/components/DefaultCatchBoundary.tsx rename to e2e/react-start/clerk-basic/src/components/DefaultCatchBoundary.tsx diff --git a/e2e/react-start/clerk-basic/app/components/NotFound.tsx b/e2e/react-start/clerk-basic/src/components/NotFound.tsx similarity index 100% rename from e2e/react-start/clerk-basic/app/components/NotFound.tsx rename to e2e/react-start/clerk-basic/src/components/NotFound.tsx diff --git a/e2e/react-start/clerk-basic/app/routeTree.gen.ts b/e2e/react-start/clerk-basic/src/routeTree.gen.ts similarity index 100% rename from e2e/react-start/clerk-basic/app/routeTree.gen.ts rename to e2e/react-start/clerk-basic/src/routeTree.gen.ts diff --git a/e2e/react-start/clerk-basic/app/router.tsx b/e2e/react-start/clerk-basic/src/router.tsx similarity index 100% rename from e2e/react-start/clerk-basic/app/router.tsx rename to e2e/react-start/clerk-basic/src/router.tsx diff --git a/e2e/react-start/clerk-basic/app/routes/__root.tsx b/e2e/react-start/clerk-basic/src/routes/__root.tsx similarity index 95% rename from e2e/react-start/clerk-basic/app/routes/__root.tsx rename to e2e/react-start/clerk-basic/src/routes/__root.tsx index 1773a381d0..0ad96f9375 100644 --- a/e2e/react-start/clerk-basic/app/routes/__root.tsx +++ b/e2e/react-start/clerk-basic/src/routes/__root.tsx @@ -18,8 +18,8 @@ import { createServerFn } from '@tanstack/react-start' import * as React from 'react' import { getAuth } from '@clerk/tanstack-start/server' import { getWebRequest } from '@tanstack/react-start/server' -import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary.js' -import { NotFound } from '~/components/NotFound.js' +import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary.js' +import { NotFound } from 'src/components/NotFound.js' import appCss from '~/styles/app.css?url' const fetchClerkAuth = createServerFn({ method: 'GET' }).handler(async () => { diff --git a/e2e/react-start/clerk-basic/app/routes/_authed.tsx b/e2e/react-start/clerk-basic/src/routes/_authed.tsx similarity index 100% rename from e2e/react-start/clerk-basic/app/routes/_authed.tsx rename to e2e/react-start/clerk-basic/src/routes/_authed.tsx diff --git a/e2e/react-start/basic-auth/app/routes/_authed/posts.$postId.tsx b/e2e/react-start/clerk-basic/src/routes/_authed/posts.$postId.tsx similarity index 88% rename from e2e/react-start/basic-auth/app/routes/_authed/posts.$postId.tsx rename to e2e/react-start/clerk-basic/src/routes/_authed/posts.$postId.tsx index 27296b9658..612394673b 100644 --- a/e2e/react-start/basic-auth/app/routes/_authed/posts.$postId.tsx +++ b/e2e/react-start/clerk-basic/src/routes/_authed/posts.$postId.tsx @@ -1,8 +1,8 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from '~/components/NotFound.js' -import { fetchPost } from '~/utils/posts.js' +import { NotFound } from 'src/components/NotFound.js' +import { fetchPost } from 'src/utils/posts.js' export const Route = createFileRoute('/_authed/posts/$postId')({ loader: ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/e2e/react-start/clerk-basic/app/routes/_authed/posts.index.tsx b/e2e/react-start/clerk-basic/src/routes/_authed/posts.index.tsx similarity index 100% rename from e2e/react-start/clerk-basic/app/routes/_authed/posts.index.tsx rename to e2e/react-start/clerk-basic/src/routes/_authed/posts.index.tsx diff --git a/e2e/react-start/clerk-basic/app/routes/_authed/posts.tsx b/e2e/react-start/clerk-basic/src/routes/_authed/posts.tsx similarity index 95% rename from e2e/react-start/clerk-basic/app/routes/_authed/posts.tsx rename to e2e/react-start/clerk-basic/src/routes/_authed/posts.tsx index c01f12c49a..d769f02b68 100644 --- a/e2e/react-start/clerk-basic/app/routes/_authed/posts.tsx +++ b/e2e/react-start/clerk-basic/src/routes/_authed/posts.tsx @@ -1,6 +1,6 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from '~/utils/posts.js' +import { fetchPosts } from 'src/utils/posts.js' export const Route = createFileRoute('/_authed/posts')({ loader: () => fetchPosts(), diff --git a/e2e/react-start/clerk-basic/app/routes/_authed/profile.$.tsx b/e2e/react-start/clerk-basic/src/routes/_authed/profile.$.tsx similarity index 95% rename from e2e/react-start/clerk-basic/app/routes/_authed/profile.$.tsx rename to e2e/react-start/clerk-basic/src/routes/_authed/profile.$.tsx index 1e5a8b1429..892d3a7fd9 100644 --- a/e2e/react-start/clerk-basic/app/routes/_authed/profile.$.tsx +++ b/e2e/react-start/clerk-basic/src/routes/_authed/profile.$.tsx @@ -1,6 +1,6 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from '~/utils/posts.js' +import { fetchPosts } from 'src/utils/posts.js' export const Route = createFileRoute('/_authed/profile/$')({ loader: () => fetchPosts(), diff --git a/e2e/react-start/clerk-basic/app/routes/index.tsx b/e2e/react-start/clerk-basic/src/routes/index.tsx similarity index 100% rename from e2e/react-start/clerk-basic/app/routes/index.tsx rename to e2e/react-start/clerk-basic/src/routes/index.tsx diff --git a/e2e/react-start/clerk-basic/app/server.tsx b/e2e/react-start/clerk-basic/src/server.tsx similarity index 100% rename from e2e/react-start/clerk-basic/app/server.tsx rename to e2e/react-start/clerk-basic/src/server.tsx diff --git a/e2e/react-start/clerk-basic/app/styles/app.css b/e2e/react-start/clerk-basic/src/styles/app.css similarity index 100% rename from e2e/react-start/clerk-basic/app/styles/app.css rename to e2e/react-start/clerk-basic/src/styles/app.css diff --git a/e2e/react-start/clerk-basic/app/utils/posts.ts b/e2e/react-start/clerk-basic/src/utils/posts.ts similarity index 100% rename from e2e/react-start/clerk-basic/app/utils/posts.ts rename to e2e/react-start/clerk-basic/src/utils/posts.ts diff --git a/e2e/react-start/clerk-basic/app/utils/seo.ts b/e2e/react-start/clerk-basic/src/utils/seo.ts similarity index 100% rename from e2e/react-start/clerk-basic/app/utils/seo.ts rename to e2e/react-start/clerk-basic/src/utils/seo.ts diff --git a/e2e/react-start/clerk-basic/tsconfig.json b/e2e/react-start/clerk-basic/tsconfig.json index d1b5b77660..9a7cf62c30 100644 --- a/e2e/react-start/clerk-basic/tsconfig.json +++ b/e2e/react-start/clerk-basic/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/e2e/react-start/scroll-restoration/app/api.ts b/e2e/react-start/scroll-restoration/src/api.ts similarity index 100% rename from e2e/react-start/scroll-restoration/app/api.ts rename to e2e/react-start/scroll-restoration/src/api.ts diff --git a/e2e/react-start/scroll-restoration/app/components/DefaultCatchBoundary.tsx b/e2e/react-start/scroll-restoration/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from e2e/react-start/scroll-restoration/app/components/DefaultCatchBoundary.tsx rename to e2e/react-start/scroll-restoration/src/components/DefaultCatchBoundary.tsx diff --git a/e2e/react-start/scroll-restoration/app/components/NotFound.tsx b/e2e/react-start/scroll-restoration/src/components/NotFound.tsx similarity index 100% rename from e2e/react-start/scroll-restoration/app/components/NotFound.tsx rename to e2e/react-start/scroll-restoration/src/components/NotFound.tsx diff --git a/e2e/react-start/scroll-restoration/app/routeTree.gen.ts b/e2e/react-start/scroll-restoration/src/routeTree.gen.ts similarity index 100% rename from e2e/react-start/scroll-restoration/app/routeTree.gen.ts rename to e2e/react-start/scroll-restoration/src/routeTree.gen.ts diff --git a/e2e/react-start/scroll-restoration/app/router.tsx b/e2e/react-start/scroll-restoration/src/router.tsx similarity index 100% rename from e2e/react-start/scroll-restoration/app/router.tsx rename to e2e/react-start/scroll-restoration/src/router.tsx diff --git a/e2e/react-start/scroll-restoration/app/routes/(tests)/normal-page.tsx b/e2e/react-start/scroll-restoration/src/routes/(tests)/normal-page.tsx similarity index 100% rename from e2e/react-start/scroll-restoration/app/routes/(tests)/normal-page.tsx rename to e2e/react-start/scroll-restoration/src/routes/(tests)/normal-page.tsx diff --git a/e2e/react-start/scroll-restoration/app/routes/(tests)/with-loader.tsx b/e2e/react-start/scroll-restoration/src/routes/(tests)/with-loader.tsx similarity index 91% rename from e2e/react-start/scroll-restoration/app/routes/(tests)/with-loader.tsx rename to e2e/react-start/scroll-restoration/src/routes/(tests)/with-loader.tsx index dfd4c7bf13..6a8a0bc545 100644 --- a/e2e/react-start/scroll-restoration/app/routes/(tests)/with-loader.tsx +++ b/e2e/react-start/scroll-restoration/src/routes/(tests)/with-loader.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/react-router' import { ScrollBlock } from '../-components/scroll-block' -import { sleep } from '~/utils/posts' +import { sleep } from 'src/utils/posts' export const Route = createFileRoute('/(tests)/with-loader')({ loader: async () => { diff --git a/e2e/react-start/scroll-restoration/app/routes/(tests)/with-search.tsx b/e2e/react-start/scroll-restoration/src/routes/(tests)/with-search.tsx similarity index 100% rename from e2e/react-start/scroll-restoration/app/routes/(tests)/with-search.tsx rename to e2e/react-start/scroll-restoration/src/routes/(tests)/with-search.tsx diff --git a/e2e/react-start/scroll-restoration/app/routes/-components/scroll-block.tsx b/e2e/react-start/scroll-restoration/src/routes/-components/scroll-block.tsx similarity index 100% rename from e2e/react-start/scroll-restoration/app/routes/-components/scroll-block.tsx rename to e2e/react-start/scroll-restoration/src/routes/-components/scroll-block.tsx diff --git a/e2e/react-start/scroll-restoration/app/routes/__root.tsx b/e2e/react-start/scroll-restoration/src/routes/__root.tsx similarity index 90% rename from e2e/react-start/scroll-restoration/app/routes/__root.tsx rename to e2e/react-start/scroll-restoration/src/routes/__root.tsx index bf315e98ae..1628a4ab07 100644 --- a/e2e/react-start/scroll-restoration/app/routes/__root.tsx +++ b/e2e/react-start/scroll-restoration/src/routes/__root.tsx @@ -7,10 +7,11 @@ import { HeadContent, Scripts, } from '@tanstack/react-router' -import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' -import { NotFound } from '~/components/NotFound' +import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' +import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' +import { NotFound } from 'src/components/NotFound' import appCss from '~/styles/app.css?url' -import { seo } from '~/utils/seo' +import { seo } from 'src/utils/seo' export const Route = createRootRoute({ head: () => ({ @@ -66,6 +67,7 @@ function RootComponent() { return ( + ) } diff --git a/e2e/react-start/scroll-restoration/app/routes/index.tsx b/e2e/react-start/scroll-restoration/src/routes/index.tsx similarity index 100% rename from e2e/react-start/scroll-restoration/app/routes/index.tsx rename to e2e/react-start/scroll-restoration/src/routes/index.tsx diff --git a/e2e/react-start/scroll-restoration/app/styles/app.css b/e2e/react-start/scroll-restoration/src/styles/app.css similarity index 100% rename from e2e/react-start/scroll-restoration/app/styles/app.css rename to e2e/react-start/scroll-restoration/src/styles/app.css diff --git a/e2e/react-start/scroll-restoration/app/utils/posts.tsx b/e2e/react-start/scroll-restoration/src/utils/posts.tsx similarity index 100% rename from e2e/react-start/scroll-restoration/app/utils/posts.tsx rename to e2e/react-start/scroll-restoration/src/utils/posts.tsx diff --git a/e2e/react-start/scroll-restoration/app/utils/seo.ts b/e2e/react-start/scroll-restoration/src/utils/seo.ts similarity index 100% rename from e2e/react-start/scroll-restoration/app/utils/seo.ts rename to e2e/react-start/scroll-restoration/src/utils/seo.ts diff --git a/e2e/react-start/scroll-restoration/app/utils/users.tsx b/e2e/react-start/scroll-restoration/src/utils/users.tsx similarity index 100% rename from e2e/react-start/scroll-restoration/app/utils/users.tsx rename to e2e/react-start/scroll-restoration/src/utils/users.tsx diff --git a/e2e/react-start/scroll-restoration/tsconfig.json b/e2e/react-start/scroll-restoration/tsconfig.json index a6747faec5..23f12840c3 100644 --- a/e2e/react-start/scroll-restoration/tsconfig.json +++ b/e2e/react-start/scroll-restoration/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/e2e/react-start/server-functions/app/components/DefaultCatchBoundary.tsx b/e2e/react-start/server-functions/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from e2e/react-start/server-functions/app/components/DefaultCatchBoundary.tsx rename to e2e/react-start/server-functions/src/components/DefaultCatchBoundary.tsx diff --git a/e2e/react-start/server-functions/app/components/NotFound.tsx b/e2e/react-start/server-functions/src/components/NotFound.tsx similarity index 100% rename from e2e/react-start/server-functions/app/components/NotFound.tsx rename to e2e/react-start/server-functions/src/components/NotFound.tsx diff --git a/e2e/react-start/server-functions/app/routeTree.gen.ts b/e2e/react-start/server-functions/src/routeTree.gen.ts similarity index 100% rename from e2e/react-start/server-functions/app/routeTree.gen.ts rename to e2e/react-start/server-functions/src/routeTree.gen.ts diff --git a/e2e/react-start/server-functions/app/router.tsx b/e2e/react-start/server-functions/src/router.tsx similarity index 100% rename from e2e/react-start/server-functions/app/router.tsx rename to e2e/react-start/server-functions/src/router.tsx diff --git a/e2e/react-start/server-functions/app/routes/__root.tsx b/e2e/react-start/server-functions/src/routes/__root.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/__root.tsx rename to e2e/react-start/server-functions/src/routes/__root.tsx diff --git a/e2e/react-start/server-functions/app/routes/abort-signal.tsx b/e2e/react-start/server-functions/src/routes/abort-signal.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/abort-signal.tsx rename to e2e/react-start/server-functions/src/routes/abort-signal.tsx diff --git a/e2e/react-start/server-functions/app/routes/consistent.tsx b/e2e/react-start/server-functions/src/routes/consistent.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/consistent.tsx rename to e2e/react-start/server-functions/src/routes/consistent.tsx diff --git a/e2e/react-start/server-functions/app/routes/cookies/index.tsx b/e2e/react-start/server-functions/src/routes/cookies/index.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/cookies/index.tsx rename to e2e/react-start/server-functions/src/routes/cookies/index.tsx diff --git a/e2e/react-start/server-functions/app/routes/cookies/set.tsx b/e2e/react-start/server-functions/src/routes/cookies/set.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/cookies/set.tsx rename to e2e/react-start/server-functions/src/routes/cookies/set.tsx diff --git a/e2e/react-start/server-functions/app/routes/dead-code-preserve.tsx b/e2e/react-start/server-functions/src/routes/dead-code-preserve.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/dead-code-preserve.tsx rename to e2e/react-start/server-functions/src/routes/dead-code-preserve.tsx diff --git a/e2e/react-start/server-functions/app/routes/env-only.tsx b/e2e/react-start/server-functions/src/routes/env-only.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/env-only.tsx rename to e2e/react-start/server-functions/src/routes/env-only.tsx diff --git a/e2e/react-start/server-functions/app/routes/headers.tsx b/e2e/react-start/server-functions/src/routes/headers.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/headers.tsx rename to e2e/react-start/server-functions/src/routes/headers.tsx diff --git a/e2e/react-start/server-functions/app/routes/index.tsx b/e2e/react-start/server-functions/src/routes/index.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/index.tsx rename to e2e/react-start/server-functions/src/routes/index.tsx diff --git a/e2e/react-start/server-functions/app/routes/isomorphic-fns.tsx b/e2e/react-start/server-functions/src/routes/isomorphic-fns.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/isomorphic-fns.tsx rename to e2e/react-start/server-functions/src/routes/isomorphic-fns.tsx diff --git a/e2e/react-start/server-functions/app/routes/multipart.tsx b/e2e/react-start/server-functions/src/routes/multipart.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/multipart.tsx rename to e2e/react-start/server-functions/src/routes/multipart.tsx diff --git a/e2e/react-start/server-functions/app/routes/raw-response.tsx b/e2e/react-start/server-functions/src/routes/raw-response.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/raw-response.tsx rename to e2e/react-start/server-functions/src/routes/raw-response.tsx diff --git a/e2e/react-start/server-functions/app/routes/return-null.tsx b/e2e/react-start/server-functions/src/routes/return-null.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/return-null.tsx rename to e2e/react-start/server-functions/src/routes/return-null.tsx diff --git a/e2e/react-start/server-functions/app/routes/serialize-form-data.tsx b/e2e/react-start/server-functions/src/routes/serialize-form-data.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/serialize-form-data.tsx rename to e2e/react-start/server-functions/src/routes/serialize-form-data.tsx diff --git a/e2e/react-start/server-functions/app/routes/status.tsx b/e2e/react-start/server-functions/src/routes/status.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/status.tsx rename to e2e/react-start/server-functions/src/routes/status.tsx diff --git a/e2e/react-start/server-functions/app/routes/submit-post-formdata.tsx b/e2e/react-start/server-functions/src/routes/submit-post-formdata.tsx similarity index 100% rename from e2e/react-start/server-functions/app/routes/submit-post-formdata.tsx rename to e2e/react-start/server-functions/src/routes/submit-post-formdata.tsx diff --git a/e2e/react-start/server-functions/app/styles/app.css b/e2e/react-start/server-functions/src/styles/app.css similarity index 100% rename from e2e/react-start/server-functions/app/styles/app.css rename to e2e/react-start/server-functions/src/styles/app.css diff --git a/examples/solid/start-bare/app/client.tsx b/e2e/solid-start/basic-tsr-config/src/client.tsx similarity index 83% rename from examples/solid/start-bare/app/client.tsx rename to e2e/solid-start/basic-tsr-config/src/client.tsx index ba0f02fac0..04f043feee 100644 --- a/examples/solid/start-bare/app/client.tsx +++ b/e2e/solid-start/basic-tsr-config/src/client.tsx @@ -1,7 +1,7 @@ /// import { hydrate } from 'solid-js/web' import { StartClient } from '@tanstack/solid-start' -import { createRouter } from './router' +import { createRouter } from './app/router' const router = createRouter() diff --git a/e2e/solid-start/basic-tsr-config/src/app/routeTree.gen.ts b/e2e/solid-start/basic-tsr-config/src/routeTree.gen.ts similarity index 96% rename from e2e/solid-start/basic-tsr-config/src/app/routeTree.gen.ts rename to e2e/solid-start/basic-tsr-config/src/routeTree.gen.ts index c260510053..7214e0cd01 100644 --- a/e2e/solid-start/basic-tsr-config/src/app/routeTree.gen.ts +++ b/e2e/solid-start/basic-tsr-config/src/routeTree.gen.ts @@ -11,7 +11,7 @@ // Import Routes import { Route as rootRoute } from './routes/__root' -import { Route as IndexImport } from './routes/index' +import { Route as IndexImport } from './app/routes/index' // Create/Update Routes diff --git a/e2e/solid-start/basic-tsr-config/src/app/router.tsx b/e2e/solid-start/basic-tsr-config/src/router.tsx similarity index 87% rename from e2e/solid-start/basic-tsr-config/src/app/router.tsx rename to e2e/solid-start/basic-tsr-config/src/router.tsx index e230377cb1..768813ab82 100644 --- a/e2e/solid-start/basic-tsr-config/src/app/router.tsx +++ b/e2e/solid-start/basic-tsr-config/src/router.tsx @@ -1,5 +1,5 @@ import { createRouter as createTanStackRouter } from '@tanstack/solid-router' -import { routeTree } from './routeTree.gen' +import { routeTree } from './app/routeTree.gen' export function createRouter() { const router = createTanStackRouter({ diff --git a/e2e/solid-start/basic-tsr-config/src/app/routes/__root.tsx b/e2e/solid-start/basic-tsr-config/src/routes/__root.tsx similarity index 100% rename from e2e/solid-start/basic-tsr-config/src/app/routes/__root.tsx rename to e2e/solid-start/basic-tsr-config/src/routes/__root.tsx diff --git a/e2e/solid-start/basic-tsr-config/src/app/routes/index.tsx b/e2e/solid-start/basic-tsr-config/src/routes/index.tsx similarity index 100% rename from e2e/solid-start/basic-tsr-config/src/app/routes/index.tsx rename to e2e/solid-start/basic-tsr-config/src/routes/index.tsx diff --git a/e2e/solid-start/website/app/ssr.tsx b/e2e/solid-start/basic-tsr-config/src/ssr.tsx similarity index 87% rename from e2e/solid-start/website/app/ssr.tsx rename to e2e/solid-start/basic-tsr-config/src/ssr.tsx index ebd14c8120..db95139de1 100644 --- a/e2e/solid-start/website/app/ssr.tsx +++ b/e2e/solid-start/basic-tsr-config/src/ssr.tsx @@ -5,7 +5,7 @@ import { } from '@tanstack/solid-start/server' import { getRouterManifest } from '@tanstack/solid-start/router-manifest' -import { createRouter } from './router' +import { createRouter } from './app/router' export default createStartHandler({ createRouter, diff --git a/e2e/solid-start/scroll-restoration/app/api.ts b/e2e/solid-start/scroll-restoration/src/api.ts similarity index 100% rename from e2e/solid-start/scroll-restoration/app/api.ts rename to e2e/solid-start/scroll-restoration/src/api.ts diff --git a/e2e/solid-start/basic-tsr-config/src/app/client.tsx b/e2e/solid-start/scroll-restoration/src/client.tsx similarity index 100% rename from e2e/solid-start/basic-tsr-config/src/app/client.tsx rename to e2e/solid-start/scroll-restoration/src/client.tsx diff --git a/e2e/solid-start/scroll-restoration/app/components/DefaultCatchBoundary.tsx b/e2e/solid-start/scroll-restoration/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from e2e/solid-start/scroll-restoration/app/components/DefaultCatchBoundary.tsx rename to e2e/solid-start/scroll-restoration/src/components/DefaultCatchBoundary.tsx diff --git a/e2e/solid-start/scroll-restoration/app/components/NotFound.tsx b/e2e/solid-start/scroll-restoration/src/components/NotFound.tsx similarity index 100% rename from e2e/solid-start/scroll-restoration/app/components/NotFound.tsx rename to e2e/solid-start/scroll-restoration/src/components/NotFound.tsx diff --git a/e2e/solid-start/scroll-restoration/app/routeTree.gen.ts b/e2e/solid-start/scroll-restoration/src/routeTree.gen.ts similarity index 100% rename from e2e/solid-start/scroll-restoration/app/routeTree.gen.ts rename to e2e/solid-start/scroll-restoration/src/routeTree.gen.ts diff --git a/e2e/solid-start/scroll-restoration/app/router.tsx b/e2e/solid-start/scroll-restoration/src/router.tsx similarity index 100% rename from e2e/solid-start/scroll-restoration/app/router.tsx rename to e2e/solid-start/scroll-restoration/src/router.tsx diff --git a/e2e/solid-start/scroll-restoration/app/routes/(tests)/normal-page.tsx b/e2e/solid-start/scroll-restoration/src/routes/(tests)/normal-page.tsx similarity index 100% rename from e2e/solid-start/scroll-restoration/app/routes/(tests)/normal-page.tsx rename to e2e/solid-start/scroll-restoration/src/routes/(tests)/normal-page.tsx diff --git a/e2e/solid-start/scroll-restoration/app/routes/(tests)/with-loader.tsx b/e2e/solid-start/scroll-restoration/src/routes/(tests)/with-loader.tsx similarity index 100% rename from e2e/solid-start/scroll-restoration/app/routes/(tests)/with-loader.tsx rename to e2e/solid-start/scroll-restoration/src/routes/(tests)/with-loader.tsx diff --git a/e2e/solid-start/scroll-restoration/app/routes/(tests)/with-search.tsx b/e2e/solid-start/scroll-restoration/src/routes/(tests)/with-search.tsx similarity index 100% rename from e2e/solid-start/scroll-restoration/app/routes/(tests)/with-search.tsx rename to e2e/solid-start/scroll-restoration/src/routes/(tests)/with-search.tsx diff --git a/e2e/solid-start/scroll-restoration/app/routes/-components/scroll-block.tsx b/e2e/solid-start/scroll-restoration/src/routes/-components/scroll-block.tsx similarity index 100% rename from e2e/solid-start/scroll-restoration/app/routes/-components/scroll-block.tsx rename to e2e/solid-start/scroll-restoration/src/routes/-components/scroll-block.tsx diff --git a/e2e/solid-start/scroll-restoration/app/routes/__root.tsx b/e2e/solid-start/scroll-restoration/src/routes/__root.tsx similarity index 93% rename from e2e/solid-start/scroll-restoration/app/routes/__root.tsx rename to e2e/solid-start/scroll-restoration/src/routes/__root.tsx index 5907fa6ecd..72e2c59c9e 100644 --- a/e2e/solid-start/scroll-restoration/app/routes/__root.tsx +++ b/e2e/solid-start/scroll-restoration/src/routes/__root.tsx @@ -7,10 +7,10 @@ import { HeadContent, Scripts, } from '@tanstack/solid-router' -import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' -import { NotFound } from '~/components/NotFound' +import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' +import { NotFound } from 'src/components/NotFound' import appCss from '~/styles/app.css?url' -import { seo } from '~/utils/seo' +import { seo } from 'src/utils/seo' import { Dynamic } from 'solid-js/web' import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools' diff --git a/e2e/solid-start/scroll-restoration/app/routes/index.tsx b/e2e/solid-start/scroll-restoration/src/routes/index.tsx similarity index 100% rename from e2e/solid-start/scroll-restoration/app/routes/index.tsx rename to e2e/solid-start/scroll-restoration/src/routes/index.tsx diff --git a/e2e/solid-start/scroll-restoration/app/ssr.tsx b/e2e/solid-start/scroll-restoration/src/ssr.tsx similarity index 100% rename from e2e/solid-start/scroll-restoration/app/ssr.tsx rename to e2e/solid-start/scroll-restoration/src/ssr.tsx diff --git a/e2e/solid-start/scroll-restoration/app/styles/app.css b/e2e/solid-start/scroll-restoration/src/styles/app.css similarity index 100% rename from e2e/solid-start/scroll-restoration/app/styles/app.css rename to e2e/solid-start/scroll-restoration/src/styles/app.css diff --git a/e2e/solid-start/scroll-restoration/app/utils/posts.tsx b/e2e/solid-start/scroll-restoration/src/utils/posts.tsx similarity index 100% rename from e2e/solid-start/scroll-restoration/app/utils/posts.tsx rename to e2e/solid-start/scroll-restoration/src/utils/posts.tsx diff --git a/e2e/solid-start/scroll-restoration/app/utils/seo.ts b/e2e/solid-start/scroll-restoration/src/utils/seo.ts similarity index 100% rename from e2e/solid-start/scroll-restoration/app/utils/seo.ts rename to e2e/solid-start/scroll-restoration/src/utils/seo.ts diff --git a/e2e/solid-start/scroll-restoration/app/utils/users.tsx b/e2e/solid-start/scroll-restoration/src/utils/users.tsx similarity index 100% rename from e2e/solid-start/scroll-restoration/app/utils/users.tsx rename to e2e/solid-start/scroll-restoration/src/utils/users.tsx diff --git a/e2e/solid-start/scroll-restoration/tsconfig.json b/e2e/solid-start/scroll-restoration/tsconfig.json index 73e4856648..3f2c37eff4 100644 --- a/e2e/solid-start/scroll-restoration/tsconfig.json +++ b/e2e/solid-start/scroll-restoration/tsconfig.json @@ -16,7 +16,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/e2e/solid-start/scroll-restoration/app/client.tsx b/e2e/solid-start/server-functions/src/client.tsx similarity index 100% rename from e2e/solid-start/scroll-restoration/app/client.tsx rename to e2e/solid-start/server-functions/src/client.tsx diff --git a/e2e/solid-start/server-functions/app/components/DefaultCatchBoundary.tsx b/e2e/solid-start/server-functions/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/components/DefaultCatchBoundary.tsx rename to e2e/solid-start/server-functions/src/components/DefaultCatchBoundary.tsx diff --git a/e2e/solid-start/server-functions/app/components/NotFound.tsx b/e2e/solid-start/server-functions/src/components/NotFound.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/components/NotFound.tsx rename to e2e/solid-start/server-functions/src/components/NotFound.tsx diff --git a/e2e/solid-start/server-functions/app/routeTree.gen.ts b/e2e/solid-start/server-functions/src/routeTree.gen.ts similarity index 100% rename from e2e/solid-start/server-functions/app/routeTree.gen.ts rename to e2e/solid-start/server-functions/src/routeTree.gen.ts diff --git a/e2e/solid-start/server-functions/app/router.tsx b/e2e/solid-start/server-functions/src/router.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/router.tsx rename to e2e/solid-start/server-functions/src/router.tsx diff --git a/e2e/solid-start/server-functions/app/routes/__root.tsx b/e2e/solid-start/server-functions/src/routes/__root.tsx similarity index 85% rename from e2e/solid-start/server-functions/app/routes/__root.tsx rename to e2e/solid-start/server-functions/src/routes/__root.tsx index 52d64bf7a7..6c801f97ad 100644 --- a/e2e/solid-start/server-functions/app/routes/__root.tsx +++ b/e2e/solid-start/server-functions/src/routes/__root.tsx @@ -1,7 +1,7 @@ import { Outlet, createRootRoute } from '@tanstack/solid-router' -import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' -import { NotFound } from '~/components/NotFound' +import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' +import { NotFound } from 'src/components/NotFound' import appCss from '~/styles/app.css?url' import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools' diff --git a/e2e/solid-start/server-functions/app/routes/abort-signal.tsx b/e2e/solid-start/server-functions/src/routes/abort-signal.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/abort-signal.tsx rename to e2e/solid-start/server-functions/src/routes/abort-signal.tsx diff --git a/e2e/solid-start/server-functions/app/routes/consistent.tsx b/e2e/solid-start/server-functions/src/routes/consistent.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/consistent.tsx rename to e2e/solid-start/server-functions/src/routes/consistent.tsx diff --git a/e2e/solid-start/server-functions/app/routes/cookies/index.tsx b/e2e/solid-start/server-functions/src/routes/cookies/index.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/cookies/index.tsx rename to e2e/solid-start/server-functions/src/routes/cookies/index.tsx diff --git a/e2e/solid-start/server-functions/app/routes/cookies/set.tsx b/e2e/solid-start/server-functions/src/routes/cookies/set.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/cookies/set.tsx rename to e2e/solid-start/server-functions/src/routes/cookies/set.tsx diff --git a/e2e/solid-start/server-functions/app/routes/dead-code-preserve.tsx b/e2e/solid-start/server-functions/src/routes/dead-code-preserve.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/dead-code-preserve.tsx rename to e2e/solid-start/server-functions/src/routes/dead-code-preserve.tsx diff --git a/e2e/solid-start/server-functions/app/routes/env-only.tsx b/e2e/solid-start/server-functions/src/routes/env-only.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/env-only.tsx rename to e2e/solid-start/server-functions/src/routes/env-only.tsx diff --git a/e2e/solid-start/server-functions/app/routes/headers.tsx b/e2e/solid-start/server-functions/src/routes/headers.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/headers.tsx rename to e2e/solid-start/server-functions/src/routes/headers.tsx diff --git a/e2e/solid-start/server-functions/app/routes/index.tsx b/e2e/solid-start/server-functions/src/routes/index.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/index.tsx rename to e2e/solid-start/server-functions/src/routes/index.tsx diff --git a/e2e/solid-start/server-functions/app/routes/isomorphic-fns.tsx b/e2e/solid-start/server-functions/src/routes/isomorphic-fns.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/isomorphic-fns.tsx rename to e2e/solid-start/server-functions/src/routes/isomorphic-fns.tsx diff --git a/e2e/solid-start/server-functions/app/routes/multipart.tsx b/e2e/solid-start/server-functions/src/routes/multipart.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/multipart.tsx rename to e2e/solid-start/server-functions/src/routes/multipart.tsx diff --git a/e2e/solid-start/server-functions/app/routes/raw-response.tsx b/e2e/solid-start/server-functions/src/routes/raw-response.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/raw-response.tsx rename to e2e/solid-start/server-functions/src/routes/raw-response.tsx diff --git a/e2e/solid-start/server-functions/app/routes/return-null.tsx b/e2e/solid-start/server-functions/src/routes/return-null.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/return-null.tsx rename to e2e/solid-start/server-functions/src/routes/return-null.tsx diff --git a/e2e/solid-start/server-functions/app/routes/serialize-form-data.tsx b/e2e/solid-start/server-functions/src/routes/serialize-form-data.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/serialize-form-data.tsx rename to e2e/solid-start/server-functions/src/routes/serialize-form-data.tsx diff --git a/e2e/solid-start/server-functions/app/routes/status.tsx b/e2e/solid-start/server-functions/src/routes/status.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/status.tsx rename to e2e/solid-start/server-functions/src/routes/status.tsx diff --git a/e2e/solid-start/server-functions/app/routes/submit-post-formdata.tsx b/e2e/solid-start/server-functions/src/routes/submit-post-formdata.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/routes/submit-post-formdata.tsx rename to e2e/solid-start/server-functions/src/routes/submit-post-formdata.tsx diff --git a/e2e/solid-start/server-functions/app/ssr.tsx b/e2e/solid-start/server-functions/src/ssr.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/ssr.tsx rename to e2e/solid-start/server-functions/src/ssr.tsx diff --git a/e2e/solid-start/server-functions/app/styles/app.css b/e2e/solid-start/server-functions/src/styles/app.css similarity index 100% rename from e2e/solid-start/server-functions/app/styles/app.css rename to e2e/solid-start/server-functions/src/styles/app.css diff --git a/e2e/solid-start/server-functions/tsconfig.json b/e2e/solid-start/server-functions/tsconfig.json index 7340ddd786..0dec3591e0 100644 --- a/e2e/solid-start/server-functions/tsconfig.json +++ b/e2e/solid-start/server-functions/tsconfig.json @@ -16,7 +16,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": "", "paths": { - "~/*": ["app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/e2e/solid-start/server-functions/app/client.tsx b/e2e/solid-start/website/src/client.tsx similarity index 100% rename from e2e/solid-start/server-functions/app/client.tsx rename to e2e/solid-start/website/src/client.tsx diff --git a/e2e/solid-start/website/app/components/DefaultCatchBoundary.tsx b/e2e/solid-start/website/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from e2e/solid-start/website/app/components/DefaultCatchBoundary.tsx rename to e2e/solid-start/website/src/components/DefaultCatchBoundary.tsx diff --git a/e2e/solid-start/website/app/components/NotFound.tsx b/e2e/solid-start/website/src/components/NotFound.tsx similarity index 100% rename from e2e/solid-start/website/app/components/NotFound.tsx rename to e2e/solid-start/website/src/components/NotFound.tsx diff --git a/e2e/solid-start/website/app/routeTree.gen.ts b/e2e/solid-start/website/src/routeTree.gen.ts similarity index 100% rename from e2e/solid-start/website/app/routeTree.gen.ts rename to e2e/solid-start/website/src/routeTree.gen.ts diff --git a/e2e/solid-start/website/app/router.tsx b/e2e/solid-start/website/src/router.tsx similarity index 100% rename from e2e/solid-start/website/app/router.tsx rename to e2e/solid-start/website/src/router.tsx diff --git a/e2e/solid-start/website/app/routes/$project.$version.docs.framework.$framework.$.tsx b/e2e/solid-start/website/src/routes/$project.$version.docs.framework.$framework.$.tsx similarity index 100% rename from e2e/solid-start/website/app/routes/$project.$version.docs.framework.$framework.$.tsx rename to e2e/solid-start/website/src/routes/$project.$version.docs.framework.$framework.$.tsx diff --git a/e2e/solid-start/website/app/routes/$project.$version.docs.framework.$framework.examples.$.tsx b/e2e/solid-start/website/src/routes/$project.$version.docs.framework.$framework.examples.$.tsx similarity index 100% rename from e2e/solid-start/website/app/routes/$project.$version.docs.framework.$framework.examples.$.tsx rename to e2e/solid-start/website/src/routes/$project.$version.docs.framework.$framework.examples.$.tsx diff --git a/e2e/solid-start/website/app/routes/$project.$version.docs.framework.$framework.index.tsx b/e2e/solid-start/website/src/routes/$project.$version.docs.framework.$framework.index.tsx similarity index 100% rename from e2e/solid-start/website/app/routes/$project.$version.docs.framework.$framework.index.tsx rename to e2e/solid-start/website/src/routes/$project.$version.docs.framework.$framework.index.tsx diff --git a/e2e/solid-start/website/app/routes/$project.$version.docs.framework.$framework.tsx b/e2e/solid-start/website/src/routes/$project.$version.docs.framework.$framework.tsx similarity index 100% rename from e2e/solid-start/website/app/routes/$project.$version.docs.framework.$framework.tsx rename to e2e/solid-start/website/src/routes/$project.$version.docs.framework.$framework.tsx diff --git a/e2e/solid-start/website/app/routes/$project.$version.docs.index.tsx b/e2e/solid-start/website/src/routes/$project.$version.docs.index.tsx similarity index 100% rename from e2e/solid-start/website/app/routes/$project.$version.docs.index.tsx rename to e2e/solid-start/website/src/routes/$project.$version.docs.index.tsx diff --git a/e2e/solid-start/website/app/routes/$project.index.tsx b/e2e/solid-start/website/src/routes/$project.index.tsx similarity index 100% rename from e2e/solid-start/website/app/routes/$project.index.tsx rename to e2e/solid-start/website/src/routes/$project.index.tsx diff --git a/e2e/solid-start/website/app/routes/__root.tsx b/e2e/solid-start/website/src/routes/__root.tsx similarity index 93% rename from e2e/solid-start/website/app/routes/__root.tsx rename to e2e/solid-start/website/src/routes/__root.tsx index d33148818f..b232d1f84a 100644 --- a/e2e/solid-start/website/app/routes/__root.tsx +++ b/e2e/solid-start/website/src/routes/__root.tsx @@ -1,8 +1,8 @@ import { Outlet, createRootRoute } from '@tanstack/solid-router' -import { NotFound } from '~/components/NotFound' +import { NotFound } from 'src/components/NotFound' import appCss from '~/styles/app.css?url' -import { seo } from '~/utils/seo' import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools' +import { seo } from 'src/utils/seo' export const Route = createRootRoute({ head: () => ({ diff --git a/e2e/solid-start/website/app/routes/_library.$project.$version.index.tsx b/e2e/solid-start/website/src/routes/_library.$project.$version.index.tsx similarity index 100% rename from e2e/solid-start/website/app/routes/_library.$project.$version.index.tsx rename to e2e/solid-start/website/src/routes/_library.$project.$version.index.tsx diff --git a/e2e/solid-start/website/app/routes/_library.$project.tsx b/e2e/solid-start/website/src/routes/_library.$project.tsx similarity index 81% rename from e2e/solid-start/website/app/routes/_library.$project.tsx rename to e2e/solid-start/website/src/routes/_library.$project.tsx index 6fdcb8e530..97e161065e 100644 --- a/e2e/solid-start/website/app/routes/_library.$project.tsx +++ b/e2e/solid-start/website/src/routes/_library.$project.tsx @@ -1,6 +1,6 @@ import { Outlet, createFileRoute } from '@tanstack/solid-router' -import { getProject } from '~/server/projects' -import { seo } from '~/utils/seo' +import { getProject } from 'src/server/projects' +import { seo } from 'src/utils/seo' export const Route = createFileRoute('/_library/$project')({ loader: ({ params: { project } }) => getProject({ data: project }), diff --git a/e2e/solid-start/website/app/routes/_library.index.tsx b/e2e/solid-start/website/src/routes/_library.index.tsx similarity index 100% rename from e2e/solid-start/website/app/routes/_library.index.tsx rename to e2e/solid-start/website/src/routes/_library.index.tsx diff --git a/e2e/solid-start/website/app/routes/_library.tsx b/e2e/solid-start/website/src/routes/_library.tsx similarity index 96% rename from e2e/solid-start/website/app/routes/_library.tsx rename to e2e/solid-start/website/src/routes/_library.tsx index c25ae5cfe1..3b1a7a406e 100644 --- a/e2e/solid-start/website/app/routes/_library.tsx +++ b/e2e/solid-start/website/src/routes/_library.tsx @@ -4,7 +4,7 @@ import { createFileRoute, useLocation, } from '@tanstack/solid-router' -import { getProjects } from '~/server/projects' +import { getProjects } from 'src/server/projects' export const Route = createFileRoute('/_library')({ loader: async () => { diff --git a/e2e/solid-start/website/app/server/document.tsx b/e2e/solid-start/website/src/server/document.tsx similarity index 100% rename from e2e/solid-start/website/app/server/document.tsx rename to e2e/solid-start/website/src/server/document.tsx diff --git a/e2e/solid-start/website/app/server/projects.tsx b/e2e/solid-start/website/src/server/projects.tsx similarity index 100% rename from e2e/solid-start/website/app/server/projects.tsx rename to e2e/solid-start/website/src/server/projects.tsx diff --git a/e2e/solid-start/basic-tsr-config/src/app/ssr.tsx b/e2e/solid-start/website/src/ssr.tsx similarity index 100% rename from e2e/solid-start/basic-tsr-config/src/app/ssr.tsx rename to e2e/solid-start/website/src/ssr.tsx diff --git a/e2e/solid-start/website/app/styles/app.css b/e2e/solid-start/website/src/styles/app.css similarity index 100% rename from e2e/solid-start/website/app/styles/app.css rename to e2e/solid-start/website/src/styles/app.css diff --git a/e2e/solid-start/website/app/utils/seo.ts b/e2e/solid-start/website/src/utils/seo.ts similarity index 100% rename from e2e/solid-start/website/app/utils/seo.ts rename to e2e/solid-start/website/src/utils/seo.ts diff --git a/e2e/solid-start/website/tsconfig.json b/e2e/solid-start/website/tsconfig.json index 86fe6d2cf5..8a61265d19 100644 --- a/e2e/solid-start/website/tsconfig.json +++ b/e2e/solid-start/website/tsconfig.json @@ -16,7 +16,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/examples/react/start-bare/app/api.ts b/examples/react/start-bare/src/api.ts similarity index 100% rename from examples/react/start-bare/app/api.ts rename to examples/react/start-bare/src/api.ts diff --git a/examples/react/start-bare/app/components/Counter.css b/examples/react/start-bare/src/components/Counter.css similarity index 100% rename from examples/react/start-bare/app/components/Counter.css rename to examples/react/start-bare/src/components/Counter.css diff --git a/examples/react/start-bare/app/components/Counter.tsx b/examples/react/start-bare/src/components/Counter.tsx similarity index 100% rename from examples/react/start-bare/app/components/Counter.tsx rename to examples/react/start-bare/src/components/Counter.tsx diff --git a/examples/react/start-bare/app/routeTree.gen.ts b/examples/react/start-bare/src/routeTree.gen.ts similarity index 100% rename from examples/react/start-bare/app/routeTree.gen.ts rename to examples/react/start-bare/src/routeTree.gen.ts diff --git a/examples/react/start-bare/app/router.tsx b/examples/react/start-bare/src/router.tsx similarity index 100% rename from examples/react/start-bare/app/router.tsx rename to examples/react/start-bare/src/router.tsx diff --git a/examples/react/start-bare/app/routes/__root.tsx b/examples/react/start-bare/src/routes/__root.tsx similarity index 100% rename from examples/react/start-bare/app/routes/__root.tsx rename to examples/react/start-bare/src/routes/__root.tsx diff --git a/examples/react/start-bare/app/routes/about.tsx b/examples/react/start-bare/src/routes/about.tsx similarity index 100% rename from examples/react/start-bare/app/routes/about.tsx rename to examples/react/start-bare/src/routes/about.tsx diff --git a/examples/react/start-bare/app/routes/index.tsx b/examples/react/start-bare/src/routes/index.tsx similarity index 86% rename from examples/react/start-bare/app/routes/index.tsx rename to examples/react/start-bare/src/routes/index.tsx index e9de615dc9..934654e3b8 100644 --- a/examples/react/start-bare/app/routes/index.tsx +++ b/examples/react/start-bare/src/routes/index.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/react-router' -import Counter from '~/components/Counter' +import Counter from 'src/components/Counter' export const Route = createFileRoute('/')({ component: RouteComponent, }) diff --git a/examples/react/start-bare/app/styles/app.css b/examples/react/start-bare/src/styles/app.css similarity index 100% rename from examples/react/start-bare/app/styles/app.css rename to examples/react/start-bare/src/styles/app.css diff --git a/examples/react/start-bare/tsconfig.json b/examples/react/start-bare/tsconfig.json index a6747faec5..23f12840c3 100644 --- a/examples/react/start-bare/tsconfig.json +++ b/examples/react/start-bare/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/examples/react/start-basic-auth/app/components/Auth.tsx b/examples/react/start-basic-auth/src/components/Auth.tsx similarity index 100% rename from examples/react/start-basic-auth/app/components/Auth.tsx rename to examples/react/start-basic-auth/src/components/Auth.tsx diff --git a/examples/react/start-basic-auth/app/components/DefaultCatchBoundary.tsx b/examples/react/start-basic-auth/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from examples/react/start-basic-auth/app/components/DefaultCatchBoundary.tsx rename to examples/react/start-basic-auth/src/components/DefaultCatchBoundary.tsx diff --git a/examples/react/start-basic-auth/app/components/Login.tsx b/examples/react/start-basic-auth/src/components/Login.tsx similarity index 97% rename from examples/react/start-basic-auth/app/components/Login.tsx rename to examples/react/start-basic-auth/src/components/Login.tsx index b6b6da0c37..9ba6b8f019 100644 --- a/examples/react/start-basic-auth/app/components/Login.tsx +++ b/examples/react/start-basic-auth/src/components/Login.tsx @@ -3,7 +3,7 @@ import { useServerFn } from '@tanstack/react-start' import { useMutation } from '../hooks/useMutation' import { loginFn } from '../routes/_authed' import { Auth } from './Auth' -import { signupFn } from '~/routes/signup' +import { signupFn } from 'src/routes/signup' export function Login() { const router = useRouter() diff --git a/examples/react/start-basic-auth/app/components/NotFound.tsx b/examples/react/start-basic-auth/src/components/NotFound.tsx similarity index 100% rename from examples/react/start-basic-auth/app/components/NotFound.tsx rename to examples/react/start-basic-auth/src/components/NotFound.tsx diff --git a/examples/react/start-basic-auth/app/hooks/useMutation.ts b/examples/react/start-basic-auth/src/hooks/useMutation.ts similarity index 100% rename from examples/react/start-basic-auth/app/hooks/useMutation.ts rename to examples/react/start-basic-auth/src/hooks/useMutation.ts diff --git a/examples/react/start-basic-auth/app/routeTree.gen.ts b/examples/react/start-basic-auth/src/routeTree.gen.ts similarity index 100% rename from examples/react/start-basic-auth/app/routeTree.gen.ts rename to examples/react/start-basic-auth/src/routeTree.gen.ts diff --git a/examples/react/start-basic-auth/app/router.tsx b/examples/react/start-basic-auth/src/router.tsx similarity index 100% rename from examples/react/start-basic-auth/app/router.tsx rename to examples/react/start-basic-auth/src/router.tsx diff --git a/examples/react/start-basic-auth/app/routes/__root.tsx b/examples/react/start-basic-auth/src/routes/__root.tsx similarity index 93% rename from examples/react/start-basic-auth/app/routes/__root.tsx rename to examples/react/start-basic-auth/src/routes/__root.tsx index 187cb0dc24..e286ac3499 100644 --- a/examples/react/start-basic-auth/app/routes/__root.tsx +++ b/examples/react/start-basic-auth/src/routes/__root.tsx @@ -8,11 +8,11 @@ import { import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' import { createServerFn } from '@tanstack/react-start' import * as React from 'react' -import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary.js' -import { NotFound } from '~/components/NotFound.js' +import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary.js' +import { NotFound } from 'src/components/NotFound.js' import appCss from '~/styles/app.css?url' -import { seo } from '~/utils/seo.js' -import { useAppSession } from '~/utils/session.js' +import { seo } from 'src/utils/seo.js' +import { useAppSession } from 'src/utils/session.js' const fetchUser = createServerFn({ method: 'GET' }).handler(async () => { // We need to auth on the server so we have access to secure cookies diff --git a/examples/react/start-basic-auth/app/routes/_authed.tsx b/examples/react/start-basic-auth/src/routes/_authed.tsx similarity index 88% rename from examples/react/start-basic-auth/app/routes/_authed.tsx rename to examples/react/start-basic-auth/src/routes/_authed.tsx index 0b1ae37317..183520c267 100644 --- a/examples/react/start-basic-auth/app/routes/_authed.tsx +++ b/examples/react/start-basic-auth/src/routes/_authed.tsx @@ -1,8 +1,8 @@ import { createFileRoute } from '@tanstack/react-router' import { createServerFn } from '@tanstack/react-start' -import { hashPassword, prismaClient } from '~/utils/prisma' -import { Login } from '~/components/Login' -import { useAppSession } from '~/utils/session' +import { hashPassword, prismaClient } from 'src/utils/prisma' +import { Login } from 'src/components/Login' +import { useAppSession } from 'src/utils/session' export const loginFn = createServerFn() .validator((d) => d as { email: string; password: string }) diff --git a/examples/react/start-clerk-basic/app/routes/_authed/posts.$postId.tsx b/examples/react/start-basic-auth/src/routes/_authed/posts.$postId.tsx similarity index 88% rename from examples/react/start-clerk-basic/app/routes/_authed/posts.$postId.tsx rename to examples/react/start-basic-auth/src/routes/_authed/posts.$postId.tsx index 039271bb89..763ac98f14 100644 --- a/examples/react/start-clerk-basic/app/routes/_authed/posts.$postId.tsx +++ b/examples/react/start-basic-auth/src/routes/_authed/posts.$postId.tsx @@ -1,7 +1,7 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from '~/components/NotFound.js' -import { fetchPost } from '~/utils/posts.js' +import { NotFound } from 'src/components/NotFound.js' +import { fetchPost } from 'src/utils/posts.js' export const Route = createFileRoute('/_authed/posts/$postId')({ loader: ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/examples/react/start-basic-auth/app/routes/_authed/posts.index.tsx b/examples/react/start-basic-auth/src/routes/_authed/posts.index.tsx similarity index 100% rename from examples/react/start-basic-auth/app/routes/_authed/posts.index.tsx rename to examples/react/start-basic-auth/src/routes/_authed/posts.index.tsx diff --git a/examples/react/start-basic-auth/app/routes/_authed/posts.route.tsx b/examples/react/start-basic-auth/src/routes/_authed/posts.route.tsx similarity index 95% rename from examples/react/start-basic-auth/app/routes/_authed/posts.route.tsx rename to examples/react/start-basic-auth/src/routes/_authed/posts.route.tsx index 86c8ef4138..a3144ce55a 100644 --- a/examples/react/start-basic-auth/app/routes/_authed/posts.route.tsx +++ b/examples/react/start-basic-auth/src/routes/_authed/posts.route.tsx @@ -1,5 +1,5 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from '~/utils/posts.js' +import { fetchPosts } from 'src/utils/posts.js' export const Route = createFileRoute('/_authed/posts')({ loader: () => fetchPosts(), diff --git a/examples/react/start-basic-auth/app/routes/index.tsx b/examples/react/start-basic-auth/src/routes/index.tsx similarity index 100% rename from examples/react/start-basic-auth/app/routes/index.tsx rename to examples/react/start-basic-auth/src/routes/index.tsx diff --git a/examples/react/start-basic-auth/app/routes/login.tsx b/examples/react/start-basic-auth/src/routes/login.tsx similarity index 79% rename from examples/react/start-basic-auth/app/routes/login.tsx rename to examples/react/start-basic-auth/src/routes/login.tsx index 03ced20832..4d06eaf91a 100644 --- a/examples/react/start-basic-auth/app/routes/login.tsx +++ b/examples/react/start-basic-auth/src/routes/login.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/react-router' -import { Login } from '~/components/Login' +import { Login } from 'src/components/Login' export const Route = createFileRoute('/login')({ component: LoginComp, diff --git a/examples/react/start-basic-auth/app/routes/logout.tsx b/examples/react/start-basic-auth/src/routes/logout.tsx similarity index 88% rename from examples/react/start-basic-auth/app/routes/logout.tsx rename to examples/react/start-basic-auth/src/routes/logout.tsx index d072c25008..5bed47b3ed 100644 --- a/examples/react/start-basic-auth/app/routes/logout.tsx +++ b/examples/react/start-basic-auth/src/routes/logout.tsx @@ -1,6 +1,6 @@ import { createFileRoute, redirect } from '@tanstack/react-router' import { createServerFn } from '@tanstack/react-start' -import { useAppSession } from '~/utils/session' +import { useAppSession } from 'src/utils/session' const logoutFn = createServerFn().handler(async () => { const session = await useAppSession() diff --git a/examples/react/start-basic-auth/app/routes/signup.tsx b/examples/react/start-basic-auth/src/routes/signup.tsx similarity index 91% rename from examples/react/start-basic-auth/app/routes/signup.tsx rename to examples/react/start-basic-auth/src/routes/signup.tsx index 8895af0579..d22930060b 100644 --- a/examples/react/start-basic-auth/app/routes/signup.tsx +++ b/examples/react/start-basic-auth/src/routes/signup.tsx @@ -1,9 +1,9 @@ import { createFileRoute, redirect } from '@tanstack/react-router' import { createServerFn, useServerFn } from '@tanstack/react-start' -import { hashPassword, prismaClient } from '~/utils/prisma' -import { useMutation } from '~/hooks/useMutation' -import { Auth } from '~/components/Auth' -import { useAppSession } from '~/utils/session' +import { hashPassword, prismaClient } from 'src/utils/prisma' +import { useMutation } from 'src/hooks/useMutation' +import { Auth } from 'src/components/Auth' +import { useAppSession } from 'src/utils/session' export const signupFn = createServerFn() .validator( diff --git a/examples/react/start-bare/app/server.ts b/examples/react/start-basic-auth/src/server.ts similarity index 100% rename from examples/react/start-bare/app/server.ts rename to examples/react/start-basic-auth/src/server.ts diff --git a/examples/react/start-basic-auth/app/styles/app.css b/examples/react/start-basic-auth/src/styles/app.css similarity index 100% rename from examples/react/start-basic-auth/app/styles/app.css rename to examples/react/start-basic-auth/src/styles/app.css diff --git a/examples/react/start-basic-auth/app/utils/posts.ts b/examples/react/start-basic-auth/src/utils/posts.ts similarity index 100% rename from examples/react/start-basic-auth/app/utils/posts.ts rename to examples/react/start-basic-auth/src/utils/posts.ts diff --git a/examples/react/start-basic-auth/app/utils/prisma.ts b/examples/react/start-basic-auth/src/utils/prisma.ts similarity index 100% rename from examples/react/start-basic-auth/app/utils/prisma.ts rename to examples/react/start-basic-auth/src/utils/prisma.ts diff --git a/examples/react/start-basic-auth/app/utils/seo.ts b/examples/react/start-basic-auth/src/utils/seo.ts similarity index 100% rename from examples/react/start-basic-auth/app/utils/seo.ts rename to examples/react/start-basic-auth/src/utils/seo.ts diff --git a/examples/react/start-basic-auth/app/utils/session.ts b/examples/react/start-basic-auth/src/utils/session.ts similarity index 100% rename from examples/react/start-basic-auth/app/utils/session.ts rename to examples/react/start-basic-auth/src/utils/session.ts diff --git a/examples/react/start-basic-auth/tsconfig.json b/examples/react/start-basic-auth/tsconfig.json index d1b5b77660..9a7cf62c30 100644 --- a/examples/react/start-basic-auth/tsconfig.json +++ b/examples/react/start-basic-auth/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/examples/react/start-basic-react-query/app/api.ts b/examples/react/start-basic-react-query/src/api.ts similarity index 100% rename from examples/react/start-basic-react-query/app/api.ts rename to examples/react/start-basic-react-query/src/api.ts diff --git a/examples/react/start-basic-react-query/app/components/DefaultCatchBoundary.tsx b/examples/react/start-basic-react-query/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/components/DefaultCatchBoundary.tsx rename to examples/react/start-basic-react-query/src/components/DefaultCatchBoundary.tsx diff --git a/examples/react/start-basic-react-query/app/components/NotFound.tsx b/examples/react/start-basic-react-query/src/components/NotFound.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/components/NotFound.tsx rename to examples/react/start-basic-react-query/src/components/NotFound.tsx diff --git a/examples/react/start-basic-react-query/app/routeTree.gen.ts b/examples/react/start-basic-react-query/src/routeTree.gen.ts similarity index 100% rename from examples/react/start-basic-react-query/app/routeTree.gen.ts rename to examples/react/start-basic-react-query/src/routeTree.gen.ts diff --git a/examples/react/start-basic-react-query/app/router.tsx b/examples/react/start-basic-react-query/src/router.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/router.tsx rename to examples/react/start-basic-react-query/src/router.tsx diff --git a/examples/react/start-basic-react-query/app/routes/__root.tsx b/examples/react/start-basic-react-query/src/routes/__root.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/__root.tsx rename to examples/react/start-basic-react-query/src/routes/__root.tsx diff --git a/examples/react/start-basic-react-query/app/routes/_pathlessLayout.tsx b/examples/react/start-basic-react-query/src/routes/_pathlessLayout.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/_pathlessLayout.tsx rename to examples/react/start-basic-react-query/src/routes/_pathlessLayout.tsx diff --git a/examples/react/start-basic-react-query/app/routes/_pathlessLayout/_nested-layout.tsx b/examples/react/start-basic-react-query/src/routes/_pathlessLayout/_nested-layout.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/_pathlessLayout/_nested-layout.tsx rename to examples/react/start-basic-react-query/src/routes/_pathlessLayout/_nested-layout.tsx diff --git a/examples/react/start-basic-react-query/app/routes/_pathlessLayout/_nested-layout/route-a.tsx b/examples/react/start-basic-react-query/src/routes/_pathlessLayout/_nested-layout/route-a.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/_pathlessLayout/_nested-layout/route-a.tsx rename to examples/react/start-basic-react-query/src/routes/_pathlessLayout/_nested-layout/route-a.tsx diff --git a/examples/react/start-basic-react-query/app/routes/_pathlessLayout/_nested-layout/route-b.tsx b/examples/react/start-basic-react-query/src/routes/_pathlessLayout/_nested-layout/route-b.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/_pathlessLayout/_nested-layout/route-b.tsx rename to examples/react/start-basic-react-query/src/routes/_pathlessLayout/_nested-layout/route-b.tsx diff --git a/examples/react/start-basic-react-query/app/routes/api.users.ts b/examples/react/start-basic-react-query/src/routes/api.users.ts similarity index 100% rename from examples/react/start-basic-react-query/app/routes/api.users.ts rename to examples/react/start-basic-react-query/src/routes/api.users.ts diff --git a/examples/react/start-basic-react-query/app/routes/api/users.$id.ts b/examples/react/start-basic-react-query/src/routes/api/users.$id.ts similarity index 100% rename from examples/react/start-basic-react-query/app/routes/api/users.$id.ts rename to examples/react/start-basic-react-query/src/routes/api/users.$id.ts diff --git a/examples/react/start-basic-react-query/app/routes/deferred.tsx b/examples/react/start-basic-react-query/src/routes/deferred.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/deferred.tsx rename to examples/react/start-basic-react-query/src/routes/deferred.tsx diff --git a/examples/react/start-basic-react-query/app/routes/index.tsx b/examples/react/start-basic-react-query/src/routes/index.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/index.tsx rename to examples/react/start-basic-react-query/src/routes/index.tsx diff --git a/examples/react/start-basic-react-query/app/routes/posts.$postId.tsx b/examples/react/start-basic-react-query/src/routes/posts.$postId.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/posts.$postId.tsx rename to examples/react/start-basic-react-query/src/routes/posts.$postId.tsx diff --git a/examples/react/start-basic-react-query/app/routes/posts.index.tsx b/examples/react/start-basic-react-query/src/routes/posts.index.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/posts.index.tsx rename to examples/react/start-basic-react-query/src/routes/posts.index.tsx diff --git a/examples/react/start-basic-react-query/app/routes/posts.route.tsx b/examples/react/start-basic-react-query/src/routes/posts.route.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/posts.route.tsx rename to examples/react/start-basic-react-query/src/routes/posts.route.tsx diff --git a/examples/react/start-basic-react-query/app/routes/posts_.$postId.deep.tsx b/examples/react/start-basic-react-query/src/routes/posts_.$postId.deep.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/posts_.$postId.deep.tsx rename to examples/react/start-basic-react-query/src/routes/posts_.$postId.deep.tsx diff --git a/examples/react/start-basic-react-query/app/routes/redirect.tsx b/examples/react/start-basic-react-query/src/routes/redirect.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/redirect.tsx rename to examples/react/start-basic-react-query/src/routes/redirect.tsx diff --git a/examples/react/start-basic-react-query/app/routes/users.$userId.tsx b/examples/react/start-basic-react-query/src/routes/users.$userId.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/users.$userId.tsx rename to examples/react/start-basic-react-query/src/routes/users.$userId.tsx diff --git a/examples/react/start-basic-react-query/app/routes/users.index.tsx b/examples/react/start-basic-react-query/src/routes/users.index.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/users.index.tsx rename to examples/react/start-basic-react-query/src/routes/users.index.tsx diff --git a/examples/react/start-basic-react-query/app/routes/users.route.tsx b/examples/react/start-basic-react-query/src/routes/users.route.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/routes/users.route.tsx rename to examples/react/start-basic-react-query/src/routes/users.route.tsx diff --git a/examples/react/start-basic-auth/app/server.ts b/examples/react/start-basic-react-query/src/server.ts similarity index 100% rename from examples/react/start-basic-auth/app/server.ts rename to examples/react/start-basic-react-query/src/server.ts diff --git a/examples/react/start-basic-react-query/app/styles/app.css b/examples/react/start-basic-react-query/src/styles/app.css similarity index 100% rename from examples/react/start-basic-react-query/app/styles/app.css rename to examples/react/start-basic-react-query/src/styles/app.css diff --git a/examples/react/start-basic-react-query/app/utils/posts.tsx b/examples/react/start-basic-react-query/src/utils/posts.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/utils/posts.tsx rename to examples/react/start-basic-react-query/src/utils/posts.tsx diff --git a/examples/react/start-basic-react-query/app/utils/seo.ts b/examples/react/start-basic-react-query/src/utils/seo.ts similarity index 100% rename from examples/react/start-basic-react-query/app/utils/seo.ts rename to examples/react/start-basic-react-query/src/utils/seo.ts diff --git a/examples/react/start-basic-react-query/app/utils/users.tsx b/examples/react/start-basic-react-query/src/utils/users.tsx similarity index 100% rename from examples/react/start-basic-react-query/app/utils/users.tsx rename to examples/react/start-basic-react-query/src/utils/users.tsx diff --git a/examples/react/start-basic-rsc/app/components/DefaultCatchBoundary.tsx b/examples/react/start-basic-rsc/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from examples/react/start-basic-rsc/app/components/DefaultCatchBoundary.tsx rename to examples/react/start-basic-rsc/src/components/DefaultCatchBoundary.tsx diff --git a/examples/react/start-basic-rsc/app/components/NotFound.tsx b/examples/react/start-basic-rsc/src/components/NotFound.tsx similarity index 100% rename from examples/react/start-basic-rsc/app/components/NotFound.tsx rename to examples/react/start-basic-rsc/src/components/NotFound.tsx diff --git a/examples/react/start-basic-rsc/app/routeTree.gen.ts b/examples/react/start-basic-rsc/src/routeTree.gen.ts similarity index 100% rename from examples/react/start-basic-rsc/app/routeTree.gen.ts rename to examples/react/start-basic-rsc/src/routeTree.gen.ts diff --git a/examples/react/start-basic-rsc/app/router.tsx b/examples/react/start-basic-rsc/src/router.tsx similarity index 100% rename from examples/react/start-basic-rsc/app/router.tsx rename to examples/react/start-basic-rsc/src/router.tsx diff --git a/examples/react/start-basic-rsc/app/routes/__root.tsx b/examples/react/start-basic-rsc/src/routes/__root.tsx similarity index 94% rename from examples/react/start-basic-rsc/app/routes/__root.tsx rename to examples/react/start-basic-rsc/src/routes/__root.tsx index 9d96f79ab3..137dea301c 100644 --- a/examples/react/start-basic-rsc/app/routes/__root.tsx +++ b/examples/react/start-basic-rsc/src/routes/__root.tsx @@ -7,10 +7,10 @@ import { } from '@tanstack/react-router' import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' import * as React from 'react' -import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' -import { NotFound } from '~/components/NotFound' +import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' +import { NotFound } from 'src/components/NotFound' import appCss from '~/styles/app.css?url' -import { seo } from '~/utils/seo' +import { seo } from 'src/utils/seo' export const Route = createRootRoute({ head: () => ({ diff --git a/examples/react/start-basic-rsc/app/routes/_pathlessLayout.tsx b/examples/react/start-basic-rsc/src/routes/_pathlessLayout.tsx similarity index 100% rename from examples/react/start-basic-rsc/app/routes/_pathlessLayout.tsx rename to examples/react/start-basic-rsc/src/routes/_pathlessLayout.tsx diff --git a/examples/react/start-basic-rsc/app/routes/_pathlessLayout/_nested-layout.tsx b/examples/react/start-basic-rsc/src/routes/_pathlessLayout/_nested-layout.tsx similarity index 100% rename from examples/react/start-basic-rsc/app/routes/_pathlessLayout/_nested-layout.tsx rename to examples/react/start-basic-rsc/src/routes/_pathlessLayout/_nested-layout.tsx diff --git a/examples/react/start-basic-rsc/app/routes/_pathlessLayout/_nested-layout/route-a.tsx b/examples/react/start-basic-rsc/src/routes/_pathlessLayout/_nested-layout/route-a.tsx similarity index 100% rename from examples/react/start-basic-rsc/app/routes/_pathlessLayout/_nested-layout/route-a.tsx rename to examples/react/start-basic-rsc/src/routes/_pathlessLayout/_nested-layout/route-a.tsx diff --git a/examples/react/start-basic-rsc/app/routes/_pathlessLayout/_nested-layout/route-b.tsx b/examples/react/start-basic-rsc/src/routes/_pathlessLayout/_nested-layout/route-b.tsx similarity index 100% rename from examples/react/start-basic-rsc/app/routes/_pathlessLayout/_nested-layout/route-b.tsx rename to examples/react/start-basic-rsc/src/routes/_pathlessLayout/_nested-layout/route-b.tsx diff --git a/examples/react/start-basic-rsc/app/routes/index.tsx b/examples/react/start-basic-rsc/src/routes/index.tsx similarity index 100% rename from examples/react/start-basic-rsc/app/routes/index.tsx rename to examples/react/start-basic-rsc/src/routes/index.tsx diff --git a/examples/react/start-basic-rsc/app/routes/posts.$postId.tsx b/examples/react/start-basic-rsc/src/routes/posts.$postId.tsx similarity index 96% rename from examples/react/start-basic-rsc/app/routes/posts.$postId.tsx rename to examples/react/start-basic-rsc/src/routes/posts.$postId.tsx index 5404a690a0..63a622a8e2 100644 --- a/examples/react/start-basic-rsc/app/routes/posts.$postId.tsx +++ b/examples/react/start-basic-rsc/src/routes/posts.$postId.tsx @@ -2,7 +2,7 @@ import { ErrorComponent, Link, createFileRoute } from '@tanstack/react-router' import { createServerFn } from '@tanstack/react-start' import { fetchPost } from '../utils/posts' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from '~/components/NotFound' +import { NotFound } from 'src/components/NotFound' const renderPost = createServerFn({ method: 'GET' }) .validator((postId: string) => postId) diff --git a/examples/react/start-basic-rsc/app/routes/posts.index.tsx b/examples/react/start-basic-rsc/src/routes/posts.index.tsx similarity index 100% rename from examples/react/start-basic-rsc/app/routes/posts.index.tsx rename to examples/react/start-basic-rsc/src/routes/posts.index.tsx diff --git a/examples/react/start-basic-rsc/app/routes/posts.tsx b/examples/react/start-basic-rsc/src/routes/posts.tsx similarity index 88% rename from examples/react/start-basic-rsc/app/routes/posts.tsx rename to examples/react/start-basic-rsc/src/routes/posts.tsx index a3ef2a2e20..5f544c568d 100644 --- a/examples/react/start-basic-rsc/app/routes/posts.tsx +++ b/examples/react/start-basic-rsc/src/routes/posts.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/react-router' import { createServerFn, renderRsc } from '@tanstack/react-start' -import { renderPosts } from '~/utils/renderPosts' +import { renderPosts } from 'src/utils/renderPosts' export const serverRenderPosts = createServerFn({ method: 'GET' }).handler( renderPosts, diff --git a/examples/react/start-basic-rsc/app/routes/posts_.$postId.deep.tsx b/examples/react/start-basic-rsc/src/routes/posts_.$postId.deep.tsx similarity index 100% rename from examples/react/start-basic-rsc/app/routes/posts_.$postId.deep.tsx rename to examples/react/start-basic-rsc/src/routes/posts_.$postId.deep.tsx diff --git a/examples/react/start-basic-react-query/app/server.ts b/examples/react/start-basic-rsc/src/server.ts similarity index 100% rename from examples/react/start-basic-react-query/app/server.ts rename to examples/react/start-basic-rsc/src/server.ts diff --git a/examples/react/start-basic-rsc/app/styles/app.css b/examples/react/start-basic-rsc/src/styles/app.css similarity index 100% rename from examples/react/start-basic-rsc/app/styles/app.css rename to examples/react/start-basic-rsc/src/styles/app.css diff --git a/examples/react/start-basic-rsc/app/utils/posts.tsx b/examples/react/start-basic-rsc/src/utils/posts.tsx similarity index 100% rename from examples/react/start-basic-rsc/app/utils/posts.tsx rename to examples/react/start-basic-rsc/src/utils/posts.tsx diff --git a/examples/react/start-basic-rsc/app/utils/renderPosts.tsx b/examples/react/start-basic-rsc/src/utils/renderPosts.tsx similarity index 100% rename from examples/react/start-basic-rsc/app/utils/renderPosts.tsx rename to examples/react/start-basic-rsc/src/utils/renderPosts.tsx diff --git a/examples/react/start-basic-rsc/app/utils/seo.ts b/examples/react/start-basic-rsc/src/utils/seo.ts similarity index 100% rename from examples/react/start-basic-rsc/app/utils/seo.ts rename to examples/react/start-basic-rsc/src/utils/seo.ts diff --git a/examples/react/start-basic-rsc/tsconfig.json b/examples/react/start-basic-rsc/tsconfig.json index d1b5b77660..9a7cf62c30 100644 --- a/examples/react/start-basic-rsc/tsconfig.json +++ b/examples/react/start-basic-rsc/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/examples/react/start-basic-static/app/routes/__root.tsx b/examples/react/start-basic-static/app/routes/__root.tsx deleted file mode 100644 index 70140f2306..0000000000 --- a/examples/react/start-basic-static/app/routes/__root.tsx +++ /dev/null @@ -1,139 +0,0 @@ -import { - HeadContent, - Link, - Outlet, - Scripts, - createRootRoute, -} from '@tanstack/react-router' -import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' -import * as React from 'react' -import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' -import { NotFound } from '~/components/NotFound' -import appCss from '~/styles/app.css?url' -import { seo } from '~/utils/seo' - -export const Route = createRootRoute({ - head: () => ({ - meta: [ - { - charSet: 'utf-8', - }, - { - name: 'viewport', - content: 'width=device-width, initial-scale=1', - }, - ...seo({ - title: - 'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework', - description: `TanStack Start is a type-safe, client-first, full-stack React framework. `, - }), - ], - links: [ - { rel: 'stylesheet', href: appCss }, - { - rel: 'apple-touch-icon', - sizes: '180x180', - href: '/apple-touch-icon.png', - }, - { - rel: 'icon', - type: 'image/png', - sizes: '32x32', - href: '/favicon-32x32.png', - }, - { - rel: 'icon', - type: 'image/png', - sizes: '16x16', - href: '/favicon-16x16.png', - }, - { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' }, - { rel: 'icon', href: '/favicon.ico' }, - ], - }), - errorComponent: (props) => { - return ( - - - - ) - }, - notFoundComponent: () => , - component: RootComponent, -}) - -function RootComponent() { - return ( - - - - ) -} - -function RootDocument({ children }: { children: React.ReactNode }) { - return ( - - - - - -
- - Home - {' '} - - Posts - {' '} - - Users - {' '} - - Pathless Layout - {' '} - - Deferred - {' '} - - This Route Does Not Exist - -
-
- {children} - - - - - ) -} diff --git a/examples/react/start-basic-static/app/components/DefaultCatchBoundary.tsx b/examples/react/start-basic-static/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from examples/react/start-basic-static/app/components/DefaultCatchBoundary.tsx rename to examples/react/start-basic-static/src/components/DefaultCatchBoundary.tsx diff --git a/examples/react/start-basic-static/app/components/NotFound.tsx b/examples/react/start-basic-static/src/components/NotFound.tsx similarity index 100% rename from examples/react/start-basic-static/app/components/NotFound.tsx rename to examples/react/start-basic-static/src/components/NotFound.tsx diff --git a/examples/react/start-basic-static/app/routeTree.gen.ts b/examples/react/start-basic-static/src/routeTree.gen.ts similarity index 100% rename from examples/react/start-basic-static/app/routeTree.gen.ts rename to examples/react/start-basic-static/src/routeTree.gen.ts diff --git a/examples/react/start-basic-static/app/router.tsx b/examples/react/start-basic-static/src/router.tsx similarity index 100% rename from examples/react/start-basic-static/app/router.tsx rename to examples/react/start-basic-static/src/router.tsx diff --git a/examples/react/start-basic/app/routes/__root.tsx b/examples/react/start-basic-static/src/routes/__root.tsx similarity index 95% rename from examples/react/start-basic/app/routes/__root.tsx rename to examples/react/start-basic-static/src/routes/__root.tsx index 70140f2306..170fcca832 100644 --- a/examples/react/start-basic/app/routes/__root.tsx +++ b/examples/react/start-basic-static/src/routes/__root.tsx @@ -7,10 +7,10 @@ import { } from '@tanstack/react-router' import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' import * as React from 'react' -import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' -import { NotFound } from '~/components/NotFound' +import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' +import { NotFound } from 'src/components/NotFound' import appCss from '~/styles/app.css?url' -import { seo } from '~/utils/seo' +import { seo } from 'src/utils/seo' export const Route = createRootRoute({ head: () => ({ diff --git a/examples/react/start-basic-static/app/routes/_pathlessLayout.tsx b/examples/react/start-basic-static/src/routes/_pathlessLayout.tsx similarity index 100% rename from examples/react/start-basic-static/app/routes/_pathlessLayout.tsx rename to examples/react/start-basic-static/src/routes/_pathlessLayout.tsx diff --git a/examples/react/start-basic-static/app/routes/_pathlessLayout/_nested-layout.tsx b/examples/react/start-basic-static/src/routes/_pathlessLayout/_nested-layout.tsx similarity index 100% rename from examples/react/start-basic-static/app/routes/_pathlessLayout/_nested-layout.tsx rename to examples/react/start-basic-static/src/routes/_pathlessLayout/_nested-layout.tsx diff --git a/examples/react/start-basic-static/app/routes/_pathlessLayout/_nested-layout/route-a.tsx b/examples/react/start-basic-static/src/routes/_pathlessLayout/_nested-layout/route-a.tsx similarity index 100% rename from examples/react/start-basic-static/app/routes/_pathlessLayout/_nested-layout/route-a.tsx rename to examples/react/start-basic-static/src/routes/_pathlessLayout/_nested-layout/route-a.tsx diff --git a/examples/react/start-basic-static/app/routes/_pathlessLayout/_nested-layout/route-b.tsx b/examples/react/start-basic-static/src/routes/_pathlessLayout/_nested-layout/route-b.tsx similarity index 100% rename from examples/react/start-basic-static/app/routes/_pathlessLayout/_nested-layout/route-b.tsx rename to examples/react/start-basic-static/src/routes/_pathlessLayout/_nested-layout/route-b.tsx diff --git a/examples/react/start-basic-static/app/routes/deferred.tsx b/examples/react/start-basic-static/src/routes/deferred.tsx similarity index 100% rename from examples/react/start-basic-static/app/routes/deferred.tsx rename to examples/react/start-basic-static/src/routes/deferred.tsx diff --git a/examples/react/start-basic-static/app/routes/index.tsx b/examples/react/start-basic-static/src/routes/index.tsx similarity index 100% rename from examples/react/start-basic-static/app/routes/index.tsx rename to examples/react/start-basic-static/src/routes/index.tsx diff --git a/examples/react/start-basic-static/app/routes/posts.$postId.tsx b/examples/react/start-basic-static/src/routes/posts.$postId.tsx similarity index 95% rename from examples/react/start-basic-static/app/routes/posts.$postId.tsx rename to examples/react/start-basic-static/src/routes/posts.$postId.tsx index 0d4d2de8eb..6a1f72bb07 100644 --- a/examples/react/start-basic-static/app/routes/posts.$postId.tsx +++ b/examples/react/start-basic-static/src/routes/posts.$postId.tsx @@ -1,7 +1,7 @@ import { ErrorComponent, Link, createFileRoute } from '@tanstack/react-router' import { fetchPost } from '../utils/posts' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from '~/components/NotFound' +import { NotFound } from 'src/components/NotFound' export const Route = createFileRoute('/posts/$postId')({ loader: ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/examples/react/start-basic-static/app/routes/posts.index.tsx b/examples/react/start-basic-static/src/routes/posts.index.tsx similarity index 100% rename from examples/react/start-basic-static/app/routes/posts.index.tsx rename to examples/react/start-basic-static/src/routes/posts.index.tsx diff --git a/examples/react/start-basic-static/app/routes/posts.tsx b/examples/react/start-basic-static/src/routes/posts.tsx similarity index 100% rename from examples/react/start-basic-static/app/routes/posts.tsx rename to examples/react/start-basic-static/src/routes/posts.tsx diff --git a/examples/react/start-basic-static/app/routes/posts_.$postId.deep.tsx b/examples/react/start-basic-static/src/routes/posts_.$postId.deep.tsx similarity index 100% rename from examples/react/start-basic-static/app/routes/posts_.$postId.deep.tsx rename to examples/react/start-basic-static/src/routes/posts_.$postId.deep.tsx diff --git a/examples/react/start-basic-static/app/routes/redirect.tsx b/examples/react/start-basic-static/src/routes/redirect.tsx similarity index 100% rename from examples/react/start-basic-static/app/routes/redirect.tsx rename to examples/react/start-basic-static/src/routes/redirect.tsx diff --git a/examples/react/start-basic-static/app/routes/users.$userId.tsx b/examples/react/start-basic-static/src/routes/users.$userId.tsx similarity index 93% rename from examples/react/start-basic-static/app/routes/users.$userId.tsx rename to examples/react/start-basic-static/src/routes/users.$userId.tsx index d166885e29..bbc21f1274 100644 --- a/examples/react/start-basic-static/app/routes/users.$userId.tsx +++ b/examples/react/start-basic-static/src/routes/users.$userId.tsx @@ -2,8 +2,8 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import axios from 'redaxios' import { createServerFn } from '@tanstack/react-start' import type { ErrorComponentProps } from '@tanstack/react-router' -import type { User } from '~/utils/users' -import { NotFound } from '~/components/NotFound' +import type { User } from 'src/utils/users' +import { NotFound } from 'src/components/NotFound' const fetchUser = createServerFn({ method: 'GET', type: 'static' }) .validator((d: string) => d) diff --git a/examples/react/start-basic-static/app/routes/users.index.tsx b/examples/react/start-basic-static/src/routes/users.index.tsx similarity index 100% rename from examples/react/start-basic-static/app/routes/users.index.tsx rename to examples/react/start-basic-static/src/routes/users.index.tsx diff --git a/examples/react/start-basic-static/app/routes/users.tsx b/examples/react/start-basic-static/src/routes/users.tsx similarity index 100% rename from examples/react/start-basic-static/app/routes/users.tsx rename to examples/react/start-basic-static/src/routes/users.tsx diff --git a/examples/react/start-basic-rsc/app/server.ts b/examples/react/start-basic-static/src/server.ts similarity index 100% rename from examples/react/start-basic-rsc/app/server.ts rename to examples/react/start-basic-static/src/server.ts diff --git a/examples/react/start-basic-static/app/styles/app.css b/examples/react/start-basic-static/src/styles/app.css similarity index 100% rename from examples/react/start-basic-static/app/styles/app.css rename to examples/react/start-basic-static/src/styles/app.css diff --git a/examples/react/start-basic-static/app/utils/loggingMiddleware.tsx b/examples/react/start-basic-static/src/utils/loggingMiddleware.tsx similarity index 100% rename from examples/react/start-basic-static/app/utils/loggingMiddleware.tsx rename to examples/react/start-basic-static/src/utils/loggingMiddleware.tsx diff --git a/examples/react/start-basic-static/app/utils/posts.tsx b/examples/react/start-basic-static/src/utils/posts.tsx similarity index 100% rename from examples/react/start-basic-static/app/utils/posts.tsx rename to examples/react/start-basic-static/src/utils/posts.tsx diff --git a/examples/react/start-basic-static/app/utils/seo.ts b/examples/react/start-basic-static/src/utils/seo.ts similarity index 100% rename from examples/react/start-basic-static/app/utils/seo.ts rename to examples/react/start-basic-static/src/utils/seo.ts diff --git a/examples/react/start-basic-static/app/utils/users.tsx b/examples/react/start-basic-static/src/utils/users.tsx similarity index 100% rename from examples/react/start-basic-static/app/utils/users.tsx rename to examples/react/start-basic-static/src/utils/users.tsx diff --git a/examples/react/start-basic-static/tsconfig.json b/examples/react/start-basic-static/tsconfig.json index d1b5b77660..9a7cf62c30 100644 --- a/examples/react/start-basic-static/tsconfig.json +++ b/examples/react/start-basic-static/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/examples/react/start-basic/app/routeTree.gen.ts b/examples/react/start-basic/app/routeTree.gen.ts deleted file mode 100644 index 762ce1516f..0000000000 --- a/examples/react/start-basic/app/routeTree.gen.ts +++ /dev/null @@ -1,479 +0,0 @@ -/* eslint-disable */ - -// @ts-nocheck - -// noinspection JSUnusedGlobalSymbols - -// This file was automatically generated by TanStack Router. -// You should NOT make any changes in this file as it will be overwritten. -// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. - -// Import Routes - -import { Route as rootRoute } from './routes/__root' -import { Route as UsersImport } from './routes/users' -import { Route as RedirectImport } from './routes/redirect' -import { Route as PostsImport } from './routes/posts' -import { Route as DeferredImport } from './routes/deferred' -import { Route as PathlessLayoutImport } from './routes/_pathlessLayout' -import { Route as IndexImport } from './routes/index' -import { Route as UsersIndexImport } from './routes/users.index' -import { Route as PostsIndexImport } from './routes/posts.index' -import { Route as UsersUserIdImport } from './routes/users.$userId' -import { Route as PostsPostIdImport } from './routes/posts.$postId' -import { Route as PathlessLayoutNestedLayoutImport } from './routes/_pathlessLayout/_nested-layout' -import { Route as PostsPostIdDeepImport } from './routes/posts_.$postId.deep' -import { Route as PathlessLayoutNestedLayoutRouteBImport } from './routes/_pathlessLayout/_nested-layout/route-b' -import { Route as PathlessLayoutNestedLayoutRouteAImport } from './routes/_pathlessLayout/_nested-layout/route-a' - -// Create/Update Routes - -const UsersRoute = UsersImport.update({ - id: '/users', - path: '/users', - getParentRoute: () => rootRoute, -} as any) - -const RedirectRoute = RedirectImport.update({ - id: '/redirect', - path: '/redirect', - getParentRoute: () => rootRoute, -} as any) - -const PostsRoute = PostsImport.update({ - id: '/posts', - path: '/posts', - getParentRoute: () => rootRoute, -} as any) - -const DeferredRoute = DeferredImport.update({ - id: '/deferred', - path: '/deferred', - getParentRoute: () => rootRoute, -} as any) - -const PathlessLayoutRoute = PathlessLayoutImport.update({ - id: '/_pathlessLayout', - getParentRoute: () => rootRoute, -} as any) - -const IndexRoute = IndexImport.update({ - id: '/', - path: '/', - getParentRoute: () => rootRoute, -} as any) - -const UsersIndexRoute = UsersIndexImport.update({ - id: '/', - path: '/', - getParentRoute: () => UsersRoute, -} as any) - -const PostsIndexRoute = PostsIndexImport.update({ - id: '/', - path: '/', - getParentRoute: () => PostsRoute, -} as any) - -const UsersUserIdRoute = UsersUserIdImport.update({ - id: '/$userId', - path: '/$userId', - getParentRoute: () => UsersRoute, -} as any) - -const PostsPostIdRoute = PostsPostIdImport.update({ - id: '/$postId', - path: '/$postId', - getParentRoute: () => PostsRoute, -} as any) - -const PathlessLayoutNestedLayoutRoute = PathlessLayoutNestedLayoutImport.update( - { - id: '/_nested-layout', - getParentRoute: () => PathlessLayoutRoute, - } as any, -) - -const PostsPostIdDeepRoute = PostsPostIdDeepImport.update({ - id: '/posts_/$postId/deep', - path: '/posts/$postId/deep', - getParentRoute: () => rootRoute, -} as any) - -const PathlessLayoutNestedLayoutRouteBRoute = - PathlessLayoutNestedLayoutRouteBImport.update({ - id: '/route-b', - path: '/route-b', - getParentRoute: () => PathlessLayoutNestedLayoutRoute, - } as any) - -const PathlessLayoutNestedLayoutRouteARoute = - PathlessLayoutNestedLayoutRouteAImport.update({ - id: '/route-a', - path: '/route-a', - getParentRoute: () => PathlessLayoutNestedLayoutRoute, - } as any) - -// Populate the FileRoutesByPath interface - -declare module '@tanstack/react-router' { - interface FileRoutesByPath { - '/': { - id: '/' - path: '/' - fullPath: '/' - preLoaderRoute: typeof IndexImport - parentRoute: typeof rootRoute - } - '/_pathlessLayout': { - id: '/_pathlessLayout' - path: '' - fullPath: '' - preLoaderRoute: typeof PathlessLayoutImport - parentRoute: typeof rootRoute - } - '/deferred': { - id: '/deferred' - path: '/deferred' - fullPath: '/deferred' - preLoaderRoute: typeof DeferredImport - parentRoute: typeof rootRoute - } - '/posts': { - id: '/posts' - path: '/posts' - fullPath: '/posts' - preLoaderRoute: typeof PostsImport - parentRoute: typeof rootRoute - } - '/redirect': { - id: '/redirect' - path: '/redirect' - fullPath: '/redirect' - preLoaderRoute: typeof RedirectImport - parentRoute: typeof rootRoute - } - '/users': { - id: '/users' - path: '/users' - fullPath: '/users' - preLoaderRoute: typeof UsersImport - parentRoute: typeof rootRoute - } - '/_pathlessLayout/_nested-layout': { - id: '/_pathlessLayout/_nested-layout' - path: '' - fullPath: '' - preLoaderRoute: typeof PathlessLayoutNestedLayoutImport - parentRoute: typeof PathlessLayoutImport - } - '/posts/$postId': { - id: '/posts/$postId' - path: '/$postId' - fullPath: '/posts/$postId' - preLoaderRoute: typeof PostsPostIdImport - parentRoute: typeof PostsImport - } - '/users/$userId': { - id: '/users/$userId' - path: '/$userId' - fullPath: '/users/$userId' - preLoaderRoute: typeof UsersUserIdImport - parentRoute: typeof UsersImport - } - '/posts/': { - id: '/posts/' - path: '/' - fullPath: '/posts/' - preLoaderRoute: typeof PostsIndexImport - parentRoute: typeof PostsImport - } - '/users/': { - id: '/users/' - path: '/' - fullPath: '/users/' - preLoaderRoute: typeof UsersIndexImport - parentRoute: typeof UsersImport - } - '/_pathlessLayout/_nested-layout/route-a': { - id: '/_pathlessLayout/_nested-layout/route-a' - path: '/route-a' - fullPath: '/route-a' - preLoaderRoute: typeof PathlessLayoutNestedLayoutRouteAImport - parentRoute: typeof PathlessLayoutNestedLayoutImport - } - '/_pathlessLayout/_nested-layout/route-b': { - id: '/_pathlessLayout/_nested-layout/route-b' - path: '/route-b' - fullPath: '/route-b' - preLoaderRoute: typeof PathlessLayoutNestedLayoutRouteBImport - parentRoute: typeof PathlessLayoutNestedLayoutImport - } - '/posts_/$postId/deep': { - id: '/posts_/$postId/deep' - path: '/posts/$postId/deep' - fullPath: '/posts/$postId/deep' - preLoaderRoute: typeof PostsPostIdDeepImport - parentRoute: typeof rootRoute - } - } -} - -// Create and export the route tree - -interface PathlessLayoutNestedLayoutRouteChildren { - PathlessLayoutNestedLayoutRouteARoute: typeof PathlessLayoutNestedLayoutRouteARoute - PathlessLayoutNestedLayoutRouteBRoute: typeof PathlessLayoutNestedLayoutRouteBRoute -} - -const PathlessLayoutNestedLayoutRouteChildren: PathlessLayoutNestedLayoutRouteChildren = - { - PathlessLayoutNestedLayoutRouteARoute: - PathlessLayoutNestedLayoutRouteARoute, - PathlessLayoutNestedLayoutRouteBRoute: - PathlessLayoutNestedLayoutRouteBRoute, - } - -const PathlessLayoutNestedLayoutRouteWithChildren = - PathlessLayoutNestedLayoutRoute._addFileChildren( - PathlessLayoutNestedLayoutRouteChildren, - ) - -interface PathlessLayoutRouteChildren { - PathlessLayoutNestedLayoutRoute: typeof PathlessLayoutNestedLayoutRouteWithChildren -} - -const PathlessLayoutRouteChildren: PathlessLayoutRouteChildren = { - PathlessLayoutNestedLayoutRoute: PathlessLayoutNestedLayoutRouteWithChildren, -} - -const PathlessLayoutRouteWithChildren = PathlessLayoutRoute._addFileChildren( - PathlessLayoutRouteChildren, -) - -interface PostsRouteChildren { - PostsPostIdRoute: typeof PostsPostIdRoute - PostsIndexRoute: typeof PostsIndexRoute -} - -const PostsRouteChildren: PostsRouteChildren = { - PostsPostIdRoute: PostsPostIdRoute, - PostsIndexRoute: PostsIndexRoute, -} - -const PostsRouteWithChildren = PostsRoute._addFileChildren(PostsRouteChildren) - -interface UsersRouteChildren { - UsersUserIdRoute: typeof UsersUserIdRoute - UsersIndexRoute: typeof UsersIndexRoute -} - -const UsersRouteChildren: UsersRouteChildren = { - UsersUserIdRoute: UsersUserIdRoute, - UsersIndexRoute: UsersIndexRoute, -} - -const UsersRouteWithChildren = UsersRoute._addFileChildren(UsersRouteChildren) - -export interface FileRoutesByFullPath { - '/': typeof IndexRoute - '': typeof PathlessLayoutNestedLayoutRouteWithChildren - '/deferred': typeof DeferredRoute - '/posts': typeof PostsRouteWithChildren - '/redirect': typeof RedirectRoute - '/users': typeof UsersRouteWithChildren - '/posts/$postId': typeof PostsPostIdRoute - '/users/$userId': typeof UsersUserIdRoute - '/posts/': typeof PostsIndexRoute - '/users/': typeof UsersIndexRoute - '/route-a': typeof PathlessLayoutNestedLayoutRouteARoute - '/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute - '/posts/$postId/deep': typeof PostsPostIdDeepRoute -} - -export interface FileRoutesByTo { - '/': typeof IndexRoute - '': typeof PathlessLayoutNestedLayoutRouteWithChildren - '/deferred': typeof DeferredRoute - '/redirect': typeof RedirectRoute - '/posts/$postId': typeof PostsPostIdRoute - '/users/$userId': typeof UsersUserIdRoute - '/posts': typeof PostsIndexRoute - '/users': typeof UsersIndexRoute - '/route-a': typeof PathlessLayoutNestedLayoutRouteARoute - '/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute - '/posts/$postId/deep': typeof PostsPostIdDeepRoute -} - -export interface FileRoutesById { - __root__: typeof rootRoute - '/': typeof IndexRoute - '/_pathlessLayout': typeof PathlessLayoutRouteWithChildren - '/deferred': typeof DeferredRoute - '/posts': typeof PostsRouteWithChildren - '/redirect': typeof RedirectRoute - '/users': typeof UsersRouteWithChildren - '/_pathlessLayout/_nested-layout': typeof PathlessLayoutNestedLayoutRouteWithChildren - '/posts/$postId': typeof PostsPostIdRoute - '/users/$userId': typeof UsersUserIdRoute - '/posts/': typeof PostsIndexRoute - '/users/': typeof UsersIndexRoute - '/_pathlessLayout/_nested-layout/route-a': typeof PathlessLayoutNestedLayoutRouteARoute - '/_pathlessLayout/_nested-layout/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute - '/posts_/$postId/deep': typeof PostsPostIdDeepRoute -} - -export interface FileRouteTypes { - fileRoutesByFullPath: FileRoutesByFullPath - fullPaths: - | '/' - | '' - | '/deferred' - | '/posts' - | '/redirect' - | '/users' - | '/posts/$postId' - | '/users/$userId' - | '/posts/' - | '/users/' - | '/route-a' - | '/route-b' - | '/posts/$postId/deep' - fileRoutesByTo: FileRoutesByTo - to: - | '/' - | '' - | '/deferred' - | '/redirect' - | '/posts/$postId' - | '/users/$userId' - | '/posts' - | '/users' - | '/route-a' - | '/route-b' - | '/posts/$postId/deep' - id: - | '__root__' - | '/' - | '/_pathlessLayout' - | '/deferred' - | '/posts' - | '/redirect' - | '/users' - | '/_pathlessLayout/_nested-layout' - | '/posts/$postId' - | '/users/$userId' - | '/posts/' - | '/users/' - | '/_pathlessLayout/_nested-layout/route-a' - | '/_pathlessLayout/_nested-layout/route-b' - | '/posts_/$postId/deep' - fileRoutesById: FileRoutesById -} - -export interface RootRouteChildren { - IndexRoute: typeof IndexRoute - PathlessLayoutRoute: typeof PathlessLayoutRouteWithChildren - DeferredRoute: typeof DeferredRoute - PostsRoute: typeof PostsRouteWithChildren - RedirectRoute: typeof RedirectRoute - UsersRoute: typeof UsersRouteWithChildren - PostsPostIdDeepRoute: typeof PostsPostIdDeepRoute -} - -const rootRouteChildren: RootRouteChildren = { - IndexRoute: IndexRoute, - PathlessLayoutRoute: PathlessLayoutRouteWithChildren, - DeferredRoute: DeferredRoute, - PostsRoute: PostsRouteWithChildren, - RedirectRoute: RedirectRoute, - UsersRoute: UsersRouteWithChildren, - PostsPostIdDeepRoute: PostsPostIdDeepRoute, -} - -export const routeTree = rootRoute - ._addFileChildren(rootRouteChildren) - ._addFileTypes() - -/* ROUTE_MANIFEST_START -{ - "routes": { - "__root__": { - "filePath": "__root.tsx", - "children": [ - "/", - "/_pathlessLayout", - "/deferred", - "/posts", - "/redirect", - "/users", - "/posts_/$postId/deep" - ] - }, - "/": { - "filePath": "index.tsx" - }, - "/_pathlessLayout": { - "filePath": "_pathlessLayout.tsx", - "children": [ - "/_pathlessLayout/_nested-layout" - ] - }, - "/deferred": { - "filePath": "deferred.tsx" - }, - "/posts": { - "filePath": "posts.tsx", - "children": [ - "/posts/$postId", - "/posts/" - ] - }, - "/redirect": { - "filePath": "redirect.tsx" - }, - "/users": { - "filePath": "users.tsx", - "children": [ - "/users/$userId", - "/users/" - ] - }, - "/_pathlessLayout/_nested-layout": { - "filePath": "_pathlessLayout/_nested-layout.tsx", - "parent": "/_pathlessLayout", - "children": [ - "/_pathlessLayout/_nested-layout/route-a", - "/_pathlessLayout/_nested-layout/route-b" - ] - }, - "/posts/$postId": { - "filePath": "posts.$postId.tsx", - "parent": "/posts" - }, - "/users/$userId": { - "filePath": "users.$userId.tsx", - "parent": "/users" - }, - "/posts/": { - "filePath": "posts.index.tsx", - "parent": "/posts" - }, - "/users/": { - "filePath": "users.index.tsx", - "parent": "/users" - }, - "/_pathlessLayout/_nested-layout/route-a": { - "filePath": "_pathlessLayout/_nested-layout/route-a.tsx", - "parent": "/_pathlessLayout/_nested-layout" - }, - "/_pathlessLayout/_nested-layout/route-b": { - "filePath": "_pathlessLayout/_nested-layout/route-b.tsx", - "parent": "/_pathlessLayout/_nested-layout" - }, - "/posts_/$postId/deep": { - "filePath": "posts_.$postId.deep.tsx" - } - } -} -ROUTE_MANIFEST_END */ diff --git a/examples/react/start-basic/src/routeTree.gen.ts b/examples/react/start-basic/src/routeTree.gen.ts index 9f7ab8107b..c7786de3e4 100644 --- a/examples/react/start-basic/src/routeTree.gen.ts +++ b/examples/react/start-basic/src/routeTree.gen.ts @@ -15,16 +15,19 @@ import { Route as UsersImport } from './routes/users' import { Route as RedirectImport } from './routes/redirect' import { Route as PostsImport } from './routes/posts' import { Route as DeferredImport } from './routes/deferred' +import { Route as PathlessLayoutImport } from './routes/_pathlessLayout' import { Route as LayoutImport } from './routes/_layout' +import { Route as UsersRouteImport } from './routes/users.route' +import { Route as PostsRouteImport } from './routes/posts.route' import { Route as IndexImport } from './routes/index' import { Route as UsersIndexImport } from './routes/users.index' import { Route as PostsIndexImport } from './routes/posts.index' import { Route as UsersUserIdImport } from './routes/users.$userId' import { Route as PostsPostIdImport } from './routes/posts.$postId' -import { Route as LayoutLayout2Import } from './routes/_layout/_layout-2' +import { Route as PathlessLayoutNestedLayoutImport } from './routes/_pathlessLayout/_nested-layout' import { Route as PostsPostIdDeepImport } from './routes/posts_.$postId.deep' -import { Route as LayoutLayout2LayoutBImport } from './routes/_layout/_layout-2/layout-b' -import { Route as LayoutLayout2LayoutAImport } from './routes/_layout/_layout-2/layout-a' +import { Route as PathlessLayoutNestedLayoutRouteBImport } from './routes/_pathlessLayout/_nested-layout/route-b' +import { Route as PathlessLayoutNestedLayoutRouteAImport } from './routes/_pathlessLayout/_nested-layout/route-a' // Create/Update Routes @@ -52,11 +55,28 @@ const DeferredRoute = DeferredImport.update({ getParentRoute: () => rootRoute, } as any) +const PathlessLayoutRoute = PathlessLayoutImport.update({ + id: '/_pathlessLayout', + getParentRoute: () => rootRoute, +} as any) + const LayoutRoute = LayoutImport.update({ id: '/_layout', getParentRoute: () => rootRoute, } as any) +const UsersRouteRoute = UsersRouteImport.update({ + id: '/users', + path: '/users', + getParentRoute: () => rootRoute, +} as any) + +const PostsRouteRoute = PostsRouteImport.update({ + id: '/posts', + path: '/posts', + getParentRoute: () => rootRoute, +} as any) + const IndexRoute = IndexImport.update({ id: '/', path: '/', @@ -87,10 +107,12 @@ const PostsPostIdRoute = PostsPostIdImport.update({ getParentRoute: () => PostsRoute, } as any) -const LayoutLayout2Route = LayoutLayout2Import.update({ - id: '/_layout-2', - getParentRoute: () => LayoutRoute, -} as any) +const PathlessLayoutNestedLayoutRoute = PathlessLayoutNestedLayoutImport.update( + { + id: '/_nested-layout', + getParentRoute: () => PathlessLayoutRoute, + } as any, +) const PostsPostIdDeepRoute = PostsPostIdDeepImport.update({ id: '/posts_/$postId/deep', @@ -98,17 +120,19 @@ const PostsPostIdDeepRoute = PostsPostIdDeepImport.update({ getParentRoute: () => rootRoute, } as any) -const LayoutLayout2LayoutBRoute = LayoutLayout2LayoutBImport.update({ - id: '/layout-b', - path: '/layout-b', - getParentRoute: () => LayoutLayout2Route, -} as any) +const PathlessLayoutNestedLayoutRouteBRoute = + PathlessLayoutNestedLayoutRouteBImport.update({ + id: '/route-b', + path: '/route-b', + getParentRoute: () => PathlessLayoutNestedLayoutRoute, + } as any) -const LayoutLayout2LayoutARoute = LayoutLayout2LayoutAImport.update({ - id: '/layout-a', - path: '/layout-a', - getParentRoute: () => LayoutLayout2Route, -} as any) +const PathlessLayoutNestedLayoutRouteARoute = + PathlessLayoutNestedLayoutRouteAImport.update({ + id: '/route-a', + path: '/route-a', + getParentRoute: () => PathlessLayoutNestedLayoutRoute, + } as any) // Populate the FileRoutesByPath interface @@ -121,6 +145,20 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof IndexImport parentRoute: typeof rootRoute } + '/posts': { + id: '/posts' + path: '/posts' + fullPath: '/posts' + preLoaderRoute: typeof PostsRouteImport + parentRoute: typeof rootRoute + } + '/users': { + id: '/users' + path: '/users' + fullPath: '/users' + preLoaderRoute: typeof UsersRouteImport + parentRoute: typeof rootRoute + } '/_layout': { id: '/_layout' path: '' @@ -128,6 +166,13 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof LayoutImport parentRoute: typeof rootRoute } + '/_pathlessLayout': { + id: '/_pathlessLayout' + path: '' + fullPath: '' + preLoaderRoute: typeof PathlessLayoutImport + parentRoute: typeof rootRoute + } '/deferred': { id: '/deferred' path: '/deferred' @@ -156,12 +201,12 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof UsersImport parentRoute: typeof rootRoute } - '/_layout/_layout-2': { - id: '/_layout/_layout-2' + '/_pathlessLayout/_nested-layout': { + id: '/_pathlessLayout/_nested-layout' path: '' fullPath: '' - preLoaderRoute: typeof LayoutLayout2Import - parentRoute: typeof LayoutImport + preLoaderRoute: typeof PathlessLayoutNestedLayoutImport + parentRoute: typeof PathlessLayoutImport } '/posts/$postId': { id: '/posts/$postId' @@ -191,19 +236,19 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof UsersIndexImport parentRoute: typeof UsersImport } - '/_layout/_layout-2/layout-a': { - id: '/_layout/_layout-2/layout-a' - path: '/layout-a' - fullPath: '/layout-a' - preLoaderRoute: typeof LayoutLayout2LayoutAImport - parentRoute: typeof LayoutLayout2Import + '/_pathlessLayout/_nested-layout/route-a': { + id: '/_pathlessLayout/_nested-layout/route-a' + path: '/route-a' + fullPath: '/route-a' + preLoaderRoute: typeof PathlessLayoutNestedLayoutRouteAImport + parentRoute: typeof PathlessLayoutNestedLayoutImport } - '/_layout/_layout-2/layout-b': { - id: '/_layout/_layout-2/layout-b' - path: '/layout-b' - fullPath: '/layout-b' - preLoaderRoute: typeof LayoutLayout2LayoutBImport - parentRoute: typeof LayoutLayout2Import + '/_pathlessLayout/_nested-layout/route-b': { + id: '/_pathlessLayout/_nested-layout/route-b' + path: '/route-b' + fullPath: '/route-b' + preLoaderRoute: typeof PathlessLayoutNestedLayoutRouteBImport + parentRoute: typeof PathlessLayoutNestedLayoutImport } '/posts_/$postId/deep': { id: '/posts_/$postId/deep' @@ -217,30 +262,35 @@ declare module '@tanstack/react-router' { // Create and export the route tree -interface LayoutLayout2RouteChildren { - LayoutLayout2LayoutARoute: typeof LayoutLayout2LayoutARoute - LayoutLayout2LayoutBRoute: typeof LayoutLayout2LayoutBRoute +interface PathlessLayoutNestedLayoutRouteChildren { + PathlessLayoutNestedLayoutRouteARoute: typeof PathlessLayoutNestedLayoutRouteARoute + PathlessLayoutNestedLayoutRouteBRoute: typeof PathlessLayoutNestedLayoutRouteBRoute } -const LayoutLayout2RouteChildren: LayoutLayout2RouteChildren = { - LayoutLayout2LayoutARoute: LayoutLayout2LayoutARoute, - LayoutLayout2LayoutBRoute: LayoutLayout2LayoutBRoute, -} +const PathlessLayoutNestedLayoutRouteChildren: PathlessLayoutNestedLayoutRouteChildren = + { + PathlessLayoutNestedLayoutRouteARoute: + PathlessLayoutNestedLayoutRouteARoute, + PathlessLayoutNestedLayoutRouteBRoute: + PathlessLayoutNestedLayoutRouteBRoute, + } -const LayoutLayout2RouteWithChildren = LayoutLayout2Route._addFileChildren( - LayoutLayout2RouteChildren, -) +const PathlessLayoutNestedLayoutRouteWithChildren = + PathlessLayoutNestedLayoutRoute._addFileChildren( + PathlessLayoutNestedLayoutRouteChildren, + ) -interface LayoutRouteChildren { - LayoutLayout2Route: typeof LayoutLayout2RouteWithChildren +interface PathlessLayoutRouteChildren { + PathlessLayoutNestedLayoutRoute: typeof PathlessLayoutNestedLayoutRouteWithChildren } -const LayoutRouteChildren: LayoutRouteChildren = { - LayoutLayout2Route: LayoutLayout2RouteWithChildren, +const PathlessLayoutRouteChildren: PathlessLayoutRouteChildren = { + PathlessLayoutNestedLayoutRoute: PathlessLayoutNestedLayoutRouteWithChildren, } -const LayoutRouteWithChildren = - LayoutRoute._addFileChildren(LayoutRouteChildren) +const PathlessLayoutRouteWithChildren = PathlessLayoutRoute._addFileChildren( + PathlessLayoutRouteChildren, +) interface PostsRouteChildren { PostsPostIdRoute: typeof PostsPostIdRoute @@ -268,49 +318,50 @@ const UsersRouteWithChildren = UsersRoute._addFileChildren(UsersRouteChildren) export interface FileRoutesByFullPath { '/': typeof IndexRoute - '': typeof LayoutLayout2RouteWithChildren - '/deferred': typeof DeferredRoute '/posts': typeof PostsRouteWithChildren - '/redirect': typeof RedirectRoute '/users': typeof UsersRouteWithChildren + '': typeof PathlessLayoutNestedLayoutRouteWithChildren + '/deferred': typeof DeferredRoute + '/redirect': typeof RedirectRoute '/posts/$postId': typeof PostsPostIdRoute '/users/$userId': typeof UsersUserIdRoute '/posts/': typeof PostsIndexRoute '/users/': typeof UsersIndexRoute - '/layout-a': typeof LayoutLayout2LayoutARoute - '/layout-b': typeof LayoutLayout2LayoutBRoute + '/route-a': typeof PathlessLayoutNestedLayoutRouteARoute + '/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute '/posts/$postId/deep': typeof PostsPostIdDeepRoute } export interface FileRoutesByTo { '/': typeof IndexRoute - '': typeof LayoutLayout2RouteWithChildren + '/posts': typeof PostsIndexRoute + '/users': typeof UsersIndexRoute + '': typeof PathlessLayoutNestedLayoutRouteWithChildren '/deferred': typeof DeferredRoute '/redirect': typeof RedirectRoute '/posts/$postId': typeof PostsPostIdRoute '/users/$userId': typeof UsersUserIdRoute - '/posts': typeof PostsIndexRoute - '/users': typeof UsersIndexRoute - '/layout-a': typeof LayoutLayout2LayoutARoute - '/layout-b': typeof LayoutLayout2LayoutBRoute + '/route-a': typeof PathlessLayoutNestedLayoutRouteARoute + '/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute '/posts/$postId/deep': typeof PostsPostIdDeepRoute } export interface FileRoutesById { __root__: typeof rootRoute '/': typeof IndexRoute - '/_layout': typeof LayoutRouteWithChildren - '/deferred': typeof DeferredRoute '/posts': typeof PostsRouteWithChildren - '/redirect': typeof RedirectRoute '/users': typeof UsersRouteWithChildren - '/_layout/_layout-2': typeof LayoutLayout2RouteWithChildren + '/_layout': typeof LayoutRoute + '/_pathlessLayout': typeof PathlessLayoutRouteWithChildren + '/deferred': typeof DeferredRoute + '/redirect': typeof RedirectRoute + '/_pathlessLayout/_nested-layout': typeof PathlessLayoutNestedLayoutRouteWithChildren '/posts/$postId': typeof PostsPostIdRoute '/users/$userId': typeof UsersUserIdRoute '/posts/': typeof PostsIndexRoute '/users/': typeof UsersIndexRoute - '/_layout/_layout-2/layout-a': typeof LayoutLayout2LayoutARoute - '/_layout/_layout-2/layout-b': typeof LayoutLayout2LayoutBRoute + '/_pathlessLayout/_nested-layout/route-a': typeof PathlessLayoutNestedLayoutRouteARoute + '/_pathlessLayout/_nested-layout/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute '/posts_/$postId/deep': typeof PostsPostIdDeepRoute } @@ -318,53 +369,57 @@ export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath fullPaths: | '/' + | '/posts' + | '/users' | '' | '/deferred' - | '/posts' | '/redirect' - | '/users' | '/posts/$postId' | '/users/$userId' | '/posts/' | '/users/' - | '/layout-a' - | '/layout-b' + | '/route-a' + | '/route-b' | '/posts/$postId/deep' fileRoutesByTo: FileRoutesByTo to: | '/' + | '/posts' + | '/users' | '' | '/deferred' | '/redirect' | '/posts/$postId' | '/users/$userId' - | '/posts' - | '/users' - | '/layout-a' - | '/layout-b' + | '/route-a' + | '/route-b' | '/posts/$postId/deep' id: | '__root__' | '/' + | '/posts' + | '/users' | '/_layout' + | '/_pathlessLayout' | '/deferred' - | '/posts' | '/redirect' - | '/users' - | '/_layout/_layout-2' + | '/_pathlessLayout/_nested-layout' | '/posts/$postId' | '/users/$userId' | '/posts/' | '/users/' - | '/_layout/_layout-2/layout-a' - | '/_layout/_layout-2/layout-b' + | '/_pathlessLayout/_nested-layout/route-a' + | '/_pathlessLayout/_nested-layout/route-b' | '/posts_/$postId/deep' fileRoutesById: FileRoutesById } export interface RootRouteChildren { IndexRoute: typeof IndexRoute - LayoutRoute: typeof LayoutRouteWithChildren + PostsRouteRoute: typeof PostsRouteRoute + UsersRouteRoute: typeof UsersRouteRoute + LayoutRoute: typeof LayoutRoute + PathlessLayoutRoute: typeof PathlessLayoutRouteWithChildren DeferredRoute: typeof DeferredRoute PostsRoute: typeof PostsRouteWithChildren RedirectRoute: typeof RedirectRoute @@ -374,7 +429,10 @@ export interface RootRouteChildren { const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, - LayoutRoute: LayoutRouteWithChildren, + PostsRouteRoute: PostsRouteRoute, + UsersRouteRoute: UsersRouteRoute, + LayoutRoute: LayoutRoute, + PathlessLayoutRoute: PathlessLayoutRouteWithChildren, DeferredRoute: DeferredRoute, PostsRoute: PostsRouteWithChildren, RedirectRoute: RedirectRoute, @@ -393,7 +451,10 @@ export const routeTree = rootRoute "filePath": "__root.tsx", "children": [ "/", + "/posts", + "/users", "/_layout", + "/_pathlessLayout", "/deferred", "/posts", "/redirect", @@ -404,15 +465,6 @@ export const routeTree = rootRoute "/": { "filePath": "index.tsx" }, - "/_layout": { - "filePath": "_layout.tsx", - "children": [ - "/_layout/_layout-2" - ] - }, - "/deferred": { - "filePath": "deferred.tsx" - }, "/posts": { "filePath": "posts.tsx", "children": [ @@ -420,9 +472,6 @@ export const routeTree = rootRoute "/posts/" ] }, - "/redirect": { - "filePath": "redirect.tsx" - }, "/users": { "filePath": "users.tsx", "children": [ @@ -430,12 +479,27 @@ export const routeTree = rootRoute "/users/" ] }, - "/_layout/_layout-2": { - "filePath": "_layout/_layout-2.tsx", - "parent": "/_layout", + "/_layout": { + "filePath": "_layout.tsx" + }, + "/_pathlessLayout": { + "filePath": "_pathlessLayout.tsx", + "children": [ + "/_pathlessLayout/_nested-layout" + ] + }, + "/deferred": { + "filePath": "deferred.tsx" + }, + "/redirect": { + "filePath": "redirect.tsx" + }, + "/_pathlessLayout/_nested-layout": { + "filePath": "_pathlessLayout/_nested-layout.tsx", + "parent": "/_pathlessLayout", "children": [ - "/_layout/_layout-2/layout-a", - "/_layout/_layout-2/layout-b" + "/_pathlessLayout/_nested-layout/route-a", + "/_pathlessLayout/_nested-layout/route-b" ] }, "/posts/$postId": { @@ -454,13 +518,13 @@ export const routeTree = rootRoute "filePath": "users.index.tsx", "parent": "/users" }, - "/_layout/_layout-2/layout-a": { - "filePath": "_layout/_layout-2/layout-a.tsx", - "parent": "/_layout/_layout-2" + "/_pathlessLayout/_nested-layout/route-a": { + "filePath": "_pathlessLayout/_nested-layout/route-a.tsx", + "parent": "/_pathlessLayout/_nested-layout" }, - "/_layout/_layout-2/layout-b": { - "filePath": "_layout/_layout-2/layout-b.tsx", - "parent": "/_layout/_layout-2" + "/_pathlessLayout/_nested-layout/route-b": { + "filePath": "_pathlessLayout/_nested-layout/route-b.tsx", + "parent": "/_pathlessLayout/_nested-layout" }, "/posts_/$postId/deep": { "filePath": "posts_.$postId.deep.tsx" diff --git a/examples/react/start-basic/src/routes/__root.tsx b/examples/react/start-basic/src/routes/__root.tsx index f6d8d8cf97..30f0a42b4c 100644 --- a/examples/react/start-basic/src/routes/__root.tsx +++ b/examples/react/start-basic/src/routes/__root.tsx @@ -7,10 +7,10 @@ import { } from '@tanstack/react-router' import { TanStackRouterDevtools } from '@tanstack/router-devtools' import * as React from 'react' -import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' -import { NotFound } from 'src/components/NotFound' -import { seo } from 'src/utils/seo' +import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' +import { NotFound } from '~/components/NotFound' import appCss from '~/styles/app.css?url' +import { seo } from '~/utils/seo' export const Route = createRootRoute({ head: () => ({ @@ -104,12 +104,12 @@ function RootDocument({ children }: { children: React.ReactNode }) { Users {' '} - Layout + Pathless Layout {' '} -
I'm a nested layout
-
- - Layout A - - - Layout B - -
-
- -
-
- ) -} diff --git a/examples/react/start-basic/src/routes/_layout/_layout-2/layout-a.tsx b/examples/react/start-basic/src/routes/_layout/_layout-2/layout-a.tsx deleted file mode 100644 index 61e19b4d9f..0000000000 --- a/examples/react/start-basic/src/routes/_layout/_layout-2/layout-a.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { createFileRoute } from '@tanstack/react-router' - -export const Route = createFileRoute('/_layout/_layout-2/layout-a')({ - component: LayoutAComponent, -}) - -function LayoutAComponent() { - return
I'm layout A!
-} diff --git a/examples/react/start-basic/src/routes/_layout/_layout-2/layout-b.tsx b/examples/react/start-basic/src/routes/_layout/_layout-2/layout-b.tsx deleted file mode 100644 index cceed1fb9a..0000000000 --- a/examples/react/start-basic/src/routes/_layout/_layout-2/layout-b.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import { createFileRoute } from '@tanstack/react-router' - -export const Route = createFileRoute('/_layout/_layout-2/layout-b')({ - component: LayoutBComponent, -}) - -function LayoutBComponent() { - return
I'm layout B!
-} diff --git a/examples/react/start-basic/app/routes/_pathlessLayout.tsx b/examples/react/start-basic/src/routes/_pathlessLayout.tsx similarity index 100% rename from examples/react/start-basic/app/routes/_pathlessLayout.tsx rename to examples/react/start-basic/src/routes/_pathlessLayout.tsx diff --git a/examples/react/start-basic/app/routes/_pathlessLayout/_nested-layout.tsx b/examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout.tsx similarity index 100% rename from examples/react/start-basic/app/routes/_pathlessLayout/_nested-layout.tsx rename to examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout.tsx diff --git a/examples/react/start-basic/app/routes/_pathlessLayout/_nested-layout/route-a.tsx b/examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-a.tsx similarity index 100% rename from examples/react/start-basic/app/routes/_pathlessLayout/_nested-layout/route-a.tsx rename to examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-a.tsx diff --git a/examples/react/start-basic/app/routes/_pathlessLayout/_nested-layout/route-b.tsx b/examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-b.tsx similarity index 100% rename from examples/react/start-basic/app/routes/_pathlessLayout/_nested-layout/route-b.tsx rename to examples/react/start-basic/src/routes/_pathlessLayout/_nested-layout/route-b.tsx diff --git a/examples/react/start-basic/app/routes/posts.route.tsx b/examples/react/start-basic/src/routes/posts.route.tsx similarity index 100% rename from examples/react/start-basic/app/routes/posts.route.tsx rename to examples/react/start-basic/src/routes/posts.route.tsx diff --git a/examples/react/start-basic/app/routes/users.route.tsx b/examples/react/start-basic/src/routes/users.route.tsx similarity index 100% rename from examples/react/start-basic/app/routes/users.route.tsx rename to examples/react/start-basic/src/routes/users.route.tsx diff --git a/examples/react/start-clerk-basic/app/components/DefaultCatchBoundary.tsx b/examples/react/start-clerk-basic/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from examples/react/start-clerk-basic/app/components/DefaultCatchBoundary.tsx rename to examples/react/start-clerk-basic/src/components/DefaultCatchBoundary.tsx diff --git a/examples/react/start-clerk-basic/app/components/NotFound.tsx b/examples/react/start-clerk-basic/src/components/NotFound.tsx similarity index 100% rename from examples/react/start-clerk-basic/app/components/NotFound.tsx rename to examples/react/start-clerk-basic/src/components/NotFound.tsx diff --git a/examples/react/start-clerk-basic/app/routeTree.gen.ts b/examples/react/start-clerk-basic/src/routeTree.gen.ts similarity index 100% rename from examples/react/start-clerk-basic/app/routeTree.gen.ts rename to examples/react/start-clerk-basic/src/routeTree.gen.ts diff --git a/examples/react/start-clerk-basic/app/router.tsx b/examples/react/start-clerk-basic/src/router.tsx similarity index 100% rename from examples/react/start-clerk-basic/app/router.tsx rename to examples/react/start-clerk-basic/src/router.tsx diff --git a/examples/react/start-clerk-basic/app/routes/__root.tsx b/examples/react/start-clerk-basic/src/routes/__root.tsx similarity index 95% rename from examples/react/start-clerk-basic/app/routes/__root.tsx rename to examples/react/start-clerk-basic/src/routes/__root.tsx index 489e80715f..358f9d8be3 100644 --- a/examples/react/start-clerk-basic/app/routes/__root.tsx +++ b/examples/react/start-clerk-basic/src/routes/__root.tsx @@ -18,8 +18,8 @@ import { createServerFn } from '@tanstack/react-start' import * as React from 'react' import { getAuth } from '@clerk/tanstack-start/server' import { getWebRequest } from '@tanstack/react-start/server' -import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary.js' -import { NotFound } from '~/components/NotFound.js' +import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary.js' +import { NotFound } from 'src/components/NotFound.js' import appCss from '~/styles/app.css?url' const fetchClerkAuth = createServerFn({ method: 'GET' }).handler(async () => { diff --git a/examples/react/start-clerk-basic/app/routes/_authed.tsx b/examples/react/start-clerk-basic/src/routes/_authed.tsx similarity index 100% rename from examples/react/start-clerk-basic/app/routes/_authed.tsx rename to examples/react/start-clerk-basic/src/routes/_authed.tsx diff --git a/examples/react/start-basic-auth/app/routes/_authed/posts.$postId.tsx b/examples/react/start-clerk-basic/src/routes/_authed/posts.$postId.tsx similarity index 88% rename from examples/react/start-basic-auth/app/routes/_authed/posts.$postId.tsx rename to examples/react/start-clerk-basic/src/routes/_authed/posts.$postId.tsx index 039271bb89..763ac98f14 100644 --- a/examples/react/start-basic-auth/app/routes/_authed/posts.$postId.tsx +++ b/examples/react/start-clerk-basic/src/routes/_authed/posts.$postId.tsx @@ -1,7 +1,7 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from '~/components/NotFound.js' -import { fetchPost } from '~/utils/posts.js' +import { NotFound } from 'src/components/NotFound.js' +import { fetchPost } from 'src/utils/posts.js' export const Route = createFileRoute('/_authed/posts/$postId')({ loader: ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/examples/react/start-clerk-basic/app/routes/_authed/posts.index.tsx b/examples/react/start-clerk-basic/src/routes/_authed/posts.index.tsx similarity index 100% rename from examples/react/start-clerk-basic/app/routes/_authed/posts.index.tsx rename to examples/react/start-clerk-basic/src/routes/_authed/posts.index.tsx diff --git a/examples/react/start-clerk-basic/app/routes/_authed/posts.tsx b/examples/react/start-clerk-basic/src/routes/_authed/posts.tsx similarity index 95% rename from examples/react/start-clerk-basic/app/routes/_authed/posts.tsx rename to examples/react/start-clerk-basic/src/routes/_authed/posts.tsx index 86c8ef4138..a3144ce55a 100644 --- a/examples/react/start-clerk-basic/app/routes/_authed/posts.tsx +++ b/examples/react/start-clerk-basic/src/routes/_authed/posts.tsx @@ -1,5 +1,5 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from '~/utils/posts.js' +import { fetchPosts } from 'src/utils/posts.js' export const Route = createFileRoute('/_authed/posts')({ loader: () => fetchPosts(), diff --git a/examples/react/start-clerk-basic/app/routes/_authed/profile.$.tsx b/examples/react/start-clerk-basic/src/routes/_authed/profile.$.tsx similarity index 95% rename from examples/react/start-clerk-basic/app/routes/_authed/profile.$.tsx rename to examples/react/start-clerk-basic/src/routes/_authed/profile.$.tsx index 208a38e230..4e0b434c2b 100644 --- a/examples/react/start-clerk-basic/app/routes/_authed/profile.$.tsx +++ b/examples/react/start-clerk-basic/src/routes/_authed/profile.$.tsx @@ -1,5 +1,5 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from '~/utils/posts.js' +import { fetchPosts } from 'src/utils/posts.js' export const Route = createFileRoute('/_authed/profile/$')({ loader: () => fetchPosts(), diff --git a/examples/react/start-clerk-basic/app/routes/index.tsx b/examples/react/start-clerk-basic/src/routes/index.tsx similarity index 100% rename from examples/react/start-clerk-basic/app/routes/index.tsx rename to examples/react/start-clerk-basic/src/routes/index.tsx diff --git a/examples/react/start-clerk-basic/app/server.ts b/examples/react/start-clerk-basic/src/server.ts similarity index 100% rename from examples/react/start-clerk-basic/app/server.ts rename to examples/react/start-clerk-basic/src/server.ts diff --git a/examples/react/start-clerk-basic/app/styles/app.css b/examples/react/start-clerk-basic/src/styles/app.css similarity index 100% rename from examples/react/start-clerk-basic/app/styles/app.css rename to examples/react/start-clerk-basic/src/styles/app.css diff --git a/examples/react/start-clerk-basic/app/utils/posts.ts b/examples/react/start-clerk-basic/src/utils/posts.ts similarity index 100% rename from examples/react/start-clerk-basic/app/utils/posts.ts rename to examples/react/start-clerk-basic/src/utils/posts.ts diff --git a/examples/react/start-clerk-basic/app/utils/seo.ts b/examples/react/start-clerk-basic/src/utils/seo.ts similarity index 100% rename from examples/react/start-clerk-basic/app/utils/seo.ts rename to examples/react/start-clerk-basic/src/utils/seo.ts diff --git a/examples/react/start-clerk-basic/tsconfig.json b/examples/react/start-clerk-basic/tsconfig.json index d1b5b77660..9a7cf62c30 100644 --- a/examples/react/start-clerk-basic/tsconfig.json +++ b/examples/react/start-clerk-basic/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/examples/react/start-convex-trellaux/app/components/Board.tsx b/examples/react/start-convex-trellaux/src/components/Board.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/components/Board.tsx rename to examples/react/start-convex-trellaux/src/components/Board.tsx diff --git a/examples/react/start-convex-trellaux/app/components/CancelButton.tsx b/examples/react/start-convex-trellaux/src/components/CancelButton.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/components/CancelButton.tsx rename to examples/react/start-convex-trellaux/src/components/CancelButton.tsx diff --git a/examples/react/start-convex-trellaux/app/components/Card.tsx b/examples/react/start-convex-trellaux/src/components/Card.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/components/Card.tsx rename to examples/react/start-convex-trellaux/src/components/Card.tsx diff --git a/examples/react/start-convex-trellaux/app/components/Column.tsx b/examples/react/start-convex-trellaux/src/components/Column.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/components/Column.tsx rename to examples/react/start-convex-trellaux/src/components/Column.tsx diff --git a/examples/react/start-convex-trellaux/app/components/DefaultCatchBoundary.tsx b/examples/react/start-convex-trellaux/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/components/DefaultCatchBoundary.tsx rename to examples/react/start-convex-trellaux/src/components/DefaultCatchBoundary.tsx diff --git a/examples/react/start-convex-trellaux/app/components/EditableText.tsx b/examples/react/start-convex-trellaux/src/components/EditableText.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/components/EditableText.tsx rename to examples/react/start-convex-trellaux/src/components/EditableText.tsx diff --git a/examples/react/start-convex-trellaux/app/components/IconLink.tsx b/examples/react/start-convex-trellaux/src/components/IconLink.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/components/IconLink.tsx rename to examples/react/start-convex-trellaux/src/components/IconLink.tsx diff --git a/examples/react/start-convex-trellaux/app/components/Loader.tsx b/examples/react/start-convex-trellaux/src/components/Loader.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/components/Loader.tsx rename to examples/react/start-convex-trellaux/src/components/Loader.tsx diff --git a/examples/react/start-convex-trellaux/app/components/NewCard.tsx b/examples/react/start-convex-trellaux/src/components/NewCard.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/components/NewCard.tsx rename to examples/react/start-convex-trellaux/src/components/NewCard.tsx diff --git a/examples/react/start-convex-trellaux/app/components/NewColumn.tsx b/examples/react/start-convex-trellaux/src/components/NewColumn.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/components/NewColumn.tsx rename to examples/react/start-convex-trellaux/src/components/NewColumn.tsx diff --git a/examples/react/start-convex-trellaux/app/components/NotFound.tsx b/examples/react/start-convex-trellaux/src/components/NotFound.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/components/NotFound.tsx rename to examples/react/start-convex-trellaux/src/components/NotFound.tsx diff --git a/examples/react/start-convex-trellaux/app/components/SaveButton.tsx b/examples/react/start-convex-trellaux/src/components/SaveButton.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/components/SaveButton.tsx rename to examples/react/start-convex-trellaux/src/components/SaveButton.tsx diff --git a/examples/react/start-convex-trellaux/app/db/schema.ts b/examples/react/start-convex-trellaux/src/db/schema.ts similarity index 100% rename from examples/react/start-convex-trellaux/app/db/schema.ts rename to examples/react/start-convex-trellaux/src/db/schema.ts diff --git a/examples/react/start-convex-trellaux/app/hooks/useOfflineIndicator.tsx b/examples/react/start-convex-trellaux/src/hooks/useOfflineIndicator.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/hooks/useOfflineIndicator.tsx rename to examples/react/start-convex-trellaux/src/hooks/useOfflineIndicator.tsx diff --git a/examples/react/start-convex-trellaux/app/icons/icons.svg b/examples/react/start-convex-trellaux/src/icons/icons.svg similarity index 100% rename from examples/react/start-convex-trellaux/app/icons/icons.svg rename to examples/react/start-convex-trellaux/src/icons/icons.svg diff --git a/examples/react/start-convex-trellaux/app/icons/icons.tsx b/examples/react/start-convex-trellaux/src/icons/icons.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/icons/icons.tsx rename to examples/react/start-convex-trellaux/src/icons/icons.tsx diff --git a/examples/react/start-convex-trellaux/app/queries.ts b/examples/react/start-convex-trellaux/src/queries.ts similarity index 100% rename from examples/react/start-convex-trellaux/app/queries.ts rename to examples/react/start-convex-trellaux/src/queries.ts diff --git a/examples/react/start-convex-trellaux/app/routeTree.gen.ts b/examples/react/start-convex-trellaux/src/routeTree.gen.ts similarity index 100% rename from examples/react/start-convex-trellaux/app/routeTree.gen.ts rename to examples/react/start-convex-trellaux/src/routeTree.gen.ts diff --git a/examples/react/start-convex-trellaux/app/router.tsx b/examples/react/start-convex-trellaux/src/router.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/router.tsx rename to examples/react/start-convex-trellaux/src/router.tsx diff --git a/examples/react/start-convex-trellaux/app/routes/__root.tsx b/examples/react/start-convex-trellaux/src/routes/__root.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/routes/__root.tsx rename to examples/react/start-convex-trellaux/src/routes/__root.tsx diff --git a/examples/react/start-convex-trellaux/app/routes/boards.$boardId.tsx b/examples/react/start-convex-trellaux/src/routes/boards.$boardId.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/routes/boards.$boardId.tsx rename to examples/react/start-convex-trellaux/src/routes/boards.$boardId.tsx diff --git a/examples/react/start-convex-trellaux/app/routes/index.tsx b/examples/react/start-convex-trellaux/src/routes/index.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/routes/index.tsx rename to examples/react/start-convex-trellaux/src/routes/index.tsx diff --git a/examples/react/start-basic-static/app/server.ts b/examples/react/start-convex-trellaux/src/server.ts similarity index 100% rename from examples/react/start-basic-static/app/server.ts rename to examples/react/start-convex-trellaux/src/server.ts diff --git a/examples/react/start-convex-trellaux/app/styles/app.css b/examples/react/start-convex-trellaux/src/styles/app.css similarity index 100% rename from examples/react/start-convex-trellaux/app/styles/app.css rename to examples/react/start-convex-trellaux/src/styles/app.css diff --git a/examples/react/start-convex-trellaux/app/types.ts b/examples/react/start-convex-trellaux/src/types.ts similarity index 100% rename from examples/react/start-convex-trellaux/app/types.ts rename to examples/react/start-convex-trellaux/src/types.ts diff --git a/examples/react/start-convex-trellaux/app/utils/posts.tsx b/examples/react/start-convex-trellaux/src/utils/posts.tsx similarity index 100% rename from examples/react/start-convex-trellaux/app/utils/posts.tsx rename to examples/react/start-convex-trellaux/src/utils/posts.tsx diff --git a/examples/react/start-convex-trellaux/app/utils/seo.ts b/examples/react/start-convex-trellaux/src/utils/seo.ts similarity index 100% rename from examples/react/start-convex-trellaux/app/utils/seo.ts rename to examples/react/start-convex-trellaux/src/utils/seo.ts diff --git a/examples/react/start-counter/app/routeTree.gen.ts b/examples/react/start-counter/src/routeTree.gen.ts similarity index 100% rename from examples/react/start-counter/app/routeTree.gen.ts rename to examples/react/start-counter/src/routeTree.gen.ts diff --git a/examples/react/start-counter/app/router.tsx b/examples/react/start-counter/src/router.tsx similarity index 100% rename from examples/react/start-counter/app/router.tsx rename to examples/react/start-counter/src/router.tsx diff --git a/examples/react/start-counter/app/routes/__root.tsx b/examples/react/start-counter/src/routes/__root.tsx similarity index 100% rename from examples/react/start-counter/app/routes/__root.tsx rename to examples/react/start-counter/src/routes/__root.tsx diff --git a/examples/react/start-counter/app/routes/index.tsx b/examples/react/start-counter/src/routes/index.tsx similarity index 100% rename from examples/react/start-counter/app/routes/index.tsx rename to examples/react/start-counter/src/routes/index.tsx diff --git a/examples/react/start-convex-trellaux/app/server.ts b/examples/react/start-counter/src/server.ts similarity index 100% rename from examples/react/start-convex-trellaux/app/server.ts rename to examples/react/start-counter/src/server.ts diff --git a/examples/react/start-large/app/createRoutes.mjs b/examples/react/start-large/src/createRoutes.mjs similarity index 100% rename from examples/react/start-large/app/createRoutes.mjs rename to examples/react/start-large/src/createRoutes.mjs diff --git a/examples/react/start-large/app/routeTree.gen.ts b/examples/react/start-large/src/routeTree.gen.ts similarity index 100% rename from examples/react/start-large/app/routeTree.gen.ts rename to examples/react/start-large/src/routeTree.gen.ts diff --git a/examples/react/start-large/app/router.tsx b/examples/react/start-large/src/router.tsx similarity index 100% rename from examples/react/start-large/app/router.tsx rename to examples/react/start-large/src/router.tsx diff --git a/examples/react/start-large/app/routes/__root.tsx b/examples/react/start-large/src/routes/__root.tsx similarity index 100% rename from examples/react/start-large/app/routes/__root.tsx rename to examples/react/start-large/src/routes/__root.tsx diff --git a/examples/react/start-large/app/routes/absolute.tsx b/examples/react/start-large/src/routes/absolute.tsx similarity index 100% rename from examples/react/start-large/app/routes/absolute.tsx rename to examples/react/start-large/src/routes/absolute.tsx diff --git a/examples/react/start-large/app/routes/index.tsx b/examples/react/start-large/src/routes/index.tsx similarity index 100% rename from examples/react/start-large/app/routes/index.tsx rename to examples/react/start-large/src/routes/index.tsx diff --git a/examples/react/start-large/app/routes/linkProps.tsx b/examples/react/start-large/src/routes/linkProps.tsx similarity index 98% rename from examples/react/start-large/app/routes/linkProps.tsx rename to examples/react/start-large/src/routes/linkProps.tsx index 4804161ccf..cb81ec1ac7 100644 --- a/examples/react/start-large/app/routes/linkProps.tsx +++ b/examples/react/start-large/src/routes/linkProps.tsx @@ -5,7 +5,7 @@ import { ListItems, MyLink, useCustomNavigate, -} from '~/typePrimitives' +} from 'src/typePrimitives' export const Route = createFileRoute('/linkProps')({ component: LinkPropsPage, diff --git a/examples/react/start-large/app/routes/params/$paramsPlaceholder.tsx b/examples/react/start-large/src/routes/params/$paramsPlaceholder.tsx similarity index 100% rename from examples/react/start-large/app/routes/params/$paramsPlaceholder.tsx rename to examples/react/start-large/src/routes/params/$paramsPlaceholder.tsx diff --git a/examples/react/start-large/app/routes/params/route.tsx b/examples/react/start-large/src/routes/params/route.tsx similarity index 100% rename from examples/react/start-large/app/routes/params/route.tsx rename to examples/react/start-large/src/routes/params/route.tsx diff --git a/examples/react/start-large/app/routes/relative.tsx b/examples/react/start-large/src/routes/relative.tsx similarity index 100% rename from examples/react/start-large/app/routes/relative.tsx rename to examples/react/start-large/src/routes/relative.tsx diff --git a/examples/react/start-large/app/routes/search/route.tsx b/examples/react/start-large/src/routes/search/route.tsx similarity index 100% rename from examples/react/start-large/app/routes/search/route.tsx rename to examples/react/start-large/src/routes/search/route.tsx diff --git a/examples/react/start-large/app/routes/search/searchPlaceholder.tsx b/examples/react/start-large/src/routes/search/searchPlaceholder.tsx similarity index 100% rename from examples/react/start-large/app/routes/search/searchPlaceholder.tsx rename to examples/react/start-large/src/routes/search/searchPlaceholder.tsx diff --git a/examples/react/start-large/app/server.ts b/examples/react/start-large/src/server.ts similarity index 100% rename from examples/react/start-large/app/server.ts rename to examples/react/start-large/src/server.ts diff --git a/examples/react/start-large/app/styles.css b/examples/react/start-large/src/styles.css similarity index 100% rename from examples/react/start-large/app/styles.css rename to examples/react/start-large/src/styles.css diff --git a/examples/react/start-large/app/typePrimitives.tsx b/examples/react/start-large/src/typePrimitives.tsx similarity index 100% rename from examples/react/start-large/app/typePrimitives.tsx rename to examples/react/start-large/src/typePrimitives.tsx diff --git a/examples/react/start-large/tsconfig.json b/examples/react/start-large/tsconfig.json index d1b5b77660..9a7cf62c30 100644 --- a/examples/react/start-large/tsconfig.json +++ b/examples/react/start-large/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/examples/react/start-material-ui/app/client.tsx b/examples/react/start-material-ui/src/client.tsx similarity index 100% rename from examples/react/start-material-ui/app/client.tsx rename to examples/react/start-material-ui/src/client.tsx diff --git a/examples/react/start-material-ui/app/components/Counter.tsx b/examples/react/start-material-ui/src/components/Counter.tsx similarity index 85% rename from examples/react/start-material-ui/app/components/Counter.tsx rename to examples/react/start-material-ui/src/components/Counter.tsx index 205bbea855..363c5f11c4 100644 --- a/examples/react/start-material-ui/app/components/Counter.tsx +++ b/examples/react/start-material-ui/src/components/Counter.tsx @@ -1,6 +1,6 @@ import { Stack } from '@mui/material' import { useSearch } from '@tanstack/react-router' -import { CustomButtonLink } from '~/components/CustomButtonLink' +import { CustomButtonLink } from 'src/components/CustomButtonLink' export function Counter() { const { count = 0 } = useSearch({ from: '/' }) diff --git a/examples/react/start-material-ui/app/components/CustomButtonLink.tsx b/examples/react/start-material-ui/src/components/CustomButtonLink.tsx similarity index 100% rename from examples/react/start-material-ui/app/components/CustomButtonLink.tsx rename to examples/react/start-material-ui/src/components/CustomButtonLink.tsx diff --git a/examples/react/start-material-ui/app/components/CustomLink.tsx b/examples/react/start-material-ui/src/components/CustomLink.tsx similarity index 100% rename from examples/react/start-material-ui/app/components/CustomLink.tsx rename to examples/react/start-material-ui/src/components/CustomLink.tsx diff --git a/examples/react/start-material-ui/app/components/Header.tsx b/examples/react/start-material-ui/src/components/Header.tsx similarity index 100% rename from examples/react/start-material-ui/app/components/Header.tsx rename to examples/react/start-material-ui/src/components/Header.tsx diff --git a/examples/react/start-material-ui/app/routeTree.gen.ts b/examples/react/start-material-ui/src/routeTree.gen.ts similarity index 100% rename from examples/react/start-material-ui/app/routeTree.gen.ts rename to examples/react/start-material-ui/src/routeTree.gen.ts diff --git a/examples/react/start-material-ui/app/router.tsx b/examples/react/start-material-ui/src/router.tsx similarity index 100% rename from examples/react/start-material-ui/app/router.tsx rename to examples/react/start-material-ui/src/router.tsx diff --git a/examples/react/start-material-ui/app/routes/__root.tsx b/examples/react/start-material-ui/src/routes/__root.tsx similarity index 94% rename from examples/react/start-material-ui/app/routes/__root.tsx rename to examples/react/start-material-ui/src/routes/__root.tsx index 6b0b217b63..e9a65ccfd5 100644 --- a/examples/react/start-material-ui/app/routes/__root.tsx +++ b/examples/react/start-material-ui/src/routes/__root.tsx @@ -10,8 +10,8 @@ import { Container, CssBaseline, ThemeProvider } from '@mui/material' import createCache from '@emotion/cache' import fontsourceVariableRobotoCss from '@fontsource-variable/roboto?url' import React from 'react' -import { theme } from '~/setup/theme' -import { Header } from '~/components/Header' +import { theme } from 'src/setup/theme' +import { Header } from 'src/components/Header' export const Route = createRootRoute({ head: () => ({ diff --git a/examples/react/start-material-ui/app/routes/about.tsx b/examples/react/start-material-ui/src/routes/about.tsx similarity index 100% rename from examples/react/start-material-ui/app/routes/about.tsx rename to examples/react/start-material-ui/src/routes/about.tsx diff --git a/examples/react/start-material-ui/app/routes/index.tsx b/examples/react/start-material-ui/src/routes/index.tsx similarity index 90% rename from examples/react/start-material-ui/app/routes/index.tsx rename to examples/react/start-material-ui/src/routes/index.tsx index 75f5d14de4..667a92881d 100644 --- a/examples/react/start-material-ui/app/routes/index.tsx +++ b/examples/react/start-material-ui/src/routes/index.tsx @@ -1,7 +1,7 @@ import { createFileRoute } from '@tanstack/react-router' import { Stack, Typography } from '@mui/material' import z from 'zod' -import { Counter } from '~/components/Counter' +import { Counter } from 'src/components/Counter' export const Route = createFileRoute('/')({ validateSearch: z.object({ diff --git a/examples/react/start-material-ui/app/setup/theme.ts b/examples/react/start-material-ui/src/setup/theme.ts similarity index 100% rename from examples/react/start-material-ui/app/setup/theme.ts rename to examples/react/start-material-ui/src/setup/theme.ts diff --git a/examples/react/start-material-ui/app/ssr.tsx b/examples/react/start-material-ui/src/ssr.tsx similarity index 100% rename from examples/react/start-material-ui/app/ssr.tsx rename to examples/react/start-material-ui/src/ssr.tsx diff --git a/examples/react/start-material-ui/tsconfig.json b/examples/react/start-material-ui/tsconfig.json index a6747faec5..23f12840c3 100644 --- a/examples/react/start-material-ui/tsconfig.json +++ b/examples/react/start-material-ui/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/examples/react/start-supabase-basic/app/components/Auth.tsx b/examples/react/start-supabase-basic/src/components/Auth.tsx similarity index 100% rename from examples/react/start-supabase-basic/app/components/Auth.tsx rename to examples/react/start-supabase-basic/src/components/Auth.tsx diff --git a/examples/react/start-supabase-basic/app/components/DefaultCatchBoundary.tsx b/examples/react/start-supabase-basic/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from examples/react/start-supabase-basic/app/components/DefaultCatchBoundary.tsx rename to examples/react/start-supabase-basic/src/components/DefaultCatchBoundary.tsx diff --git a/examples/react/start-supabase-basic/app/components/Login.tsx b/examples/react/start-supabase-basic/src/components/Login.tsx similarity index 100% rename from examples/react/start-supabase-basic/app/components/Login.tsx rename to examples/react/start-supabase-basic/src/components/Login.tsx diff --git a/examples/react/start-supabase-basic/app/components/NotFound.tsx b/examples/react/start-supabase-basic/src/components/NotFound.tsx similarity index 100% rename from examples/react/start-supabase-basic/app/components/NotFound.tsx rename to examples/react/start-supabase-basic/src/components/NotFound.tsx diff --git a/examples/react/start-supabase-basic/app/hooks/useMutation.ts b/examples/react/start-supabase-basic/src/hooks/useMutation.ts similarity index 100% rename from examples/react/start-supabase-basic/app/hooks/useMutation.ts rename to examples/react/start-supabase-basic/src/hooks/useMutation.ts diff --git a/examples/react/start-supabase-basic/app/routeTree.gen.ts b/examples/react/start-supabase-basic/src/routeTree.gen.ts similarity index 100% rename from examples/react/start-supabase-basic/app/routeTree.gen.ts rename to examples/react/start-supabase-basic/src/routeTree.gen.ts diff --git a/examples/react/start-supabase-basic/app/router.tsx b/examples/react/start-supabase-basic/src/router.tsx similarity index 100% rename from examples/react/start-supabase-basic/app/router.tsx rename to examples/react/start-supabase-basic/src/router.tsx diff --git a/examples/react/start-supabase-basic/app/routes/__root.tsx b/examples/react/start-supabase-basic/src/routes/__root.tsx similarity index 100% rename from examples/react/start-supabase-basic/app/routes/__root.tsx rename to examples/react/start-supabase-basic/src/routes/__root.tsx diff --git a/examples/react/start-supabase-basic/app/routes/_authed.tsx b/examples/react/start-supabase-basic/src/routes/_authed.tsx similarity index 100% rename from examples/react/start-supabase-basic/app/routes/_authed.tsx rename to examples/react/start-supabase-basic/src/routes/_authed.tsx diff --git a/examples/react/start-supabase-basic/app/routes/_authed/posts.$postId.tsx b/examples/react/start-supabase-basic/src/routes/_authed/posts.$postId.tsx similarity index 89% rename from examples/react/start-supabase-basic/app/routes/_authed/posts.$postId.tsx rename to examples/react/start-supabase-basic/src/routes/_authed/posts.$postId.tsx index 4dd11756a8..059f35ff73 100644 --- a/examples/react/start-supabase-basic/app/routes/_authed/posts.$postId.tsx +++ b/examples/react/start-supabase-basic/src/routes/_authed/posts.$postId.tsx @@ -1,7 +1,7 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from '~/components/NotFound' -import { fetchPost } from '~/utils/posts' +import { NotFound } from 'src/components/NotFound' +import { fetchPost } from 'src/utils/posts' export const Route = createFileRoute('/_authed/posts/$postId')({ loader: ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/examples/react/start-supabase-basic/app/routes/_authed/posts.index.tsx b/examples/react/start-supabase-basic/src/routes/_authed/posts.index.tsx similarity index 100% rename from examples/react/start-supabase-basic/app/routes/_authed/posts.index.tsx rename to examples/react/start-supabase-basic/src/routes/_authed/posts.index.tsx diff --git a/examples/react/start-supabase-basic/app/routes/_authed/posts.tsx b/examples/react/start-supabase-basic/src/routes/_authed/posts.tsx similarity index 100% rename from examples/react/start-supabase-basic/app/routes/_authed/posts.tsx rename to examples/react/start-supabase-basic/src/routes/_authed/posts.tsx diff --git a/examples/react/start-supabase-basic/app/routes/index.tsx b/examples/react/start-supabase-basic/src/routes/index.tsx similarity index 100% rename from examples/react/start-supabase-basic/app/routes/index.tsx rename to examples/react/start-supabase-basic/src/routes/index.tsx diff --git a/examples/react/start-supabase-basic/app/routes/login.tsx b/examples/react/start-supabase-basic/src/routes/login.tsx similarity index 100% rename from examples/react/start-supabase-basic/app/routes/login.tsx rename to examples/react/start-supabase-basic/src/routes/login.tsx diff --git a/examples/react/start-supabase-basic/app/routes/logout.tsx b/examples/react/start-supabase-basic/src/routes/logout.tsx similarity index 100% rename from examples/react/start-supabase-basic/app/routes/logout.tsx rename to examples/react/start-supabase-basic/src/routes/logout.tsx diff --git a/examples/react/start-supabase-basic/app/routes/signup.tsx b/examples/react/start-supabase-basic/src/routes/signup.tsx similarity index 100% rename from examples/react/start-supabase-basic/app/routes/signup.tsx rename to examples/react/start-supabase-basic/src/routes/signup.tsx diff --git a/examples/react/start-supabase-basic/app/server.ts b/examples/react/start-supabase-basic/src/server.ts similarity index 100% rename from examples/react/start-supabase-basic/app/server.ts rename to examples/react/start-supabase-basic/src/server.ts diff --git a/examples/react/start-supabase-basic/app/styles/app.css b/examples/react/start-supabase-basic/src/styles/app.css similarity index 100% rename from examples/react/start-supabase-basic/app/styles/app.css rename to examples/react/start-supabase-basic/src/styles/app.css diff --git a/examples/react/start-supabase-basic/app/utils/posts.ts b/examples/react/start-supabase-basic/src/utils/posts.ts similarity index 100% rename from examples/react/start-supabase-basic/app/utils/posts.ts rename to examples/react/start-supabase-basic/src/utils/posts.ts diff --git a/examples/react/start-supabase-basic/app/utils/seo.ts b/examples/react/start-supabase-basic/src/utils/seo.ts similarity index 100% rename from examples/react/start-supabase-basic/app/utils/seo.ts rename to examples/react/start-supabase-basic/src/utils/seo.ts diff --git a/examples/react/start-supabase-basic/app/utils/supabase.ts b/examples/react/start-supabase-basic/src/utils/supabase.ts similarity index 100% rename from examples/react/start-supabase-basic/app/utils/supabase.ts rename to examples/react/start-supabase-basic/src/utils/supabase.ts diff --git a/examples/react/start-supabase-basic/tsconfig.json b/examples/react/start-supabase-basic/tsconfig.json index d1b5b77660..9a7cf62c30 100644 --- a/examples/react/start-supabase-basic/tsconfig.json +++ b/examples/react/start-supabase-basic/tsconfig.json @@ -15,7 +15,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/examples/react/start-trellaux/app/server.ts b/examples/react/start-trellaux/app/server.ts deleted file mode 100644 index 65a580f25e..0000000000 --- a/examples/react/start-trellaux/app/server.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/examples/react/start-trellaux/app/assets/react.svg b/examples/react/start-trellaux/src/assets/react.svg similarity index 100% rename from examples/react/start-trellaux/app/assets/react.svg rename to examples/react/start-trellaux/src/assets/react.svg diff --git a/examples/react/start-trellaux/app/components/Board.tsx b/examples/react/start-trellaux/src/components/Board.tsx similarity index 100% rename from examples/react/start-trellaux/app/components/Board.tsx rename to examples/react/start-trellaux/src/components/Board.tsx diff --git a/examples/react/start-trellaux/app/components/CancelButton.tsx b/examples/react/start-trellaux/src/components/CancelButton.tsx similarity index 100% rename from examples/react/start-trellaux/app/components/CancelButton.tsx rename to examples/react/start-trellaux/src/components/CancelButton.tsx diff --git a/examples/react/start-trellaux/app/components/Card.tsx b/examples/react/start-trellaux/src/components/Card.tsx similarity index 100% rename from examples/react/start-trellaux/app/components/Card.tsx rename to examples/react/start-trellaux/src/components/Card.tsx diff --git a/examples/react/start-trellaux/app/components/Column.tsx b/examples/react/start-trellaux/src/components/Column.tsx similarity index 100% rename from examples/react/start-trellaux/app/components/Column.tsx rename to examples/react/start-trellaux/src/components/Column.tsx diff --git a/examples/react/start-trellaux/app/components/DefaultCatchBoundary.tsx b/examples/react/start-trellaux/src/components/DefaultCatchBoundary.tsx similarity index 100% rename from examples/react/start-trellaux/app/components/DefaultCatchBoundary.tsx rename to examples/react/start-trellaux/src/components/DefaultCatchBoundary.tsx diff --git a/examples/react/start-trellaux/app/components/EditableText.tsx b/examples/react/start-trellaux/src/components/EditableText.tsx similarity index 100% rename from examples/react/start-trellaux/app/components/EditableText.tsx rename to examples/react/start-trellaux/src/components/EditableText.tsx diff --git a/examples/react/start-trellaux/app/components/IconLink.tsx b/examples/react/start-trellaux/src/components/IconLink.tsx similarity index 100% rename from examples/react/start-trellaux/app/components/IconLink.tsx rename to examples/react/start-trellaux/src/components/IconLink.tsx diff --git a/examples/react/start-trellaux/app/components/Loader.tsx b/examples/react/start-trellaux/src/components/Loader.tsx similarity index 100% rename from examples/react/start-trellaux/app/components/Loader.tsx rename to examples/react/start-trellaux/src/components/Loader.tsx diff --git a/examples/react/start-trellaux/app/components/NewCard.tsx b/examples/react/start-trellaux/src/components/NewCard.tsx similarity index 100% rename from examples/react/start-trellaux/app/components/NewCard.tsx rename to examples/react/start-trellaux/src/components/NewCard.tsx diff --git a/examples/react/start-trellaux/app/components/NewColumn.tsx b/examples/react/start-trellaux/src/components/NewColumn.tsx similarity index 100% rename from examples/react/start-trellaux/app/components/NewColumn.tsx rename to examples/react/start-trellaux/src/components/NewColumn.tsx diff --git a/examples/react/start-trellaux/app/components/NotFound.tsx b/examples/react/start-trellaux/src/components/NotFound.tsx similarity index 100% rename from examples/react/start-trellaux/app/components/NotFound.tsx rename to examples/react/start-trellaux/src/components/NotFound.tsx diff --git a/examples/react/start-trellaux/app/components/SaveButton.tsx b/examples/react/start-trellaux/src/components/SaveButton.tsx similarity index 100% rename from examples/react/start-trellaux/app/components/SaveButton.tsx rename to examples/react/start-trellaux/src/components/SaveButton.tsx diff --git a/examples/react/start-trellaux/app/db/board.ts b/examples/react/start-trellaux/src/db/board.ts similarity index 100% rename from examples/react/start-trellaux/app/db/board.ts rename to examples/react/start-trellaux/src/db/board.ts diff --git a/examples/react/start-trellaux/app/db/schema.ts b/examples/react/start-trellaux/src/db/schema.ts similarity index 100% rename from examples/react/start-trellaux/app/db/schema.ts rename to examples/react/start-trellaux/src/db/schema.ts diff --git a/examples/react/start-trellaux/app/hooks/useOfflineIndicator.tsx b/examples/react/start-trellaux/src/hooks/useOfflineIndicator.tsx similarity index 100% rename from examples/react/start-trellaux/app/hooks/useOfflineIndicator.tsx rename to examples/react/start-trellaux/src/hooks/useOfflineIndicator.tsx diff --git a/examples/react/start-trellaux/app/icons/icons.svg b/examples/react/start-trellaux/src/icons/icons.svg similarity index 100% rename from examples/react/start-trellaux/app/icons/icons.svg rename to examples/react/start-trellaux/src/icons/icons.svg diff --git a/examples/react/start-trellaux/app/icons/icons.tsx b/examples/react/start-trellaux/src/icons/icons.tsx similarity index 100% rename from examples/react/start-trellaux/app/icons/icons.tsx rename to examples/react/start-trellaux/src/icons/icons.tsx diff --git a/examples/react/start-trellaux/app/queries.ts b/examples/react/start-trellaux/src/queries.ts similarity index 100% rename from examples/react/start-trellaux/app/queries.ts rename to examples/react/start-trellaux/src/queries.ts diff --git a/examples/react/start-trellaux/app/routeTree.gen.ts b/examples/react/start-trellaux/src/routeTree.gen.ts similarity index 100% rename from examples/react/start-trellaux/app/routeTree.gen.ts rename to examples/react/start-trellaux/src/routeTree.gen.ts diff --git a/examples/react/start-trellaux/app/router.tsx b/examples/react/start-trellaux/src/router.tsx similarity index 100% rename from examples/react/start-trellaux/app/router.tsx rename to examples/react/start-trellaux/src/router.tsx diff --git a/examples/react/start-trellaux/app/routes/__root.tsx b/examples/react/start-trellaux/src/routes/__root.tsx similarity index 100% rename from examples/react/start-trellaux/app/routes/__root.tsx rename to examples/react/start-trellaux/src/routes/__root.tsx diff --git a/examples/react/start-trellaux/app/routes/boards.$boardId.tsx b/examples/react/start-trellaux/src/routes/boards.$boardId.tsx similarity index 100% rename from examples/react/start-trellaux/app/routes/boards.$boardId.tsx rename to examples/react/start-trellaux/src/routes/boards.$boardId.tsx diff --git a/examples/react/start-trellaux/app/routes/index.tsx b/examples/react/start-trellaux/src/routes/index.tsx similarity index 100% rename from examples/react/start-trellaux/app/routes/index.tsx rename to examples/react/start-trellaux/src/routes/index.tsx diff --git a/examples/react/start-counter/app/server.ts b/examples/react/start-trellaux/src/server.ts similarity index 100% rename from examples/react/start-counter/app/server.ts rename to examples/react/start-trellaux/src/server.ts diff --git a/examples/react/start-trellaux/app/styles/app.css b/examples/react/start-trellaux/src/styles/app.css similarity index 100% rename from examples/react/start-trellaux/app/styles/app.css rename to examples/react/start-trellaux/src/styles/app.css diff --git a/examples/react/start-trellaux/app/types.ts b/examples/react/start-trellaux/src/types.ts similarity index 100% rename from examples/react/start-trellaux/app/types.ts rename to examples/react/start-trellaux/src/types.ts diff --git a/examples/react/start-trellaux/app/utils/posts.tsx b/examples/react/start-trellaux/src/utils/posts.tsx similarity index 100% rename from examples/react/start-trellaux/app/utils/posts.tsx rename to examples/react/start-trellaux/src/utils/posts.tsx diff --git a/examples/react/start-trellaux/app/utils/seo.ts b/examples/react/start-trellaux/src/utils/seo.ts similarity index 100% rename from examples/react/start-trellaux/app/utils/seo.ts rename to examples/react/start-trellaux/src/utils/seo.ts diff --git a/examples/react/with-trpc-react-query/app/main.tsx b/examples/react/with-trpc-react-query/src/main.tsx similarity index 100% rename from examples/react/with-trpc-react-query/app/main.tsx rename to examples/react/with-trpc-react-query/src/main.tsx diff --git a/examples/react/with-trpc-react-query/app/routeTree.gen.ts b/examples/react/with-trpc-react-query/src/routeTree.gen.ts similarity index 100% rename from examples/react/with-trpc-react-query/app/routeTree.gen.ts rename to examples/react/with-trpc-react-query/src/routeTree.gen.ts diff --git a/examples/react/with-trpc-react-query/app/router.tsx b/examples/react/with-trpc-react-query/src/router.tsx similarity index 100% rename from examples/react/with-trpc-react-query/app/router.tsx rename to examples/react/with-trpc-react-query/src/router.tsx diff --git a/examples/react/with-trpc-react-query/app/routes/-components/spinner.tsx b/examples/react/with-trpc-react-query/src/routes/-components/spinner.tsx similarity index 100% rename from examples/react/with-trpc-react-query/app/routes/-components/spinner.tsx rename to examples/react/with-trpc-react-query/src/routes/-components/spinner.tsx diff --git a/examples/react/with-trpc-react-query/app/routes/__root.tsx b/examples/react/with-trpc-react-query/src/routes/__root.tsx similarity index 100% rename from examples/react/with-trpc-react-query/app/routes/__root.tsx rename to examples/react/with-trpc-react-query/src/routes/__root.tsx diff --git a/examples/react/with-trpc-react-query/app/routes/dashboard.index.tsx b/examples/react/with-trpc-react-query/src/routes/dashboard.index.tsx similarity index 100% rename from examples/react/with-trpc-react-query/app/routes/dashboard.index.tsx rename to examples/react/with-trpc-react-query/src/routes/dashboard.index.tsx diff --git a/examples/react/with-trpc-react-query/app/routes/dashboard.posts.$postId.tsx b/examples/react/with-trpc-react-query/src/routes/dashboard.posts.$postId.tsx similarity index 100% rename from examples/react/with-trpc-react-query/app/routes/dashboard.posts.$postId.tsx rename to examples/react/with-trpc-react-query/src/routes/dashboard.posts.$postId.tsx diff --git a/examples/react/with-trpc-react-query/app/routes/dashboard.posts.index.tsx b/examples/react/with-trpc-react-query/src/routes/dashboard.posts.index.tsx similarity index 100% rename from examples/react/with-trpc-react-query/app/routes/dashboard.posts.index.tsx rename to examples/react/with-trpc-react-query/src/routes/dashboard.posts.index.tsx diff --git a/examples/react/with-trpc-react-query/app/routes/dashboard.posts.tsx b/examples/react/with-trpc-react-query/src/routes/dashboard.posts.tsx similarity index 100% rename from examples/react/with-trpc-react-query/app/routes/dashboard.posts.tsx rename to examples/react/with-trpc-react-query/src/routes/dashboard.posts.tsx diff --git a/examples/react/with-trpc-react-query/app/routes/dashboard.tsx b/examples/react/with-trpc-react-query/src/routes/dashboard.tsx similarity index 100% rename from examples/react/with-trpc-react-query/app/routes/dashboard.tsx rename to examples/react/with-trpc-react-query/src/routes/dashboard.tsx diff --git a/examples/react/with-trpc-react-query/app/routes/index.tsx b/examples/react/with-trpc-react-query/src/routes/index.tsx similarity index 100% rename from examples/react/with-trpc-react-query/app/routes/index.tsx rename to examples/react/with-trpc-react-query/src/routes/index.tsx diff --git a/examples/react/with-trpc-react-query/app/styles.css b/examples/react/with-trpc-react-query/src/styles.css similarity index 100% rename from examples/react/with-trpc-react-query/app/styles.css rename to examples/react/with-trpc-react-query/src/styles.css diff --git a/examples/react/with-trpc/app/main.tsx b/examples/react/with-trpc/src/main.tsx similarity index 100% rename from examples/react/with-trpc/app/main.tsx rename to examples/react/with-trpc/src/main.tsx diff --git a/examples/react/with-trpc/app/routeTree.gen.ts b/examples/react/with-trpc/src/routeTree.gen.ts similarity index 100% rename from examples/react/with-trpc/app/routeTree.gen.ts rename to examples/react/with-trpc/src/routeTree.gen.ts diff --git a/examples/react/with-trpc/app/routes/-components/spinner.tsx b/examples/react/with-trpc/src/routes/-components/spinner.tsx similarity index 100% rename from examples/react/with-trpc/app/routes/-components/spinner.tsx rename to examples/react/with-trpc/src/routes/-components/spinner.tsx diff --git a/examples/react/with-trpc/app/routes/__root.tsx b/examples/react/with-trpc/src/routes/__root.tsx similarity index 100% rename from examples/react/with-trpc/app/routes/__root.tsx rename to examples/react/with-trpc/src/routes/__root.tsx diff --git a/examples/react/with-trpc/app/routes/dashboard.index.tsx b/examples/react/with-trpc/src/routes/dashboard.index.tsx similarity index 100% rename from examples/react/with-trpc/app/routes/dashboard.index.tsx rename to examples/react/with-trpc/src/routes/dashboard.index.tsx diff --git a/examples/react/with-trpc/app/routes/dashboard.posts.$postId.tsx b/examples/react/with-trpc/src/routes/dashboard.posts.$postId.tsx similarity index 100% rename from examples/react/with-trpc/app/routes/dashboard.posts.$postId.tsx rename to examples/react/with-trpc/src/routes/dashboard.posts.$postId.tsx diff --git a/examples/react/with-trpc/app/routes/dashboard.posts.index.tsx b/examples/react/with-trpc/src/routes/dashboard.posts.index.tsx similarity index 100% rename from examples/react/with-trpc/app/routes/dashboard.posts.index.tsx rename to examples/react/with-trpc/src/routes/dashboard.posts.index.tsx diff --git a/examples/react/with-trpc/app/routes/dashboard.posts.tsx b/examples/react/with-trpc/src/routes/dashboard.posts.tsx similarity index 100% rename from examples/react/with-trpc/app/routes/dashboard.posts.tsx rename to examples/react/with-trpc/src/routes/dashboard.posts.tsx diff --git a/examples/react/with-trpc/app/routes/dashboard.tsx b/examples/react/with-trpc/src/routes/dashboard.tsx similarity index 100% rename from examples/react/with-trpc/app/routes/dashboard.tsx rename to examples/react/with-trpc/src/routes/dashboard.tsx diff --git a/examples/react/with-trpc/app/routes/index.tsx b/examples/react/with-trpc/src/routes/index.tsx similarity index 100% rename from examples/react/with-trpc/app/routes/index.tsx rename to examples/react/with-trpc/src/routes/index.tsx diff --git a/examples/react/with-trpc/app/styles.css b/examples/react/with-trpc/src/styles.css similarity index 100% rename from examples/react/with-trpc/app/styles.css rename to examples/react/with-trpc/src/styles.css diff --git a/examples/react/with-trpc/app/trpc.ts b/examples/react/with-trpc/src/trpc.ts similarity index 100% rename from examples/react/with-trpc/app/trpc.ts rename to examples/react/with-trpc/src/trpc.ts diff --git a/e2e/solid-start/website/app/client.tsx b/examples/solid/start-bare/src/client.tsx similarity index 100% rename from e2e/solid-start/website/app/client.tsx rename to examples/solid/start-bare/src/client.tsx diff --git a/examples/solid/start-bare/app/components/Counter.css b/examples/solid/start-bare/src/components/Counter.css similarity index 100% rename from examples/solid/start-bare/app/components/Counter.css rename to examples/solid/start-bare/src/components/Counter.css diff --git a/examples/solid/start-bare/app/components/Counter.tsx b/examples/solid/start-bare/src/components/Counter.tsx similarity index 100% rename from examples/solid/start-bare/app/components/Counter.tsx rename to examples/solid/start-bare/src/components/Counter.tsx diff --git a/examples/solid/start-bare/app/routeTree.gen.ts b/examples/solid/start-bare/src/routeTree.gen.ts similarity index 100% rename from examples/solid/start-bare/app/routeTree.gen.ts rename to examples/solid/start-bare/src/routeTree.gen.ts diff --git a/examples/solid/start-bare/app/router.tsx b/examples/solid/start-bare/src/router.tsx similarity index 100% rename from examples/solid/start-bare/app/router.tsx rename to examples/solid/start-bare/src/router.tsx diff --git a/examples/solid/start-bare/app/routes/__root.tsx b/examples/solid/start-bare/src/routes/__root.tsx similarity index 100% rename from examples/solid/start-bare/app/routes/__root.tsx rename to examples/solid/start-bare/src/routes/__root.tsx diff --git a/examples/solid/start-bare/app/routes/about.tsx b/examples/solid/start-bare/src/routes/about.tsx similarity index 100% rename from examples/solid/start-bare/app/routes/about.tsx rename to examples/solid/start-bare/src/routes/about.tsx diff --git a/examples/solid/start-bare/app/routes/index.tsx b/examples/solid/start-bare/src/routes/index.tsx similarity index 86% rename from examples/solid/start-bare/app/routes/index.tsx rename to examples/solid/start-bare/src/routes/index.tsx index 6a91bd1999..507865f60f 100644 --- a/examples/solid/start-bare/app/routes/index.tsx +++ b/examples/solid/start-bare/src/routes/index.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/solid-router' -import Counter from '~/components/Counter' +import Counter from 'src/components/Counter' export const Route = createFileRoute('/')({ component: RouteComponent, }) diff --git a/examples/solid/start-bare/app/ssr.tsx b/examples/solid/start-bare/src/ssr.tsx similarity index 100% rename from examples/solid/start-bare/app/ssr.tsx rename to examples/solid/start-bare/src/ssr.tsx diff --git a/examples/solid/start-bare/app/styles/app.css b/examples/solid/start-bare/src/styles/app.css similarity index 100% rename from examples/solid/start-bare/app/styles/app.css rename to examples/solid/start-bare/src/styles/app.css diff --git a/examples/solid/start-bare/tsconfig.json b/examples/solid/start-bare/tsconfig.json index 73e4856648..3f2c37eff4 100644 --- a/examples/solid/start-bare/tsconfig.json +++ b/examples/solid/start-bare/tsconfig.json @@ -16,7 +16,7 @@ "forceConsistentCasingInFileNames": true, "baseUrl": ".", "paths": { - "~/*": ["./app/*"] + "~/*": ["src/*"] }, "noEmit": true } diff --git a/packages/create-start/src/modules/core/template/app/client.tsx b/packages/create-start/src/modules/core/template/src/client.tsx similarity index 100% rename from packages/create-start/src/modules/core/template/app/client.tsx rename to packages/create-start/src/modules/core/template/src/client.tsx diff --git a/packages/create-start/src/modules/core/template/app/router.tsx b/packages/create-start/src/modules/core/template/src/router.tsx similarity index 100% rename from packages/create-start/src/modules/core/template/app/router.tsx rename to packages/create-start/src/modules/core/template/src/router.tsx diff --git a/packages/create-start/src/modules/core/template/app/routes/__root.tsx b/packages/create-start/src/modules/core/template/src/routes/__root.tsx similarity index 100% rename from packages/create-start/src/modules/core/template/app/routes/__root.tsx rename to packages/create-start/src/modules/core/template/src/routes/__root.tsx From 8cce13b9e993d799b699f034ec29b46375c8c9cd Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Fri, 7 Mar 2025 23:28:51 -0700 Subject: [PATCH 027/155] fix start-basic --- .../react/start-basic/src/routeTree.gen.ts | 86 ++++++------------- .../start-basic/src/routes/posts.route.tsx | 38 -------- .../start-basic/src/routes/users.route.tsx | 48 ----------- 3 files changed, 26 insertions(+), 146 deletions(-) delete mode 100644 examples/react/start-basic/src/routes/posts.route.tsx delete mode 100644 examples/react/start-basic/src/routes/users.route.tsx diff --git a/examples/react/start-basic/src/routeTree.gen.ts b/examples/react/start-basic/src/routeTree.gen.ts index c7786de3e4..12ee484c06 100644 --- a/examples/react/start-basic/src/routeTree.gen.ts +++ b/examples/react/start-basic/src/routeTree.gen.ts @@ -17,8 +17,6 @@ import { Route as PostsImport } from './routes/posts' import { Route as DeferredImport } from './routes/deferred' import { Route as PathlessLayoutImport } from './routes/_pathlessLayout' import { Route as LayoutImport } from './routes/_layout' -import { Route as UsersRouteImport } from './routes/users.route' -import { Route as PostsRouteImport } from './routes/posts.route' import { Route as IndexImport } from './routes/index' import { Route as UsersIndexImport } from './routes/users.index' import { Route as PostsIndexImport } from './routes/posts.index' @@ -65,18 +63,6 @@ const LayoutRoute = LayoutImport.update({ getParentRoute: () => rootRoute, } as any) -const UsersRouteRoute = UsersRouteImport.update({ - id: '/users', - path: '/users', - getParentRoute: () => rootRoute, -} as any) - -const PostsRouteRoute = PostsRouteImport.update({ - id: '/posts', - path: '/posts', - getParentRoute: () => rootRoute, -} as any) - const IndexRoute = IndexImport.update({ id: '/', path: '/', @@ -145,20 +131,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof IndexImport parentRoute: typeof rootRoute } - '/posts': { - id: '/posts' - path: '/posts' - fullPath: '/posts' - preLoaderRoute: typeof PostsRouteImport - parentRoute: typeof rootRoute - } - '/users': { - id: '/users' - path: '/users' - fullPath: '/users' - preLoaderRoute: typeof UsersRouteImport - parentRoute: typeof rootRoute - } '/_layout': { id: '/_layout' path: '' @@ -318,11 +290,11 @@ const UsersRouteWithChildren = UsersRoute._addFileChildren(UsersRouteChildren) export interface FileRoutesByFullPath { '/': typeof IndexRoute - '/posts': typeof PostsRouteWithChildren - '/users': typeof UsersRouteWithChildren '': typeof PathlessLayoutNestedLayoutRouteWithChildren '/deferred': typeof DeferredRoute + '/posts': typeof PostsRouteWithChildren '/redirect': typeof RedirectRoute + '/users': typeof UsersRouteWithChildren '/posts/$postId': typeof PostsPostIdRoute '/users/$userId': typeof UsersUserIdRoute '/posts/': typeof PostsIndexRoute @@ -334,13 +306,13 @@ export interface FileRoutesByFullPath { export interface FileRoutesByTo { '/': typeof IndexRoute - '/posts': typeof PostsIndexRoute - '/users': typeof UsersIndexRoute '': typeof PathlessLayoutNestedLayoutRouteWithChildren '/deferred': typeof DeferredRoute '/redirect': typeof RedirectRoute '/posts/$postId': typeof PostsPostIdRoute '/users/$userId': typeof UsersUserIdRoute + '/posts': typeof PostsIndexRoute + '/users': typeof UsersIndexRoute '/route-a': typeof PathlessLayoutNestedLayoutRouteARoute '/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute '/posts/$postId/deep': typeof PostsPostIdDeepRoute @@ -349,12 +321,12 @@ export interface FileRoutesByTo { export interface FileRoutesById { __root__: typeof rootRoute '/': typeof IndexRoute - '/posts': typeof PostsRouteWithChildren - '/users': typeof UsersRouteWithChildren '/_layout': typeof LayoutRoute '/_pathlessLayout': typeof PathlessLayoutRouteWithChildren '/deferred': typeof DeferredRoute + '/posts': typeof PostsRouteWithChildren '/redirect': typeof RedirectRoute + '/users': typeof UsersRouteWithChildren '/_pathlessLayout/_nested-layout': typeof PathlessLayoutNestedLayoutRouteWithChildren '/posts/$postId': typeof PostsPostIdRoute '/users/$userId': typeof UsersUserIdRoute @@ -369,11 +341,11 @@ export interface FileRouteTypes { fileRoutesByFullPath: FileRoutesByFullPath fullPaths: | '/' - | '/posts' - | '/users' | '' | '/deferred' + | '/posts' | '/redirect' + | '/users' | '/posts/$postId' | '/users/$userId' | '/posts/' @@ -384,25 +356,25 @@ export interface FileRouteTypes { fileRoutesByTo: FileRoutesByTo to: | '/' - | '/posts' - | '/users' | '' | '/deferred' | '/redirect' | '/posts/$postId' | '/users/$userId' + | '/posts' + | '/users' | '/route-a' | '/route-b' | '/posts/$postId/deep' id: | '__root__' | '/' - | '/posts' - | '/users' | '/_layout' | '/_pathlessLayout' | '/deferred' + | '/posts' | '/redirect' + | '/users' | '/_pathlessLayout/_nested-layout' | '/posts/$postId' | '/users/$userId' @@ -416,8 +388,6 @@ export interface FileRouteTypes { export interface RootRouteChildren { IndexRoute: typeof IndexRoute - PostsRouteRoute: typeof PostsRouteRoute - UsersRouteRoute: typeof UsersRouteRoute LayoutRoute: typeof LayoutRoute PathlessLayoutRoute: typeof PathlessLayoutRouteWithChildren DeferredRoute: typeof DeferredRoute @@ -429,8 +399,6 @@ export interface RootRouteChildren { const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, - PostsRouteRoute: PostsRouteRoute, - UsersRouteRoute: UsersRouteRoute, LayoutRoute: LayoutRoute, PathlessLayoutRoute: PathlessLayoutRouteWithChildren, DeferredRoute: DeferredRoute, @@ -451,8 +419,6 @@ export const routeTree = rootRoute "filePath": "__root.tsx", "children": [ "/", - "/posts", - "/users", "/_layout", "/_pathlessLayout", "/deferred", @@ -465,20 +431,6 @@ export const routeTree = rootRoute "/": { "filePath": "index.tsx" }, - "/posts": { - "filePath": "posts.tsx", - "children": [ - "/posts/$postId", - "/posts/" - ] - }, - "/users": { - "filePath": "users.tsx", - "children": [ - "/users/$userId", - "/users/" - ] - }, "/_layout": { "filePath": "_layout.tsx" }, @@ -491,9 +443,23 @@ export const routeTree = rootRoute "/deferred": { "filePath": "deferred.tsx" }, + "/posts": { + "filePath": "posts.tsx", + "children": [ + "/posts/$postId", + "/posts/" + ] + }, "/redirect": { "filePath": "redirect.tsx" }, + "/users": { + "filePath": "users.tsx", + "children": [ + "/users/$userId", + "/users/" + ] + }, "/_pathlessLayout/_nested-layout": { "filePath": "_pathlessLayout/_nested-layout.tsx", "parent": "/_pathlessLayout", diff --git a/examples/react/start-basic/src/routes/posts.route.tsx b/examples/react/start-basic/src/routes/posts.route.tsx deleted file mode 100644 index f29619363e..0000000000 --- a/examples/react/start-basic/src/routes/posts.route.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from '../utils/posts' - -export const Route = createFileRoute('/posts')({ - loader: async () => fetchPosts(), - component: PostsLayoutComponent, -}) - -function PostsLayoutComponent() { - const posts = Route.useLoaderData() - - return ( -
-
    - {[...posts, { id: 'i-do-not-exist', title: 'Non-existent Post' }].map( - (post) => { - return ( -
  • - -
    {post.title.substring(0, 20)}
    - -
  • - ) - }, - )} -
-
- -
- ) -} diff --git a/examples/react/start-basic/src/routes/users.route.tsx b/examples/react/start-basic/src/routes/users.route.tsx deleted file mode 100644 index 76cf588f6a..0000000000 --- a/examples/react/start-basic/src/routes/users.route.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import axios from 'redaxios' -import { DEPLOY_URL } from '../utils/users' -import type { User } from '../utils/users' - -export const Route = createFileRoute('/users')({ - loader: async () => { - return await axios - .get>(DEPLOY_URL + '/api/users') - .then((r) => r.data) - .catch(() => { - throw new Error('Failed to fetch users') - }) - }, - component: UsersLayoutComponent, -}) - -function UsersLayoutComponent() { - const users = Route.useLoaderData() - - return ( -
-
    - {[ - ...users, - { id: 'i-do-not-exist', name: 'Non-existent User', email: '' }, - ].map((user) => { - return ( -
  • - -
    {user.name}
    - -
  • - ) - })} -
-
- -
- ) -} From 2aa374014b9f6fdbf00c5cfdeffbf302a8dd393d Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Sat, 8 Mar 2025 20:30:54 +1300 Subject: [PATCH 028/155] fix(react-router): revert experimental change about removing the route path for `createFileRoute` --- packages/react-router/src/fileRoute.ts | 40 +++++++++----------------- 1 file changed, 13 insertions(+), 27 deletions(-) diff --git a/packages/react-router/src/fileRoute.ts b/packages/react-router/src/fileRoute.ts index c72e45ca15..d645cc840d 100644 --- a/packages/react-router/src/fileRoute.ts +++ b/packages/react-router/src/fileRoute.ts @@ -33,33 +33,19 @@ import type { UseLoaderDepsRoute } from './useLoaderDeps' import type { UseLoaderDataRoute } from './useLoaderData' import type { UseRouteContextRoute } from './useRouteContext' -type RouteInfo = { - parentRoute: AnyRoute - id: RouteConstraints['TId'] - path: keyof FileRoutesByPath - fullPath: RouteConstraints['TFullPath'] -} - -export function createFileRoute(): FileRoute< - TRouteInfo['path'], - TRouteInfo['parentRoute'], - TRouteInfo['id'], - TRouteInfo['path'], - TRouteInfo['fullPath'] ->['createRoute'] { - return new FileRoute< - TRouteInfo['path'], - TRouteInfo['parentRoute'], - TRouteInfo['id'], - TRouteInfo['path'], - TRouteInfo['fullPath'] - >( - // @ts-expect-error - undefined, - { - silent: true, - }, - ).createRoute +export function createFileRoute< + TFilePath extends keyof FileRoutesByPath, + TParentRoute extends AnyRoute = FileRoutesByPath[TFilePath]['parentRoute'], + TId extends RouteConstraints['TId'] = FileRoutesByPath[TFilePath]['id'], + TPath extends RouteConstraints['TPath'] = FileRoutesByPath[TFilePath]['path'], + TFullPath extends + RouteConstraints['TFullPath'] = FileRoutesByPath[TFilePath]['fullPath'], +>( + path: TFilePath, +): FileRoute['createRoute'] { + return new FileRoute(path, { + silent: true, + }).createRoute } /** From 18f91ad125e73038e7710c65e34be59ef2f687db Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Mon, 10 Mar 2025 00:09:14 +0100 Subject: [PATCH 029/155] remove unwanted client/ssr files --- e2e/react-start/basic-auth/src/client.tsx | 8 -------- e2e/react-start/basic-auth/src/ssr.tsx | 12 ------------ e2e/react-start/basic-react-query/src/ssr.tsx | 12 ------------ e2e/react-start/basic-rsc/src/ssr.tsx | 12 ------------ e2e/react-start/clerk-basic/src/ssr.tsx | 16 ---------------- .../scroll-restoration/src/client.tsx | 9 --------- e2e/react-start/scroll-restoration/src/ssr.tsx | 12 ------------ e2e/react-start/server-functions/src/ssr.tsx | 12 ------------ examples/react/start-bare/src/ssr.tsx | 12 ------------ examples/react/start-basic-auth/src/ssr.tsx | 14 -------------- .../react/start-basic-react-query/src/ssr.tsx | 14 -------------- examples/react/start-basic-rsc/src/ssr.tsx | 12 ------------ examples/react/start-basic-static/src/ssr.tsx | 13 ------------- 13 files changed, 158 deletions(-) delete mode 100644 e2e/react-start/basic-auth/src/client.tsx delete mode 100644 e2e/react-start/basic-auth/src/ssr.tsx delete mode 100644 e2e/react-start/basic-react-query/src/ssr.tsx delete mode 100644 e2e/react-start/basic-rsc/src/ssr.tsx delete mode 100644 e2e/react-start/clerk-basic/src/ssr.tsx delete mode 100644 e2e/react-start/scroll-restoration/src/client.tsx delete mode 100644 e2e/react-start/scroll-restoration/src/ssr.tsx delete mode 100644 e2e/react-start/server-functions/src/ssr.tsx delete mode 100644 examples/react/start-bare/src/ssr.tsx delete mode 100644 examples/react/start-basic-auth/src/ssr.tsx delete mode 100644 examples/react/start-basic-react-query/src/ssr.tsx delete mode 100644 examples/react/start-basic-rsc/src/ssr.tsx delete mode 100644 examples/react/start-basic-static/src/ssr.tsx diff --git a/e2e/react-start/basic-auth/src/client.tsx b/e2e/react-start/basic-auth/src/client.tsx deleted file mode 100644 index 1593d1b3c7..0000000000 --- a/e2e/react-start/basic-auth/src/client.tsx +++ /dev/null @@ -1,8 +0,0 @@ -/// -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/basic-auth/src/ssr.tsx b/e2e/react-start/basic-auth/src/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/e2e/react-start/basic-auth/src/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/e2e/react-start/basic-react-query/src/ssr.tsx b/e2e/react-start/basic-react-query/src/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/e2e/react-start/basic-react-query/src/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/e2e/react-start/basic-rsc/src/ssr.tsx b/e2e/react-start/basic-rsc/src/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/e2e/react-start/basic-rsc/src/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/e2e/react-start/clerk-basic/src/ssr.tsx b/e2e/react-start/clerk-basic/src/ssr.tsx deleted file mode 100644 index ef5ba0bc95..0000000000 --- a/e2e/react-start/clerk-basic/src/ssr.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' -import { createClerkHandler } from '@clerk/tanstack-start/server' -import { createRouter } from './router' - -const handler = createStartHandler({ - createRouter, - getRouterManifest, -}) - -const clerkHandler = createClerkHandler(handler) - -export default clerkHandler(defaultStreamHandler) diff --git a/e2e/react-start/scroll-restoration/src/client.tsx b/e2e/react-start/scroll-restoration/src/client.tsx deleted file mode 100644 index f675b9c39d..0000000000 --- a/e2e/react-start/scroll-restoration/src/client.tsx +++ /dev/null @@ -1,9 +0,0 @@ -// @ts-nocheck - -import { hydrateRoot } from 'react-dom/client' -import { StartClient } from '@tanstack/react-start' -import { createRouter } from './router' - -const router = createRouter() - -hydrateRoot(document, ) diff --git a/e2e/react-start/scroll-restoration/src/ssr.tsx b/e2e/react-start/scroll-restoration/src/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/e2e/react-start/scroll-restoration/src/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/e2e/react-start/server-functions/src/ssr.tsx b/e2e/react-start/server-functions/src/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/e2e/react-start/server-functions/src/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/examples/react/start-bare/src/ssr.tsx b/examples/react/start-bare/src/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/examples/react/start-bare/src/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/examples/react/start-basic-auth/src/ssr.tsx b/examples/react/start-basic-auth/src/ssr.tsx deleted file mode 100644 index cb5ab731aa..0000000000 --- a/examples/react/start-basic-auth/src/ssr.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// src/server.tsx - -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/examples/react/start-basic-react-query/src/ssr.tsx b/examples/react/start-basic-react-query/src/ssr.tsx deleted file mode 100644 index cb5ab731aa..0000000000 --- a/examples/react/start-basic-react-query/src/ssr.tsx +++ /dev/null @@ -1,14 +0,0 @@ -// src/server.tsx - -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/examples/react/start-basic-rsc/src/ssr.tsx b/examples/react/start-basic-rsc/src/ssr.tsx deleted file mode 100644 index 65a580f25e..0000000000 --- a/examples/react/start-basic-rsc/src/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/react-start/server' -import { getRouterManifest } from '@tanstack/react-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/examples/react/start-basic-static/src/ssr.tsx b/examples/react/start-basic-static/src/ssr.tsx deleted file mode 100644 index db95139de1..0000000000 --- a/examples/react/start-basic-static/src/ssr.tsx +++ /dev/null @@ -1,13 +0,0 @@ -/// -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/solid-start/server' -import { getRouterManifest } from '@tanstack/solid-start/router-manifest' - -import { createRouter } from './app/router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) From 07e00db28eef5fb20764c8f9d9acb1c31a8f98d2 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Mon, 10 Mar 2025 05:59:34 +0100 Subject: [PATCH 030/155] merge main to devinxi --- .../src/createStartHandler.ts | 6 +- packages/react-start-server/src/h3.ts | 490 ------------------ .../src/server-functions-handler.ts | 4 +- packages/react-start-server/tsconfig.json | 2 +- packages/start-server-core/src/h3.ts | 77 ++- packages/start-server-core/src/index.tsx | 4 +- .../src/router-manifest.ts | 0 packages/start-server-core/vite.config.ts | 1 + pnpm-lock.yaml | 37 ++ 9 files changed, 81 insertions(+), 540 deletions(-) rename packages/{start-server-core => react-start-server}/src/createStartHandler.ts (91%) delete mode 100644 packages/react-start-server/src/h3.ts rename packages/{react-start-server => start-server-core}/src/router-manifest.ts (100%) diff --git a/packages/start-server-core/src/createStartHandler.ts b/packages/react-start-server/src/createStartHandler.ts similarity index 91% rename from packages/start-server-core/src/createStartHandler.ts rename to packages/react-start-server/src/createStartHandler.ts index 83bbcb895a..2236cb4c46 100644 --- a/packages/start-server-core/src/createStartHandler.ts +++ b/packages/react-start-server/src/createStartHandler.ts @@ -2,10 +2,10 @@ import path from 'node:path' import { createMemoryHistory } from '@tanstack/history' import { mergeHeaders } from '@tanstack/start-client-core' import { eventHandler, getResponseHeaders, toWebRequest } from 'h3' -import { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server' +import { getStartManifest } from '@tanstack/start-server-core' +import { attachRouterServerSsrUtils, dehydrateRouter } from '../../start-server-core/src/ssr-server' import serverFunctionsHandler from './server-functions-handler' -import { getStartManifest } from './router-manifest' -import type { HandlerCallback } from './handlerCallback' +import type { HandlerCallback } from '../../start-server-core/src/handlerCallback' import type { EventHandlerResponse, H3Event } from 'h3' import type { AnyRouter } from '@tanstack/router-core' diff --git a/packages/react-start-server/src/h3.ts b/packages/react-start-server/src/h3.ts deleted file mode 100644 index 8e7dbc049c..0000000000 --- a/packages/react-start-server/src/h3.ts +++ /dev/null @@ -1,490 +0,0 @@ -import { AsyncLocalStorage } from 'node:async_hooks' -import { - H3Event, - appendCorsHeaders as _appendCorsHeaders, - appendCorsPreflightHeaders as _appendCorsPreflightHeaders, - appendHeader as _appendHeader, - appendHeaders as _appendHeaders, - appendResponseHeader as _appendResponseHeader, - appendResponseHeaders as _appendResponseHeaders, - assertMethod as _assertMethod, - clearResponseHeaders as _clearResponseHeaders, - clearSession as _clearSession, - defaultContentType as _defaultContentType, - defineEventHandler as _defineEventHandler, - deleteCookie as _deleteCookie, - eventHandler as _eventHandler, - fetchWithEvent as _fetchWithEvent, - getCookie as _getCookie, - getHeader as _getHeader, - getHeaders as _getHeaders, - getProxyRequestHeaders as _getProxyRequestHeaders, - getQuery as _getQuery, - getRequestFingerprint as _getRequestFingerprint, - getRequestHeader as _getRequestHeader, - getRequestHeaders as _getRequestHeaders, - getRequestHost as _getRequestHost, - getRequestIP as _getRequestIP, - getRequestProtocol as _getRequestProtocol, - getRequestURL as _getRequestURL, - getRequestWebStream as _getRequestWebStream, - getResponseHeader as _getResponseHeader, - getResponseHeaders as _getResponseHeaders, - getResponseStatus as _getResponseStatus, - getResponseStatusText as _getResponseStatusText, - getRouterParam as _getRouterParam, - getRouterParams as _getRouterParams, - getSession as _getSession, - getValidatedQuery as _getValidatedQuery, - getValidatedRouterParams as _getValidatedRouterParams, - handleCacheHeaders as _handleCacheHeaders, - handleCors as _handleCors, - isMethod as _isMethod, - isPreflightRequest as _isPreflightRequest, - parseCookies as _parseCookies, - proxyRequest as _proxyRequest, - readBody as _readBody, - readFormData as _readFormData, - readMultipartFormData as _readMultipartFormData, - readRawBody as _readRawBody, - readValidatedBody as _readValidatedBody, - removeResponseHeader as _removeResponseHeader, - sealSession as _sealSession, - send as _send, - sendError as _sendError, - sendNoContent as _sendNoContent, - sendProxy as _sendProxy, - sendRedirect as _sendRedirect, - sendStream as _sendStream, - sendWebResponse as _sendWebResponse, - setCookie as _setCookie, - setHeader as _setHeader, - setHeaders as _setHeaders, - setResponseHeader as _setResponseHeader, - setResponseHeaders as _setResponseHeaders, - setResponseStatus as _setResponseStatus, - unsealSession as _unsealSession, - updateSession as _updateSession, - useSession as _useSession, - writeEarlyHints as _writeEarlyHints, -} from 'h3' - -import type { - Encoding, - EventHandler, - HTTPHeaderName, - InferEventInput, - _RequestMiddleware, - _ResponseMiddleware, -} from 'h3' - -const eventStorage = new AsyncLocalStorage() - -function _setContext(event: H3Event, key: string, value: any) { - event.context[key] = value -} - -function _getContext(event: H3Event, key: string) { - return event.context[key] -} - -export function defineMiddleware(options: { - onRequest?: _RequestMiddleware | Array<_RequestMiddleware> - onBeforeResponse?: _ResponseMiddleware | Array<_ResponseMiddleware> -}) { - return options -} - -function toWebRequestH3(event: H3Event) { - /** - * @type {ReadableStream | undefined} - */ - let readableStream: ReadableStream | undefined - - const url = getRequestURL(event) - const base = { - // @ts-ignore Undici option - duplex: 'half', - method: event.method, - headers: event.headers, - } - - if ((event.node.req as any).body instanceof ArrayBuffer) { - return new Request(url, { - ...base, - body: (event.node.req as any).body, - }) - } - - return new Request(url, { - ...base, - get body() { - if (readableStream) { - return readableStream - } - readableStream = getRequestWebStream(event) - return readableStream - }, - }) -} - -export function toWebRequest(event: H3Event) { - event.web ??= { - request: toWebRequestH3(event), - url: getRequestURL(event), - } - return event.web.request -} - -export { - H3Error, - H3Event, - MIMES, - callNodeListener, - createApp, - createAppEventHandler, - createEvent, - createRouter, - defineLazyEventHandler, - defineNodeListener, - defineNodeMiddleware, - defineRequestMiddleware, - defineResponseMiddleware, - dynamicEventHandler, - defineWebSocket, - splitCookiesString, - fromNodeMiddleware, - fromPlainHandler, - fromWebHandler, - isError, - isEventHandler, - isWebResponse, - lazyEventHandler, - promisifyNodeListener, - serveStatic, - toEventHandler, - toNodeListener, - toPlainHandler, - toWebHandler, - isCorsOriginAllowed, - isStream, - createError, - sanitizeStatusCode, - sanitizeStatusMessage, - useBase, - type AddRouteShortcuts, - type App, - type AppOptions, - type AppUse, - type CacheConditions, - type CreateRouterOptions, - type Duplex, - type DynamicEventHandler, - type Encoding, - type EventHandler, - type EventHandlerObject, - type EventHandlerRequest, - type EventHandlerResponse, - type H3CorsOptions, - type H3EventContext, - type HTTPHeaderName, - type HTTPMethod, - type InferEventInput, - type InputLayer, - type InputStack, - type Layer, - type LazyEventHandler, - type Matcher, - type MultiPartData, - type NodeEventContext, - type NodeListener, - type NodeMiddleware, - type NodePromisifiedHandler, - type PlainHandler, - type PlainRequest, - type PlainResponse, - type ProxyOptions, - type RequestFingerprintOptions, - type RequestHeaders, - type RouteNode, - type Router, - type RouterMethod, - type RouterUse, - type ServeStaticOptions, - type Session, - type SessionConfig, - type SessionData, - type Stack, - type StaticAssetMeta, - type ValidateFunction, - type ValidateResult, - type WebEventContext, - type WebHandler, - type _RequestMiddleware, - type _ResponseMiddleware, -} from 'h3' - -export function defineEventHandler(handler: EventHandler) { - return _defineEventHandler((event) => { - return runWithEvent(event, () => handler(event)) - }) -} - -export function eventHandler(handler: EventHandler) { - return _eventHandler((event) => { - return runWithEvent(event, () => handler(event)) - }) -} - -export async function runWithEvent( - event: H3Event, - fn: () => T | Promise, -): Promise { - return eventStorage.run(event, fn) -} - -export function getEvent() { - const event = eventStorage.getStore() as H3Event | undefined - if (!event) { - throw new Error( - `No HTTPEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`, - ) - } - return event -} - -export const HTTPEventSymbol = Symbol('$HTTPEvent') - -export function isEvent( - obj: any, -): obj is H3Event | { [HTTPEventSymbol]: H3Event } { - return ( - typeof obj === 'object' && - (obj instanceof H3Event || - obj?.[HTTPEventSymbol] instanceof H3Event || - obj?.__is_event__ === true) - ) - // Implement logic to check if obj is an H3Event -} - -type Tail = T extends [any, ...infer U] ? U : never - -type PrependOverload< - TOriginal extends (...args: Array) => any, - TOverload extends (...args: Array) => any, -> = TOverload & TOriginal - -// add an overload to the function without the event argument -type WrapFunction) => any> = PrependOverload< - TFn, - ( - ...args: Parameters extends [H3Event, ...infer TArgs] - ? TArgs - : Parameters - ) => ReturnType -> - -function createWrapperFunction) => any>( - h3Function: TFn, -): WrapFunction { - return function (...args: Array) { - const event = args[0] - if (!isEvent(event)) { - args.unshift(getEvent()) - } else { - args[0] = - event instanceof H3Event || (event as any).__is_event__ - ? event - : event[HTTPEventSymbol] - } - - return (h3Function as any)(...args) - } as any -} - -// Creating wrappers for each utility and exporting them with their original names -type WrappedReadRawBody = ( - ...args: Tail>> -) => ReturnType> -export const readRawBody: PrependOverload< - typeof _readRawBody, - WrappedReadRawBody -> = createWrapperFunction(_readRawBody) -type WrappedReadBody = >( - ...args: Tail>> -) => ReturnType> -export const readBody: PrependOverload = - createWrapperFunction(_readBody) -type WrappedGetQuery = < - T, - TEventInput = Exclude, undefined>, ->( - ...args: Tail>> -) => ReturnType> -export const getQuery: PrependOverload = - createWrapperFunction(_getQuery) -export const isMethod = createWrapperFunction(_isMethod) -export const isPreflightRequest = createWrapperFunction(_isPreflightRequest) -type WrappedGetValidatedQuery = < - T, - TEventInput = InferEventInput<'query', H3Event, T>, ->( - ...args: Tail>> -) => ReturnType> -export const getValidatedQuery: PrependOverload< - typeof _getValidatedQuery, - WrappedGetValidatedQuery -> = createWrapperFunction(_getValidatedQuery) -export const getRouterParams = createWrapperFunction(_getRouterParams) -export const getRouterParam = createWrapperFunction(_getRouterParam) -type WrappedGetValidatedRouterParams = < - T, - TEventInput = InferEventInput<'routerParams', H3Event, T>, ->( - ...args: Tail< - Parameters> - > -) => ReturnType> -export const getValidatedRouterParams: PrependOverload< - typeof _getValidatedRouterParams, - WrappedGetValidatedRouterParams -> = createWrapperFunction(_getValidatedRouterParams) -export const assertMethod = createWrapperFunction(_assertMethod) -export const getRequestHeaders = createWrapperFunction(_getRequestHeaders) -export const getRequestHeader = createWrapperFunction(_getRequestHeader) -export const getRequestURL = createWrapperFunction(_getRequestURL) -export const getRequestHost = createWrapperFunction(_getRequestHost) -export const getRequestProtocol = createWrapperFunction(_getRequestProtocol) -export const getRequestIP = createWrapperFunction(_getRequestIP) -export const send = createWrapperFunction(_send) -export const sendNoContent = createWrapperFunction(_sendNoContent) -export const setResponseStatus = createWrapperFunction(_setResponseStatus) -export const getResponseStatus = createWrapperFunction(_getResponseStatus) -export const getResponseStatusText = createWrapperFunction( - _getResponseStatusText, -) -export const getResponseHeaders = createWrapperFunction(_getResponseHeaders) -export const getResponseHeader = createWrapperFunction(_getResponseHeader) -export const setResponseHeaders = createWrapperFunction(_setResponseHeaders) -type WrappedSetResponseHeader = ( - ...args: Tail>> -) => ReturnType> -export const setResponseHeader: PrependOverload< - typeof _setResponseHeader, - WrappedSetResponseHeader -> = createWrapperFunction(_setResponseHeader) -export const appendResponseHeaders = createWrapperFunction( - _appendResponseHeaders, -) -type WrappedAppendResponseHeader = ( - ...args: Tail>> -) => ReturnType> -export const appendResponseHeader: PrependOverload< - typeof _appendResponseHeader, - WrappedAppendResponseHeader -> = createWrapperFunction(_appendResponseHeader) -export const defaultContentType = createWrapperFunction(_defaultContentType) -export const sendRedirect = createWrapperFunction(_sendRedirect) -export const sendStream = createWrapperFunction(_sendStream) -export const writeEarlyHints = createWrapperFunction(_writeEarlyHints) -export const sendError = createWrapperFunction(_sendError) -export const sendProxy = createWrapperFunction(_sendProxy) -export const proxyRequest = createWrapperFunction(_proxyRequest) -type WrappedFetchWithEvent = < - T = unknown, - TResponse = any, - TFetch extends (req: RequestInfo | URL, opts?: any) => any = typeof fetch, ->( - ...args: Tail>> -) => ReturnType> -export const fetchWithEvent: PrependOverload< - typeof _fetchWithEvent, - WrappedFetchWithEvent -> = createWrapperFunction(_fetchWithEvent) -export const getProxyRequestHeaders = createWrapperFunction( - _getProxyRequestHeaders, -) - -export const parseCookies = createWrapperFunction(_parseCookies) -export const getCookie = createWrapperFunction(_getCookie) -export const setCookie = createWrapperFunction(_setCookie) -export const deleteCookie = createWrapperFunction(_deleteCookie) -// not exported :( -type SessionDataT = Record -type WrappedUseSession = ( - ...args: Tail>> -) => ReturnType> -// we need to `as` these because the WrapFunction doesn't work for them -// because they also accept CompatEvent instead of H3Event -export const useSession = createWrapperFunction(_useSession) as PrependOverload< - typeof _useSession, - WrappedUseSession -> -type WrappedGetSession = ( - ...args: Tail>> -) => ReturnType> -export const getSession = createWrapperFunction(_getSession) as PrependOverload< - typeof _getSession, - WrappedGetSession -> -type WrappedUpdateSession = ( - ...args: Tail>> -) => ReturnType> -export const updateSession: PrependOverload< - typeof _updateSession, - WrappedUpdateSession -> = createWrapperFunction(_updateSession) -type WrappedSealSession = ( - ...args: Tail>> -) => ReturnType> -export const sealSession = createWrapperFunction( - _sealSession, -) as PrependOverload -export const unsealSession = createWrapperFunction(_unsealSession) -export const clearSession = createWrapperFunction(_clearSession) -export const handleCacheHeaders = createWrapperFunction(_handleCacheHeaders) -export const handleCors = createWrapperFunction(_handleCors) -export const appendCorsHeaders = createWrapperFunction(_appendCorsHeaders) -export const appendCorsPreflightHeaders = createWrapperFunction( - _appendCorsPreflightHeaders, -) -export const sendWebResponse = createWrapperFunction(_sendWebResponse) -type WrappedAppendHeader = ( - ...args: Tail>> -) => ReturnType> -export const appendHeader: PrependOverload< - typeof _appendHeader, - WrappedAppendHeader -> = createWrapperFunction(_appendHeader) -export const appendHeaders = createWrapperFunction(_appendHeaders) -type WrappedSetHeader = ( - ...args: Tail>> -) => ReturnType> -export const setHeader: PrependOverload = - createWrapperFunction(_setHeader) -export const setHeaders = createWrapperFunction(_setHeaders) -export const getHeader = createWrapperFunction(_getHeader) -export const getHeaders = createWrapperFunction(_getHeaders) -export const getRequestFingerprint = createWrapperFunction( - _getRequestFingerprint, -) -export const getRequestWebStream = createWrapperFunction(_getRequestWebStream) -export const readFormData = createWrapperFunction(_readFormData) -export const readMultipartFormData = createWrapperFunction( - _readMultipartFormData, -) -type WrappedReadValidatedBody = < - T, - TEventInput = InferEventInput<'body', H3Event, T>, ->( - ...args: Tail>> -) => ReturnType> -export const readValidatedBody: PrependOverload< - typeof _readValidatedBody, - WrappedReadValidatedBody -> = createWrapperFunction(_readValidatedBody) -export const removeResponseHeader = createWrapperFunction(_removeResponseHeader) -export const getContext = createWrapperFunction(_getContext) -export const setContext = createWrapperFunction(_setContext) -export const clearResponseHeaders = createWrapperFunction(_clearResponseHeaders) -export const getWebRequest = createWrapperFunction(toWebRequest) diff --git a/packages/react-start-server/src/server-functions-handler.ts b/packages/react-start-server/src/server-functions-handler.ts index 72e083c124..6129c1bc52 100644 --- a/packages/react-start-server/src/server-functions-handler.ts +++ b/packages/react-start-server/src/server-functions-handler.ts @@ -2,8 +2,8 @@ import { invariant, isNotFound, isRedirect } from '@tanstack/react-router' import { startSerializer } from '@tanstack/start-client-core' // @ts-expect-error import _serverFnManifest from 'tsr:server-fn-manifest' -import { eventHandler, getEvent, getResponseStatus, toWebRequest } from './h3' -import type { H3Event } from './h3' +import { eventHandler, getEvent, getResponseStatus, toWebRequest } from '../../start-server-core/src/h3' +import type { H3Event } from '../../start-server-core/src/h3' // NOTE: This is a dummy export to silence warnings about // only having a default export. diff --git a/packages/react-start-server/tsconfig.json b/packages/react-start-server/tsconfig.json index 108c78712f..e4271c4d64 100644 --- a/packages/react-start-server/tsconfig.json +++ b/packages/react-start-server/tsconfig.json @@ -4,5 +4,5 @@ "jsx": "react-jsx", "module": "esnext" }, - "include": ["src", "tests", "vite.config.ts"] + "include": ["src", "tests", "vite.config.ts", "../start-server-core/src/router-manifest.ts", "../start-server-core/src/h3.ts"] } diff --git a/packages/start-server-core/src/h3.ts b/packages/start-server-core/src/h3.ts index d5a2c94844..8e7dbc049c 100644 --- a/packages/start-server-core/src/h3.ts +++ b/packages/start-server-core/src/h3.ts @@ -11,7 +11,9 @@ import { clearResponseHeaders as _clearResponseHeaders, clearSession as _clearSession, defaultContentType as _defaultContentType, + defineEventHandler as _defineEventHandler, deleteCookie as _deleteCookie, + eventHandler as _eventHandler, fetchWithEvent as _fetchWithEvent, getCookie as _getCookie, getHeader as _getHeader, @@ -66,15 +68,18 @@ import { useSession as _useSession, writeEarlyHints as _writeEarlyHints, } from 'h3' -import { getContext as getUnctxContext } from 'unctx' + import type { Encoding, + EventHandler, HTTPHeaderName, InferEventInput, _RequestMiddleware, _ResponseMiddleware, } from 'h3' +const eventStorage = new AsyncLocalStorage() + function _setContext(event: H3Event, key: string, value: any) { event.context[key] = value } @@ -140,7 +145,6 @@ export { createAppEventHandler, createEvent, createRouter, - defineEventHandler, defineLazyEventHandler, defineNodeListener, defineNodeMiddleware, @@ -148,7 +152,6 @@ export { defineResponseMiddleware, dynamicEventHandler, defineWebSocket, - eventHandler, splitCookiesString, fromNodeMiddleware, fromPlainHandler, @@ -221,8 +224,33 @@ export { type _ResponseMiddleware, } from 'h3' -function getHTTPEvent() { - return getEvent() +export function defineEventHandler(handler: EventHandler) { + return _defineEventHandler((event) => { + return runWithEvent(event, () => handler(event)) + }) +} + +export function eventHandler(handler: EventHandler) { + return _eventHandler((event) => { + return runWithEvent(event, () => handler(event)) + }) +} + +export async function runWithEvent( + event: H3Event, + fn: () => T | Promise, +): Promise { + return eventStorage.run(event, fn) +} + +export function getEvent() { + const event = eventStorage.getStore() as H3Event | undefined + if (!event) { + throw new Error( + `No HTTPEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`, + ) + } + return event } export const HTTPEventSymbol = Symbol('$HTTPEvent') @@ -262,12 +290,7 @@ function createWrapperFunction) => any>( return function (...args: Array) { const event = args[0] if (!isEvent(event)) { - if (!(globalThis as any).app.config.server.experimental?.asyncContext) { - throw new Error( - 'AsyncLocalStorage was not enabled. Use the `server.experimental.asyncContext: true` option in your app configuration to enable it. Or, pass the instance of HTTPEvent that you have as the first argument to the function.', - ) - } - args.unshift(getHTTPEvent()) + args.unshift(getEvent()) } else { args[0] = event instanceof H3Event || (event as any).__is_event__ @@ -463,37 +486,5 @@ export const readValidatedBody: PrependOverload< export const removeResponseHeader = createWrapperFunction(_removeResponseHeader) export const getContext = createWrapperFunction(_getContext) export const setContext = createWrapperFunction(_setContext) - export const clearResponseHeaders = createWrapperFunction(_clearResponseHeaders) - export const getWebRequest = createWrapperFunction(toWebRequest) - -export { createApp as createServer } from 'h3' - -function getNitroAsyncContext() { - const nitroAsyncContext = getUnctxContext('nitro-app', { - asyncContext: (globalThis as any).app.config.server.experimental - ?.asyncContext - ? true - : false, - AsyncLocalStorage, - }) - - return nitroAsyncContext -} - -export function getEvent() { - const event = (getNitroAsyncContext().use() as any).event as - | H3Event - | undefined - if (!event) { - throw new Error( - `No HTTPEvent found in AsyncLocalStorage. Make sure you are using the function within the server runtime.`, - ) - } - return event -} - -export async function handleHTTPEvent(event: H3Event) { - return await (globalThis as any).$handle(event) -} diff --git a/packages/start-server-core/src/index.tsx b/packages/start-server-core/src/index.tsx index d24477934d..072fbeb051 100644 --- a/packages/start-server-core/src/index.tsx +++ b/packages/start-server-core/src/index.tsx @@ -3,9 +3,11 @@ export { transformPipeableStreamWithRouter, } from './transformStreamWithRouter' -export { createStartHandler } from './createStartHandler' +// export { createStartHandler } from './createStartHandler' export { createRequestHandler } from './createRequestHandler' +export { getStartManifest } from './router-manifest' + export { defineHandlerCallback } from './handlerCallback' export type { HandlerCallback } from './handlerCallback' diff --git a/packages/react-start-server/src/router-manifest.ts b/packages/start-server-core/src/router-manifest.ts similarity index 100% rename from packages/react-start-server/src/router-manifest.ts rename to packages/start-server-core/src/router-manifest.ts diff --git a/packages/start-server-core/vite.config.ts b/packages/start-server-core/vite.config.ts index 71f9948e0a..99f7062bb5 100644 --- a/packages/start-server-core/vite.config.ts +++ b/packages/start-server-core/vite.config.ts @@ -18,5 +18,6 @@ export default mergeConfig( tanstackViteConfig({ srcDir: './src', entry: './src/index.tsx', + externalDeps: ['tsr:server-fn-manifest', 'tsr:start-manifest'], }), ) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 32c7ee5a54..0dea5fe477 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6669,6 +6669,43 @@ importers: specifier: ^1.0.3 version: 1.0.3 + packages/start-server-core: + dependencies: + '@tanstack/history': + specifier: workspace:* + version: link:../history + '@tanstack/router-core': + specifier: workspace:* + version: link:../router-core + '@tanstack/start-client-core': + specifier: workspace:* + version: link:../start-client-core + h3: + specifier: 1.13.0 + version: 1.13.0 + isbot: + specifier: ^5.1.22 + version: 5.1.22 + jsesc: + specifier: ^3.1.0 + version: 3.1.0 + tiny-warning: + specifier: ^1.0.3 + version: 1.0.3 + unctx: + specifier: ^2.4.1 + version: 2.4.1 + devDependencies: + '@types/jsesc': + specifier: ^3.0.3 + version: 3.0.3 + esbuild: + specifier: ^0.25.0 + version: 0.25.0 + typescript: + specifier: ^5.7.2 + version: 5.8.2 + packages/start-server-functions-server: dependencies: '@tanstack/server-functions-plugin': From 59b92ec4f2ba5e27e1e47c8dc325cd8b77540816 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Mon, 10 Mar 2025 06:03:49 +0100 Subject: [PATCH 031/155] fix imports from ssr-server --- packages/react-start-server/src/createStartHandler.ts | 9 ++++++--- .../react-start-server/src/server-functions-handler.ts | 4 ++-- packages/start-server-core/src/index.tsx | 2 ++ 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/react-start-server/src/createStartHandler.ts b/packages/react-start-server/src/createStartHandler.ts index 2236cb4c46..789c068ab0 100644 --- a/packages/react-start-server/src/createStartHandler.ts +++ b/packages/react-start-server/src/createStartHandler.ts @@ -2,10 +2,13 @@ import path from 'node:path' import { createMemoryHistory } from '@tanstack/history' import { mergeHeaders } from '@tanstack/start-client-core' import { eventHandler, getResponseHeaders, toWebRequest } from 'h3' -import { getStartManifest } from '@tanstack/start-server-core' -import { attachRouterServerSsrUtils, dehydrateRouter } from '../../start-server-core/src/ssr-server' +import { + attachRouterServerSsrUtils, + dehydrateRouter, + getStartManifest, +} from '@tanstack/start-server-core' import serverFunctionsHandler from './server-functions-handler' -import type { HandlerCallback } from '../../start-server-core/src/handlerCallback' +import type { HandlerCallback } from '@tanstack/start-server-core' import type { EventHandlerResponse, H3Event } from 'h3' import type { AnyRouter } from '@tanstack/router-core' diff --git a/packages/react-start-server/src/server-functions-handler.ts b/packages/react-start-server/src/server-functions-handler.ts index 6129c1bc52..2fada415d8 100644 --- a/packages/react-start-server/src/server-functions-handler.ts +++ b/packages/react-start-server/src/server-functions-handler.ts @@ -2,8 +2,8 @@ import { invariant, isNotFound, isRedirect } from '@tanstack/react-router' import { startSerializer } from '@tanstack/start-client-core' // @ts-expect-error import _serverFnManifest from 'tsr:server-fn-manifest' -import { eventHandler, getEvent, getResponseStatus, toWebRequest } from '../../start-server-core/src/h3' -import type { H3Event } from '../../start-server-core/src/h3' +import { eventHandler, getEvent, getResponseStatus, toWebRequest } from '@tanstack/start-server-core' +import type { H3Event } from '@tanstack/start-server-core' // NOTE: This is a dummy export to silence warnings about // only having a default export. diff --git a/packages/start-server-core/src/index.tsx b/packages/start-server-core/src/index.tsx index 072fbeb051..a2a239bee4 100644 --- a/packages/start-server-core/src/index.tsx +++ b/packages/start-server-core/src/index.tsx @@ -11,4 +11,6 @@ export { getStartManifest } from './router-manifest' export { defineHandlerCallback } from './handlerCallback' export type { HandlerCallback } from './handlerCallback' +export { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server' + export * from './h3' From 3e57adedec1c0b6952a7ac0f084bd4b7c2ea5777 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Mon, 10 Mar 2025 06:04:51 +0100 Subject: [PATCH 032/155] format --- .../react-start-server/src/server-functions-handler.ts | 7 ++++++- packages/react-start-server/tsconfig.json | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/packages/react-start-server/src/server-functions-handler.ts b/packages/react-start-server/src/server-functions-handler.ts index 2fada415d8..b744f19754 100644 --- a/packages/react-start-server/src/server-functions-handler.ts +++ b/packages/react-start-server/src/server-functions-handler.ts @@ -2,7 +2,12 @@ import { invariant, isNotFound, isRedirect } from '@tanstack/react-router' import { startSerializer } from '@tanstack/start-client-core' // @ts-expect-error import _serverFnManifest from 'tsr:server-fn-manifest' -import { eventHandler, getEvent, getResponseStatus, toWebRequest } from '@tanstack/start-server-core' +import { + eventHandler, + getEvent, + getResponseStatus, + toWebRequest, +} from '@tanstack/start-server-core' import type { H3Event } from '@tanstack/start-server-core' // NOTE: This is a dummy export to silence warnings about diff --git a/packages/react-start-server/tsconfig.json b/packages/react-start-server/tsconfig.json index e4271c4d64..108c78712f 100644 --- a/packages/react-start-server/tsconfig.json +++ b/packages/react-start-server/tsconfig.json @@ -4,5 +4,5 @@ "jsx": "react-jsx", "module": "esnext" }, - "include": ["src", "tests", "vite.config.ts", "../start-server-core/src/router-manifest.ts", "../start-server-core/src/h3.ts"] + "include": ["src", "tests", "vite.config.ts"] } From 325ec8c3ef1fc1427e3d104cae3550b5810be893 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Mon, 10 Mar 2025 06:24:30 +0100 Subject: [PATCH 033/155] fix lockfile --- pnpm-lock.yaml | 19 +++---------------- 1 file changed, 3 insertions(+), 16 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 57e3a77489..95ec8ad9e6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5725,19 +5725,6 @@ importers: specifier: ^0.25.0 version: 0.25.0 - packages/react-start-api-routes: - dependencies: - '@tanstack/react-start-server': - specifier: workspace:* - version: link:../react-start-server - '@tanstack/router-core': - specifier: workspace:* - version: link:../router-core - devDependencies: - typescript: - specifier: ^5.7.2 - version: 5.8.2 - packages/react-start-client: dependencies: '@tanstack/react-router': @@ -6631,6 +6618,9 @@ importers: '@tanstack/react-start-server-functions-ssr': specifier: workspace:* version: link:../react-start-server-functions-ssr + '@tanstack/start-api-routes': + specifier: workspace:* + version: link:../start-api-routes '@tanstack/start-server-functions-server': specifier: workspace:* version: link:../start-server-functions-server @@ -6643,9 +6633,6 @@ importers: '@tanstack/start-server-core': specifier: workspace:* version: link:../start-server-core - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) devDependencies: typescript: specifier: ^5.7.2 From caad30ce318f4979982a63a8bc807eebecd69bdf Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Mon, 10 Mar 2025 12:03:29 +0100 Subject: [PATCH 034/155] delete handler --- packages/react-start-server/package.json | 1 + .../start-server-functions-handler/README.md | 33 -- .../eslint.config.js | 20 -- .../package.json | 73 ---- .../src/index.ts | 323 ------------------ 5 files changed, 1 insertion(+), 449 deletions(-) delete mode 100644 packages/start-server-functions-handler/README.md delete mode 100644 packages/start-server-functions-handler/eslint.config.js delete mode 100644 packages/start-server-functions-handler/package.json delete mode 100644 packages/start-server-functions-handler/src/index.ts diff --git a/packages/react-start-server/package.json b/packages/react-start-server/package.json index 8db5e6fea0..d06ea43dc0 100644 --- a/packages/react-start-server/package.json +++ b/packages/react-start-server/package.json @@ -68,6 +68,7 @@ "@tanstack/start-client-core": "workspace:^", "@tanstack/start-server-core": "workspace:^", "tiny-warning": "^1.0.3", + "tiny-invariant": "^1.3.3", "h3": "1.13.0", "isbot": "^5.1.22", "jsesc": "^3.1.0", diff --git a/packages/start-server-functions-handler/README.md b/packages/start-server-functions-handler/README.md deleted file mode 100644 index bb009b0c87..0000000000 --- a/packages/start-server-functions-handler/README.md +++ /dev/null @@ -1,33 +0,0 @@ -> 🤫 we're cooking up something special! - - - -# TanStack Start - -![TanStack Router Header](https://github.com/tanstack/router/raw/main/media/header.png) - -🤖 Type-safe router w/ built-in caching & URL state management for React! - - - #TanStack - - - - - - - - semantic-release - - Join the discussion on Github -Best of JS - - - - - - - -Enjoy this library? Try the entire [TanStack](https://tanstack.com)! [React Query](https://github.com/tannerlinsley/react-query), [React Table](https://github.com/tanstack/react-table), [React Charts](https://github.com/tannerlinsley/react-charts), [React Virtual](https://github.com/tannerlinsley/react-virtual) - -## Visit [tanstack.com/router](https://tanstack.com/router) for docs, guides, API and more! diff --git a/packages/start-server-functions-handler/eslint.config.js b/packages/start-server-functions-handler/eslint.config.js deleted file mode 100644 index bd7118fa1a..0000000000 --- a/packages/start-server-functions-handler/eslint.config.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check - -import rootConfig from '../../eslint.config.js' - -export default [ - ...rootConfig, - { - files: ['**/*.{ts,tsx}'], - }, - { - plugins: {}, - rules: {}, - }, - { - files: ['**/__tests__/**'], - rules: { - '@typescript-eslint/no-unnecessary-condition': 'off', - }, - }, -] diff --git a/packages/start-server-functions-handler/package.json b/packages/start-server-functions-handler/package.json deleted file mode 100644 index bd424aaea9..0000000000 --- a/packages/start-server-functions-handler/package.json +++ /dev/null @@ -1,73 +0,0 @@ -{ - "name": "@tanstack/start-server-functions-handler", - "version": "1.114.10", - "description": "Modern and scalable routing for applications", - "author": "Tanner Linsley", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/TanStack/router.git", - "directory": "packages/start-server-functions-handler" - }, - "homepage": "https://tanstack.com/start", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "keywords": [ - "react", - "location", - "router", - "routing", - "async", - "async router", - "typescript" - ], - "scripts": { - "clean": "rimraf ./dist && rimraf ./coverage", - "test": "pnpm test:eslint && pnpm test:types && pnpm test:build && pnpm test:unit", - "test:unit": "exit 0; vitest", - "test:eslint": "eslint ./src", - "test:types": "pnpm run \"/^test:types:ts[0-9]{2}$/\"", - "test:types:ts53": "node ../../node_modules/typescript53/lib/tsc.js", - "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": "tsc", - "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .", - "build": "vite build" - }, - "type": "module", - "types": "dist/esm/index.d.ts", - "exports": { - ".": { - "import": { - "types": "./dist/esm/index.d.ts", - "default": "./dist/esm/index.js" - }, - "require": { - "types": "./dist/cjs/index.d.cts", - "default": "./dist/cjs/index.cjs" - } - }, - "./package.json": "./package.json" - }, - "sideEffects": false, - "files": [ - "dist", - "src" - ], - "engines": { - "node": ">=12" - }, - "dependencies": { - "@tanstack/router-core": "workspace:^", - "@tanstack/start-client-core": "workspace:^", - "@tanstack/start-server-core": "workspace:^", - "tiny-invariant": "^1.3.3" - }, - "devDependencies": { - "typescript": "^5.7.2" - } -} diff --git a/packages/start-server-functions-handler/src/index.ts b/packages/start-server-functions-handler/src/index.ts deleted file mode 100644 index be2f992bf3..0000000000 --- a/packages/start-server-functions-handler/src/index.ts +++ /dev/null @@ -1,323 +0,0 @@ -<<<<<<<< HEAD:packages/react-start-server/src/server-functions-handler.ts -import { invariant, isNotFound, isRedirect } from '@tanstack/react-router' -import { startSerializer } from '@tanstack/start-client-core' -// @ts-expect-error -import _serverFnManifest from 'tsr:server-fn-manifest' -======== -import { isNotFound, isRedirect } from '@tanstack/router-core' -import invariant from 'tiny-invariant' ->>>>>>>> main:packages/start-server-functions-handler/src/index.ts -import { - eventHandler, - getEvent, - getResponseStatus, - toWebRequest, -} from '@tanstack/start-server-core' -<<<<<<<< HEAD:packages/react-start-server/src/server-functions-handler.ts -======== -import { startSerializer } from '@tanstack/start-client-core' -// @ts-expect-error -import _serverFnManifest from 'tsr:server-fn-manifest' ->>>>>>>> main:packages/start-server-functions-handler/src/index.ts -import type { H3Event } from '@tanstack/start-server-core' - -// NOTE: This is a dummy export to silence warnings about -// only having a default export. -export const dummy = 2 - -export default eventHandler(handleServerAction) - -const serverFnManifest = _serverFnManifest as Record< - string, - { - functionName: string - extractedFilename: string - importer: () => Promise - } -> - -async function handleServerAction(event: H3Event) { - const request = toWebRequest(event)! - - const response = await handleServerRequest({ - request, - event, - }) - return response -} - -function sanitizeBase(base: string | undefined) { - if (!base) { - throw new Error( - '🚨 process.env.TSS_SERVER_FN_BASE is required in start/server-handler/index', - ) - } - - return base.replace(/^\/|\/$/g, '') -} - -async function handleServerRequest({ - request, - event, -}: { - request: Request - event: H3Event -}) { - const controller = new AbortController() - const signal = controller.signal - const abort = () => controller.abort() - event.node.req.on('close', abort) - - const method = request.method - const url = new URL(request.url, 'http://localhost:3000') - // extract the serverFnId from the url as host/_server/:serverFnId - // Define a regex to match the path and extract the :thing part - const regex = new RegExp( - `${sanitizeBase(process.env.TSS_SERVER_FN_BASE)}/([^/?#]+)`, - ) - - // Execute the regex - const match = url.pathname.match(regex) - const serverFnId = match ? match[1] : null - const search = Object.fromEntries(url.searchParams.entries()) as { - payload?: any - createServerFn?: boolean - } - - const isCreateServerFn = 'createServerFn' in search - const isRaw = 'raw' in search - - if (typeof serverFnId !== 'string') { - throw new Error('Invalid server action param for serverFnId: ' + serverFnId) - } - - const serverFnInfo = serverFnManifest[serverFnId] - - if (!serverFnInfo) { - console.log('serverFnManifest', serverFnManifest) - throw new Error('Server function info not found for ' + serverFnId) - } - - if (process.env.NODE_ENV === 'development') - console.info(`\nServerFn Request: ${serverFnId}`) - - let fnModule: undefined | { [key: string]: any } - - if (process.env.NODE_ENV === 'development') { - const serverEnv = (globalThis as any).viteDevServer.environments['server'] - if (!serverEnv) { - throw new Error(`'server' vite dev environment not found`) - } - fnModule = await serverEnv.runner.import(serverFnInfo.extractedFilename) - } else { - fnModule = await serverFnInfo.importer() - } - - if (!fnModule) { - console.log('serverFnInfo', serverFnInfo) - throw new Error('Server function module not resolved for ' + serverFnId) - } - - const action = fnModule[serverFnInfo.functionName] - - if (!action) { - console.log('serverFnInfo', serverFnInfo) - console.log('fnModule', fnModule) - throw new Error( - `Server function module export not resolved for serverFn ID: ${serverFnId}`, - ) - } - - // Known FormData 'Content-Type' header values - const formDataContentTypes = [ - 'multipart/form-data', - 'application/x-www-form-urlencoded', - ] - - const response = await (async () => { - try { - let result = await (async () => { - // FormData - if ( - request.headers.get('Content-Type') && - formDataContentTypes.some((type) => - request.headers.get('Content-Type')?.includes(type), - ) - ) { - // We don't support GET requests with FormData payloads... that seems impossible - invariant( - method.toLowerCase() !== 'get', - 'GET requests with FormData payloads are not supported', - ) - - return await action(await request.formData(), signal) - } - - // Get requests use the query string - if (method.toLowerCase() === 'get') { - // By default the payload is the search params - let payload: any = search - - // If this GET request was created by createServerFn, - // then the payload will be on the payload param - if (isCreateServerFn) { - payload = search.payload - } - - // If there's a payload, we should try to parse it - payload = payload ? startSerializer.parse(payload) : payload - - // Send it through! - return await action(payload, signal) - } - - // This must be a POST request, likely JSON??? - const jsonPayloadAsString = await request.text() - - // We should probably try to deserialize the payload - // as JSON, but we'll just pass it through for now. - const payload = startSerializer.parse(jsonPayloadAsString) - - // If this POST request was created by createServerFn, - // it's payload will be the only argument - if (isCreateServerFn) { - return await action(payload, signal) - } - - // Otherwise, we'll spread the payload. Need to - // support `use server` functions that take multiple - // arguments. - return await action(...(payload as any), signal) - })() - - // Any time we get a Response back, we should just - // return it immediately. - if (result.result instanceof Response) { - return result.result - } - - // If this is a non createServerFn request, we need to - // pull out the result from the result object - if (!isCreateServerFn) { - result = result.result - - // The result might again be a response, - // and if it is, return it. - if (result instanceof Response) { - return result - } - } - - // if (!search.createServerFn) { - // result = result.result - // } - - // else if ( - // isPlainObject(result) && - // 'result' in result && - // result.result instanceof Response - // ) { - // return result.result - // } - - // TODO: RSCs Where are we getting this package? - // if (isValidElement(result)) { - // const { renderToPipeableStream } = await import( - // // @ts-expect-error - // 'react-server-dom/server' - // ) - - // const pipeableStream = renderToPipeableStream(result) - - // setHeaders(event, { - // 'Content-Type': 'text/x-component', - // } as any) - - // sendStream(event, response) - // event._handled = true - - // return new Response(null, { status: 200 }) - // } - - if (isRedirect(result) || isNotFound(result)) { - return redirectOrNotFoundResponse(result) - } - - return new Response( - result !== undefined ? startSerializer.stringify(result) : undefined, - { - status: getResponseStatus(getEvent()), - headers: { - 'Content-Type': 'application/json', - }, - }, - ) - } catch (error: any) { - if (error instanceof Response) { - return error - } - // else if ( - // isPlainObject(error) && - // 'result' in error && - // error.result instanceof Response - // ) { - // return error.result - // } - - // Currently this server-side context has no idea how to - // build final URLs, so we need to defer that to the client. - // The client will check for __redirect and __notFound keys, - // and if they exist, it will handle them appropriately. - - if (isRedirect(error) || isNotFound(error)) { - return redirectOrNotFoundResponse(error) - } - - console.info() - console.info('Server Fn Error!') - console.info() - console.error(error) - console.info() - - return new Response(startSerializer.stringify(error), { - status: 500, - headers: { - 'Content-Type': 'application/json', - }, - }) - } - })() - event.node.req.removeListener('close', abort) - - if (isRaw) { - return response - } - if (process.env.NODE_ENV === 'development') - console.info(`ServerFn Response: ${response.status}`) - - if (response.headers.get('Content-Type') === 'application/json') { - const cloned = response.clone() - const text = await cloned.text() - const payload = text ? JSON.stringify(JSON.parse(text)) : 'undefined' - - if (process.env.NODE_ENV === 'development') - console.info( - ` - Payload: ${payload.length > 100 ? payload.substring(0, 100) + '...' : payload}`, - ) - } - if (process.env.NODE_ENV === 'development') console.info() - - return response -} - -function redirectOrNotFoundResponse(error: any) { - const { headers, ...rest } = error - - return new Response(JSON.stringify(rest), { - status: 200, - headers: { - 'Content-Type': 'application/json', - ...(headers || {}), - }, - }) -} From 01d22a35468bc43727a2fe87fd0d811af8374181 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Mon, 10 Mar 2025 12:10:34 +0100 Subject: [PATCH 035/155] catch up some for solid-start --- packages/solid-start-config/README.md | 33 - packages/solid-start-config/eslint.config.js | 31 - packages/solid-start-config/package.json | 72 -- packages/solid-start-config/src/index.ts | 672 ------------------ packages/solid-start-config/src/schema.ts | 194 ----- .../src/vinxi-file-router.ts | 87 --- packages/solid-start-config/tsconfig.json | 10 - .../solid-start-router-manifest/README.md | 33 - .../eslint.config.js | 31 - .../solid-start-router-manifest/src/index.ts | 83 --- .../solid-start-router-manifest/tsconfig.json | 10 - .../vite.config.ts | 22 - packages/solid-start/package.json | 24 +- packages/solid-start/src/config.tsx | 1 - packages/solid-start/src/plugin.tsx | 1 + packages/solid-start/src/router-manifest.tsx | 1 - .../src/server-functions-handler.tsx | 1 - packages/solid-start/vite.config.ts | 6 +- .../package.json | 25 +- pnpm-lock.yaml | 177 +---- 20 files changed, 35 insertions(+), 1479 deletions(-) delete mode 100644 packages/solid-start-config/README.md delete mode 100644 packages/solid-start-config/eslint.config.js delete mode 100644 packages/solid-start-config/package.json delete mode 100644 packages/solid-start-config/src/index.ts delete mode 100644 packages/solid-start-config/src/schema.ts delete mode 100644 packages/solid-start-config/src/vinxi-file-router.ts delete mode 100644 packages/solid-start-config/tsconfig.json delete mode 100644 packages/solid-start-router-manifest/README.md delete mode 100644 packages/solid-start-router-manifest/eslint.config.js delete mode 100644 packages/solid-start-router-manifest/src/index.ts delete mode 100644 packages/solid-start-router-manifest/tsconfig.json delete mode 100644 packages/solid-start-router-manifest/vite.config.ts delete mode 100644 packages/solid-start/src/config.tsx create mode 100644 packages/solid-start/src/plugin.tsx delete mode 100644 packages/solid-start/src/router-manifest.tsx delete mode 100644 packages/solid-start/src/server-functions-handler.tsx rename packages/{solid-start-router-manifest => start-server-functions-ssr}/package.json (73%) diff --git a/packages/solid-start-config/README.md b/packages/solid-start-config/README.md deleted file mode 100644 index bb009b0c87..0000000000 --- a/packages/solid-start-config/README.md +++ /dev/null @@ -1,33 +0,0 @@ -> 🤫 we're cooking up something special! - - - -# TanStack Start - -![TanStack Router Header](https://github.com/tanstack/router/raw/main/media/header.png) - -🤖 Type-safe router w/ built-in caching & URL state management for React! - - - #TanStack - - - - - - - - semantic-release - - Join the discussion on Github -Best of JS - - - - - - - -Enjoy this library? Try the entire [TanStack](https://tanstack.com)! [React Query](https://github.com/tannerlinsley/react-query), [React Table](https://github.com/tanstack/react-table), [React Charts](https://github.com/tannerlinsley/react-charts), [React Virtual](https://github.com/tannerlinsley/react-virtual) - -## Visit [tanstack.com/router](https://tanstack.com/router) for docs, guides, API and more! diff --git a/packages/solid-start-config/eslint.config.js b/packages/solid-start-config/eslint.config.js deleted file mode 100644 index 931f0ec774..0000000000 --- a/packages/solid-start-config/eslint.config.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check - -import pluginReact from '@eslint-react/eslint-plugin' -import pluginReactHooks from 'eslint-plugin-react-hooks' -import rootConfig from '../../eslint.config.js' - -export default [ - ...rootConfig, - { - ...pluginReact.configs.recommended, - files: ['**/*.{ts,tsx}'], - }, - { - plugins: { - 'react-hooks': pluginReactHooks, - }, - rules: { - '@eslint-react/no-unstable-context-value': 'off', - '@eslint-react/no-unstable-default-props': 'off', - '@eslint-react/dom/no-missing-button-type': 'off', - 'react-hooks/exhaustive-deps': 'error', - 'react-hooks/rules-of-hooks': 'error', - }, - }, - { - files: ['**/__tests__/**'], - rules: { - '@typescript-eslint/no-unnecessary-condition': 'off', - }, - }, -] diff --git a/packages/solid-start-config/package.json b/packages/solid-start-config/package.json deleted file mode 100644 index cb516ba9d6..0000000000 --- a/packages/solid-start-config/package.json +++ /dev/null @@ -1,72 +0,0 @@ -{ - "name": "@tanstack/solid-start-config", - "version": "1.109.2", - "description": "Modern and scalable routing for React applications", - "author": "Tanner Linsley", - "license": "MIT", - "repository": { - "type": "git", - "url": "https://github.com/TanStack/router.git", - "directory": "packages/start" - }, - "homepage": "https://tanstack.com/start", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "keywords": [ - "react", - "location", - "router", - "routing", - "async", - "async router", - "typescript" - ], - "scripts": { - "clean": "rimraf ./dist && rimraf ./coverage", - "build": "tsc", - "test": "pnpm test:eslint && pnpm test:types && pnpm test:build && pnpm test:unit", - "test:unit": "exit 0;vitest", - "test:eslint": "eslint ./src", - "test:types": "exit 0; vitest" - }, - "type": "module", - "types": "dist/esm/index.d.ts", - "exports": { - ".": { - "import": { - "types": "./dist/esm/index.d.ts", - "default": "./dist/esm/index.js" - } - }, - "./package.json": "./package.json" - }, - "sideEffects": false, - "files": [ - "dist", - "src" - ], - "engines": { - "node": ">=12" - }, - "dependencies": { - "@tanstack/router-core": "workspace:^", - "@tanstack/router-generator": "workspace:^", - "@tanstack/router-plugin": "workspace:^", - "@tanstack/server-functions-plugin": "workspace:^", - "@tanstack/solid-start-plugin": "workspace:^", - "@tanstack/start-server-functions-handler": "workspace:^", - "vite-plugin-solid": "^2.11.2", - "import-meta-resolve": "^4.1.0", - "nitropack": "^2.10.4", - "ofetch": "^1.4.1", - "vite": "^6.1.0", - "vinxi": "0.5.3", - "zod": "^3.24.2" - }, - "peerDependencies": { - "solid-js": ">=1.0.0", - "vite": "^6.0.0" - } -} diff --git a/packages/solid-start-config/src/index.ts b/packages/solid-start-config/src/index.ts deleted file mode 100644 index b148a4470c..0000000000 --- a/packages/solid-start-config/src/index.ts +++ /dev/null @@ -1,672 +0,0 @@ -import path from 'node:path' -import { existsSync, readFileSync } from 'node:fs' -import { readFile } from 'node:fs/promises' -import { fileURLToPath } from 'node:url' -import viteSolid from 'vite-plugin-solid' -import { resolve } from 'import-meta-resolve' -import { TanStackRouterVite } from '@tanstack/router-plugin/vite' -import { getConfig } from '@tanstack/router-generator' -import { createApp } from 'vinxi' -import { config } from 'vinxi/plugins/config' -// // @ts-expect-error -// import { serverComponents } from '@vinxi/server-components/plugin' -import { createTanStackServerFnPlugin } from '@tanstack/server-functions-plugin' -import { createTanStackStartPlugin } from '@tanstack/solid-start-plugin' -import { createFetch } from 'ofetch' -import { createNitro } from 'nitropack' -import { tanstackStartVinxiFileRouter } from './vinxi-file-router.js' -import { - checkDeploymentPresetInput, - getUserViteConfig, - inlineConfigSchema, - serverSchema, -} from './schema.js' -import type { configSchema } from '@tanstack/router-generator' -import type { z } from 'zod' -import type { - TanStackStartInputConfig, - TanStackStartOutputConfig, -} from './schema.js' -import type { App as VinxiApp } from 'vinxi' -import type { Manifest } from '@tanstack/router-core' -import type * as vite from 'vite' - -export type { - TanStackStartInputConfig, - TanStackStartOutputConfig, -} from './schema.js' - -function setTsrDefaults(config: TanStackStartOutputConfig['tsr']) { - // Normally these are `./src/___`, but we're using `./app/___` for Start stuff - const appDirectory = config?.appDirectory ?? './app' - return { - ...config, - appDirectory: config?.appDirectory ?? appDirectory, - routesDirectory: - config?.routesDirectory ?? path.join(appDirectory, 'routes'), - generatedRouteTree: - config?.generatedRouteTree ?? path.join(appDirectory, 'routeTree.gen.ts'), - } -} - -function mergeSsrOptions(options: Array) { - let ssrOptions: vite.SSROptions = {} - let noExternal: vite.SSROptions['noExternal'] = [] - for (const option of options) { - if (!option) { - continue - } - - if (option.noExternal) { - if (option.noExternal === true) { - noExternal = true - } else if (noExternal !== true) { - if (Array.isArray(option.noExternal)) { - noExternal.push(...option.noExternal) - } else { - noExternal.push(option.noExternal) - } - } - } - - ssrOptions = { - ...ssrOptions, - ...option, - noExternal, - } - } - - return ssrOptions -} - -export async function defineConfig( - inlineConfig: TanStackStartInputConfig = {}, -): Promise { - const opts = inlineConfigSchema.parse(inlineConfig) - - const { preset: configDeploymentPreset, ...serverOptions } = - serverSchema.parse(opts.server || {}) - - const deploymentPreset = checkDeploymentPresetInput( - configDeploymentPreset || 'node-server', - ) - const tsr = setTsrDefaults(opts.tsr) - const tsrConfig = getConfig(tsr) - - const appDirectory = tsr.appDirectory - const publicDir = opts.routers?.public?.dir || './public' - - const publicBase = opts.routers?.public?.base || '/' - const clientBase = opts.routers?.client?.base || '/_build' - const apiBase = opts.tsr?.apiBase || '/api' - const serverBase = opts.routers?.server?.base || '/_server' - - const apiMiddleware = opts.routers?.api?.middleware || undefined - const serverMiddleware = opts.routers?.server?.middleware || undefined - const ssrMiddleware = opts.routers?.ssr?.middleware || undefined - - const clientEntry = - opts.routers?.client?.entry || path.join(appDirectory, 'client.tsx') - const ssrEntry = - opts.routers?.ssr?.entry || path.join(appDirectory, 'ssr.tsx') - const apiEntry = opts.routers?.api?.entry || path.join(appDirectory, 'api.ts') - - const globalMiddlewareEntry = - opts.routers?.server?.globalMiddlewareEntry || - path.join(appDirectory, 'global-middleware.ts') - - const apiEntryExists = existsSync(apiEntry) - - const viteConfig = getUserViteConfig(opts.vite) - - const TanStackServerFnsPlugin = createTanStackServerFnPlugin({ - // This is the ID that will be available to look up and import - // our server function manifest and resolve its module - manifestVirtualImportId: 'tsr:server-fn-manifest', - client: { - getRuntimeCode: () => - `import { createClientRpc } from '@tanstack/solid-start/server-functions-client'`, - replacer: (opts) => - `createClientRpc('${opts.functionId}', '${serverBase}')`, - }, - ssr: { - getRuntimeCode: () => - `import { createSsrRpc } from '@tanstack/solid-start/server-functions-ssr'`, - replacer: (opts) => `createSsrRpc('${opts.functionId}', '${serverBase}')`, - }, - server: { - getRuntimeCode: () => - `import { createServerRpc } from '@tanstack/solid-start/server-functions-server'`, - replacer: (opts) => - `createServerRpc('${opts.functionId}', '${serverBase}', ${opts.fn})`, - }, - }) - - const TanStackStartPlugin = createTanStackStartPlugin({ - globalMiddlewareEntry, - }) - - // Create a dummy nitro app to get the resolved public output path - const dummyNitroApp = await createNitro({ - preset: deploymentPreset, - compatibilityDate: '2024-12-01', - }) - - const nitroOutputPublicDir = dummyNitroApp.options.output.publicDir - await dummyNitroApp.close() - - let vinxiApp = createApp({ - server: { - ...serverOptions, - preset: deploymentPreset, - experimental: { - ...serverOptions.experimental, - asyncContext: true, - }, - }, - routers: [ - { - name: 'public', - type: 'static', - dir: publicDir, - base: publicBase, - }, - { - name: 'client', - type: 'client', - target: 'browser', - handler: clientEntry, - base: clientBase, - // @ts-expect-error - build: { - sourcemap: true, - }, - plugins: () => { - const routerType = 'client' - const clientViteConfig = getUserViteConfig( - opts.routers?.[routerType]?.vite, - ) - - return [ - config('tss-vite-config-client', { - ...viteConfig.userConfig, - ...clientViteConfig.userConfig, - define: { - ...(viteConfig.userConfig.define || {}), - ...(clientViteConfig.userConfig.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', publicBase), - ...injectDefineEnv('TSS_CLIENT_BASE', clientBase), - ...injectDefineEnv('TSS_API_BASE', apiBase), - ...injectDefineEnv( - 'TSS_OUTPUT_PUBLIC_DIR', - nitroOutputPublicDir, - ), - }, - ssr: mergeSsrOptions([ - viteConfig.userConfig.ssr, - clientViteConfig.userConfig.ssr, - { - noExternal, - }, - ]), - optimizeDeps: { - entries: [], - ...(viteConfig.userConfig.optimizeDeps || {}), - ...(clientViteConfig.userConfig.optimizeDeps || {}), - }, - }), - TanStackRouterVite({ - ...tsrConfig, - target: 'solid', - enableRouteGeneration: true, - autoCodeSplitting: true, - __enableAPIRoutesGeneration: true, - experimental: { - ...tsrConfig.experimental, - }, - }), - TanStackStartPlugin.client, - TanStackServerFnsPlugin.client, - ...(viteConfig.plugins || []), - ...(clientViteConfig.plugins || []), - viteSolid({ ...opts.solid, ssr: true }), - // TODO: RSCS - enable this - // serverComponents.client(), - ] - }, - }, - { - name: 'ssr', - type: 'http', - target: 'server', - handler: ssrEntry, - middleware: ssrMiddleware, - // @ts-expect-error - link: { - client: 'client', - }, - plugins: () => { - const routerType = 'ssr' - const ssrViteConfig = getUserViteConfig( - opts.routers?.[routerType]?.vite, - ) - - return [ - config('tss-vite-config-ssr', { - ...viteConfig.userConfig, - ...ssrViteConfig.userConfig, - define: { - ...(viteConfig.userConfig.define || {}), - ...(ssrViteConfig.userConfig.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', publicBase), - ...injectDefineEnv('TSS_CLIENT_BASE', clientBase), - ...injectDefineEnv('TSS_API_BASE', apiBase), - ...injectDefineEnv( - 'TSS_OUTPUT_PUBLIC_DIR', - nitroOutputPublicDir, - ), - }, - ssr: mergeSsrOptions([ - viteConfig.userConfig.ssr, - ssrViteConfig.userConfig.ssr, - { - noExternal, - external: ['@vinxi/react-server-dom/client'], - }, - ]), - optimizeDeps: { - entries: [], - ...(viteConfig.userConfig.optimizeDeps || {}), - ...(ssrViteConfig.userConfig.optimizeDeps || {}), - }, - }), - TanStackRouterVite({ - ...tsrConfig, - target: 'solid', - enableRouteGeneration: false, - autoCodeSplitting: true, - __enableAPIRoutesGeneration: true, - experimental: { - ...tsrConfig.experimental, - }, - }), - TanStackStartPlugin.ssr, - TanStackServerFnsPlugin.ssr, - tsrRoutesManifest({ - tsrConfig, - clientBase, - }), - ...(getUserViteConfig(opts.vite).plugins || []), - ...(getUserViteConfig(opts.routers?.ssr?.vite).plugins || []), - viteSolid({ ...opts.solid, ssr: true }), - ] - }, - }, - { - name: 'server', - type: 'http', - target: 'server', - base: serverBase, - middleware: serverMiddleware, - // TODO: RSCS - enable this - // worker: true, - handler: importToProjectRelative( - '@tanstack/start-server-functions-handler', - ), - plugins: () => { - const routerType = 'server' - const serverViteConfig = getUserViteConfig( - opts.routers?.[routerType]?.vite, - ) - - return [ - config('tss-vite-config-server', { - ...viteConfig.userConfig, - ...serverViteConfig.userConfig, - define: { - ...(viteConfig.userConfig.define || {}), - ...(serverViteConfig.userConfig.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', publicBase), - ...injectDefineEnv('TSS_CLIENT_BASE', clientBase), - ...injectDefineEnv('TSS_API_BASE', apiBase), - ...injectDefineEnv('TSS_SERVER_FN_BASE', serverBase), - ...injectDefineEnv( - 'TSS_OUTPUT_PUBLIC_DIR', - nitroOutputPublicDir, - ), - }, - ssr: mergeSsrOptions([ - viteConfig.userConfig.ssr, - serverViteConfig.userConfig.ssr, - { - noExternal, - }, - ]), - optimizeDeps: { - entries: [], - ...(viteConfig.userConfig.optimizeDeps || {}), - ...(serverViteConfig.userConfig.optimizeDeps || {}), - }, - }), - TanStackRouterVite({ - ...tsrConfig, - target: 'solid', - enableRouteGeneration: false, - autoCodeSplitting: true, - __enableAPIRoutesGeneration: true, - experimental: { - ...tsrConfig.experimental, - }, - }), - TanStackStartPlugin.server, - TanStackServerFnsPlugin.server, - // TODO: RSCS - remove this - // resolve: { - // conditions: [], - // }, - // TODO: RSCs - add this - // serverComponents.serverActions({ - // resolve: { - // conditions: [ - // 'react-server', - // // 'node', - // 'import', - // process.env.NODE_ENV, - // ], - // }, - // runtime: '@vinxi/react-server-dom/runtime', - // transpileDeps: ['react', 'react-dom', '@vinxi/react-server-dom'], - // }), - ...(viteConfig.plugins || []), - ...(serverViteConfig.plugins || []), - viteSolid({ ...opts.solid, ssr: true }), - ] - }, - }, - ], - }) - - const noExternal = [ - '@tanstack/solid-start', - '@tanstack/solid-start/server', - '@tanstack/solid-start-client', - '@tanstack/solid-start-server', - '@tanstack/start-server-functions-fetcher', - '@tanstack/start-server-functions-handler', - '@tanstack/start-server-functions-client', - '@tanstack/start-server-functions-ssr', - '@tanstack/start-server-functions-server', - '@tanstack/solid-start-router-manifest', - '@tanstack/solid-start-config', - '@tanstack/start-api-routes', - '@tanstack/server-functions-plugin', - 'tsr:routes-manifest', - 'tsr:server-fn-manifest', - ] - - // If API routes handler exists, add a router for it - if (apiEntryExists) { - vinxiApp = vinxiApp.addRouter({ - name: 'api', - type: 'http', - target: 'server', - base: apiBase, - handler: apiEntry, - middleware: apiMiddleware, - routes: tanstackStartVinxiFileRouter({ tsrConfig, apiBase }), - plugins: () => { - const viteConfig = getUserViteConfig(opts.vite) - const apiViteConfig = getUserViteConfig(opts.routers?.api?.vite) - - return [ - config('tsr-vite-config-api', { - ...viteConfig.userConfig, - ...apiViteConfig.userConfig, - ssr: mergeSsrOptions([ - viteConfig.userConfig.ssr, - apiViteConfig.userConfig.ssr, - { - noExternal, - }, - ]), - optimizeDeps: { - entries: [], - ...(viteConfig.userConfig.optimizeDeps || {}), - ...(apiViteConfig.userConfig.optimizeDeps || {}), - }, - define: { - ...(viteConfig.userConfig.define || {}), - ...(apiViteConfig.userConfig.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', publicBase), - ...injectDefineEnv('TSS_CLIENT_BASE', clientBase), - ...injectDefineEnv('TSS_API_BASE', apiBase), - ...injectDefineEnv('TSS_OUTPUT_PUBLIC_DIR', nitroOutputPublicDir), - }, - }), - TanStackRouterVite({ - ...tsrConfig, - target: 'solid', - enableRouteGeneration: false, - autoCodeSplitting: true, - __enableAPIRoutesGeneration: true, - experimental: { - ...tsrConfig.experimental, - }, - }), - ...(viteConfig.plugins || []), - ...(apiViteConfig.plugins || []), - viteSolid({ ...opts.solid, ssr: true }), - ] - }, - }) - } - - // Because Vinxi doesn't use the normal nitro dev server, it doesn't - // supply $fetch during dev. We need to hook into the dev server creation, - // nab the proper utils from the custom nitro instance that is used - // during dev and supply the $fetch to app. - // Hopefully and likely, this will just get removed when we move to - // Nitro directly. - vinxiApp.hooks.hook('app:dev:nitro:config', (devServer) => { - vinxiApp.hooks.hook( - 'app:dev:server:created', - ({ devApp: { localFetch } }) => { - const $fetch = createFetch({ - fetch: localFetch, - defaults: { - baseURL: devServer.nitro.options.runtimeConfig.app.baseURL, - }, - }) - - // @ts-expect-error - globalThis.$fetch = $fetch - }, - ) - }) - - return vinxiApp -} - -function importToProjectRelative(p: string) { - const resolved = fileURLToPath(resolve(p, import.meta.url)) - - const relative = path.relative(process.cwd(), resolved) - - return relative -} - -function tsrRoutesManifest(opts: { - tsrConfig: z.infer - clientBase: string -}): vite.Plugin { - let config: vite.ResolvedConfig - - return { - name: 'tsr-routes-manifest', - configResolved(resolvedConfig) { - config = resolvedConfig - }, - resolveId(id) { - if (id === 'tsr:routes-manifest') { - return id - } - return - }, - async load(id) { - if (id === 'tsr:routes-manifest') { - // If we're in development, return a dummy manifest - - if (config.command === 'serve') { - return `export default () => ({ - routes: {} - })` - } - - const clientViteManifestPath = path.resolve( - config.build.outDir, - `../client/${opts.clientBase}/.vite/manifest.json`, - ) - - type ViteManifest = Record< - string, - { - file: string - isEntry: boolean - imports: Array - } - > - - let manifest: ViteManifest - try { - manifest = JSON.parse(await readFile(clientViteManifestPath, 'utf-8')) - } catch (err) { - console.error(err) - throw new Error( - `Could not find the production client vite manifest at '${clientViteManifestPath}'!`, - ) - } - - const routeTreePath = path.resolve(opts.tsrConfig.generatedRouteTree) - - let routeTreeContent: string - try { - routeTreeContent = readFileSync(routeTreePath, 'utf-8') - } catch (err) { - console.error(err) - throw new Error( - `Could not find the generated route tree at '${routeTreePath}'!`, - ) - } - - // Extract the routesManifest JSON from the route tree file. - // It's located between the /* ROUTE_MANIFEST_START and ROUTE_MANIFEST_END */ comment block. - - const routerManifest = JSON.parse( - routeTreeContent.match( - /\/\* ROUTE_MANIFEST_START([\s\S]*?)ROUTE_MANIFEST_END \*\//, - )?.[1] || '{ routes: {} }', - ) as Manifest - - const routes = routerManifest.routes - - let entryFile: - | { - file: string - imports: Array - } - | undefined - - const filesByRouteFilePath: ViteManifest = Object.fromEntries( - Object.entries(manifest).map(([k, v]) => { - if (v.isEntry) { - entryFile = v - } - - const rPath = k.split('?')[0] - - return [rPath, v] - }, {}), - ) - - // Add preloads to the routes from the vite manifest - Object.entries(routes).forEach(([k, v]) => { - const file = - filesByRouteFilePath[ - path.join(opts.tsrConfig.routesDirectory, v.filePath as string) - ] - - if (file) { - const preloads = file.imports.map((d) => - path.join(opts.clientBase, manifest[d]!.file), - ) - - preloads.unshift(path.join(opts.clientBase, file.file)) - - routes[k] = { - ...v, - preloads, - } - } - }) - - if (entryFile) { - routes.__root__!.preloads = [ - path.join(opts.clientBase, entryFile.file), - ...entryFile.imports.map((d) => - path.join(opts.clientBase, manifest[d]!.file), - ), - ] - } - - const recurseRoute = ( - route: { - preloads?: Array - children?: Array - }, - seenPreloads = {} as Record, - ) => { - route.preloads = route.preloads?.filter((preload) => { - if (seenPreloads[preload]) { - return false - } - seenPreloads[preload] = true - return true - }) - - if (route.children) { - route.children.forEach((child) => { - const childRoute = routes[child]! - recurseRoute(childRoute, { ...seenPreloads }) - }) - } - } - - // @ts-expect-error - recurseRoute(routes.__root__) - - const routesManifest = { - routes, - } - - if (process.env.TSR_VITE_DEBUG) { - console.info( - 'Routes Manifest: \n' + JSON.stringify(routesManifest, null, 2), - ) - } - - return `export default () => (${JSON.stringify(routesManifest)})` - } - return - }, - } -} - -function injectDefineEnv( - key: TKey, - value: TValue, -): { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } { - return { - [`process.env.${key}`]: JSON.stringify(value), - [`import.meta.env.${key}`]: JSON.stringify(value), - } as { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } -} diff --git a/packages/solid-start-config/src/schema.ts b/packages/solid-start-config/src/schema.ts deleted file mode 100644 index caa4ecbc41..0000000000 --- a/packages/solid-start-config/src/schema.ts +++ /dev/null @@ -1,194 +0,0 @@ -import { configSchema } from '@tanstack/router-generator' -import { z } from 'zod' -import type { PluginOption } from 'vite' -import type { AppOptions as VinxiAppOptions } from 'vinxi' -import type { NitroOptions } from 'nitropack' -import type { Options as ViteSolidOptions } from 'vite-plugin-solid' -import type { CustomizableConfig } from 'vinxi/dist/types/lib/vite-dev' - -type StartUserViteConfig = CustomizableConfig | (() => CustomizableConfig) - -export function getUserViteConfig(config?: StartUserViteConfig): { - plugins: Array | undefined - userConfig: CustomizableConfig -} { - const { plugins, ...userConfig } = - typeof config === 'function' ? config() : { ...config } - return { plugins, userConfig } -} - -/** - * Not all the deployment presets are fully functional or tested. - * @see https://github.com/TanStack/router/pull/2002 - */ -const vinxiDeploymentPresets = [ - 'alwaysdata', // untested - 'aws-amplify', // untested - 'aws-lambda', // untested - 'azure', // untested - 'azure-functions', // untested - 'base-worker', // untested - 'bun', // ✅ working - 'cleavr', // untested - 'cli', // untested - 'cloudflare', // untested - 'cloudflare-module', // untested - 'cloudflare-pages', // ✅ working - 'cloudflare-pages-static', // untested - 'deno', // untested - 'deno-deploy', // untested - 'deno-server', // untested - 'digital-ocean', // untested - 'edgio', // untested - 'firebase', // untested - 'flight-control', // untested - 'github-pages', // untested - 'heroku', // untested - 'iis', // untested - 'iis-handler', // untested - 'iis-node', // untested - 'koyeb', // untested - 'layer0', // untested - 'netlify', // ✅ working - 'netlify-builder', // untested - 'netlify-edge', // untested - 'netlify-static', // untested - 'nitro-dev', // untested - 'nitro-prerender', // untested - 'node', // partially working - 'node-cluster', // untested - 'node-server', // ✅ working - 'platform-sh', // untested - 'service-worker', // untested - 'static', // 🟧 partially working - 'stormkit', // untested - 'vercel', // ✅ working - 'vercel-edge', // untested - 'vercel-static', // untested - 'winterjs', // untested - 'zeabur', // untested - 'zeabur-static', // untested -] as const - -type DeploymentPreset = (typeof vinxiDeploymentPresets)[number] | (string & {}) - -const testedDeploymentPresets: Array = [ - 'bun', - 'netlify', - 'vercel', - 'cloudflare-pages', - 'node-server', -] - -export function checkDeploymentPresetInput(preset: string): DeploymentPreset { - if (!vinxiDeploymentPresets.includes(preset as any)) { - console.warn( - `Invalid deployment preset "${preset}". Available presets are: ${vinxiDeploymentPresets - .map((p) => `"${p}"`) - .join(', ')}.`, - ) - } - - if (!testedDeploymentPresets.includes(preset as any)) { - console.warn( - `The deployment preset '${preset}' is not fully supported yet and may not work as expected.`, - ) - } - - return preset -} - -type HTTPSOptions = { - cert?: string - key?: string - pfx?: string - passphrase?: string - validityDays?: number - domains?: Array -} - -type ServerOptions_ = VinxiAppOptions['server'] & { - https?: boolean | HTTPSOptions -} - -type ServerOptions = { - [K in keyof ServerOptions_]: ServerOptions_[K] -} - -export const serverSchema = z - .object({ - routeRules: z.custom().optional(), - preset: z.custom().optional(), - static: z.boolean().optional(), - prerender: z - .object({ - routes: z.array(z.string()), - ignore: z - .array( - z.custom< - string | RegExp | ((path: string) => undefined | null | boolean) - >(), - ) - .optional(), - crawlLinks: z.boolean().optional(), - }) - .optional(), - }) - .and(z.custom()) - -const viteSchema = z.custom() - -const viteSolidSchema = z.custom() - -const routersSchema = z.object({ - ssr: z - .object({ - entry: z.string().optional(), - middleware: z.string().optional(), - vite: viteSchema.optional(), - }) - .optional(), - client: z - .object({ - entry: z.string().optional(), - base: z.string().optional(), - vite: viteSchema.optional(), - }) - .optional(), - server: z - .object({ - base: z.string().optional(), - globalMiddlewareEntry: z.string().optional(), - middleware: z.string().optional(), - vite: viteSchema.optional(), - }) - .optional(), - api: z - .object({ - entry: z.string().optional(), - middleware: z.string().optional(), - vite: viteSchema.optional(), - }) - .optional(), - public: z - .object({ - dir: z.string().optional(), - base: z.string().optional(), - }) - .optional(), -}) - -const tsrConfig = configSchema.partial().extend({ - appDirectory: z.string().optional(), -}) - -export const inlineConfigSchema = z.object({ - solid: viteSolidSchema.optional(), - vite: viteSchema.optional(), - tsr: tsrConfig.optional(), - routers: routersSchema.optional(), - server: serverSchema.optional(), -}) - -export type TanStackStartInputConfig = z.input -export type TanStackStartOutputConfig = z.infer diff --git a/packages/solid-start-config/src/vinxi-file-router.ts b/packages/solid-start-config/src/vinxi-file-router.ts deleted file mode 100644 index 9e6d829d1b..0000000000 --- a/packages/solid-start-config/src/vinxi-file-router.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { - BaseFileSystemRouter as VinxiBaseFileSystemRouter, - analyzeModule as vinxiFsRouterAnalyzeModule, - cleanPath as vinxiFsRouterCleanPath, -} from 'vinxi/fs-router' -import { - CONSTANTS as GENERATOR_CONSTANTS, - startAPIRouteSegmentsFromTSRFilePath, -} from '@tanstack/router-generator' -import type { configSchema } from '@tanstack/router-generator' -import type { - AppOptions as VinxiAppOptions, - RouterSchemaInput as VinxiRouterSchemaInput, -} from 'vinxi' -import type { z } from 'zod' - -export function tanstackStartVinxiFileRouter(opts: { - tsrConfig: z.infer - apiBase: string -}) { - const apiBaseSegment = opts.apiBase.split('/').filter(Boolean).join('/') - const isAPIPath = new RegExp(`/${apiBaseSegment}/`) - - return function (router: VinxiRouterSchemaInput, app: VinxiAppOptions) { - // Our own custom File Router that extends the VinxiBaseFileSystemRouter - // for splitting the API routes into its own "bundle" - // and adding the $APIRoute metadata to the route object - // This could be customized in future to support more complex splits - class TanStackStartFsRouter extends VinxiBaseFileSystemRouter { - toPath(src: string): string { - const inputPath = vinxiFsRouterCleanPath(src, this.config) - - const segments = startAPIRouteSegmentsFromTSRFilePath( - inputPath, - opts.tsrConfig, - ) - - const pathname = segments - .map((part) => { - if (part.type === 'splat') { - return `*splat` - } - - if (part.type === 'param') { - return `:${part.value}?` - } - - return part.value - }) - .join('/') - - return pathname.length > 0 ? `/${pathname}` : '/' - } - - toRoute(src: string) { - const webPath = this.toPath(src) - - const [_, exports] = vinxiFsRouterAnalyzeModule(src) - - const hasAPIRoute = exports.find( - (exp) => exp.n === GENERATOR_CONSTANTS.APIRouteExportVariable, - ) - - return { - path: webPath, - filePath: src, - $APIRoute: - isAPIPath.test(webPath) && hasAPIRoute - ? { - src, - pick: [GENERATOR_CONSTANTS.APIRouteExportVariable], - } - : undefined, - } - } - } - - return new TanStackStartFsRouter( - { - dir: opts.tsrConfig.routesDirectory, - extensions: ['js', 'jsx', 'ts', 'tsx'], - }, - router, - app, - ) - } -} diff --git a/packages/solid-start-config/tsconfig.json b/packages/solid-start-config/tsconfig.json deleted file mode 100644 index 940a9cce0a..0000000000 --- a/packages/solid-start-config/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "include": ["src/index.ts"], - "compilerOptions": { - "rootDir": "src", - "outDir": "dist/esm", - "target": "esnext", - "noEmit": false - } -} diff --git a/packages/solid-start-router-manifest/README.md b/packages/solid-start-router-manifest/README.md deleted file mode 100644 index bb009b0c87..0000000000 --- a/packages/solid-start-router-manifest/README.md +++ /dev/null @@ -1,33 +0,0 @@ -> 🤫 we're cooking up something special! - - - -# TanStack Start - -![TanStack Router Header](https://github.com/tanstack/router/raw/main/media/header.png) - -🤖 Type-safe router w/ built-in caching & URL state management for React! - - - #TanStack - - - - - - - - semantic-release - - Join the discussion on Github -Best of JS - - - - - - - -Enjoy this library? Try the entire [TanStack](https://tanstack.com)! [React Query](https://github.com/tannerlinsley/react-query), [React Table](https://github.com/tanstack/react-table), [React Charts](https://github.com/tannerlinsley/react-charts), [React Virtual](https://github.com/tannerlinsley/react-virtual) - -## Visit [tanstack.com/router](https://tanstack.com/router) for docs, guides, API and more! diff --git a/packages/solid-start-router-manifest/eslint.config.js b/packages/solid-start-router-manifest/eslint.config.js deleted file mode 100644 index 931f0ec774..0000000000 --- a/packages/solid-start-router-manifest/eslint.config.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check - -import pluginReact from '@eslint-react/eslint-plugin' -import pluginReactHooks from 'eslint-plugin-react-hooks' -import rootConfig from '../../eslint.config.js' - -export default [ - ...rootConfig, - { - ...pluginReact.configs.recommended, - files: ['**/*.{ts,tsx}'], - }, - { - plugins: { - 'react-hooks': pluginReactHooks, - }, - rules: { - '@eslint-react/no-unstable-context-value': 'off', - '@eslint-react/no-unstable-default-props': 'off', - '@eslint-react/dom/no-missing-button-type': 'off', - 'react-hooks/exhaustive-deps': 'error', - 'react-hooks/rules-of-hooks': 'error', - }, - }, - { - files: ['**/__tests__/**'], - rules: { - '@typescript-eslint/no-unnecessary-condition': 'off', - }, - }, -] diff --git a/packages/solid-start-router-manifest/src/index.ts b/packages/solid-start-router-manifest/src/index.ts deleted file mode 100644 index 9a41e3f788..0000000000 --- a/packages/solid-start-router-manifest/src/index.ts +++ /dev/null @@ -1,83 +0,0 @@ -// @ts-expect-error -import tsrGetManifest from 'tsr:routes-manifest' -import { getManifest } from 'vinxi/manifest' -import { default as invariant } from 'tiny-invariant' -import type { Manifest } from '@tanstack/router-core' - -function sanitizeBase(base: string) { - return base.replace(/^\/|\/$/g, '') -} - -/** - * @description Returns the full, unfiltered router manifest. This includes relationships - * between routes, assets, and preloads and is NOT what you want to serialize and - * send to the client. - */ -export function getFullRouterManifest() { - const routerManifest = tsrGetManifest() as Manifest - - const rootRoute = (routerManifest.routes.__root__ = - routerManifest.routes.__root__ || {}) - - rootRoute.assets = rootRoute.assets || [] - - const script = '' - // Always fake that HMR is ready - if (process.env.NODE_ENV === 'development') { - const CLIENT_BASE = sanitizeBase(process.env.TSS_CLIENT_BASE || '') - - if (!CLIENT_BASE) { - throw new Error( - 'tanstack/solid-start-router-manifest: TSS_CLIENT_BASE must be defined in your environment for getFullRouterManifest()', - ) - } - } - - // Get the entry for the client from vinxi - const vinxiClientManifest = getManifest('client') - - const importPath = - vinxiClientManifest.inputs[vinxiClientManifest.handler]?.output.path - if (!importPath) { - invariant(importPath, 'Could not find client entry in vinxi manifest') - } - - rootRoute.assets.push({ - tag: 'script', - attrs: { - type: 'module', - suppressHydrationWarning: true, - async: true, - }, - children: `${script}import("${importPath}")`, - }) - - return routerManifest -} - -/** - * @description Returns the router manifest that should be sent to the client. - * This includes only the assets and preloads for the current route and any - * special assets that are needed for the client. It does not include relationships - * between routes or any other data that is not needed for the client. - */ -export function getRouterManifest() { - const routerManifest = getFullRouterManifest() - - // Strip out anything that isn't needed for the client - return { - ...routerManifest, - routes: Object.fromEntries( - Object.entries(routerManifest.routes).map(([k, v]: any) => { - const { preloads, assets } = v - return [ - k, - { - preloads, - assets, - }, - ] - }), - ), - } -} diff --git a/packages/solid-start-router-manifest/tsconfig.json b/packages/solid-start-router-manifest/tsconfig.json deleted file mode 100644 index 940a9cce0a..0000000000 --- a/packages/solid-start-router-manifest/tsconfig.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "extends": "../../tsconfig.json", - "include": ["src/index.ts"], - "compilerOptions": { - "rootDir": "src", - "outDir": "dist/esm", - "target": "esnext", - "noEmit": false - } -} diff --git a/packages/solid-start-router-manifest/vite.config.ts b/packages/solid-start-router-manifest/vite.config.ts deleted file mode 100644 index d6472068fb..0000000000 --- a/packages/solid-start-router-manifest/vite.config.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { defineConfig, mergeConfig } from 'vitest/config' -import { tanstackViteConfig } from '@tanstack/config/vite' -import packageJson from './package.json' -import type { ViteUserConfig } from 'vitest/config' - -const config = defineConfig({ - plugins: [] as ViteUserConfig['plugins'], - test: { - name: packageJson.name, - watch: false, - environment: 'jsdom', - }, -}) - -export default mergeConfig( - config, - tanstackViteConfig({ - entry: './src/index.ts', - srcDir: './src', - externalDeps: ['tsr:routes-manifest'], - }), -) diff --git a/packages/solid-start/package.json b/packages/solid-start/package.json index 4782d3421a..7c4bea024e 100644 --- a/packages/solid-start/package.json +++ b/packages/solid-start/package.json @@ -62,14 +62,14 @@ "default": "./dist/cjs/server.cjs" } }, - "./config": { + "./plugin": { "import": { - "types": "./dist/esm/config.d.ts", - "default": "./dist/esm/config.js" + "types": "./dist/esm/plugin.d.ts", + "default": "./dist/esm/plugin.js" }, "require": { - "types": "./dist/cjs/config.d.cts", - "default": "./dist/cjs/config.cjs" + "types": "./dist/cjs/plugin.d.cts", + "default": "./dist/cjs/plugin.cjs" } }, "./api": { @@ -82,16 +82,6 @@ "default": "./dist/cjs/api.cjs" } }, - "./router-manifest": { - "import": { - "types": "./dist/esm/router-manifest.d.ts", - "default": "./dist/esm/router-manifest.js" - }, - "require": { - "types": "./dist/cjs/router-manifest.d.cts", - "default": "./dist/cjs/router-manifest.cjs" - } - }, "./server-functions-client": { "import": { "types": "./dist/esm/server-functions-client.d.ts", @@ -145,11 +135,9 @@ "dependencies": { "@tanstack/solid-start-client": "workspace:^", "@tanstack/solid-start-server": "workspace:^", - "@tanstack/solid-start-config": "workspace:^", - "@tanstack/solid-start-router-manifest": "workspace:^", + "@tanstack/solid-start-plugin": "workspace:^", "@tanstack/start-server-functions-client": "workspace:^", "@tanstack/start-server-functions-server": "workspace:^", - "@tanstack/start-server-functions-handler": "workspace:^", "@tanstack/start-server-functions-ssr": "workspace:^", "@tanstack/start-api-routes": "workspace:^" }, diff --git a/packages/solid-start/src/config.tsx b/packages/solid-start/src/config.tsx deleted file mode 100644 index 5a71360c3a..0000000000 --- a/packages/solid-start/src/config.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from '@tanstack/solid-start-config' diff --git a/packages/solid-start/src/plugin.tsx b/packages/solid-start/src/plugin.tsx new file mode 100644 index 0000000000..24c76d5516 --- /dev/null +++ b/packages/solid-start/src/plugin.tsx @@ -0,0 +1 @@ +export * from '@tanstack/solid-start-plugin' diff --git a/packages/solid-start/src/router-manifest.tsx b/packages/solid-start/src/router-manifest.tsx deleted file mode 100644 index 4e939be275..0000000000 --- a/packages/solid-start/src/router-manifest.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from '@tanstack/solid-start-router-manifest' diff --git a/packages/solid-start/src/server-functions-handler.tsx b/packages/solid-start/src/server-functions-handler.tsx deleted file mode 100644 index c3cc9770d2..0000000000 --- a/packages/solid-start/src/server-functions-handler.tsx +++ /dev/null @@ -1 +0,0 @@ -export * from '@tanstack/start-server-functions-handler' diff --git a/packages/solid-start/vite.config.ts b/packages/solid-start/vite.config.ts index dfcd5b4b41..262e126d5c 100644 --- a/packages/solid-start/vite.config.ts +++ b/packages/solid-start/vite.config.ts @@ -17,8 +17,7 @@ export default mergeConfig( entry: [ './src/client.tsx', './src/server.tsx', - './src/config.tsx', - './src/router-manifest.tsx', + './src/plugin.tsx', './src/server-functions-client.tsx', './src/server-functions-server.tsx', './src/server-functions-ssr.tsx', @@ -27,8 +26,7 @@ export default mergeConfig( externalDeps: [ '@tanstack/solid-start-client', '@tanstack/solid-start-server', - '@tanstack/solid-start-config', - '@tanstack/solid-start-router-manifest', + '@tanstack/solid-start-plugin', '@tanstack/start-server-functions-client', '@tanstack/start-server-functions-server', '@tanstack/start-server-functions-ssr', diff --git a/packages/solid-start-router-manifest/package.json b/packages/start-server-functions-ssr/package.json similarity index 73% rename from packages/solid-start-router-manifest/package.json rename to packages/start-server-functions-ssr/package.json index 22d9650333..538f5bcb60 100644 --- a/packages/solid-start-router-manifest/package.json +++ b/packages/start-server-functions-ssr/package.json @@ -1,13 +1,13 @@ { - "name": "@tanstack/solid-start-router-manifest", - "version": "1.111.7", - "description": "Modern and scalable routing for React applications", + "name": "@tanstack/start-server-functions-ssr", + "version": "1.114.10", + "description": "Modern and scalable routing for applications", "author": "Tanner Linsley", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/TanStack/router.git", - "directory": "packages/start" + "directory": "packages/start-server-functions-ssr" }, "homepage": "https://tanstack.com/start", "funding": { @@ -15,7 +15,6 @@ "url": "https://github.com/sponsors/tannerlinsley" }, "keywords": [ - "react", "location", "router", "routing", @@ -36,7 +35,7 @@ "test:types:ts57": "node ../../node_modules/typescript57/lib/tsc.js", "test:types:ts58": "tsc", "test:build": "publint --strict && attw --ignore-rules no-resolution --pack .", - "build": "tsc" + "build": "vite build" }, "type": "module", "types": "dist/esm/index.d.ts", @@ -45,6 +44,10 @@ "import": { "types": "./dist/esm/index.d.ts", "default": "./dist/esm/index.js" + }, + "require": { + "types": "./dist/cjs/index.d.cts", + "default": "./dist/cjs/index.cjs" } }, "./package.json": "./package.json" @@ -58,11 +61,13 @@ "node": ">=12" }, "dependencies": { - "@tanstack/router-core": "workspace:^", - "tiny-invariant": "^1.3.3", - "vinxi": "0.5.3" + "@tanstack/server-functions-plugin": "workspace:^", + "@tanstack/start-server-functions-fetcher": "workspace:^", + "@tanstack/start-client-core": "workspace:^", + "@tanstack/start-server-core": "workspace:^", + "tiny-invariant": "^1.3.3" }, "devDependencies": { "typescript": "^5.7.2" } -} +} \ No newline at end of file diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 4aa4091dd0..e6f6704bd0 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -33,9 +33,9 @@ overrides: '@tanstack/react-start-client': workspace:* '@tanstack/react-start-server': workspace:* '@tanstack/start-api-routes': workspace:* - '@tanstack/react-start-server-functions-fetcher': workspace:* - '@tanstack/react-start-server-functions-client': workspace:* - '@tanstack/react-start-server-functions-ssr': workspace:* + '@tanstack/start-server-functions-fetcher': workspace:* + '@tanstack/start-server-functions-client': workspace:* + '@tanstack/start-server-functions-ssr': workspace:* '@tanstack/start-server-functions-server': workspace:* '@tanstack/react-start-plugin': workspace:* '@tanstack/start-client-core': workspace:* @@ -5702,21 +5702,12 @@ importers: '@tanstack/react-start-server': specifier: workspace:* version: link:../react-start-server - '@tanstack/react-start-server-functions-client': - specifier: workspace:* - version: link:../react-start-server-functions-client - '@tanstack/react-start-server-functions-ssr': - specifier: workspace:* - version: link:../react-start-server-functions-ssr '@tanstack/start-api-routes': specifier: workspace:* version: link:../start-api-routes '@tanstack/start-server-functions-client': specifier: workspace:* version: link:../start-server-functions-client - '@tanstack/start-server-functions-handler': - specifier: workspace:* - version: link:../start-server-functions-handler '@tanstack/start-server-functions-server': specifier: workspace:* version: link:../start-server-functions-server @@ -5884,6 +5875,9 @@ importers: jsesc: specifier: ^3.1.0 version: 3.1.0 + tiny-invariant: + specifier: ^1.3.3 + version: 1.3.3 tiny-warning: specifier: ^1.0.3 version: 1.0.3 @@ -5910,66 +5904,6 @@ importers: specifier: ^5.7.2 version: 5.8.2 - packages/react-start-server-functions-client: - dependencies: - '@tanstack/react-start-server-functions-fetcher': - specifier: workspace:* - version: link:../react-start-server-functions-fetcher - '@tanstack/server-functions-plugin': - specifier: workspace:* - version: link:../server-functions-plugin - devDependencies: - typescript: - specifier: ^5.7.2 - version: 5.8.2 - - packages/react-start-server-functions-fetcher: - dependencies: - '@tanstack/react-router': - specifier: workspace:* - version: link:../react-router - '@tanstack/router-core': - specifier: workspace:* - version: link:../router-core - '@tanstack/start-client-core': - specifier: workspace:* - version: link:../start-client-core - devDependencies: - '@vitejs/plugin-react': - specifier: ^4.3.4 - version: 4.3.4(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) - react: - specifier: ^19.0.0 - version: 19.0.0 - react-dom: - specifier: ^19.0.0 - version: 19.0.0(react@19.0.0) - typescript: - specifier: ^5.7.2 - version: 5.8.2 - - packages/react-start-server-functions-ssr: - dependencies: - '@tanstack/react-start-server': - specifier: workspace:* - version: link:../react-start-server - '@tanstack/react-start-server-functions-fetcher': - specifier: workspace:* - version: link:../react-start-server-functions-fetcher - '@tanstack/server-functions-plugin': - specifier: workspace:* - version: link:../server-functions-plugin - '@tanstack/start-client-core': - specifier: workspace:* - version: link:../start-client-core - tiny-invariant: - specifier: ^1.3.3 - version: 1.3.3 - devDependencies: - typescript: - specifier: ^5.7.2 - version: 5.8.2 - packages/router-cli: dependencies: '@tanstack/router-generator': @@ -6291,12 +6225,9 @@ importers: '@tanstack/solid-start-client': specifier: workspace:^ version: link:../solid-start-client - '@tanstack/solid-start-config': - specifier: workspace:^ - version: link:../solid-start-config - '@tanstack/solid-start-router-manifest': + '@tanstack/solid-start-plugin': specifier: workspace:^ - version: link:../solid-start-router-manifest + version: link:../solid-start-plugin '@tanstack/solid-start-server': specifier: workspace:^ version: link:../solid-start-server @@ -6306,9 +6237,6 @@ importers: '@tanstack/start-server-functions-client': specifier: workspace:* version: link:../start-server-functions-client - '@tanstack/start-server-functions-handler': - specifier: workspace:* - version: link:../start-server-functions-handler '@tanstack/start-server-functions-server': specifier: workspace:* version: link:../start-server-functions-server @@ -6369,51 +6297,6 @@ importers: specifier: ^2.11.2 version: 2.11.6(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) - packages/solid-start-config: - dependencies: - '@tanstack/router-core': - specifier: workspace:* - version: link:../router-core - '@tanstack/router-generator': - specifier: workspace:* - version: link:../router-generator - '@tanstack/router-plugin': - specifier: workspace:* - version: link:../router-plugin - '@tanstack/server-functions-plugin': - specifier: workspace:* - version: link:../server-functions-plugin - '@tanstack/solid-start-plugin': - specifier: workspace:^ - version: link:../solid-start-plugin - '@tanstack/start-server-functions-handler': - specifier: workspace:* - version: link:../start-server-functions-handler - import-meta-resolve: - specifier: ^4.1.0 - version: 4.1.0 - nitropack: - specifier: ^2.10.4 - version: 2.10.4(typescript@5.8.2) - ofetch: - specifier: ^1.4.1 - version: 1.4.1 - solid-js: - specifier: '>=1.0.0' - version: 1.9.5 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) - vite: - specifier: 6.1.0 - version: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - vite-plugin-solid: - specifier: ^2.11.2 - version: 2.11.6(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) - zod: - specifier: ^3.24.2 - version: 3.24.2 - packages/solid-start-plugin: dependencies: '@babel/code-frame': @@ -6463,22 +6346,6 @@ importers: specifier: ^7.20.6 version: 7.20.6 - packages/solid-start-router-manifest: - dependencies: - '@tanstack/router-core': - specifier: workspace:* - version: link:../router-core - tiny-invariant: - specifier: ^1.3.3 - version: 1.3.3 - vinxi: - specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) - devDependencies: - typescript: - specifier: ^5.7.2 - version: 5.8.2 - packages/solid-start-server: dependencies: '@solidjs/meta': @@ -6542,15 +6409,12 @@ importers: '@tanstack/react-start-server': specifier: workspace:* version: link:../react-start-server - '@tanstack/react-start-server-functions-client': - specifier: workspace:* - version: link:../react-start-server-functions-client - '@tanstack/react-start-server-functions-ssr': - specifier: workspace:* - version: link:../react-start-server-functions-ssr '@tanstack/start-api-routes': specifier: workspace:* version: link:../start-api-routes + '@tanstack/start-server-functions-client': + specifier: workspace:* + version: link:../start-server-functions-client '@tanstack/start-server-functions-server': specifier: workspace:* version: link:../start-server-functions-server @@ -6649,25 +6513,6 @@ importers: specifier: ^5.7.2 version: 5.8.2 - packages/start-server-functions-handler: - dependencies: - '@tanstack/router-core': - specifier: workspace:* - version: link:../router-core - '@tanstack/start-client-core': - specifier: workspace:* - version: link:../start-client-core - '@tanstack/start-server-core': - specifier: workspace:* - version: link:../start-server-core - tiny-invariant: - specifier: ^1.3.3 - version: 1.3.3 - devDependencies: - typescript: - specifier: ^5.7.2 - version: 5.8.2 - packages/start-server-functions-server: dependencies: '@tanstack/server-functions-plugin': From 0b9f6b067689556072c0040e2bdcf821bafeaf93 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Mon, 10 Mar 2025 19:34:02 +0100 Subject: [PATCH 036/155] keep tsr config routes in src/app/routes --- e2e/react-start/basic-tsr-config/src/{ => app}/routeTree.gen.ts | 0 e2e/react-start/basic-tsr-config/src/{ => app}/router.tsx | 0 .../basic-tsr-config/src/{ => app}/routes/__root.tsx | 0 e2e/react-start/basic-tsr-config/src/{ => app}/routes/index.tsx | 0 e2e/solid-start/basic-tsr-config/src/{ => app}/client.tsx | 2 +- e2e/solid-start/basic-tsr-config/src/{ => app}/routeTree.gen.ts | 2 +- e2e/solid-start/basic-tsr-config/src/{ => app}/router.tsx | 2 +- .../basic-tsr-config/src/{ => app}/routes/__root.tsx | 0 e2e/solid-start/basic-tsr-config/src/{ => app}/routes/index.tsx | 0 e2e/solid-start/basic-tsr-config/src/{ => app}/ssr.tsx | 2 +- 10 files changed, 4 insertions(+), 4 deletions(-) rename e2e/react-start/basic-tsr-config/src/{ => app}/routeTree.gen.ts (100%) rename e2e/react-start/basic-tsr-config/src/{ => app}/router.tsx (100%) rename e2e/react-start/basic-tsr-config/src/{ => app}/routes/__root.tsx (100%) rename e2e/react-start/basic-tsr-config/src/{ => app}/routes/index.tsx (100%) rename e2e/solid-start/basic-tsr-config/src/{ => app}/client.tsx (83%) rename e2e/solid-start/basic-tsr-config/src/{ => app}/routeTree.gen.ts (96%) rename e2e/solid-start/basic-tsr-config/src/{ => app}/router.tsx (87%) rename e2e/solid-start/basic-tsr-config/src/{ => app}/routes/__root.tsx (100%) rename e2e/solid-start/basic-tsr-config/src/{ => app}/routes/index.tsx (100%) rename e2e/solid-start/basic-tsr-config/src/{ => app}/ssr.tsx (87%) diff --git a/e2e/react-start/basic-tsr-config/src/routeTree.gen.ts b/e2e/react-start/basic-tsr-config/src/app/routeTree.gen.ts similarity index 100% rename from e2e/react-start/basic-tsr-config/src/routeTree.gen.ts rename to e2e/react-start/basic-tsr-config/src/app/routeTree.gen.ts diff --git a/e2e/react-start/basic-tsr-config/src/router.tsx b/e2e/react-start/basic-tsr-config/src/app/router.tsx similarity index 100% rename from e2e/react-start/basic-tsr-config/src/router.tsx rename to e2e/react-start/basic-tsr-config/src/app/router.tsx diff --git a/e2e/react-start/basic-tsr-config/src/routes/__root.tsx b/e2e/react-start/basic-tsr-config/src/app/routes/__root.tsx similarity index 100% rename from e2e/react-start/basic-tsr-config/src/routes/__root.tsx rename to e2e/react-start/basic-tsr-config/src/app/routes/__root.tsx diff --git a/e2e/react-start/basic-tsr-config/src/routes/index.tsx b/e2e/react-start/basic-tsr-config/src/app/routes/index.tsx similarity index 100% rename from e2e/react-start/basic-tsr-config/src/routes/index.tsx rename to e2e/react-start/basic-tsr-config/src/app/routes/index.tsx diff --git a/e2e/solid-start/basic-tsr-config/src/client.tsx b/e2e/solid-start/basic-tsr-config/src/app/client.tsx similarity index 83% rename from e2e/solid-start/basic-tsr-config/src/client.tsx rename to e2e/solid-start/basic-tsr-config/src/app/client.tsx index 04f043feee..ba0f02fac0 100644 --- a/e2e/solid-start/basic-tsr-config/src/client.tsx +++ b/e2e/solid-start/basic-tsr-config/src/app/client.tsx @@ -1,7 +1,7 @@ /// import { hydrate } from 'solid-js/web' import { StartClient } from '@tanstack/solid-start' -import { createRouter } from './app/router' +import { createRouter } from './router' const router = createRouter() diff --git a/e2e/solid-start/basic-tsr-config/src/routeTree.gen.ts b/e2e/solid-start/basic-tsr-config/src/app/routeTree.gen.ts similarity index 96% rename from e2e/solid-start/basic-tsr-config/src/routeTree.gen.ts rename to e2e/solid-start/basic-tsr-config/src/app/routeTree.gen.ts index 7214e0cd01..c260510053 100644 --- a/e2e/solid-start/basic-tsr-config/src/routeTree.gen.ts +++ b/e2e/solid-start/basic-tsr-config/src/app/routeTree.gen.ts @@ -11,7 +11,7 @@ // Import Routes import { Route as rootRoute } from './routes/__root' -import { Route as IndexImport } from './app/routes/index' +import { Route as IndexImport } from './routes/index' // Create/Update Routes diff --git a/e2e/solid-start/basic-tsr-config/src/router.tsx b/e2e/solid-start/basic-tsr-config/src/app/router.tsx similarity index 87% rename from e2e/solid-start/basic-tsr-config/src/router.tsx rename to e2e/solid-start/basic-tsr-config/src/app/router.tsx index 768813ab82..e230377cb1 100644 --- a/e2e/solid-start/basic-tsr-config/src/router.tsx +++ b/e2e/solid-start/basic-tsr-config/src/app/router.tsx @@ -1,5 +1,5 @@ import { createRouter as createTanStackRouter } from '@tanstack/solid-router' -import { routeTree } from './app/routeTree.gen' +import { routeTree } from './routeTree.gen' export function createRouter() { const router = createTanStackRouter({ diff --git a/e2e/solid-start/basic-tsr-config/src/routes/__root.tsx b/e2e/solid-start/basic-tsr-config/src/app/routes/__root.tsx similarity index 100% rename from e2e/solid-start/basic-tsr-config/src/routes/__root.tsx rename to e2e/solid-start/basic-tsr-config/src/app/routes/__root.tsx diff --git a/e2e/solid-start/basic-tsr-config/src/routes/index.tsx b/e2e/solid-start/basic-tsr-config/src/app/routes/index.tsx similarity index 100% rename from e2e/solid-start/basic-tsr-config/src/routes/index.tsx rename to e2e/solid-start/basic-tsr-config/src/app/routes/index.tsx diff --git a/e2e/solid-start/basic-tsr-config/src/ssr.tsx b/e2e/solid-start/basic-tsr-config/src/app/ssr.tsx similarity index 87% rename from e2e/solid-start/basic-tsr-config/src/ssr.tsx rename to e2e/solid-start/basic-tsr-config/src/app/ssr.tsx index db95139de1..ebd14c8120 100644 --- a/e2e/solid-start/basic-tsr-config/src/ssr.tsx +++ b/e2e/solid-start/basic-tsr-config/src/app/ssr.tsx @@ -5,7 +5,7 @@ import { } from '@tanstack/solid-start/server' import { getRouterManifest } from '@tanstack/solid-start/router-manifest' -import { createRouter } from './app/router' +import { createRouter } from './router' export default createStartHandler({ createRouter, From d34c97dda378cf2091bb32fc34954a9f13a1dce8 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Mon, 10 Mar 2025 19:38:18 +0100 Subject: [PATCH 037/155] change back imports from "src/" to "~/" --- examples/react/start-bare/src/routes/index.tsx | 2 +- examples/react/start-basic-auth/src/components/Login.tsx | 2 +- examples/react/start-basic-auth/src/routes/__root.tsx | 8 ++++---- examples/react/start-basic-auth/src/routes/_authed.tsx | 6 +++--- .../start-basic-auth/src/routes/_authed/posts.$postId.tsx | 4 ++-- .../start-basic-auth/src/routes/_authed/posts.route.tsx | 2 +- examples/react/start-basic-auth/src/routes/login.tsx | 2 +- examples/react/start-basic-auth/src/routes/logout.tsx | 2 +- examples/react/start-basic-auth/src/routes/signup.tsx | 8 ++++---- examples/react/start-basic-rsc/src/routes/__root.tsx | 6 +++--- .../react/start-basic-rsc/src/routes/posts.$postId.tsx | 2 +- examples/react/start-basic-rsc/src/routes/posts.tsx | 2 +- examples/react/start-basic-static/src/routes/__root.tsx | 6 +++--- .../react/start-basic-static/src/routes/posts.$postId.tsx | 2 +- .../react/start-basic-static/src/routes/users.$userId.tsx | 4 ++-- examples/react/start-clerk-basic/src/routes/__root.tsx | 4 ++-- .../src/routes/_authed/posts.$postId.tsx | 4 ++-- .../react/start-clerk-basic/src/routes/_authed/posts.tsx | 2 +- .../start-clerk-basic/src/routes/_authed/profile.$.tsx | 2 +- examples/react/start-large/src/routes/linkProps.tsx | 2 +- .../react/start-material-ui/src/components/Counter.tsx | 2 +- examples/react/start-material-ui/src/routes/__root.tsx | 4 ++-- examples/react/start-material-ui/src/routes/index.tsx | 2 +- .../src/routes/_authed/posts.$postId.tsx | 4 ++-- examples/solid/start-bare/src/routes/index.tsx | 2 +- 25 files changed, 43 insertions(+), 43 deletions(-) diff --git a/examples/react/start-bare/src/routes/index.tsx b/examples/react/start-bare/src/routes/index.tsx index 934654e3b8..e9de615dc9 100644 --- a/examples/react/start-bare/src/routes/index.tsx +++ b/examples/react/start-bare/src/routes/index.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/react-router' -import Counter from 'src/components/Counter' +import Counter from '~/components/Counter' export const Route = createFileRoute('/')({ component: RouteComponent, }) diff --git a/examples/react/start-basic-auth/src/components/Login.tsx b/examples/react/start-basic-auth/src/components/Login.tsx index 9ba6b8f019..b6b6da0c37 100644 --- a/examples/react/start-basic-auth/src/components/Login.tsx +++ b/examples/react/start-basic-auth/src/components/Login.tsx @@ -3,7 +3,7 @@ import { useServerFn } from '@tanstack/react-start' import { useMutation } from '../hooks/useMutation' import { loginFn } from '../routes/_authed' import { Auth } from './Auth' -import { signupFn } from 'src/routes/signup' +import { signupFn } from '~/routes/signup' export function Login() { const router = useRouter() diff --git a/examples/react/start-basic-auth/src/routes/__root.tsx b/examples/react/start-basic-auth/src/routes/__root.tsx index e286ac3499..187cb0dc24 100644 --- a/examples/react/start-basic-auth/src/routes/__root.tsx +++ b/examples/react/start-basic-auth/src/routes/__root.tsx @@ -8,11 +8,11 @@ import { import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' import { createServerFn } from '@tanstack/react-start' import * as React from 'react' -import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary.js' -import { NotFound } from 'src/components/NotFound.js' +import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary.js' +import { NotFound } from '~/components/NotFound.js' import appCss from '~/styles/app.css?url' -import { seo } from 'src/utils/seo.js' -import { useAppSession } from 'src/utils/session.js' +import { seo } from '~/utils/seo.js' +import { useAppSession } from '~/utils/session.js' const fetchUser = createServerFn({ method: 'GET' }).handler(async () => { // We need to auth on the server so we have access to secure cookies diff --git a/examples/react/start-basic-auth/src/routes/_authed.tsx b/examples/react/start-basic-auth/src/routes/_authed.tsx index 183520c267..0b1ae37317 100644 --- a/examples/react/start-basic-auth/src/routes/_authed.tsx +++ b/examples/react/start-basic-auth/src/routes/_authed.tsx @@ -1,8 +1,8 @@ import { createFileRoute } from '@tanstack/react-router' import { createServerFn } from '@tanstack/react-start' -import { hashPassword, prismaClient } from 'src/utils/prisma' -import { Login } from 'src/components/Login' -import { useAppSession } from 'src/utils/session' +import { hashPassword, prismaClient } from '~/utils/prisma' +import { Login } from '~/components/Login' +import { useAppSession } from '~/utils/session' export const loginFn = createServerFn() .validator((d) => d as { email: string; password: string }) diff --git a/examples/react/start-basic-auth/src/routes/_authed/posts.$postId.tsx b/examples/react/start-basic-auth/src/routes/_authed/posts.$postId.tsx index 763ac98f14..039271bb89 100644 --- a/examples/react/start-basic-auth/src/routes/_authed/posts.$postId.tsx +++ b/examples/react/start-basic-auth/src/routes/_authed/posts.$postId.tsx @@ -1,7 +1,7 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from 'src/components/NotFound.js' -import { fetchPost } from 'src/utils/posts.js' +import { NotFound } from '~/components/NotFound.js' +import { fetchPost } from '~/utils/posts.js' export const Route = createFileRoute('/_authed/posts/$postId')({ loader: ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/examples/react/start-basic-auth/src/routes/_authed/posts.route.tsx b/examples/react/start-basic-auth/src/routes/_authed/posts.route.tsx index a3144ce55a..86c8ef4138 100644 --- a/examples/react/start-basic-auth/src/routes/_authed/posts.route.tsx +++ b/examples/react/start-basic-auth/src/routes/_authed/posts.route.tsx @@ -1,5 +1,5 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from 'src/utils/posts.js' +import { fetchPosts } from '~/utils/posts.js' export const Route = createFileRoute('/_authed/posts')({ loader: () => fetchPosts(), diff --git a/examples/react/start-basic-auth/src/routes/login.tsx b/examples/react/start-basic-auth/src/routes/login.tsx index 4d06eaf91a..03ced20832 100644 --- a/examples/react/start-basic-auth/src/routes/login.tsx +++ b/examples/react/start-basic-auth/src/routes/login.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/react-router' -import { Login } from 'src/components/Login' +import { Login } from '~/components/Login' export const Route = createFileRoute('/login')({ component: LoginComp, diff --git a/examples/react/start-basic-auth/src/routes/logout.tsx b/examples/react/start-basic-auth/src/routes/logout.tsx index 5bed47b3ed..d072c25008 100644 --- a/examples/react/start-basic-auth/src/routes/logout.tsx +++ b/examples/react/start-basic-auth/src/routes/logout.tsx @@ -1,6 +1,6 @@ import { createFileRoute, redirect } from '@tanstack/react-router' import { createServerFn } from '@tanstack/react-start' -import { useAppSession } from 'src/utils/session' +import { useAppSession } from '~/utils/session' const logoutFn = createServerFn().handler(async () => { const session = await useAppSession() diff --git a/examples/react/start-basic-auth/src/routes/signup.tsx b/examples/react/start-basic-auth/src/routes/signup.tsx index d22930060b..8895af0579 100644 --- a/examples/react/start-basic-auth/src/routes/signup.tsx +++ b/examples/react/start-basic-auth/src/routes/signup.tsx @@ -1,9 +1,9 @@ import { createFileRoute, redirect } from '@tanstack/react-router' import { createServerFn, useServerFn } from '@tanstack/react-start' -import { hashPassword, prismaClient } from 'src/utils/prisma' -import { useMutation } from 'src/hooks/useMutation' -import { Auth } from 'src/components/Auth' -import { useAppSession } from 'src/utils/session' +import { hashPassword, prismaClient } from '~/utils/prisma' +import { useMutation } from '~/hooks/useMutation' +import { Auth } from '~/components/Auth' +import { useAppSession } from '~/utils/session' export const signupFn = createServerFn() .validator( diff --git a/examples/react/start-basic-rsc/src/routes/__root.tsx b/examples/react/start-basic-rsc/src/routes/__root.tsx index 137dea301c..9d96f79ab3 100644 --- a/examples/react/start-basic-rsc/src/routes/__root.tsx +++ b/examples/react/start-basic-rsc/src/routes/__root.tsx @@ -7,10 +7,10 @@ import { } from '@tanstack/react-router' import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' import * as React from 'react' -import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' -import { NotFound } from 'src/components/NotFound' +import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' +import { NotFound } from '~/components/NotFound' import appCss from '~/styles/app.css?url' -import { seo } from 'src/utils/seo' +import { seo } from '~/utils/seo' export const Route = createRootRoute({ head: () => ({ diff --git a/examples/react/start-basic-rsc/src/routes/posts.$postId.tsx b/examples/react/start-basic-rsc/src/routes/posts.$postId.tsx index 63a622a8e2..5404a690a0 100644 --- a/examples/react/start-basic-rsc/src/routes/posts.$postId.tsx +++ b/examples/react/start-basic-rsc/src/routes/posts.$postId.tsx @@ -2,7 +2,7 @@ import { ErrorComponent, Link, createFileRoute } from '@tanstack/react-router' import { createServerFn } from '@tanstack/react-start' import { fetchPost } from '../utils/posts' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from 'src/components/NotFound' +import { NotFound } from '~/components/NotFound' const renderPost = createServerFn({ method: 'GET' }) .validator((postId: string) => postId) diff --git a/examples/react/start-basic-rsc/src/routes/posts.tsx b/examples/react/start-basic-rsc/src/routes/posts.tsx index 5f544c568d..a3ef2a2e20 100644 --- a/examples/react/start-basic-rsc/src/routes/posts.tsx +++ b/examples/react/start-basic-rsc/src/routes/posts.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/react-router' import { createServerFn, renderRsc } from '@tanstack/react-start' -import { renderPosts } from 'src/utils/renderPosts' +import { renderPosts } from '~/utils/renderPosts' export const serverRenderPosts = createServerFn({ method: 'GET' }).handler( renderPosts, diff --git a/examples/react/start-basic-static/src/routes/__root.tsx b/examples/react/start-basic-static/src/routes/__root.tsx index 170fcca832..70140f2306 100644 --- a/examples/react/start-basic-static/src/routes/__root.tsx +++ b/examples/react/start-basic-static/src/routes/__root.tsx @@ -7,10 +7,10 @@ import { } from '@tanstack/react-router' import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' import * as React from 'react' -import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' -import { NotFound } from 'src/components/NotFound' +import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' +import { NotFound } from '~/components/NotFound' import appCss from '~/styles/app.css?url' -import { seo } from 'src/utils/seo' +import { seo } from '~/utils/seo' export const Route = createRootRoute({ head: () => ({ diff --git a/examples/react/start-basic-static/src/routes/posts.$postId.tsx b/examples/react/start-basic-static/src/routes/posts.$postId.tsx index 6a1f72bb07..0d4d2de8eb 100644 --- a/examples/react/start-basic-static/src/routes/posts.$postId.tsx +++ b/examples/react/start-basic-static/src/routes/posts.$postId.tsx @@ -1,7 +1,7 @@ import { ErrorComponent, Link, createFileRoute } from '@tanstack/react-router' import { fetchPost } from '../utils/posts' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from 'src/components/NotFound' +import { NotFound } from '~/components/NotFound' export const Route = createFileRoute('/posts/$postId')({ loader: ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/examples/react/start-basic-static/src/routes/users.$userId.tsx b/examples/react/start-basic-static/src/routes/users.$userId.tsx index bbc21f1274..d166885e29 100644 --- a/examples/react/start-basic-static/src/routes/users.$userId.tsx +++ b/examples/react/start-basic-static/src/routes/users.$userId.tsx @@ -2,8 +2,8 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import axios from 'redaxios' import { createServerFn } from '@tanstack/react-start' import type { ErrorComponentProps } from '@tanstack/react-router' -import type { User } from 'src/utils/users' -import { NotFound } from 'src/components/NotFound' +import type { User } from '~/utils/users' +import { NotFound } from '~/components/NotFound' const fetchUser = createServerFn({ method: 'GET', type: 'static' }) .validator((d: string) => d) diff --git a/examples/react/start-clerk-basic/src/routes/__root.tsx b/examples/react/start-clerk-basic/src/routes/__root.tsx index 358f9d8be3..489e80715f 100644 --- a/examples/react/start-clerk-basic/src/routes/__root.tsx +++ b/examples/react/start-clerk-basic/src/routes/__root.tsx @@ -18,8 +18,8 @@ import { createServerFn } from '@tanstack/react-start' import * as React from 'react' import { getAuth } from '@clerk/tanstack-start/server' import { getWebRequest } from '@tanstack/react-start/server' -import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary.js' -import { NotFound } from 'src/components/NotFound.js' +import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary.js' +import { NotFound } from '~/components/NotFound.js' import appCss from '~/styles/app.css?url' const fetchClerkAuth = createServerFn({ method: 'GET' }).handler(async () => { diff --git a/examples/react/start-clerk-basic/src/routes/_authed/posts.$postId.tsx b/examples/react/start-clerk-basic/src/routes/_authed/posts.$postId.tsx index 763ac98f14..039271bb89 100644 --- a/examples/react/start-clerk-basic/src/routes/_authed/posts.$postId.tsx +++ b/examples/react/start-clerk-basic/src/routes/_authed/posts.$postId.tsx @@ -1,7 +1,7 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from 'src/components/NotFound.js' -import { fetchPost } from 'src/utils/posts.js' +import { NotFound } from '~/components/NotFound.js' +import { fetchPost } from '~/utils/posts.js' export const Route = createFileRoute('/_authed/posts/$postId')({ loader: ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/examples/react/start-clerk-basic/src/routes/_authed/posts.tsx b/examples/react/start-clerk-basic/src/routes/_authed/posts.tsx index a3144ce55a..86c8ef4138 100644 --- a/examples/react/start-clerk-basic/src/routes/_authed/posts.tsx +++ b/examples/react/start-clerk-basic/src/routes/_authed/posts.tsx @@ -1,5 +1,5 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from 'src/utils/posts.js' +import { fetchPosts } from '~/utils/posts.js' export const Route = createFileRoute('/_authed/posts')({ loader: () => fetchPosts(), diff --git a/examples/react/start-clerk-basic/src/routes/_authed/profile.$.tsx b/examples/react/start-clerk-basic/src/routes/_authed/profile.$.tsx index 4e0b434c2b..208a38e230 100644 --- a/examples/react/start-clerk-basic/src/routes/_authed/profile.$.tsx +++ b/examples/react/start-clerk-basic/src/routes/_authed/profile.$.tsx @@ -1,5 +1,5 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from 'src/utils/posts.js' +import { fetchPosts } from '~/utils/posts.js' export const Route = createFileRoute('/_authed/profile/$')({ loader: () => fetchPosts(), diff --git a/examples/react/start-large/src/routes/linkProps.tsx b/examples/react/start-large/src/routes/linkProps.tsx index cb81ec1ac7..4804161ccf 100644 --- a/examples/react/start-large/src/routes/linkProps.tsx +++ b/examples/react/start-large/src/routes/linkProps.tsx @@ -5,7 +5,7 @@ import { ListItems, MyLink, useCustomNavigate, -} from 'src/typePrimitives' +} from '~/typePrimitives' export const Route = createFileRoute('/linkProps')({ component: LinkPropsPage, diff --git a/examples/react/start-material-ui/src/components/Counter.tsx b/examples/react/start-material-ui/src/components/Counter.tsx index 363c5f11c4..205bbea855 100644 --- a/examples/react/start-material-ui/src/components/Counter.tsx +++ b/examples/react/start-material-ui/src/components/Counter.tsx @@ -1,6 +1,6 @@ import { Stack } from '@mui/material' import { useSearch } from '@tanstack/react-router' -import { CustomButtonLink } from 'src/components/CustomButtonLink' +import { CustomButtonLink } from '~/components/CustomButtonLink' export function Counter() { const { count = 0 } = useSearch({ from: '/' }) diff --git a/examples/react/start-material-ui/src/routes/__root.tsx b/examples/react/start-material-ui/src/routes/__root.tsx index e9a65ccfd5..6b0b217b63 100644 --- a/examples/react/start-material-ui/src/routes/__root.tsx +++ b/examples/react/start-material-ui/src/routes/__root.tsx @@ -10,8 +10,8 @@ import { Container, CssBaseline, ThemeProvider } from '@mui/material' import createCache from '@emotion/cache' import fontsourceVariableRobotoCss from '@fontsource-variable/roboto?url' import React from 'react' -import { theme } from 'src/setup/theme' -import { Header } from 'src/components/Header' +import { theme } from '~/setup/theme' +import { Header } from '~/components/Header' export const Route = createRootRoute({ head: () => ({ diff --git a/examples/react/start-material-ui/src/routes/index.tsx b/examples/react/start-material-ui/src/routes/index.tsx index 667a92881d..75f5d14de4 100644 --- a/examples/react/start-material-ui/src/routes/index.tsx +++ b/examples/react/start-material-ui/src/routes/index.tsx @@ -1,7 +1,7 @@ import { createFileRoute } from '@tanstack/react-router' import { Stack, Typography } from '@mui/material' import z from 'zod' -import { Counter } from 'src/components/Counter' +import { Counter } from '~/components/Counter' export const Route = createFileRoute('/')({ validateSearch: z.object({ diff --git a/examples/react/start-supabase-basic/src/routes/_authed/posts.$postId.tsx b/examples/react/start-supabase-basic/src/routes/_authed/posts.$postId.tsx index 059f35ff73..4dd11756a8 100644 --- a/examples/react/start-supabase-basic/src/routes/_authed/posts.$postId.tsx +++ b/examples/react/start-supabase-basic/src/routes/_authed/posts.$postId.tsx @@ -1,7 +1,7 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from 'src/components/NotFound' -import { fetchPost } from 'src/utils/posts' +import { NotFound } from '~/components/NotFound' +import { fetchPost } from '~/utils/posts' export const Route = createFileRoute('/_authed/posts/$postId')({ loader: ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/examples/solid/start-bare/src/routes/index.tsx b/examples/solid/start-bare/src/routes/index.tsx index 507865f60f..6a91bd1999 100644 --- a/examples/solid/start-bare/src/routes/index.tsx +++ b/examples/solid/start-bare/src/routes/index.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/solid-router' -import Counter from 'src/components/Counter' +import Counter from '~/components/Counter' export const Route = createFileRoute('/')({ component: RouteComponent, }) From 006bba29ee62c63d23a0c6676ccf1b8c062b26ba Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Mon, 10 Mar 2025 19:40:35 +0100 Subject: [PATCH 038/155] change "src/" back to "~/" --- e2e/react-start/basic-auth/src/components/Login.tsx | 2 +- e2e/react-start/basic-auth/src/routes/__root.tsx | 8 ++++---- e2e/react-start/basic-auth/src/routes/_authed.tsx | 6 +++--- .../basic-auth/src/routes/_authed/posts.$postId.tsx | 4 ++-- e2e/react-start/basic-auth/src/routes/_authed/posts.tsx | 2 +- e2e/react-start/basic-auth/src/routes/login.tsx | 2 +- e2e/react-start/basic-auth/src/routes/logout.tsx | 2 +- e2e/react-start/basic-auth/src/routes/signup.tsx | 8 ++++---- e2e/react-start/basic-react-query/src/routes/__root.tsx | 6 +++--- .../basic-react-query/src/routes/posts.$postId.tsx | 4 ++-- e2e/react-start/basic-react-query/src/routes/posts.tsx | 2 +- .../basic-react-query/src/routes/users.$userId.tsx | 4 ++-- e2e/react-start/basic-react-query/src/routes/users.tsx | 2 +- e2e/react-start/basic/src/routes/__root.tsx | 6 +++--- e2e/react-start/basic/src/routes/index.tsx | 2 +- e2e/react-start/basic/src/routes/posts.$postId.tsx | 4 ++-- e2e/react-start/basic/src/routes/posts.tsx | 2 +- e2e/react-start/basic/src/routes/users.$userId.tsx | 6 +++--- e2e/react-start/basic/src/routes/users.tsx | 4 ++-- e2e/react-start/clerk-basic/src/routes/__root.tsx | 4 ++-- .../clerk-basic/src/routes/_authed/posts.$postId.tsx | 4 ++-- e2e/react-start/clerk-basic/src/routes/_authed/posts.tsx | 2 +- .../clerk-basic/src/routes/_authed/profile.$.tsx | 2 +- .../scroll-restoration/src/routes/(tests)/with-loader.tsx | 2 +- e2e/react-start/scroll-restoration/src/routes/__root.tsx | 6 +++--- e2e/solid-start/scroll-restoration/src/routes/__root.tsx | 6 +++--- e2e/solid-start/server-functions/src/routes/__root.tsx | 4 ++-- e2e/solid-start/website/src/routes/__root.tsx | 4 ++-- e2e/solid-start/website/src/routes/_library.$project.tsx | 4 ++-- e2e/solid-start/website/src/routes/_library.tsx | 2 +- 30 files changed, 58 insertions(+), 58 deletions(-) diff --git a/e2e/react-start/basic-auth/src/components/Login.tsx b/e2e/react-start/basic-auth/src/components/Login.tsx index 9ba6b8f019..b6b6da0c37 100644 --- a/e2e/react-start/basic-auth/src/components/Login.tsx +++ b/e2e/react-start/basic-auth/src/components/Login.tsx @@ -3,7 +3,7 @@ import { useServerFn } from '@tanstack/react-start' import { useMutation } from '../hooks/useMutation' import { loginFn } from '../routes/_authed' import { Auth } from './Auth' -import { signupFn } from 'src/routes/signup' +import { signupFn } from '~/routes/signup' export function Login() { const router = useRouter() diff --git a/e2e/react-start/basic-auth/src/routes/__root.tsx b/e2e/react-start/basic-auth/src/routes/__root.tsx index 3eeb03a93d..a3c8d1e872 100644 --- a/e2e/react-start/basic-auth/src/routes/__root.tsx +++ b/e2e/react-start/basic-auth/src/routes/__root.tsx @@ -9,11 +9,11 @@ import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' import { createServerFn } from '@tanstack/react-start' import * as React from 'react' -import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary.js' -import { NotFound } from 'src/components/NotFound.js' +import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary.js' +import { NotFound } from '~/components/NotFound.js' import appCss from '~/styles/app.css?url' -import { seo } from 'src/utils/seo.js' -import { useAppSession } from 'src/utils/session.js' +import { seo } from '~/utils/seo.js' +import { useAppSession } from '~/utils/session.js' const fetchUser = createServerFn({ method: 'GET' }).handler(async () => { // We need to auth on the server so we have access to secure cookies diff --git a/e2e/react-start/basic-auth/src/routes/_authed.tsx b/e2e/react-start/basic-auth/src/routes/_authed.tsx index b238afe63f..c457cf5e57 100644 --- a/e2e/react-start/basic-auth/src/routes/_authed.tsx +++ b/e2e/react-start/basic-auth/src/routes/_authed.tsx @@ -1,9 +1,9 @@ import { createFileRoute } from '@tanstack/react-router' import { createServerFn } from '@tanstack/react-start' -import { hashPassword, prismaClient } from 'src/utils/prisma' -import { Login } from 'src/components/Login' -import { useAppSession } from 'src/utils/session' +import { hashPassword, prismaClient } from '~/utils/prisma' +import { Login } from '~/components/Login' +import { useAppSession } from '~/utils/session' export const loginFn = createServerFn({ method: 'POST', diff --git a/e2e/react-start/basic-auth/src/routes/_authed/posts.$postId.tsx b/e2e/react-start/basic-auth/src/routes/_authed/posts.$postId.tsx index 612394673b..27296b9658 100644 --- a/e2e/react-start/basic-auth/src/routes/_authed/posts.$postId.tsx +++ b/e2e/react-start/basic-auth/src/routes/_authed/posts.$postId.tsx @@ -1,8 +1,8 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from 'src/components/NotFound.js' -import { fetchPost } from 'src/utils/posts.js' +import { NotFound } from '~/components/NotFound.js' +import { fetchPost } from '~/utils/posts.js' export const Route = createFileRoute('/_authed/posts/$postId')({ loader: ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/e2e/react-start/basic-auth/src/routes/_authed/posts.tsx b/e2e/react-start/basic-auth/src/routes/_authed/posts.tsx index d769f02b68..c01f12c49a 100644 --- a/e2e/react-start/basic-auth/src/routes/_authed/posts.tsx +++ b/e2e/react-start/basic-auth/src/routes/_authed/posts.tsx @@ -1,6 +1,6 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from 'src/utils/posts.js' +import { fetchPosts } from '~/utils/posts.js' export const Route = createFileRoute('/_authed/posts')({ loader: () => fetchPosts(), diff --git a/e2e/react-start/basic-auth/src/routes/login.tsx b/e2e/react-start/basic-auth/src/routes/login.tsx index ef419a72f7..19dc34a439 100644 --- a/e2e/react-start/basic-auth/src/routes/login.tsx +++ b/e2e/react-start/basic-auth/src/routes/login.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/react-router' -import { Login } from 'src/components/Login' +import { Login } from '~/components/Login' export const Route = createFileRoute('/login')({ component: LoginComp, diff --git a/e2e/react-start/basic-auth/src/routes/logout.tsx b/e2e/react-start/basic-auth/src/routes/logout.tsx index 0060780d11..43a14fa39a 100644 --- a/e2e/react-start/basic-auth/src/routes/logout.tsx +++ b/e2e/react-start/basic-auth/src/routes/logout.tsx @@ -1,7 +1,7 @@ import { createFileRoute, redirect } from '@tanstack/react-router' import { createServerFn } from '@tanstack/react-start' -import { useAppSession } from 'src/utils/session' +import { useAppSession } from '~/utils/session' const logoutFn = createServerFn({ method: 'POST' }).handler(async () => { const session = await useAppSession() diff --git a/e2e/react-start/basic-auth/src/routes/signup.tsx b/e2e/react-start/basic-auth/src/routes/signup.tsx index 864ab0ab38..5edbb4993f 100644 --- a/e2e/react-start/basic-auth/src/routes/signup.tsx +++ b/e2e/react-start/basic-auth/src/routes/signup.tsx @@ -1,10 +1,10 @@ import { createFileRoute, redirect } from '@tanstack/react-router' import { createServerFn, useServerFn } from '@tanstack/react-start' -import { hashPassword, prismaClient } from 'src/utils/prisma' -import { useMutation } from 'src/hooks/useMutation' -import { Auth } from 'src/components/Auth' -import { useAppSession } from 'src/utils/session' +import { hashPassword, prismaClient } from '~/utils/prisma' +import { useMutation } from '~/hooks/useMutation' +import { Auth } from '~/components/Auth' +import { useAppSession } from '~/utils/session' export const signupFn = createServerFn({ method: 'POST', diff --git a/e2e/react-start/basic-react-query/src/routes/__root.tsx b/e2e/react-start/basic-react-query/src/routes/__root.tsx index ff8b829c6a..6bd9e76801 100644 --- a/e2e/react-start/basic-react-query/src/routes/__root.tsx +++ b/e2e/react-start/basic-react-query/src/routes/__root.tsx @@ -9,10 +9,10 @@ import { ReactQueryDevtools } from '@tanstack/react-query-devtools' import { TanStackRouterDevtoolsInProd } from '@tanstack/react-router-devtools' import * as React from 'react' import type { QueryClient } from '@tanstack/react-query' -import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' -import { NotFound } from 'src/components/NotFound' +import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' +import { NotFound } from '~/components/NotFound' import appCss from '~/styles/app.css?url' -import { seo } from 'src/utils/seo' +import { seo } from '~/utils/seo' export const Route = createRootRouteWithContext<{ queryClient: QueryClient diff --git a/e2e/react-start/basic-react-query/src/routes/posts.$postId.tsx b/e2e/react-start/basic-react-query/src/routes/posts.$postId.tsx index 688e23a674..16a6bf29aa 100644 --- a/e2e/react-start/basic-react-query/src/routes/posts.$postId.tsx +++ b/e2e/react-start/basic-react-query/src/routes/posts.$postId.tsx @@ -2,8 +2,8 @@ import { ErrorComponent, Link, createFileRoute } from '@tanstack/react-router' import { useSuspenseQuery } from '@tanstack/react-query' import type { ErrorComponentProps } from '@tanstack/react-router' -import { postQueryOptions } from 'src/utils/posts' -import { NotFound } from 'src/components/NotFound' +import { postQueryOptions } from '~/utils/posts' +import { NotFound } from '~/components/NotFound' export const Route = createFileRoute('/posts/$postId')({ loader: async ({ params: { postId }, context }) => { diff --git a/e2e/react-start/basic-react-query/src/routes/posts.tsx b/e2e/react-start/basic-react-query/src/routes/posts.tsx index 83919aafc9..3f678ed1f1 100644 --- a/e2e/react-start/basic-react-query/src/routes/posts.tsx +++ b/e2e/react-start/basic-react-query/src/routes/posts.tsx @@ -1,7 +1,7 @@ import { useSuspenseQuery } from '@tanstack/react-query' import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { postsQueryOptions } from 'src/utils/posts' +import { postsQueryOptions } from '~/utils/posts' export const Route = createFileRoute('/posts')({ loader: async ({ context }) => { diff --git a/e2e/react-start/basic-react-query/src/routes/users.$userId.tsx b/e2e/react-start/basic-react-query/src/routes/users.$userId.tsx index 8db366a551..656fb6dbb8 100644 --- a/e2e/react-start/basic-react-query/src/routes/users.$userId.tsx +++ b/e2e/react-start/basic-react-query/src/routes/users.$userId.tsx @@ -2,8 +2,8 @@ import { useSuspenseQuery } from '@tanstack/react-query' import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from 'src/components/NotFound' -import { userQueryOptions } from 'src/utils/users' +import { NotFound } from '~/components/NotFound' +import { userQueryOptions } from '~/utils/users' export const Route = createFileRoute('/users/$userId')({ loader: async ({ context, params: { userId } }) => { diff --git a/e2e/react-start/basic-react-query/src/routes/users.tsx b/e2e/react-start/basic-react-query/src/routes/users.tsx index c0ad4349aa..1b56bb9890 100644 --- a/e2e/react-start/basic-react-query/src/routes/users.tsx +++ b/e2e/react-start/basic-react-query/src/routes/users.tsx @@ -1,7 +1,7 @@ import { useSuspenseQuery } from '@tanstack/react-query' import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { usersQueryOptions } from 'src/utils/users' +import { usersQueryOptions } from '~/utils/users' export const Route = createFileRoute('/users')({ loader: async ({ context }) => { diff --git a/e2e/react-start/basic/src/routes/__root.tsx b/e2e/react-start/basic/src/routes/__root.tsx index 9c62771a63..1b64b1c468 100644 --- a/e2e/react-start/basic/src/routes/__root.tsx +++ b/e2e/react-start/basic/src/routes/__root.tsx @@ -7,10 +7,10 @@ import { createRootRoute, } from '@tanstack/react-router' -import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' -import { NotFound } from 'src/components/NotFound' +import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' +import { NotFound } from '~/components/NotFound' import appCss from '~/styles/app.css?url' -import { seo } from 'src/utils/seo' +import { seo } from '~/utils/seo' export const Route = createRootRoute({ head: () => ({ diff --git a/e2e/react-start/basic/src/routes/index.tsx b/e2e/react-start/basic/src/routes/index.tsx index 55e4693651..37169a78b4 100644 --- a/e2e/react-start/basic/src/routes/index.tsx +++ b/e2e/react-start/basic/src/routes/index.tsx @@ -1,5 +1,5 @@ import { createFileRoute } from '@tanstack/react-router' -import { CustomMessage } from 'src/components/CustomMessage' +import { CustomMessage } from '~/components/CustomMessage' export const Route = createFileRoute('/')({ component: Home, diff --git a/e2e/react-start/basic/src/routes/posts.$postId.tsx b/e2e/react-start/basic/src/routes/posts.$postId.tsx index 368c1d3c1f..005228a0fe 100644 --- a/e2e/react-start/basic/src/routes/posts.$postId.tsx +++ b/e2e/react-start/basic/src/routes/posts.$postId.tsx @@ -1,8 +1,8 @@ import { ErrorComponent, Link, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { fetchPost } from 'src/utils/posts' -import { NotFound } from 'src/components/NotFound' +import { fetchPost } from '~/utils/posts' +import { NotFound } from '~/components/NotFound' export const Route = createFileRoute('/posts/$postId')({ loader: async ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/e2e/react-start/basic/src/routes/posts.tsx b/e2e/react-start/basic/src/routes/posts.tsx index 60e9aa37c3..0f69c18341 100644 --- a/e2e/react-start/basic/src/routes/posts.tsx +++ b/e2e/react-start/basic/src/routes/posts.tsx @@ -1,6 +1,6 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from 'src/utils/posts' +import { fetchPosts } from '~/utils/posts' export const Route = createFileRoute('/posts')({ head: () => ({ diff --git a/e2e/react-start/basic/src/routes/users.$userId.tsx b/e2e/react-start/basic/src/routes/users.$userId.tsx index 56f0a472da..1e2921411a 100644 --- a/e2e/react-start/basic/src/routes/users.$userId.tsx +++ b/e2e/react-start/basic/src/routes/users.$userId.tsx @@ -2,9 +2,9 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import axios from 'redaxios' import type { ErrorComponentProps } from '@tanstack/react-router' -import type { User } from 'src/utils/users' -import { DEPLOY_URL } from 'src/utils/users' -import { NotFound } from 'src/components/NotFound' +import type { User } from '~/utils/users' +import { DEPLOY_URL } from '~/utils/users' +import { NotFound } from '~/components/NotFound' export const Route = createFileRoute('/users/$userId')({ loader: async ({ params: { userId } }) => { diff --git a/e2e/react-start/basic/src/routes/users.tsx b/e2e/react-start/basic/src/routes/users.tsx index d4bdb8f53c..45e070657e 100644 --- a/e2e/react-start/basic/src/routes/users.tsx +++ b/e2e/react-start/basic/src/routes/users.tsx @@ -1,8 +1,8 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' import axios from 'redaxios' -import type { User } from 'src/utils/users' -import { DEPLOY_URL } from 'src/utils/users' +import type { User } from '~/utils/users' +import { DEPLOY_URL } from '~/utils/users' export const Route = createFileRoute('/users')({ loader: async () => { diff --git a/e2e/react-start/clerk-basic/src/routes/__root.tsx b/e2e/react-start/clerk-basic/src/routes/__root.tsx index 0ad96f9375..1773a381d0 100644 --- a/e2e/react-start/clerk-basic/src/routes/__root.tsx +++ b/e2e/react-start/clerk-basic/src/routes/__root.tsx @@ -18,8 +18,8 @@ import { createServerFn } from '@tanstack/react-start' import * as React from 'react' import { getAuth } from '@clerk/tanstack-start/server' import { getWebRequest } from '@tanstack/react-start/server' -import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary.js' -import { NotFound } from 'src/components/NotFound.js' +import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary.js' +import { NotFound } from '~/components/NotFound.js' import appCss from '~/styles/app.css?url' const fetchClerkAuth = createServerFn({ method: 'GET' }).handler(async () => { diff --git a/e2e/react-start/clerk-basic/src/routes/_authed/posts.$postId.tsx b/e2e/react-start/clerk-basic/src/routes/_authed/posts.$postId.tsx index 612394673b..27296b9658 100644 --- a/e2e/react-start/clerk-basic/src/routes/_authed/posts.$postId.tsx +++ b/e2e/react-start/clerk-basic/src/routes/_authed/posts.$postId.tsx @@ -1,8 +1,8 @@ import { ErrorComponent, createFileRoute } from '@tanstack/react-router' import type { ErrorComponentProps } from '@tanstack/react-router' -import { NotFound } from 'src/components/NotFound.js' -import { fetchPost } from 'src/utils/posts.js' +import { NotFound } from '~/components/NotFound.js' +import { fetchPost } from '~/utils/posts.js' export const Route = createFileRoute('/_authed/posts/$postId')({ loader: ({ params: { postId } }) => fetchPost({ data: postId }), diff --git a/e2e/react-start/clerk-basic/src/routes/_authed/posts.tsx b/e2e/react-start/clerk-basic/src/routes/_authed/posts.tsx index d769f02b68..c01f12c49a 100644 --- a/e2e/react-start/clerk-basic/src/routes/_authed/posts.tsx +++ b/e2e/react-start/clerk-basic/src/routes/_authed/posts.tsx @@ -1,6 +1,6 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from 'src/utils/posts.js' +import { fetchPosts } from '~/utils/posts.js' export const Route = createFileRoute('/_authed/posts')({ loader: () => fetchPosts(), diff --git a/e2e/react-start/clerk-basic/src/routes/_authed/profile.$.tsx b/e2e/react-start/clerk-basic/src/routes/_authed/profile.$.tsx index 892d3a7fd9..1e5a8b1429 100644 --- a/e2e/react-start/clerk-basic/src/routes/_authed/profile.$.tsx +++ b/e2e/react-start/clerk-basic/src/routes/_authed/profile.$.tsx @@ -1,6 +1,6 @@ import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from 'src/utils/posts.js' +import { fetchPosts } from '~/utils/posts.js' export const Route = createFileRoute('/_authed/profile/$')({ loader: () => fetchPosts(), diff --git a/e2e/react-start/scroll-restoration/src/routes/(tests)/with-loader.tsx b/e2e/react-start/scroll-restoration/src/routes/(tests)/with-loader.tsx index 6a8a0bc545..dfd4c7bf13 100644 --- a/e2e/react-start/scroll-restoration/src/routes/(tests)/with-loader.tsx +++ b/e2e/react-start/scroll-restoration/src/routes/(tests)/with-loader.tsx @@ -1,6 +1,6 @@ import { createFileRoute } from '@tanstack/react-router' import { ScrollBlock } from '../-components/scroll-block' -import { sleep } from 'src/utils/posts' +import { sleep } from '~/utils/posts' export const Route = createFileRoute('/(tests)/with-loader')({ loader: async () => { diff --git a/e2e/react-start/scroll-restoration/src/routes/__root.tsx b/e2e/react-start/scroll-restoration/src/routes/__root.tsx index 1628a4ab07..07037679f0 100644 --- a/e2e/react-start/scroll-restoration/src/routes/__root.tsx +++ b/e2e/react-start/scroll-restoration/src/routes/__root.tsx @@ -8,10 +8,10 @@ import { Scripts, } from '@tanstack/react-router' import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' -import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' -import { NotFound } from 'src/components/NotFound' +import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' +import { NotFound } from '~/components/NotFound' import appCss from '~/styles/app.css?url' -import { seo } from 'src/utils/seo' +import { seo } from '~/utils/seo' export const Route = createRootRoute({ head: () => ({ diff --git a/e2e/solid-start/scroll-restoration/src/routes/__root.tsx b/e2e/solid-start/scroll-restoration/src/routes/__root.tsx index 72e2c59c9e..5907fa6ecd 100644 --- a/e2e/solid-start/scroll-restoration/src/routes/__root.tsx +++ b/e2e/solid-start/scroll-restoration/src/routes/__root.tsx @@ -7,10 +7,10 @@ import { HeadContent, Scripts, } from '@tanstack/solid-router' -import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' -import { NotFound } from 'src/components/NotFound' +import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' +import { NotFound } from '~/components/NotFound' import appCss from '~/styles/app.css?url' -import { seo } from 'src/utils/seo' +import { seo } from '~/utils/seo' import { Dynamic } from 'solid-js/web' import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools' diff --git a/e2e/solid-start/server-functions/src/routes/__root.tsx b/e2e/solid-start/server-functions/src/routes/__root.tsx index 6c801f97ad..52d64bf7a7 100644 --- a/e2e/solid-start/server-functions/src/routes/__root.tsx +++ b/e2e/solid-start/server-functions/src/routes/__root.tsx @@ -1,7 +1,7 @@ import { Outlet, createRootRoute } from '@tanstack/solid-router' -import { DefaultCatchBoundary } from 'src/components/DefaultCatchBoundary' -import { NotFound } from 'src/components/NotFound' +import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' +import { NotFound } from '~/components/NotFound' import appCss from '~/styles/app.css?url' import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools' diff --git a/e2e/solid-start/website/src/routes/__root.tsx b/e2e/solid-start/website/src/routes/__root.tsx index b232d1f84a..514d187924 100644 --- a/e2e/solid-start/website/src/routes/__root.tsx +++ b/e2e/solid-start/website/src/routes/__root.tsx @@ -1,8 +1,8 @@ import { Outlet, createRootRoute } from '@tanstack/solid-router' -import { NotFound } from 'src/components/NotFound' +import { NotFound } from '~/components/NotFound' import appCss from '~/styles/app.css?url' import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools' -import { seo } from 'src/utils/seo' +import { seo } from '~/utils/seo' export const Route = createRootRoute({ head: () => ({ diff --git a/e2e/solid-start/website/src/routes/_library.$project.tsx b/e2e/solid-start/website/src/routes/_library.$project.tsx index 97e161065e..6fdcb8e530 100644 --- a/e2e/solid-start/website/src/routes/_library.$project.tsx +++ b/e2e/solid-start/website/src/routes/_library.$project.tsx @@ -1,6 +1,6 @@ import { Outlet, createFileRoute } from '@tanstack/solid-router' -import { getProject } from 'src/server/projects' -import { seo } from 'src/utils/seo' +import { getProject } from '~/server/projects' +import { seo } from '~/utils/seo' export const Route = createFileRoute('/_library/$project')({ loader: ({ params: { project } }) => getProject({ data: project }), diff --git a/e2e/solid-start/website/src/routes/_library.tsx b/e2e/solid-start/website/src/routes/_library.tsx index 3b1a7a406e..c25ae5cfe1 100644 --- a/e2e/solid-start/website/src/routes/_library.tsx +++ b/e2e/solid-start/website/src/routes/_library.tsx @@ -4,7 +4,7 @@ import { createFileRoute, useLocation, } from '@tanstack/solid-router' -import { getProjects } from 'src/server/projects' +import { getProjects } from '~/server/projects' export const Route = createFileRoute('/_library')({ loader: async () => { From 8176e758dd43bdd7aa5aaa7937ca33b86978411e Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Mon, 10 Mar 2025 20:03:13 +0100 Subject: [PATCH 039/155] sync main --- docs/start/framework/react/path-aliases.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/start/framework/react/path-aliases.md b/docs/start/framework/react/path-aliases.md index ef65f4771b..d0c0b24577 100644 --- a/docs/start/framework/react/path-aliases.md +++ b/docs/start/framework/react/path-aliases.md @@ -12,7 +12,7 @@ By default, TanStack Start does not include path aliases. However, you can easil "compilerOptions": { "baseUrl": ".", "paths": { - "~/*": ["src/*"] + "~/*": ["./src/*"] } } } From 916e1a51be203bcd60b1a14bc2a4239ef6be2b00 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Mon, 10 Mar 2025 15:46:39 -0600 Subject: [PATCH 040/155] fix: devinxi checkpoint --- .../react/start-basic/src/routeTree.gen.ts | 21 -------- .../react/start-basic/src/routes/__root.tsx | 2 +- .../react/start-basic/src/routes/_layout.tsx | 16 ------- .../start-basic/src/routes/posts.route.tsx | 38 --------------- .../start-basic/src/routes/users.route.tsx | 48 ------------------- packages/react-start-server/tsconfig.json | 7 ++- packages/start-server-core/package.json | 3 +- .../src/createStartHandler.ts | 9 ++-- packages/start-server-core/src/index.tsx | 2 +- .../src/server-functions-handler.ts | 13 +---- pnpm-lock.yaml | 3 ++ 11 files changed, 18 insertions(+), 144 deletions(-) delete mode 100644 examples/react/start-basic/src/routes/_layout.tsx delete mode 100644 examples/react/start-basic/src/routes/posts.route.tsx delete mode 100644 examples/react/start-basic/src/routes/users.route.tsx rename packages/{react-start-server => start-server-core}/src/createStartHandler.ts (93%) rename packages/{react-start-server => start-server-core}/src/server-functions-handler.ts (98%) diff --git a/examples/react/start-basic/src/routeTree.gen.ts b/examples/react/start-basic/src/routeTree.gen.ts index 12ee484c06..762ce1516f 100644 --- a/examples/react/start-basic/src/routeTree.gen.ts +++ b/examples/react/start-basic/src/routeTree.gen.ts @@ -16,7 +16,6 @@ import { Route as RedirectImport } from './routes/redirect' import { Route as PostsImport } from './routes/posts' import { Route as DeferredImport } from './routes/deferred' import { Route as PathlessLayoutImport } from './routes/_pathlessLayout' -import { Route as LayoutImport } from './routes/_layout' import { Route as IndexImport } from './routes/index' import { Route as UsersIndexImport } from './routes/users.index' import { Route as PostsIndexImport } from './routes/posts.index' @@ -58,11 +57,6 @@ const PathlessLayoutRoute = PathlessLayoutImport.update({ getParentRoute: () => rootRoute, } as any) -const LayoutRoute = LayoutImport.update({ - id: '/_layout', - getParentRoute: () => rootRoute, -} as any) - const IndexRoute = IndexImport.update({ id: '/', path: '/', @@ -131,13 +125,6 @@ declare module '@tanstack/react-router' { preLoaderRoute: typeof IndexImport parentRoute: typeof rootRoute } - '/_layout': { - id: '/_layout' - path: '' - fullPath: '' - preLoaderRoute: typeof LayoutImport - parentRoute: typeof rootRoute - } '/_pathlessLayout': { id: '/_pathlessLayout' path: '' @@ -321,7 +308,6 @@ export interface FileRoutesByTo { export interface FileRoutesById { __root__: typeof rootRoute '/': typeof IndexRoute - '/_layout': typeof LayoutRoute '/_pathlessLayout': typeof PathlessLayoutRouteWithChildren '/deferred': typeof DeferredRoute '/posts': typeof PostsRouteWithChildren @@ -369,7 +355,6 @@ export interface FileRouteTypes { id: | '__root__' | '/' - | '/_layout' | '/_pathlessLayout' | '/deferred' | '/posts' @@ -388,7 +373,6 @@ export interface FileRouteTypes { export interface RootRouteChildren { IndexRoute: typeof IndexRoute - LayoutRoute: typeof LayoutRoute PathlessLayoutRoute: typeof PathlessLayoutRouteWithChildren DeferredRoute: typeof DeferredRoute PostsRoute: typeof PostsRouteWithChildren @@ -399,7 +383,6 @@ export interface RootRouteChildren { const rootRouteChildren: RootRouteChildren = { IndexRoute: IndexRoute, - LayoutRoute: LayoutRoute, PathlessLayoutRoute: PathlessLayoutRouteWithChildren, DeferredRoute: DeferredRoute, PostsRoute: PostsRouteWithChildren, @@ -419,7 +402,6 @@ export const routeTree = rootRoute "filePath": "__root.tsx", "children": [ "/", - "/_layout", "/_pathlessLayout", "/deferred", "/posts", @@ -431,9 +413,6 @@ export const routeTree = rootRoute "/": { "filePath": "index.tsx" }, - "/_layout": { - "filePath": "_layout.tsx" - }, "/_pathlessLayout": { "filePath": "_pathlessLayout.tsx", "children": [ diff --git a/examples/react/start-basic/src/routes/__root.tsx b/examples/react/start-basic/src/routes/__root.tsx index 30f0a42b4c..70140f2306 100644 --- a/examples/react/start-basic/src/routes/__root.tsx +++ b/examples/react/start-basic/src/routes/__root.tsx @@ -5,7 +5,7 @@ import { Scripts, createRootRoute, } from '@tanstack/react-router' -import { TanStackRouterDevtools } from '@tanstack/router-devtools' +import { TanStackRouterDevtools } from '@tanstack/react-router-devtools' import * as React from 'react' import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' import { NotFound } from '~/components/NotFound' diff --git a/examples/react/start-basic/src/routes/_layout.tsx b/examples/react/start-basic/src/routes/_layout.tsx deleted file mode 100644 index 02ddbb1cd9..0000000000 --- a/examples/react/start-basic/src/routes/_layout.tsx +++ /dev/null @@ -1,16 +0,0 @@ -import { Outlet, createFileRoute } from '@tanstack/react-router' - -export const Route = createFileRoute('/_layout')({ - component: LayoutComponent, -}) - -function LayoutComponent() { - return ( -
-
I'm a layout
-
- -
-
- ) -} diff --git a/examples/react/start-basic/src/routes/posts.route.tsx b/examples/react/start-basic/src/routes/posts.route.tsx deleted file mode 100644 index ae49032459..0000000000 --- a/examples/react/start-basic/src/routes/posts.route.tsx +++ /dev/null @@ -1,38 +0,0 @@ -import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import { fetchPosts } from '../utils/posts' - -export const Route = createFileRoute('/posts')({ - loader: async () => fetchPosts(), - component: PostsComponent, -}) - -function PostsComponent() { - const posts = Route.useLoaderData() - - return ( -
-
    - {[...posts, { id: 'i-do-not-exist', title: 'Non-existent Post' }].map( - (post) => { - return ( -
  • - -
    {post.title.substring(0, 20)}
    - -
  • - ) - }, - )} -
-
- -
- ) -} diff --git a/examples/react/start-basic/src/routes/users.route.tsx b/examples/react/start-basic/src/routes/users.route.tsx deleted file mode 100644 index 1c51b659d9..0000000000 --- a/examples/react/start-basic/src/routes/users.route.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import { Link, Outlet, createFileRoute } from '@tanstack/react-router' -import axios from 'redaxios' -import { DEPLOY_URL } from '../utils/users' -import type { User } from '../utils/users' - -export const Route = createFileRoute('/users')({ - loader: async () => { - return await axios - .get>(DEPLOY_URL + '/api/users') - .then((r) => r.data) - .catch(() => { - throw new Error('Failed to fetch users') - }) - }, - component: UsersComponent, -}) - -function UsersComponent() { - const users = Route.useLoaderData() - - return ( -
-
    - {[ - ...users, - { id: 'i-do-not-exist', name: 'Non-existent User', email: '' }, - ].map((user) => { - return ( -
  • - -
    {user.name}
    - -
  • - ) - })} -
-
- -
- ) -} diff --git a/packages/react-start-server/tsconfig.json b/packages/react-start-server/tsconfig.json index 108c78712f..b447592593 100644 --- a/packages/react-start-server/tsconfig.json +++ b/packages/react-start-server/tsconfig.json @@ -4,5 +4,10 @@ "jsx": "react-jsx", "module": "esnext" }, - "include": ["src", "tests", "vite.config.ts"] + "include": [ + "src", + "tests", + "vite.config.ts", + "../start-server-core/src/server-functions-handler.ts" + ] } diff --git a/packages/start-server-core/package.json b/packages/start-server-core/package.json index 07517956fa..db7584a345 100644 --- a/packages/start-server-core/package.json +++ b/packages/start-server-core/package.json @@ -65,10 +65,11 @@ "@tanstack/history": "workspace:^", "@tanstack/router-core": "workspace:^", "@tanstack/start-client-core": "workspace:^", - "tiny-warning": "^1.0.3", "h3": "1.13.0", "isbot": "^5.1.22", "jsesc": "^3.1.0", + "tiny-invariant": "^1.3.3", + "tiny-warning": "^1.0.3", "unctx": "^2.4.1" }, "devDependencies": { diff --git a/packages/react-start-server/src/createStartHandler.ts b/packages/start-server-core/src/createStartHandler.ts similarity index 93% rename from packages/react-start-server/src/createStartHandler.ts rename to packages/start-server-core/src/createStartHandler.ts index 789c068ab0..b39540c05f 100644 --- a/packages/react-start-server/src/createStartHandler.ts +++ b/packages/start-server-core/src/createStartHandler.ts @@ -2,13 +2,10 @@ import path from 'node:path' import { createMemoryHistory } from '@tanstack/history' import { mergeHeaders } from '@tanstack/start-client-core' import { eventHandler, getResponseHeaders, toWebRequest } from 'h3' -import { - attachRouterServerSsrUtils, - dehydrateRouter, - getStartManifest, -} from '@tanstack/start-server-core' import serverFunctionsHandler from './server-functions-handler' -import type { HandlerCallback } from '@tanstack/start-server-core' +import { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server' +import { getStartManifest } from './router-manifest' +import type { HandlerCallback } from './handlerCallback' import type { EventHandlerResponse, H3Event } from 'h3' import type { AnyRouter } from '@tanstack/router-core' diff --git a/packages/start-server-core/src/index.tsx b/packages/start-server-core/src/index.tsx index a2a239bee4..88dccaab53 100644 --- a/packages/start-server-core/src/index.tsx +++ b/packages/start-server-core/src/index.tsx @@ -3,7 +3,7 @@ export { transformPipeableStreamWithRouter, } from './transformStreamWithRouter' -// export { createStartHandler } from './createStartHandler' +export { createStartHandler } from './createStartHandler' export { createRequestHandler } from './createRequestHandler' export { getStartManifest } from './router-manifest' diff --git a/packages/react-start-server/src/server-functions-handler.ts b/packages/start-server-core/src/server-functions-handler.ts similarity index 98% rename from packages/react-start-server/src/server-functions-handler.ts rename to packages/start-server-core/src/server-functions-handler.ts index 8ecd96df16..3422f5254a 100644 --- a/packages/react-start-server/src/server-functions-handler.ts +++ b/packages/start-server-core/src/server-functions-handler.ts @@ -1,19 +1,10 @@ - import { isNotFound, isRedirect } from '@tanstack/router-core' import invariant from 'tiny-invariant' - -import { - eventHandler, - getEvent, - getResponseStatus, - toWebRequest, -} from '@tanstack/start-server-core' - import { startSerializer } from '@tanstack/start-client-core' // @ts-expect-error import _serverFnManifest from 'tsr:server-fn-manifest' - -import type { H3Event } from '@tanstack/start-server-core' +import { eventHandler, getEvent, getResponseStatus, toWebRequest } from './h3' +import type { H3Event } from './h3' // NOTE: This is a dummy export to silence warnings about // only having a default export. diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e6f6704bd0..932c4cbd7e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6470,6 +6470,9 @@ importers: jsesc: specifier: ^3.1.0 version: 3.1.0 + tiny-invariant: + specifier: ^1.3.3 + version: 1.3.3 tiny-warning: specifier: ^1.0.3 version: 1.0.3 From 233860badfdffbab8155b7200adfcb441be07431 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Tue, 11 Mar 2025 09:32:46 -0600 Subject: [PATCH 041/155] checkpoint --- examples/solid/start-bare/src/ssr.tsx | 12 ---- .../src/nitro/nitro-plugin.ts | 56 +++++++++++++++---- .../src/core/router-generator-plugin.ts | 11 ++++ 3 files changed, 55 insertions(+), 24 deletions(-) delete mode 100644 examples/solid/start-bare/src/ssr.tsx diff --git a/examples/solid/start-bare/src/ssr.tsx b/examples/solid/start-bare/src/ssr.tsx deleted file mode 100644 index 6d10bea05f..0000000000 --- a/examples/solid/start-bare/src/ssr.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { - createStartHandler, - defaultStreamHandler, -} from '@tanstack/solid-start/server' -import { getRouterManifest } from '@tanstack/solid-start/router-manifest' - -import { createRouter } from './router' - -export default createStartHandler({ - createRouter, - getRouterManifest, -})(defaultStreamHandler) diff --git a/packages/react-start-plugin/src/nitro/nitro-plugin.ts b/packages/react-start-plugin/src/nitro/nitro-plugin.ts index 13af417ecb..6e35dd62e4 100644 --- a/packages/react-start-plugin/src/nitro/nitro-plugin.ts +++ b/packages/react-start-plugin/src/nitro/nitro-plugin.ts @@ -9,7 +9,7 @@ import { devServerPlugin } from './dev-server-plugin.js' import type { NitroConfig } from 'nitropack' import type { TanStackStartOutputConfig } from '../schema.js' -import type { PluginOption } from 'vite' +import type { EnvironmentOptions, PluginOption } from 'vite' export type { TanStackStartInputConfig, @@ -26,6 +26,9 @@ export function nitroPlugin( devServerPlugin(options), { name: 'tanstack-vite-plugin-nitro', + configResolved(config) { + // console.log(config.environments) + }, async config() { const buildPreset = process.env['BUILD_PRESET'] ?? @@ -50,21 +53,41 @@ export function nitroPlugin( const nitroRollupOptions = getRollupConfig(nitro) - return { - environments: { - server: { - build: { - ssr: true, - rollupOptions: { - ...nitroRollupOptions, - plugins: nitroRollupOptions.plugins as Array, - }, + const clientOptions: EnvironmentOptions = { + build: { + rollupOptions: { + input: { + main: options.clientEntryPath, + }, + }, + }, + } + + const serverOptions: EnvironmentOptions = { + build: { + ssr: true, + sourcemap: true, + rollupOptions: { + ...nitroRollupOptions, + output: { + ...nitroRollupOptions.output, + sourcemap: undefined, }, + // plugins: nitroRollupOptions.plugins as Array, }, }, + } + + // console.log('serverOptions', serverOptions.build?.rollupOptions) + + return { + environments: { + client: clientOptions, + server: serverOptions, + }, builder: { sharedPlugins: true, - buildApp: async (builder) => { + async buildApp(builder) { if (!builder.environments['client']) { throw new Error('Client environment not found') } @@ -73,9 +96,18 @@ export function nitroPlugin( throw new Error('SSR environment not found') } + console.log( + builder.environments['server'].config.build.rollupOptions, + ) + + console.log('\n\nBuilding client...') await builder.build(builder.environments['client']) + + console.log('\n\nBuilding server...') await builder.build(builder.environments['server']) + console.log('\n\nBuilding index.html...') + if (nitroConfig.prerender?.routes?.length && options.sitemap) { console.log('Building Sitemap...') // sitemap needs to be built after all directories are built @@ -87,7 +119,7 @@ export function nitroPlugin( } console.log( - `\n\nThe 'tanstack-platform' server has been successfully built.`, + `\n\n✅ Client and server bundles successfully built.`, ) }, }, diff --git a/packages/router-plugin/src/core/router-generator-plugin.ts b/packages/router-plugin/src/core/router-generator-plugin.ts index f61fd2fee5..38d6f7a5fb 100644 --- a/packages/router-plugin/src/core/router-generator-plugin.ts +++ b/packages/router-plugin/src/core/router-generator-plugin.ts @@ -85,8 +85,19 @@ export const unpluginRouterGeneratorFactory: UnpluginFactory< ROOT = config.root userConfig = getConfig(options, ROOT) + if (config.command === 'serve') { + await run(generate) + } + }, + async buildStart() { + if (this.environment.name === 'server') { + // When building in environment mode, we only need to generate routes + // for the client environment + return + } await run(generate) }, + sharedDuringBuild: true, }, async rspack(compiler) { userConfig = getConfig(options, ROOT) From 3c1064e75b0cb3bd943c1c8fa3c1581bfe2ca78b Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Tue, 11 Mar 2025 16:19:08 -0600 Subject: [PATCH 042/155] checkpoint --- examples/react/start-basic/vite.config.ts | 6 +- packages/react-start-plugin/src/index.ts | 55 ++-- .../src/nitro/hooks/post-rendering-hook.ts | 12 - .../nitro/hooks/post-rendering-hooks.spec.ts | 33 --- .../src/nitro/nitro-plugin.ts | 205 +++++++++----- .../src/routesManifestPlugin.ts | 34 ++- .../src/core/router-generator-plugin.ts | 8 +- packages/server-functions-plugin/src/index.ts | 26 +- packages/start-client-core/vite.config.ts | 1 + pnpm-lock.yaml | 259 ++---------------- 10 files changed, 229 insertions(+), 410 deletions(-) delete mode 100644 packages/react-start-plugin/src/nitro/hooks/post-rendering-hook.ts delete mode 100644 packages/react-start-plugin/src/nitro/hooks/post-rendering-hooks.spec.ts diff --git a/examples/react/start-basic/vite.config.ts b/examples/react/start-basic/vite.config.ts index 698e4856da..dfee8b17e9 100644 --- a/examples/react/start-basic/vite.config.ts +++ b/examples/react/start-basic/vite.config.ts @@ -10,6 +10,10 @@ export default defineConfig({ tsConfigPaths({ projects: ['./tsconfig.json'], }), - TanStackStartVitePlugin(), + TanStackStartVitePlugin({ + server: { + // preset: 'netlify', + }, + }), ], }) diff --git a/packages/react-start-plugin/src/index.ts b/packages/react-start-plugin/src/index.ts index 3ab92a4701..eb29cad8cc 100644 --- a/packages/react-start-plugin/src/index.ts +++ b/packages/react-start-plugin/src/index.ts @@ -6,7 +6,7 @@ import viteReact from '@vitejs/plugin-react' import { mergeConfig } from 'vite' import { getTanStackStartOptions } from './schema.js' import { nitroPlugin } from './nitro/nitro-plugin.js' -import { tsrManifestPlugin } from './routesManifestPlugin.js' +import { startManifestPlugin } from './routesManifestPlugin.js' import { TanStackStartCompilerPlugin } from './start-compiler-plugin.js' import type { PluginOption } from 'vite' import type { TanStackStartInputConfig } from './schema.js' @@ -16,6 +16,8 @@ export type { TanStackStartOutputConfig, } from './schema.js' +export const clientDistDir = 'node_modules/.tanstack-start/client-dist' + export function TanStackStartVitePlugin( opts?: TanStackStartInputConfig, ): Array { @@ -25,7 +27,7 @@ export function TanStackStartVitePlugin( { name: 'tss-vite-config-client', ...options.vite, - async config(config) { + async config() { // Create a dummy nitro app to get the resolved public output path const dummyNitroApp = await createNitro({ preset: options.server.preset, @@ -35,20 +37,32 @@ export function TanStackStartVitePlugin( const nitroOutputPublicDir = dummyNitroApp.options.output.publicDir await dummyNitroApp.close() - config.environments = { - ...(config.environments ?? {}), - server: { - ...(config.environments?.server ?? {}), + return { + environments: { + client: { + build: { + manifest: true, + rollupOptions: { + input: { + main: options.clientEntryPath, + }, + output: { + dir: clientDistDir, + }, + external: ['node:fs', 'node:path', 'node:os', 'node:crypto'], + }, + }, + }, + server: {}, }, - } - - return mergeConfig(config, { resolve: { noExternal: [ '@tanstack/start', '@tanstack/start/server', '@tanstack/start-client', + '@tanstack/start-client-core', '@tanstack/start-server', + '@tanstack/start-server-core', '@tanstack/start-server-functions-fetcher', '@tanstack/start-server-functions-client', '@tanstack/start-server-functions-ssr', @@ -59,11 +73,18 @@ export function TanStackStartVitePlugin( '@tanstack/server-functions-plugin', 'tsr:start-manifest', 'tsr:server-fn-manifest', + 'use-sync-external-store', + 'use-sync-external-store/shim/with-selector', ], }, optimizeDeps: { entries: [], ...(options.vite?.optimizeDeps || {}), + include: [ + 'use-sync-external-store', + 'use-sync-external-store/shim/with-selector', + ...(options.vite?.optimizeDeps?.include || []), + ], }, /* prettier-ignore */ define: { @@ -74,18 +95,10 @@ export function TanStackStartVitePlugin( ...injectDefineEnv('TSS_SERVER_FN_BASE', options.routers.server.base), ...injectDefineEnv('TSS_OUTPUT_PUBLIC_DIR', nitroOutputPublicDir), }, - }) + } }, configEnvironment(env, config) { if (env === 'server') { - config = mergeConfig(config, { - plugins: [], - }) - - config = mergeConfig( - mergeConfig(config, options.vite || {}), - options.routers.server.vite || {}, - ) } else { config = mergeConfig( mergeConfig(config, options.vite || {}), @@ -125,7 +138,6 @@ hydrateRoot(document, ) } if (id === '/~start/default-server-entry.tsx') { - console.log('routerImportPath', routerImportPath) return ` import { createStartHandler, defaultStreamHandler } from '@tanstack/react-start/server' import { createRouter } from ${routerImportPath} @@ -157,10 +169,7 @@ export default createStartHandler({ `createServerRpc('${d.functionId}', '${options.routers.server.base}', ${d.fn})`, }, }), - tsrManifestPlugin({ - clientBase: options.routers.client.base, - tsrConfig: options.tsr, - }), + startManifestPlugin(options), TanStackRouterVite({ ...options.tsr, enableRouteGeneration: true, diff --git a/packages/react-start-plugin/src/nitro/hooks/post-rendering-hook.ts b/packages/react-start-plugin/src/nitro/hooks/post-rendering-hook.ts deleted file mode 100644 index 5bc1168c8f..0000000000 --- a/packages/react-start-plugin/src/nitro/hooks/post-rendering-hook.ts +++ /dev/null @@ -1,12 +0,0 @@ -import type { Nitro, PrerenderRoute } from 'nitropack' - -export function addPostRenderingHooks( - nitro: Nitro, - hooks: Array<(pr: PrerenderRoute) => Promise>, -): void { - hooks.forEach((hook: (preRoute: PrerenderRoute) => void) => { - nitro.hooks.hook('prerender:generate', (route: PrerenderRoute) => { - hook(route) - }) - }) -} diff --git a/packages/react-start-plugin/src/nitro/hooks/post-rendering-hooks.spec.ts b/packages/react-start-plugin/src/nitro/hooks/post-rendering-hooks.spec.ts deleted file mode 100644 index bda3dbc7f3..0000000000 --- a/packages/react-start-plugin/src/nitro/hooks/post-rendering-hooks.spec.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { describe, expect, it, vi } from 'vitest' - -import { addPostRenderingHooks } from './post-rendering-hook' -import type { Nitro } from 'nitropack' - -describe('postRenderingHook', () => { - const genRoute = { - route: 'test/testRoute', - contents: 'This is a test.', - } - - const nitroMock = { - hooks: { - hook: vi.fn((name: string, callback: (route: any) => void) => - callback(genRoute), - ), - }, - } as unknown as Nitro - - const mockFunc1 = vi.fn() - const mockFunc2 = vi.fn() - - it('should not attempt to call nitro mocks if no callbacks provided', () => { - addPostRenderingHooks(nitroMock, []) - expect(nitroMock.hooks.hook).not.toHaveBeenCalled() - }) - - it('should call provided hooks', () => { - addPostRenderingHooks(nitroMock, [mockFunc1, mockFunc2]) - expect(mockFunc1).toHaveBeenCalledWith(genRoute) - expect(mockFunc2).toHaveBeenCalled() - }) -}) diff --git a/packages/react-start-plugin/src/nitro/nitro-plugin.ts b/packages/react-start-plugin/src/nitro/nitro-plugin.ts index 6e35dd62e4..f3d0b3e847 100644 --- a/packages/react-start-plugin/src/nitro/nitro-plugin.ts +++ b/packages/react-start-plugin/src/nitro/nitro-plugin.ts @@ -1,16 +1,17 @@ -import { resolve } from 'node:path' import { platform } from 'node:os' +import { promises as fsp } from 'node:fs' +import path from 'node:path' +import { copyPublicAssets, createNitro, prepare } from 'nitropack' +import { version } from 'nitropack/meta' import { normalizePath } from 'vite' -import { getRollupConfig } from 'nitropack/rollup' -import { createNitro } from 'nitropack' -import { buildSitemap } from './build-sitemap.js' +import { getRollupConfig } from 'nitropack/rollup' +import { clientDistDir } from '../index.js' import { devServerPlugin } from './dev-server-plugin.js' -import type { NitroConfig } from 'nitropack' +import type { PluginOption } from 'vite' +import type { Nitro, NitroConfig } from 'nitropack' import type { TanStackStartOutputConfig } from '../schema.js' -import type { EnvironmentOptions, PluginOption } from 'vite' - export type { TanStackStartInputConfig, TanStackStartOutputConfig, @@ -22,69 +23,68 @@ const filePrefix = isWindows ? 'file:///' : '' export function nitroPlugin( options: TanStackStartOutputConfig, ): Array { + let nitro: Nitro + let nitroRollupOptions: ReturnType + + const buildPreset = + process.env['BUILD_PRESET'] ?? (options.server.preset as string | undefined) + + const nitroConfig: NitroConfig = { + compatibilityDate: '2024-11-19', + logLevel: options.server.logLevel || 0, + srcDir: normalizePath(options.tsr.srcDirectory), + ...options.server, + preset: buildPreset, + publicAssets: [ + { + dir: clientDistDir, + }, + ], + typescript: { + generateTsConfig: false, + }, + prerender: { + ...options.server.prerender, + routes: ['/', ...(options.server.prerender?.routes || [])], + }, + renderer: options.serverEntryPath, + } + return [ devServerPlugin(options), { name: 'tanstack-vite-plugin-nitro', - configResolved(config) { + configResolved() { // console.log(config.environments) }, - async config() { - const buildPreset = - process.env['BUILD_PRESET'] ?? - (options.server.preset as string | undefined) - - const nitroConfig: NitroConfig = { - ...options.server, - preset: buildPreset, - compatibilityDate: '2024-11-19', - logLevel: options.server.logLevel || 0, - srcDir: normalizePath(options.tsr.srcDirectory), - // renderer: filePrefix + normalizePath(options.ssrEntryPath), - } - - const nitro = await createNitro({ + async configEnvironment(name) { + nitro = await createNitro({ dev: false, ...nitroConfig, - typescript: { - generateTsConfig: false, - }, }) - const nitroRollupOptions = getRollupConfig(nitro) - - const clientOptions: EnvironmentOptions = { - build: { - rollupOptions: { - input: { - main: options.clientEntryPath, + nitroRollupOptions = getRollupConfig(nitro) + + if (name === 'server') { + return { + build: { + ssr: true, + sourcemap: true, + rollupOptions: { + ...nitroRollupOptions, + output: { + ...nitroRollupOptions.output, + sourcemap: undefined, + }, }, }, - }, + } } - const serverOptions: EnvironmentOptions = { - build: { - ssr: true, - sourcemap: true, - rollupOptions: { - ...nitroRollupOptions, - output: { - ...nitroRollupOptions.output, - sourcemap: undefined, - }, - // plugins: nitroRollupOptions.plugins as Array, - }, - }, - } - - // console.log('serverOptions', serverOptions.build?.rollupOptions) - + return null + }, + config() { return { - environments: { - client: clientOptions, - server: serverOptions, - }, builder: { sharedPlugins: true, async buildApp(builder) { @@ -96,35 +96,96 @@ export function nitroPlugin( throw new Error('SSR environment not found') } - console.log( - builder.environments['server'].config.build.rollupOptions, - ) - - console.log('\n\nBuilding client...') await builder.build(builder.environments['client']) + await prepare(nitro) + await copyPublicAssets(nitro) + + // if ( + // nitroConfig.prerender?.routes && + // nitroConfig.prerender.routes.length > 0 + // ) { + // console.log(`Prerendering static pages...`) + // await prerender(nitro) + // } - console.log('\n\nBuilding server...') await builder.build(builder.environments['server']) - console.log('\n\nBuilding index.html...') + const buildInfoPath = path.resolve( + nitro.options.output.dir, + 'nitro.json', + ) - if (nitroConfig.prerender?.routes?.length && options.sitemap) { - console.log('Building Sitemap...') - // sitemap needs to be built after all directories are built - await buildSitemap({ - host: options.sitemap.host, - routes: nitroConfig.prerender.routes, - outputDir: resolve(options.root, 'dist/public'), - }) + const presetsWithConfig = [ + 'awsAmplify', + 'awsLambda', + 'azure', + 'cloudflare', + 'firebase', + 'netlify', + 'vercel', + ] + + const buildInfo = { + date: /* @__PURE__ */ new Date().toJSON(), + preset: nitro.options.preset, + framework: nitro.options.framework, + versions: { + nitro: version, + }, + commands: { + preview: nitro.options.commands.preview, + deploy: nitro.options.commands.deploy, + }, + config: { + ...Object.fromEntries( + presetsWithConfig.map((key) => [ + key, + (nitro.options as any)[key], + ]), + ), + }, } - console.log( - `\n\n✅ Client and server bundles successfully built.`, + await fsp.writeFile( + buildInfoPath, + JSON.stringify(buildInfo, null, 2), ) + + await nitro.close() + + // if (nitroConfig.prerender?.routes?.length && options.sitemap) { + // console.log('Building Sitemap...') + // // sitemap needs to be built after all directories are built + // await buildSitemap({ + // host: options.sitemap.host, + // routes: nitroConfig.prerender.routes, + // outputDir: resolve(options.root, 'dist/public'), + // }) + // } + + // console.log( + // `\n\n✅ Client and server bundles successfully built.`, + // ) }, }, } }, + // async buildStart() { + // await Promise.all( + // [ + // nitro.options.output.dir, + // nitro.options.output.serverDir, + // nitro.options.output.publicDir, + // ].map((dir) => { + // if (dir) { + // return promises.mkdir(dir, { + // recursive: true, + // }) + // } + // return + // }), + // ) + // }, }, ] } diff --git a/packages/react-start-plugin/src/routesManifestPlugin.ts b/packages/react-start-plugin/src/routesManifestPlugin.ts index be94ff2405..291dea7c79 100644 --- a/packages/react-start-plugin/src/routesManifestPlugin.ts +++ b/packages/react-start-plugin/src/routesManifestPlugin.ts @@ -1,14 +1,12 @@ import { readFileSync } from 'node:fs' import path from 'node:path' -import type { configSchema } from '@tanstack/router-generator' import type { PluginOption, ResolvedConfig } from 'vite' -import type { z } from 'zod' import type { Manifest } from '@tanstack/react-router' +import type { TanStackStartOutputConfig } from './schema' -export function tsrManifestPlugin(opts: { - tsrConfig: z.infer - clientBase: string -}): PluginOption { +export function startManifestPlugin( + opts: TanStackStartOutputConfig, +): PluginOption { let config: ResolvedConfig return { @@ -39,8 +37,8 @@ export function tsrManifestPlugin(opts: { } const clientViteManifestPath = path.resolve( - config.build.outDir, - `../client/${opts.clientBase}/.vite/manifest.json`, + opts.root, + 'node_modules/.tanstack-start/client-dist/.vite/manifest.json', ) type ViteManifest = Record< @@ -62,7 +60,7 @@ export function tsrManifestPlugin(opts: { ) } - const routeTreePath = path.resolve(opts.tsrConfig.generatedRouteTree) + const routeTreePath = path.resolve(opts.tsr.generatedRouteTree) let routeTreeContent: string try { @@ -88,7 +86,7 @@ export function tsrManifestPlugin(opts: { let entryFile: | { file: string - imports: Array + imports?: Array } | undefined @@ -108,15 +106,15 @@ export function tsrManifestPlugin(opts: { Object.entries(routes).forEach(([k, v]) => { const file = filesByRouteFilePath[ - path.join(opts.tsrConfig.routesDirectory, v.filePath as string) + path.join(opts.tsr.routesDirectory, v.filePath as string) ] - if (file) { + if (file?.imports.length) { const preloads = file.imports.map((d) => - path.join(opts.clientBase, manifest[d]!.file), + path.join(opts.routers.client.base, manifest[d]!.file), ) - preloads.unshift(path.join(opts.clientBase, file.file)) + preloads.unshift(path.join(opts.routers.client.base, file.file)) routes[k] = { ...v, @@ -127,10 +125,10 @@ export function tsrManifestPlugin(opts: { if (entryFile) { routes.__root__!.preloads = [ - path.join(opts.clientBase, entryFile.file), - ...entryFile.imports.map((d) => - path.join(opts.clientBase, manifest[d]!.file), - ), + path.join(opts.routers.client.base, entryFile.file), + ...(entryFile.imports?.map((d) => + path.join(opts.routers.client.base, manifest[d]!.file), + ) || []), ] } diff --git a/packages/router-plugin/src/core/router-generator-plugin.ts b/packages/router-plugin/src/core/router-generator-plugin.ts index 38d6f7a5fb..a23e9627b0 100644 --- a/packages/router-plugin/src/core/router-generator-plugin.ts +++ b/packages/router-plugin/src/core/router-generator-plugin.ts @@ -81,13 +81,13 @@ export const unpluginRouterGeneratorFactory: UnpluginFactory< }) }, vite: { - async configResolved(config) { + configResolved(config) { ROOT = config.root userConfig = getConfig(options, ROOT) - if (config.command === 'serve') { - await run(generate) - } + // if (config.command === 'serve') { + // await run(generate) + // } }, async buildStart() { if (this.environment.name === 'server') { diff --git a/packages/server-functions-plugin/src/index.ts b/packages/server-functions-plugin/src/index.ts index 6f52ddda45..83ae6c0ab9 100644 --- a/packages/server-functions-plugin/src/index.ts +++ b/packages/server-functions-plugin/src/index.ts @@ -40,7 +40,7 @@ export function createTanStackServerFnPlugin(opts: ServerFnPluginOpts): { } { const ROOT = process.cwd() const manifestFilename = - 'node_modules/.tanstack-start/server-functions-manifest.json' + 'node_modules/.tanstack-start/server/server-functions-manifest.json' globalThis.TSR_directiveFnsById = {} @@ -95,7 +95,9 @@ export function createTanStackServerFnPlugin(opts: ServerFnPluginOpts): { // build. // Ensure the manifest directory exists - mkdirSync(path.dirname(manifestFilename), { recursive: true }) + mkdirSync(path.join(ROOT, path.dirname(manifestFilename)), { + recursive: true, + }) // Write the manifest to disk writeFileSync( @@ -200,9 +202,21 @@ export function TanStackServerFnPluginEnv(opts: { replacer: ReplacerFn } }): Array { + opts = { + ...opts, + client: { + ...opts.client, + envName: opts.client.envName || 'client', + }, + server: { + ...opts.server, + envName: opts.server.envName || 'server', + }, + } + const root = process.cwd() const manifestFilename = - 'node_modules/.tanstack-start/server-functions-manifest.json' + 'node_modules/.tanstack-start/server/server-functions-manifest.json' globalThis.TSR_directiveFnsById = {} @@ -261,7 +275,7 @@ export function TanStackServerFnPluginEnv(opts: { applyToEnvironment(environment) { return environment.name === opts.client.envName }, - generateBundle() { + buildEnd() { // In production, we create a manifest so we can // access it later in the server build, which likely does not run in the // same vite build environment. This is essentially a @@ -269,7 +283,9 @@ export function TanStackServerFnPluginEnv(opts: { // build. // Ensure the manifest directory exists - mkdirSync(path.dirname(manifestFilename), { recursive: true }) + mkdirSync(path.join(root, path.dirname(manifestFilename)), { + recursive: true, + }) // Write the manifest to disk writeFileSync( diff --git a/packages/start-client-core/vite.config.ts b/packages/start-client-core/vite.config.ts index ac2026fbb7..fb0b2664aa 100644 --- a/packages/start-client-core/vite.config.ts +++ b/packages/start-client-core/vite.config.ts @@ -16,5 +16,6 @@ export default mergeConfig( tanstackViteConfig({ srcDir: './src', entry: './src/index.tsx', + // externalDeps: ['node:fs', 'node:path', 'node:os', 'node:crypto'], }), ) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 932c4cbd7e..c70342310b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -345,7 +345,7 @@ importers: version: 5.66.0(react@19.0.0) '@tanstack/react-query-devtools': specifier: ^5.66.0 - version: 5.66.0(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) + version: 5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -397,7 +397,7 @@ importers: version: 5.66.0(react@19.0.0) '@tanstack/react-query-devtools': specifier: ^5.66.0 - version: 5.66.0(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) + version: 5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -959,7 +959,7 @@ importers: version: 5.66.0(react@19.0.0) '@tanstack/react-query-devtools': specifier: ^5.66.0 - version: 5.66.0(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) + version: 5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -2496,7 +2496,7 @@ importers: version: 5.66.0(react@19.0.0) '@tanstack/react-query-devtools': specifier: ^5.66.0 - version: 5.66.0(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) + version: 5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -2545,7 +2545,7 @@ importers: version: 5.66.0(react@19.0.0) '@tanstack/react-query-devtools': specifier: ^5.66.0 - version: 5.66.0(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) + version: 5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -2994,7 +2994,7 @@ importers: version: 5.66.0(react@19.0.0) '@tanstack/react-query-devtools': specifier: ^5.66.0 - version: 5.66.0(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) + version: 5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -3049,7 +3049,7 @@ importers: version: 5.66.0(react@19.0.0) '@tanstack/react-query-devtools': specifier: ^5.66.0 - version: 5.66.0(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) + version: 5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -3466,7 +3466,7 @@ importers: version: 5.66.0(react@19.0.0) '@tanstack/react-query-devtools': specifier: ^5.66.0 - version: 5.66.0(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) + version: 5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -4264,7 +4264,7 @@ importers: version: 5.66.0(react@19.0.0) '@tanstack/react-query-devtools': specifier: ^5.66.0 - version: 5.66.0(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) + version: 5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -4475,7 +4475,7 @@ importers: version: 5.66.0(react@19.0.0) '@tanstack/react-query-devtools': specifier: ^5.66.0 - version: 5.66.0(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) + version: 5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -4667,7 +4667,7 @@ importers: version: 19.0.0(react@19.0.0) vinxi: specifier: 0.5.3 - version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0) + version: 0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0) zod: specifier: ^3.24.2 version: 3.24.2 @@ -4683,10 +4683,10 @@ importers: version: 19.0.3(@types/react@19.0.8) typescript: specifier: ^5.7.2 - version: 5.7.3 + version: 5.8.2 vite-tsconfig-paths: specifier: ^5.1.4 - version: 5.1.4(typescript@5.7.3)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) + version: 5.1.4(typescript@5.8.2)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) examples/react/start-supabase-basic: dependencies: @@ -4741,7 +4741,7 @@ importers: version: 5.66.0(react@19.0.0) '@tanstack/react-query-devtools': specifier: ^5.66.0 - version: 5.66.0(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) + version: 5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -4912,7 +4912,7 @@ importers: version: 5.66.0(react@19.0.0) '@tanstack/react-query-devtools': specifier: ^5.66.0 - version: 5.66.0(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) + version: 5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0) '@tanstack/react-router': specifier: workspace:* version: link:../../../packages/react-router @@ -6202,7 +6202,7 @@ importers: version: 2.11.6(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) zod: specifier: ^3.23.8 - version: 3.24.1 + version: 3.24.2 packages/solid-router-devtools: dependencies: @@ -7758,10 +7758,6 @@ packages: resolution: {integrity: sha512-yaVPAiNAalnCZedKLdR21GOGILMLKPyqSLWaAjQFvYA2i/ciDi8ArYVr69Anohb6cH2Ukhqti4aFnYyPm8wdwQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.20.0': - resolution: {integrity: sha512-iZA07H9io9Wn836aVTytRaNqh00Sad+EamwOVJT12GTLw1VGMFV/4JaME+JjLtr9fiGaoWgYnS54wrfWsSs4oQ==} - engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.22.0': resolution: {integrity: sha512-vLFajx9o8d1/oL2ZkpMYbkLv8nDB6yaIwFNt7nI4+I80U/z03SxmfOMsLbvWr3p7C+Wnoh//aOu2pQW8cS0HCQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -9492,12 +9488,6 @@ packages: '@tanstack/query-devtools@5.67.2': resolution: {integrity: sha512-O4QXFFd7xqp6EX7sdvc9tsVO8nm4lpWBqwpgjpVLW5g7IeOY6VnS/xvs/YzbRhBVkKTMaJMOUGU7NhSX+YGoNg==} - '@tanstack/react-query-devtools@5.66.0': - resolution: {integrity: sha512-uB57wA2YZaQ2fPcFW0E9O1zAGDGSbRKRx84uMk/86VyU9jWVxvJ3Uzp+zNm+nZJYsuekCIo2opTdgNuvM3cKgA==} - peerDependencies: - '@tanstack/react-query': 5.66.0 - react: ^19.0.0 - '@tanstack/react-query-devtools@5.67.2': resolution: {integrity: sha512-cmj2DxBc+/9btQ66n5xI8wTtAma2BLVa403K7zIYiguzJ/kV201jnGensYqJeu1Rd8uRMLLRM74jLVMLDWNRJA==} peerDependencies: @@ -14836,9 +14826,6 @@ packages: resolution: {integrity: sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==} engines: {node: '>= 14'} - zod@3.24.1: - resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} - zod@3.24.2: resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} @@ -15862,8 +15849,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.20.0': {} - '@eslint/js@9.22.0': {} '@eslint/object-schema@2.1.6': {} @@ -17709,7 +17694,7 @@ snapshots: '@tanstack/config@0.16.1(@types/node@22.13.4)(esbuild@0.25.0)(eslint@9.22.0(jiti@2.4.2))(rollup@4.34.0)(typescript@5.8.2)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0))': dependencies: '@commitlint/parse': 19.5.0 - '@eslint/js': 9.20.0 + '@eslint/js': 9.22.0 '@stylistic/eslint-plugin-js': 2.13.0(eslint@9.22.0(jiti@2.4.2)) commander: 13.1.0 esbuild-register: 3.6.0(esbuild@0.25.0) @@ -17747,12 +17732,6 @@ snapshots: '@tanstack/query-devtools@5.67.2': {} - '@tanstack/react-query-devtools@5.66.0(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0)': - dependencies: - '@tanstack/query-devtools': 5.65.0 - '@tanstack/react-query': 5.66.0(react@19.0.0) - react: 19.0.0 - '@tanstack/react-query-devtools@5.67.2(@tanstack/react-query@5.66.0(react@19.0.0))(react@19.0.0)': dependencies: '@tanstack/query-devtools': 5.67.2 @@ -21257,104 +21236,6 @@ snapshots: neo-async@2.6.2: {} - nitropack@2.10.4(typescript@5.7.3): - dependencies: - '@cloudflare/kv-asset-handler': 0.3.4 - '@netlify/functions': 2.8.2 - '@rollup/plugin-alias': 5.1.1(rollup@4.34.0) - '@rollup/plugin-commonjs': 28.0.2(rollup@4.34.0) - '@rollup/plugin-inject': 5.0.5(rollup@4.34.0) - '@rollup/plugin-json': 6.1.0(rollup@4.34.0) - '@rollup/plugin-node-resolve': 15.3.1(rollup@4.34.0) - '@rollup/plugin-replace': 6.0.2(rollup@4.34.0) - '@rollup/plugin-terser': 0.4.4(rollup@4.34.0) - '@rollup/pluginutils': 5.1.4(rollup@4.34.0) - '@types/http-proxy': 1.17.15 - '@vercel/nft': 0.27.10(rollup@4.34.0) - archiver: 7.0.1 - c12: 2.0.1(magicast@0.3.5) - chokidar: 3.6.0 - citty: 0.1.6 - compatx: 0.1.8 - confbox: 0.1.8 - consola: 3.4.0 - cookie-es: 1.2.2 - croner: 9.0.0 - crossws: 0.3.3 - db0: 0.2.3 - defu: 6.1.4 - destr: 2.0.3 - dot-prop: 9.0.0 - esbuild: 0.24.2 - escape-string-regexp: 5.0.0 - etag: 1.8.1 - fs-extra: 11.3.0 - globby: 14.0.2 - gzip-size: 7.0.0 - h3: 1.13.0 - hookable: 5.5.3 - httpxy: 0.1.7 - ioredis: 5.4.2 - jiti: 2.4.2 - klona: 2.0.6 - knitwork: 1.2.0 - listhen: 1.9.0 - magic-string: 0.30.17 - magicast: 0.3.5 - mime: 4.0.6 - mlly: 1.7.4 - node-fetch-native: 1.6.6 - ofetch: 1.4.1 - ohash: 1.1.4 - openapi-typescript: 7.6.0(typescript@5.7.3) - pathe: 1.1.2 - perfect-debounce: 1.0.0 - pkg-types: 1.3.1 - pretty-bytes: 6.1.1 - radix3: 1.1.2 - rollup: 4.34.0 - rollup-plugin-visualizer: 5.14.0(rollup@4.34.0) - scule: 1.3.0 - semver: 7.7.0 - serve-placeholder: 2.0.2 - serve-static: 1.16.2 - std-env: 3.8.0 - ufo: 1.5.4 - uncrypto: 0.1.3 - unctx: 2.4.1 - unenv: 1.10.0 - unimport: 3.14.6(rollup@4.34.0) - unstorage: 1.14.4(db0@0.2.3)(ioredis@5.4.2) - untyped: 1.5.2 - unwasm: 0.3.9 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@electric-sql/pglite' - - '@libsql/client' - - '@netlify/blobs' - - '@planetscale/database' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/kv' - - aws4fetch - - better-sqlite3 - - drizzle-orm - - encoding - - idb-keyval - - mysql2 - - rolldown - - sqlite3 - - supports-color - - typescript - - uploadthing - nitropack@2.10.4(typescript@5.8.2): dependencies: '@cloudflare/kv-asset-handler': 0.3.4 @@ -21629,16 +21510,6 @@ snapshots: is-docker: 2.2.1 is-wsl: 2.2.0 - openapi-typescript@7.6.0(typescript@5.7.3): - dependencies: - '@redocly/openapi-core': 1.28.0(supports-color@9.4.0) - ansi-colors: 4.1.3 - change-case: 5.4.4 - parse-json: 8.1.0 - supports-color: 9.4.0 - typescript: 5.7.3 - yargs-parser: 21.1.1 - openapi-typescript@7.6.0(typescript@5.8.2): dependencies: '@redocly/openapi-core': 1.28.0(supports-color@9.4.0) @@ -22970,10 +22841,6 @@ snapshots: ts-pattern@5.6.2: {} - tsconfck@3.1.4(typescript@5.7.3): - optionalDependencies: - typescript: 5.7.3 - tsconfck@3.1.4(typescript@5.8.2): optionalDependencies: typescript: 5.8.2 @@ -23276,85 +23143,6 @@ snapshots: vary@1.1.2: {} - vinxi@0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.7.3)(yaml@2.7.0): - dependencies: - '@babel/core': 7.26.8 - '@babel/plugin-syntax-jsx': 7.25.9(@babel/core@7.26.8) - '@babel/plugin-syntax-typescript': 7.25.9(@babel/core@7.26.8) - '@types/micromatch': 4.0.9 - '@vinxi/listhen': 1.5.6 - boxen: 7.1.1 - chokidar: 3.6.0 - citty: 0.1.6 - consola: 3.4.0 - crossws: 0.3.3 - dax-sh: 0.39.2 - defu: 6.1.4 - es-module-lexer: 1.6.0 - esbuild: 0.20.2 - fast-glob: 3.3.3 - get-port-please: 3.1.2 - h3: 1.13.0 - hookable: 5.5.3 - http-proxy: 1.18.1 - micromatch: 4.0.8 - nitropack: 2.10.4(typescript@5.7.3) - node-fetch-native: 1.6.6 - path-to-regexp: 6.3.0 - pathe: 1.1.2 - radix3: 1.1.2 - resolve: 1.22.10 - serve-placeholder: 2.0.2 - serve-static: 1.16.2 - ufo: 1.5.4 - unctx: 2.4.1 - unenv: 1.10.0 - unstorage: 1.14.4(db0@0.2.3)(ioredis@5.4.2) - vite: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - zod: 3.24.2 - transitivePeerDependencies: - - '@azure/app-configuration' - - '@azure/cosmos' - - '@azure/data-tables' - - '@azure/identity' - - '@azure/keyvault-secrets' - - '@azure/storage-blob' - - '@capacitor/preferences' - - '@deno/kv' - - '@electric-sql/pglite' - - '@libsql/client' - - '@netlify/blobs' - - '@planetscale/database' - - '@types/node' - - '@upstash/redis' - - '@vercel/blob' - - '@vercel/kv' - - aws4fetch - - better-sqlite3 - - db0 - - debug - - drizzle-orm - - encoding - - idb-keyval - - ioredis - - jiti - - less - - lightningcss - - mysql2 - - rolldown - - sass - - sass-embedded - - sqlite3 - - stylus - - sugarss - - supports-color - - terser - - tsx - - typescript - - uploadthing - - xml2js - - yaml - vinxi@0.5.3(@types/node@22.13.4)(db0@0.2.3)(ioredis@5.4.2)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(typescript@5.8.2)(yaml@2.7.0): dependencies: '@babel/core': 7.26.8 @@ -23513,17 +23301,6 @@ snapshots: transitivePeerDependencies: - supports-color - vite-tsconfig-paths@5.1.4(typescript@5.7.3)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)): - dependencies: - debug: 4.4.0(supports-color@9.4.0) - globrex: 0.1.2 - tsconfck: 3.1.4(typescript@5.7.3) - optionalDependencies: - vite: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - transitivePeerDependencies: - - supports-color - - typescript - vite-tsconfig-paths@5.1.4(typescript@5.8.2)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)): dependencies: debug: 4.4.0(supports-color@9.4.0) @@ -23923,6 +23700,4 @@ snapshots: compress-commons: 6.0.2 readable-stream: 4.7.0 - zod@3.24.1: {} - zod@3.24.2: {} From c1d9288577f2e0c36223cee1f6778980d3e35834 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Wed, 12 Mar 2025 01:58:19 +0100 Subject: [PATCH 043/155] fix commonjsOptions --- packages/react-start-plugin/src/index.ts | 8 +------- packages/react-start-plugin/src/nitro/nitro-plugin.ts | 10 +++++----- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/packages/react-start-plugin/src/index.ts b/packages/react-start-plugin/src/index.ts index eb29cad8cc..f344f916f9 100644 --- a/packages/react-start-plugin/src/index.ts +++ b/packages/react-start-plugin/src/index.ts @@ -73,18 +73,12 @@ export function TanStackStartVitePlugin( '@tanstack/server-functions-plugin', 'tsr:start-manifest', 'tsr:server-fn-manifest', - 'use-sync-external-store', - 'use-sync-external-store/shim/with-selector', ], }, optimizeDeps: { entries: [], ...(options.vite?.optimizeDeps || {}), - include: [ - 'use-sync-external-store', - 'use-sync-external-store/shim/with-selector', - ...(options.vite?.optimizeDeps?.include || []), - ], + include: [...(options.vite?.optimizeDeps?.include || [])], }, /* prettier-ignore */ define: { diff --git a/packages/react-start-plugin/src/nitro/nitro-plugin.ts b/packages/react-start-plugin/src/nitro/nitro-plugin.ts index f3d0b3e847..10c1fbc734 100644 --- a/packages/react-start-plugin/src/nitro/nitro-plugin.ts +++ b/packages/react-start-plugin/src/nitro/nitro-plugin.ts @@ -8,7 +8,7 @@ import { normalizePath } from 'vite' import { getRollupConfig } from 'nitropack/rollup' import { clientDistDir } from '../index.js' import { devServerPlugin } from './dev-server-plugin.js' -import type { PluginOption } from 'vite' +import type { EnvironmentOptions, PluginOption } from 'vite' import type { Nitro, NitroConfig } from 'nitropack' import type { TanStackStartOutputConfig } from '../schema.js' @@ -54,9 +54,6 @@ export function nitroPlugin( devServerPlugin(options), { name: 'tanstack-vite-plugin-nitro', - configResolved() { - // console.log(config.environments) - }, async configEnvironment(name) { nitro = await createNitro({ dev: false, @@ -68,6 +65,9 @@ export function nitroPlugin( if (name === 'server') { return { build: { + commonjsOptions: { + include: [], + }, ssr: true, sourcemap: true, rollupOptions: { @@ -78,7 +78,7 @@ export function nitroPlugin( }, }, }, - } + } satisfies EnvironmentOptions } return null From 552e94168c13382735db2e806d900f30d3d2abfb Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Wed, 12 Mar 2025 00:40:44 -0600 Subject: [PATCH 044/155] checkpoint --- packages/react-start-plugin/src/index.ts | 2 +- .../src/nitro/nitro-plugin.ts | 2 +- .../src/routesManifestPlugin.ts | 39 +++++++----- .../start-server-core/src/router-manifest.ts | 63 ++++++++++--------- 4 files changed, 59 insertions(+), 47 deletions(-) diff --git a/packages/react-start-plugin/src/index.ts b/packages/react-start-plugin/src/index.ts index f344f916f9..1a8c2837d6 100644 --- a/packages/react-start-plugin/src/index.ts +++ b/packages/react-start-plugin/src/index.ts @@ -47,7 +47,7 @@ export function TanStackStartVitePlugin( main: options.clientEntryPath, }, output: { - dir: clientDistDir, + dir: path.resolve(options.root, clientDistDir), }, external: ['node:fs', 'node:path', 'node:os', 'node:crypto'], }, diff --git a/packages/react-start-plugin/src/nitro/nitro-plugin.ts b/packages/react-start-plugin/src/nitro/nitro-plugin.ts index 10c1fbc734..d179dc95ee 100644 --- a/packages/react-start-plugin/src/nitro/nitro-plugin.ts +++ b/packages/react-start-plugin/src/nitro/nitro-plugin.ts @@ -37,7 +37,7 @@ export function nitroPlugin( preset: buildPreset, publicAssets: [ { - dir: clientDistDir, + dir: path.resolve(options.root, clientDistDir), }, ], typescript: { diff --git a/packages/react-start-plugin/src/routesManifestPlugin.ts b/packages/react-start-plugin/src/routesManifestPlugin.ts index 291dea7c79..9e706eef28 100644 --- a/packages/react-start-plugin/src/routesManifestPlugin.ts +++ b/packages/react-start-plugin/src/routesManifestPlugin.ts @@ -46,7 +46,7 @@ export function startManifestPlugin( { file: string isEntry: boolean - imports: Array + imports?: Array } > @@ -102,19 +102,26 @@ export function startManifestPlugin( }, {}), ) + const routesDirectoryFromRoot = path.relative( + opts.root, + opts.tsr.routesDirectory, + ) + // Add preloads to the routes from the vite manifest Object.entries(routes).forEach(([k, v]) => { const file = filesByRouteFilePath[ - path.join(opts.tsr.routesDirectory, v.filePath as string) + path.join(routesDirectoryFromRoot, v.filePath as string) ] - if (file?.imports.length) { - const preloads = file.imports.map((d) => - path.join(opts.routers.client.base, manifest[d]!.file), + if (file) { + const preloads = (file.imports ?? []).map((d) => + path.join('/', manifest[d]!.file), ) - preloads.unshift(path.join(opts.routers.client.base, file.file)) + if (file.file) { + preloads.unshift(path.join('/', file.file)) + } routes[k] = { ...v, @@ -125,11 +132,21 @@ export function startManifestPlugin( if (entryFile) { routes.__root__!.preloads = [ - path.join(opts.routers.client.base, entryFile.file), + path.join('/', entryFile.file), ...(entryFile.imports?.map((d) => - path.join(opts.routers.client.base, manifest[d]!.file), + path.join('/', manifest[d]!.file), ) || []), ] + routes.__root__!.assets = [ + ...(routes.__root__!.assets || []), + { + tag: 'script', + attrs: { + src: path.join('/', entryFile.file), + type: 'module', + }, + }, + ] } const recurseRoute = ( @@ -162,12 +179,6 @@ export function startManifestPlugin( routes, } - if (process.env.TSR_VITE_DEBUG) { - console.info( - 'Routes Manifest: \n' + JSON.stringify(routesManifest, null, 2), - ) - } - return `export default () => (${JSON.stringify(routesManifest)})` } return diff --git a/packages/start-server-core/src/router-manifest.ts b/packages/start-server-core/src/router-manifest.ts index 44e851527d..546342724f 100644 --- a/packages/start-server-core/src/router-manifest.ts +++ b/packages/start-server-core/src/router-manifest.ts @@ -21,23 +21,6 @@ export function getStartManifest() { rootRoute.assets = rootRoute.assets || [] - let script = '' - // Always fake that HMR is ready - if (process.env.NODE_ENV === 'development') { - const CLIENT_BASE = sanitizeBase(process.env.TSS_CLIENT_BASE || '') - - if (!CLIENT_BASE) { - throw new Error( - 'tanstack/start-router-manifest: TSS_CLIENT_BASE must be defined in your environment for getFullRouterManifest()', - ) - } - script = `import RefreshRuntime from "${path.join('/', '@react-refresh')}"; - RefreshRuntime.injectIntoGlobalHook(window) - window.$RefreshReg$ = () => {} - window.$RefreshSig$ = () => (type) => type - window.__vite_plugin_react_preamble_installed__ = true;` - } - // Get the entry for the client from vinxi // const vinxiClientManifest = getManifest('client') @@ -47,26 +30,41 @@ export function getStartManifest() { // invariant(importPath, 'Could not find client entry in vinxi manifest') // } - if (!process.env.TSS_CLIENT_ENTRY) { + if (process.env.NODE_ENV === 'development' && !process.env.TSS_CLIENT_ENTRY) { throw new Error( 'tanstack/start-router-manifest: TSS_CLIENT_ENTRY must be defined in your environment for getStartManifest()', ) } - rootRoute.assets.push({ - tag: 'script', - attrs: { - type: 'module', - suppressHydrationWarning: true, - async: true, - }, - children: `${script};\nimport(${JSON.stringify( - process.env.TSS_CLIENT_ENTRY, - )})`, - }) + if (process.env.NODE_ENV === 'development') { + // Always fake that HMR is ready + // const CLIENT_BASE = sanitizeBase(process.env.TSS_CLIENT_BASE || '') - // Strip out anything that isn't needed for the client - return { + // if (!CLIENT_BASE) { + // throw new Error( + // 'tanstack/start-router-manifest: TSS_CLIENT_BASE must be defined in your environment for getFullRouterManifest()', + // ) + // } + + const script = `import RefreshRuntime from "${path.join('/', '@react-refresh')}"; + RefreshRuntime.injectIntoGlobalHook(window) + window.$RefreshReg$ = () => {} + window.$RefreshSig$ = () => (type) => type + window.__vite_plugin_react_preamble_installed__ = true; + import(${JSON.stringify(process.env.TSS_CLIENT_ENTRY)})` + + rootRoute.assets.push({ + tag: 'script', + attrs: { + type: 'module', + suppressHydrationWarning: true, + async: true, + }, + children: script, + }) + } + + const manifest = { ...startManifest, routes: Object.fromEntries( Object.entries(startManifest.routes).map(([k, v]: any) => { @@ -81,4 +79,7 @@ export function getStartManifest() { }), ), } + + // Strip out anything that isn't needed for the client + return manifest } From e06b787b9ca18e4d57a1ec4217a98e9f17d5c78a Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Wed, 12 Mar 2025 15:19:35 +0100 Subject: [PATCH 045/155] add solid-start-plugin and start-basic example --- examples/solid/start-basic/.gitignore | 18 + examples/solid/start-basic/.prettierignore | 4 + .../solid/start-basic/.vscode/settings.json | 11 + examples/solid/start-basic/README.md | 72 +++ examples/solid/start-basic/package.json | 28 + examples/solid/start-basic/postcss.config.mjs | 6 + .../public/android-chrome-192x192.png | Bin 0 -> 29964 bytes .../public/android-chrome-512x512.png | Bin 0 -> 109271 bytes .../start-basic/public/apple-touch-icon.png | Bin 0 -> 27246 bytes .../start-basic/public/favicon-16x16.png | Bin 0 -> 832 bytes .../start-basic/public/favicon-32x32.png | Bin 0 -> 2115 bytes examples/solid/start-basic/public/favicon.ico | Bin 0 -> 15406 bytes examples/solid/start-basic/public/favicon.png | Bin 0 -> 1507 bytes .../solid/start-basic/public/site.webmanifest | 19 + .../src/components/DefaultCatchBoundary.tsx | 53 ++ .../start-basic/src/components/NotFound.tsx | 25 + .../start-basic/src/components/PostError.tsx | 5 + .../start-basic/src/components/UserError.tsx | 5 + .../solid/start-basic/src/routeTree.gen.ts | 479 ++++++++++++++++++ examples/solid/start-basic/src/router.tsx | 22 + .../solid/start-basic/src/routes/__root.tsx | 139 +++++ .../src/routes/_pathlessLayout.tsx | 16 + .../routes/_pathlessLayout/_nested-layout.tsx | 34 ++ .../_nested-layout/route-a.tsx | 11 + .../_nested-layout/route-b.tsx | 11 + .../start-basic/src/routes/api/users.$id.ts | 24 + .../solid/start-basic/src/routes/api/users.ts | 17 + .../solid/start-basic/src/routes/deferred.tsx | 62 +++ .../solid/start-basic/src/routes/index.tsx | 13 + .../start-basic/src/routes/posts.$postId.tsx | 34 ++ .../start-basic/src/routes/posts.index.tsx | 9 + .../solid/start-basic/src/routes/posts.tsx | 38 ++ .../src/routes/posts_.$postId.deep.tsx | 29 ++ .../solid/start-basic/src/routes/redirect.tsx | 9 + .../start-basic/src/routes/users.$userId.tsx | 33 ++ .../start-basic/src/routes/users.index.tsx | 9 + .../solid/start-basic/src/routes/users.tsx | 48 ++ examples/solid/start-basic/src/styles/app.css | 22 + .../src/utils/loggingMiddleware.tsx | 41 ++ .../solid/start-basic/src/utils/posts.tsx | 36 ++ examples/solid/start-basic/src/utils/seo.ts | 33 ++ .../solid/start-basic/src/utils/users.tsx | 7 + .../solid/start-basic/tailwind.config.mjs | 4 + examples/solid/start-basic/tsconfig.json | 23 + examples/solid/start-basic/vite.config.ts | 19 + packages/solid-start-plugin/README.md | 2 +- packages/solid-start-plugin/package.json | 27 +- packages/solid-start-plugin/src/index.ts | 287 +++++++---- .../src/nitro/build-server.ts | 39 ++ .../src/nitro/build-sitemap.ts | 79 +++ .../src/nitro/dev-server-plugin.ts | 152 ++++++ .../src/nitro/nitro-plugin.ts | 191 +++++++ .../solid-start-plugin/src/nitro/options.ts | 80 +++ .../src/routesManifestPlugin.ts | 187 +++++++ packages/solid-start-plugin/src/schema.ts | 150 ++++++ .../src/start-compiler-plugin.ts | 150 ++++++ packages/solid-start-plugin/tsconfig.json | 5 +- packages/solid-start-plugin/vite.config.ts | 1 + pnpm-lock.yaml | 95 +++- 59 files changed, 2782 insertions(+), 131 deletions(-) create mode 100644 examples/solid/start-basic/.gitignore create mode 100644 examples/solid/start-basic/.prettierignore create mode 100644 examples/solid/start-basic/.vscode/settings.json create mode 100644 examples/solid/start-basic/README.md create mode 100644 examples/solid/start-basic/package.json create mode 100644 examples/solid/start-basic/postcss.config.mjs create mode 100644 examples/solid/start-basic/public/android-chrome-192x192.png create mode 100644 examples/solid/start-basic/public/android-chrome-512x512.png create mode 100644 examples/solid/start-basic/public/apple-touch-icon.png create mode 100644 examples/solid/start-basic/public/favicon-16x16.png create mode 100644 examples/solid/start-basic/public/favicon-32x32.png create mode 100644 examples/solid/start-basic/public/favicon.ico create mode 100644 examples/solid/start-basic/public/favicon.png create mode 100644 examples/solid/start-basic/public/site.webmanifest create mode 100644 examples/solid/start-basic/src/components/DefaultCatchBoundary.tsx create mode 100644 examples/solid/start-basic/src/components/NotFound.tsx create mode 100644 examples/solid/start-basic/src/components/PostError.tsx create mode 100644 examples/solid/start-basic/src/components/UserError.tsx create mode 100644 examples/solid/start-basic/src/routeTree.gen.ts create mode 100644 examples/solid/start-basic/src/router.tsx create mode 100644 examples/solid/start-basic/src/routes/__root.tsx create mode 100644 examples/solid/start-basic/src/routes/_pathlessLayout.tsx create mode 100644 examples/solid/start-basic/src/routes/_pathlessLayout/_nested-layout.tsx create mode 100644 examples/solid/start-basic/src/routes/_pathlessLayout/_nested-layout/route-a.tsx create mode 100644 examples/solid/start-basic/src/routes/_pathlessLayout/_nested-layout/route-b.tsx create mode 100644 examples/solid/start-basic/src/routes/api/users.$id.ts create mode 100644 examples/solid/start-basic/src/routes/api/users.ts create mode 100644 examples/solid/start-basic/src/routes/deferred.tsx create mode 100644 examples/solid/start-basic/src/routes/index.tsx create mode 100644 examples/solid/start-basic/src/routes/posts.$postId.tsx create mode 100644 examples/solid/start-basic/src/routes/posts.index.tsx create mode 100644 examples/solid/start-basic/src/routes/posts.tsx create mode 100644 examples/solid/start-basic/src/routes/posts_.$postId.deep.tsx create mode 100644 examples/solid/start-basic/src/routes/redirect.tsx create mode 100644 examples/solid/start-basic/src/routes/users.$userId.tsx create mode 100644 examples/solid/start-basic/src/routes/users.index.tsx create mode 100644 examples/solid/start-basic/src/routes/users.tsx create mode 100644 examples/solid/start-basic/src/styles/app.css create mode 100644 examples/solid/start-basic/src/utils/loggingMiddleware.tsx create mode 100644 examples/solid/start-basic/src/utils/posts.tsx create mode 100644 examples/solid/start-basic/src/utils/seo.ts create mode 100644 examples/solid/start-basic/src/utils/users.tsx create mode 100644 examples/solid/start-basic/tailwind.config.mjs create mode 100644 examples/solid/start-basic/tsconfig.json create mode 100644 examples/solid/start-basic/vite.config.ts create mode 100644 packages/solid-start-plugin/src/nitro/build-server.ts create mode 100644 packages/solid-start-plugin/src/nitro/build-sitemap.ts create mode 100644 packages/solid-start-plugin/src/nitro/dev-server-plugin.ts create mode 100644 packages/solid-start-plugin/src/nitro/nitro-plugin.ts create mode 100644 packages/solid-start-plugin/src/nitro/options.ts create mode 100644 packages/solid-start-plugin/src/routesManifestPlugin.ts create mode 100644 packages/solid-start-plugin/src/schema.ts create mode 100644 packages/solid-start-plugin/src/start-compiler-plugin.ts diff --git a/examples/solid/start-basic/.gitignore b/examples/solid/start-basic/.gitignore new file mode 100644 index 0000000000..ca63f49885 --- /dev/null +++ b/examples/solid/start-basic/.gitignore @@ -0,0 +1,18 @@ +node_modules +package-lock.json +yarn.lock + +.DS_Store +.cache +.env +.vercel +.output +/build/ +/api/ +/server/build +/public/build# Sentry Config File +.env.sentry-build-plugin +/test-results/ +/playwright-report/ +/blob-report/ +/playwright/.cache/ diff --git a/examples/solid/start-basic/.prettierignore b/examples/solid/start-basic/.prettierignore new file mode 100644 index 0000000000..2be5eaa6ec --- /dev/null +++ b/examples/solid/start-basic/.prettierignore @@ -0,0 +1,4 @@ +**/build +**/public +pnpm-lock.yaml +routeTree.gen.ts \ No newline at end of file diff --git a/examples/solid/start-basic/.vscode/settings.json b/examples/solid/start-basic/.vscode/settings.json new file mode 100644 index 0000000000..00b5278e58 --- /dev/null +++ b/examples/solid/start-basic/.vscode/settings.json @@ -0,0 +1,11 @@ +{ + "files.watcherExclude": { + "**/routeTree.gen.ts": true + }, + "search.exclude": { + "**/routeTree.gen.ts": true + }, + "files.readonlyInclude": { + "**/routeTree.gen.ts": true + } +} diff --git a/examples/solid/start-basic/README.md b/examples/solid/start-basic/README.md new file mode 100644 index 0000000000..90cba4aac1 --- /dev/null +++ b/examples/solid/start-basic/README.md @@ -0,0 +1,72 @@ +# Welcome to TanStack.com! + +This site is built with TanStack Router! + +- [TanStack Router Docs](https://tanstack.com/router) + +It's deployed automagically with Netlify! + +- [Netlify](https://netlify.com/) + +## Development + +From your terminal: + +```sh +pnpm install +pnpm dev +``` + +This starts your app in development mode, rebuilding assets on file changes. + +## Editing and previewing the docs of TanStack projects locally + +The documentations for all TanStack projects except for `React Charts` are hosted on [https://tanstack.com](https://tanstack.com), powered by this TanStack Router app. +In production, the markdown doc pages are fetched from the GitHub repos of the projects, but in development they are read from the local file system. + +Follow these steps if you want to edit the doc pages of a project (in these steps we'll assume it's [`TanStack/form`](https://github.com/tanstack/form)) and preview them locally : + +1. Create a new directory called `tanstack`. + +```sh +mkdir tanstack +``` + +2. Enter the directory and clone this repo and the repo of the project there. + +```sh +cd tanstack +git clone git@github.com:TanStack/tanstack.com.git +git clone git@github.com:TanStack/form.git +``` + +> [!NOTE] +> Your `tanstack` directory should look like this: +> +> ``` +> tanstack/ +> | +> +-- form/ +> | +> +-- tanstack.com/ +> ``` + +> [!WARNING] +> Make sure the name of the directory in your local file system matches the name of the project's repo. For example, `tanstack/form` must be cloned into `form` (this is the default) instead of `some-other-name`, because that way, the doc pages won't be found. + +3. Enter the `tanstack/tanstack.com` directory, install the dependencies and run the app in dev mode: + +```sh +cd tanstack.com +pnpm i +# The app will run on https://localhost:3000 by default +pnpm dev +``` + +4. Now you can visit http://localhost:3000/form/latest/docs/overview in the browser and see the changes you make in `tanstack/form/docs`. + +> [!NOTE] +> The updated pages need to be manually reloaded in the browser. + +> [!WARNING] +> You will need to update the `docs/config.json` file (in the project's repo) if you add a new doc page! diff --git a/examples/solid/start-basic/package.json b/examples/solid/start-basic/package.json new file mode 100644 index 0000000000..4695a931f6 --- /dev/null +++ b/examples/solid/start-basic/package.json @@ -0,0 +1,28 @@ +{ + "name": "tanstack-start-example-basic", + "private": true, + "sideEffects": false, + "type": "module", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "start": "vite start" + }, + "dependencies": { + "@tanstack/solid-router": "^1.114.17", + "@tanstack/solid-router-devtools": "^1.114.17", + "@tanstack/solid-start": "workspace:*", + "solid-js": "^1.9.5", + "redaxios": "^0.5.1", + "tailwind-merge": "^2.6.0", + "vite": "6.1.0" + }, + "devDependencies": { + "@types/node": "^22.5.4", + "autoprefixer": "^10.4.20", + "postcss": "^8.5.1", + "tailwindcss": "^3.4.17", + "typescript": "^5.7.2", + "vite-tsconfig-paths": "^5.1.4" + } +} diff --git a/examples/solid/start-basic/postcss.config.mjs b/examples/solid/start-basic/postcss.config.mjs new file mode 100644 index 0000000000..2e7af2b7f1 --- /dev/null +++ b/examples/solid/start-basic/postcss.config.mjs @@ -0,0 +1,6 @@ +export default { + plugins: { + tailwindcss: {}, + autoprefixer: {}, + }, +} diff --git a/examples/solid/start-basic/public/android-chrome-192x192.png b/examples/solid/start-basic/public/android-chrome-192x192.png new file mode 100644 index 0000000000000000000000000000000000000000..09c8324f8c6781bc90fcf5dd38e0702bd5f171f3 GIT binary patch literal 29964 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 b=FG literal 0 HcmV?d00001 diff --git a/examples/solid/start-basic/public/android-chrome-512x512.png b/examples/solid/start-basic/public/android-chrome-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..11d626ea3d00fddd52861bf0af5554a92fc30d69 GIT binary patch literal 109271 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 Ef@mE(_W%F@ literal 0 HcmV?d00001 diff --git a/examples/solid/start-basic/public/apple-touch-icon.png b/examples/solid/start-basic/public/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..5a9423cc02c40ea066d2a061cdcdf621c0718cb1 GIT binary patch literal 27246 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⪼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 N002ovPDHLkV1k;v<;Va4 literal 0 HcmV?d00001 diff --git a/examples/solid/start-basic/public/favicon-16x16.png b/examples/solid/start-basic/public/favicon-16x16.png new file mode 100644 index 0000000000000000000000000000000000000000..e3389b00443d602a249b48ae0e21e333971c9c1e GIT binary patch literal 832 zcmV-G1Hb%Px%`bk7VR5(v%lW%BSRTRK~=OuZ4FYhI3vvy^4t8t~UDHGBS#44K%hSiDal!9Nj zeb^RZ;3&cb72F3w6s4;uUA7>Cf>1=Z56;a$8wZ=NKHtq z33GDV=_|V0E(QPTEB1=edhG{{=-+C??RQi7*e9J7YBnZR+PppIKjA8EV+}Yt`zH<7 zGR%O5D3|Ef)99hUXu19=Cxaki@6toZIe&u-X0(oDFRl|x6P7Bwc^mB(i9|gOY)Jh6DaPkmt z8Wr!@TP1|RPlYRlJe^eRB0K(gn91{(=zi{HrkpHIflw8&q%;+U!V&dFPYDQAWJh@< zwcklN9VEX?vG;}75GqCepKC25M^xV%BcR%A8c!)S5k4P0$g}HS#lA6zy`~K@9&EX4 zOrvr%_1U2dp~gg6G*;&`Jag*?jZTJv+$S`*#)zme_SFWOCm*F4U&hJihqxAu;8z}x zWv7!u>YKRa3PUJQs55wC)i4QvFOAV0jW$?1cnUJJ7Vl?z_ge{9q!zpfCJxd8vJ>-ql@0&`Bttn1~4;s>8tax%hr(^q#A_*wqAv( zh(T&>hJD?OhiP$sxAzkd1W1^EHV1WL3xM&6$*HhG@|8}OjPpG{+!;GC>w;ha0000< KMNUMnLSTZGXp5cz literal 0 HcmV?d00001 diff --git a/examples/solid/start-basic/public/favicon-32x32.png b/examples/solid/start-basic/public/favicon-32x32.png new file mode 100644 index 0000000000000000000000000000000000000000..900c77d444c9b31e6144b6ac0bb1ab7bb7ca767f GIT binary patch literal 2115 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 literal 0 HcmV?d00001 diff --git a/examples/solid/start-basic/public/favicon.ico b/examples/solid/start-basic/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..1a1751676f7e22811b1070572093996c93c87617 GIT binary patch literal 15406 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 literal 0 HcmV?d00001 diff --git a/examples/solid/start-basic/public/favicon.png b/examples/solid/start-basic/public/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..1e77bc06091ade4496525a09d8900675afcf03f0 GIT binary patch literal 1507 zcmV<91swW`P)Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031000^Q000001E2u_0{{R30RRC20H6W@ z1ONa40RR91AfN*P1ONa40RR91AOHXW0IY^$^8f$^O-V#SR9Fd>S3Qp$MHK9ro!#4$ zEP@L_hX|b@f=!*_42h6mKu7{)4)_U*>1>0bCkUj;Z1X!7 zHe(Ew^Oi(|bW3J~xu+)XbtFF?4>!7TH$>(D_atUQVEj(8fGvYu2NF33#JZX>)(Vj8 zIi@z>Glt?6t~;Lf(|C8F>;WF^8F<^s7Scr!sZc01uB?HMHoL5+FZ>B(g+r-)?Sn)#3Zal#?G@GAwO5U27MpGOlC2+_saA)rl zP-<@-n~;PQOlm|Hi<+W;NdR;5+=zADzM&?!+CPD36=cGwHy6!D^vPEHG?rO`K>G|M z3FposX{yT132wuw1OR3Um_5JoKB#6?!QgBupIT;?YIr;WcpmuCE>S75mZid+ens#E zGPuYjiG0UNNVWu=f!Id^?9)34)eIpu-`j_~W0iAQzK(}XYc_!;87Tk~?4tq|h=2(! zuq0HCiNK)@+ocCKR3q1REdUju>HdYxd>JX@%oOibg+J~D+}rhz54D!NfC{h-OYk{M zkzmFtdrL@nL0bm8nF@pob1CeLC>12ef#in-Bzv2!wi)Iuwq24)`AH}|0QNQ^f$KHv z?5PBPo1*#GAuAk+Poe`?UJ>mP`@~d4a(103j0lwUx@_+$#B&VC%7r>#2$HIiD`KO8L|s3Yp%M}BT0;NJDzZtPnx=4%enhU zhW*pNN0t`^4%5MKAR+}=^Q?QeqQ`>bbK zf+-ji$Uz8V0?LpX@kh`k%DL)GCA2=@SJNKg56Wh>>pr=7{1PmHqG|~=AdLV3002ov JPDHLkV1ivgp)>#h literal 0 HcmV?d00001 diff --git a/examples/solid/start-basic/public/site.webmanifest b/examples/solid/start-basic/public/site.webmanifest new file mode 100644 index 0000000000..fa99de77db --- /dev/null +++ b/examples/solid/start-basic/public/site.webmanifest @@ -0,0 +1,19 @@ +{ + "name": "", + "short_name": "", + "icons": [ + { + "src": "/android-chrome-192x192.png", + "sizes": "192x192", + "type": "image/png" + }, + { + "src": "/android-chrome-512x512.png", + "sizes": "512x512", + "type": "image/png" + } + ], + "theme_color": "#ffffff", + "background_color": "#ffffff", + "display": "standalone" +} diff --git a/examples/solid/start-basic/src/components/DefaultCatchBoundary.tsx b/examples/solid/start-basic/src/components/DefaultCatchBoundary.tsx new file mode 100644 index 0000000000..0dff3919fd --- /dev/null +++ b/examples/solid/start-basic/src/components/DefaultCatchBoundary.tsx @@ -0,0 +1,53 @@ +import { + ErrorComponent, + Link, + rootRouteId, + useMatch, + useRouter, +} from '@tanstack/solid-router' +import type { ErrorComponentProps } from '@tanstack/solid-router' + +export function DefaultCatchBoundary({ error }: ErrorComponentProps) { + const router = useRouter() + const isRoot = useMatch({ + strict: false, + select: (state) => state.id === rootRouteId, + }) + + console.error('DefaultCatchBoundary Error:', error) + + return ( +
+ +
+ + {isRoot() ? ( + + Home + + ) : ( + { + e.preventDefault() + window.history.back() + }} + > + Go Back + + )} +
+
+ ) +} diff --git a/examples/solid/start-basic/src/components/NotFound.tsx b/examples/solid/start-basic/src/components/NotFound.tsx new file mode 100644 index 0000000000..ca4c1960fa --- /dev/null +++ b/examples/solid/start-basic/src/components/NotFound.tsx @@ -0,0 +1,25 @@ +import { Link } from '@tanstack/solid-router' + +export function NotFound({ children }: { children?: any }) { + return ( +
+
+ {children ||

The page you are looking for does not exist.

} +
+

+ + + Start Over + +

+
+ ) +} diff --git a/examples/solid/start-basic/src/components/PostError.tsx b/examples/solid/start-basic/src/components/PostError.tsx new file mode 100644 index 0000000000..3e5d62c79b --- /dev/null +++ b/examples/solid/start-basic/src/components/PostError.tsx @@ -0,0 +1,5 @@ +import { ErrorComponent, ErrorComponentProps } from '@tanstack/solid-router' + +export function PostErrorComponent({ error }: ErrorComponentProps) { + return +} diff --git a/examples/solid/start-basic/src/components/UserError.tsx b/examples/solid/start-basic/src/components/UserError.tsx new file mode 100644 index 0000000000..69762add4c --- /dev/null +++ b/examples/solid/start-basic/src/components/UserError.tsx @@ -0,0 +1,5 @@ +import { ErrorComponent, ErrorComponentProps } from '@tanstack/solid-router' + +export function UserErrorComponent({ error }: ErrorComponentProps) { + return +} diff --git a/examples/solid/start-basic/src/routeTree.gen.ts b/examples/solid/start-basic/src/routeTree.gen.ts new file mode 100644 index 0000000000..85d334d325 --- /dev/null +++ b/examples/solid/start-basic/src/routeTree.gen.ts @@ -0,0 +1,479 @@ +/* eslint-disable */ + +// @ts-nocheck + +// noinspection JSUnusedGlobalSymbols + +// This file was automatically generated by TanStack Router. +// You should NOT make any changes in this file as it will be overwritten. +// Additionally, you should also exclude this file from your linter and/or formatter to prevent it from being checked or modified. + +// Import Routes + +import { Route as rootRoute } from './routes/__root' +import { Route as UsersImport } from './routes/users' +import { Route as RedirectImport } from './routes/redirect' +import { Route as PostsImport } from './routes/posts' +import { Route as DeferredImport } from './routes/deferred' +import { Route as PathlessLayoutImport } from './routes/_pathlessLayout' +import { Route as IndexImport } from './routes/index' +import { Route as UsersIndexImport } from './routes/users.index' +import { Route as PostsIndexImport } from './routes/posts.index' +import { Route as UsersUserIdImport } from './routes/users.$userId' +import { Route as PostsPostIdImport } from './routes/posts.$postId' +import { Route as PathlessLayoutNestedLayoutImport } from './routes/_pathlessLayout/_nested-layout' +import { Route as PostsPostIdDeepImport } from './routes/posts_.$postId.deep' +import { Route as PathlessLayoutNestedLayoutRouteBImport } from './routes/_pathlessLayout/_nested-layout/route-b' +import { Route as PathlessLayoutNestedLayoutRouteAImport } from './routes/_pathlessLayout/_nested-layout/route-a' + +// Create/Update Routes + +const UsersRoute = UsersImport.update({ + id: '/users', + path: '/users', + getParentRoute: () => rootRoute, +} as any) + +const RedirectRoute = RedirectImport.update({ + id: '/redirect', + path: '/redirect', + getParentRoute: () => rootRoute, +} as any) + +const PostsRoute = PostsImport.update({ + id: '/posts', + path: '/posts', + getParentRoute: () => rootRoute, +} as any) + +const DeferredRoute = DeferredImport.update({ + id: '/deferred', + path: '/deferred', + getParentRoute: () => rootRoute, +} as any) + +const PathlessLayoutRoute = PathlessLayoutImport.update({ + id: '/_pathlessLayout', + getParentRoute: () => rootRoute, +} as any) + +const IndexRoute = IndexImport.update({ + id: '/', + path: '/', + getParentRoute: () => rootRoute, +} as any) + +const UsersIndexRoute = UsersIndexImport.update({ + id: '/', + path: '/', + getParentRoute: () => UsersRoute, +} as any) + +const PostsIndexRoute = PostsIndexImport.update({ + id: '/', + path: '/', + getParentRoute: () => PostsRoute, +} as any) + +const UsersUserIdRoute = UsersUserIdImport.update({ + id: '/$userId', + path: '/$userId', + getParentRoute: () => UsersRoute, +} as any) + +const PostsPostIdRoute = PostsPostIdImport.update({ + id: '/$postId', + path: '/$postId', + getParentRoute: () => PostsRoute, +} as any) + +const PathlessLayoutNestedLayoutRoute = PathlessLayoutNestedLayoutImport.update( + { + id: '/_nested-layout', + getParentRoute: () => PathlessLayoutRoute, + } as any, +) + +const PostsPostIdDeepRoute = PostsPostIdDeepImport.update({ + id: '/posts_/$postId/deep', + path: '/posts/$postId/deep', + getParentRoute: () => rootRoute, +} as any) + +const PathlessLayoutNestedLayoutRouteBRoute = + PathlessLayoutNestedLayoutRouteBImport.update({ + id: '/route-b', + path: '/route-b', + getParentRoute: () => PathlessLayoutNestedLayoutRoute, + } as any) + +const PathlessLayoutNestedLayoutRouteARoute = + PathlessLayoutNestedLayoutRouteAImport.update({ + id: '/route-a', + path: '/route-a', + getParentRoute: () => PathlessLayoutNestedLayoutRoute, + } as any) + +// Populate the FileRoutesByPath interface + +declare module '@tanstack/solid-router' { + interface FileRoutesByPath { + '/': { + id: '/' + path: '/' + fullPath: '/' + preLoaderRoute: typeof IndexImport + parentRoute: typeof rootRoute + } + '/_pathlessLayout': { + id: '/_pathlessLayout' + path: '' + fullPath: '' + preLoaderRoute: typeof PathlessLayoutImport + parentRoute: typeof rootRoute + } + '/deferred': { + id: '/deferred' + path: '/deferred' + fullPath: '/deferred' + preLoaderRoute: typeof DeferredImport + parentRoute: typeof rootRoute + } + '/posts': { + id: '/posts' + path: '/posts' + fullPath: '/posts' + preLoaderRoute: typeof PostsImport + parentRoute: typeof rootRoute + } + '/redirect': { + id: '/redirect' + path: '/redirect' + fullPath: '/redirect' + preLoaderRoute: typeof RedirectImport + parentRoute: typeof rootRoute + } + '/users': { + id: '/users' + path: '/users' + fullPath: '/users' + preLoaderRoute: typeof UsersImport + parentRoute: typeof rootRoute + } + '/_pathlessLayout/_nested-layout': { + id: '/_pathlessLayout/_nested-layout' + path: '' + fullPath: '' + preLoaderRoute: typeof PathlessLayoutNestedLayoutImport + parentRoute: typeof PathlessLayoutImport + } + '/posts/$postId': { + id: '/posts/$postId' + path: '/$postId' + fullPath: '/posts/$postId' + preLoaderRoute: typeof PostsPostIdImport + parentRoute: typeof PostsImport + } + '/users/$userId': { + id: '/users/$userId' + path: '/$userId' + fullPath: '/users/$userId' + preLoaderRoute: typeof UsersUserIdImport + parentRoute: typeof UsersImport + } + '/posts/': { + id: '/posts/' + path: '/' + fullPath: '/posts/' + preLoaderRoute: typeof PostsIndexImport + parentRoute: typeof PostsImport + } + '/users/': { + id: '/users/' + path: '/' + fullPath: '/users/' + preLoaderRoute: typeof UsersIndexImport + parentRoute: typeof UsersImport + } + '/_pathlessLayout/_nested-layout/route-a': { + id: '/_pathlessLayout/_nested-layout/route-a' + path: '/route-a' + fullPath: '/route-a' + preLoaderRoute: typeof PathlessLayoutNestedLayoutRouteAImport + parentRoute: typeof PathlessLayoutNestedLayoutImport + } + '/_pathlessLayout/_nested-layout/route-b': { + id: '/_pathlessLayout/_nested-layout/route-b' + path: '/route-b' + fullPath: '/route-b' + preLoaderRoute: typeof PathlessLayoutNestedLayoutRouteBImport + parentRoute: typeof PathlessLayoutNestedLayoutImport + } + '/posts_/$postId/deep': { + id: '/posts_/$postId/deep' + path: '/posts/$postId/deep' + fullPath: '/posts/$postId/deep' + preLoaderRoute: typeof PostsPostIdDeepImport + parentRoute: typeof rootRoute + } + } +} + +// Create and export the route tree + +interface PathlessLayoutNestedLayoutRouteChildren { + PathlessLayoutNestedLayoutRouteARoute: typeof PathlessLayoutNestedLayoutRouteARoute + PathlessLayoutNestedLayoutRouteBRoute: typeof PathlessLayoutNestedLayoutRouteBRoute +} + +const PathlessLayoutNestedLayoutRouteChildren: PathlessLayoutNestedLayoutRouteChildren = + { + PathlessLayoutNestedLayoutRouteARoute: + PathlessLayoutNestedLayoutRouteARoute, + PathlessLayoutNestedLayoutRouteBRoute: + PathlessLayoutNestedLayoutRouteBRoute, + } + +const PathlessLayoutNestedLayoutRouteWithChildren = + PathlessLayoutNestedLayoutRoute._addFileChildren( + PathlessLayoutNestedLayoutRouteChildren, + ) + +interface PathlessLayoutRouteChildren { + PathlessLayoutNestedLayoutRoute: typeof PathlessLayoutNestedLayoutRouteWithChildren +} + +const PathlessLayoutRouteChildren: PathlessLayoutRouteChildren = { + PathlessLayoutNestedLayoutRoute: PathlessLayoutNestedLayoutRouteWithChildren, +} + +const PathlessLayoutRouteWithChildren = PathlessLayoutRoute._addFileChildren( + PathlessLayoutRouteChildren, +) + +interface PostsRouteChildren { + PostsPostIdRoute: typeof PostsPostIdRoute + PostsIndexRoute: typeof PostsIndexRoute +} + +const PostsRouteChildren: PostsRouteChildren = { + PostsPostIdRoute: PostsPostIdRoute, + PostsIndexRoute: PostsIndexRoute, +} + +const PostsRouteWithChildren = PostsRoute._addFileChildren(PostsRouteChildren) + +interface UsersRouteChildren { + UsersUserIdRoute: typeof UsersUserIdRoute + UsersIndexRoute: typeof UsersIndexRoute +} + +const UsersRouteChildren: UsersRouteChildren = { + UsersUserIdRoute: UsersUserIdRoute, + UsersIndexRoute: UsersIndexRoute, +} + +const UsersRouteWithChildren = UsersRoute._addFileChildren(UsersRouteChildren) + +export interface FileRoutesByFullPath { + '/': typeof IndexRoute + '': typeof PathlessLayoutNestedLayoutRouteWithChildren + '/deferred': typeof DeferredRoute + '/posts': typeof PostsRouteWithChildren + '/redirect': typeof RedirectRoute + '/users': typeof UsersRouteWithChildren + '/posts/$postId': typeof PostsPostIdRoute + '/users/$userId': typeof UsersUserIdRoute + '/posts/': typeof PostsIndexRoute + '/users/': typeof UsersIndexRoute + '/route-a': typeof PathlessLayoutNestedLayoutRouteARoute + '/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute + '/posts/$postId/deep': typeof PostsPostIdDeepRoute +} + +export interface FileRoutesByTo { + '/': typeof IndexRoute + '': typeof PathlessLayoutNestedLayoutRouteWithChildren + '/deferred': typeof DeferredRoute + '/redirect': typeof RedirectRoute + '/posts/$postId': typeof PostsPostIdRoute + '/users/$userId': typeof UsersUserIdRoute + '/posts': typeof PostsIndexRoute + '/users': typeof UsersIndexRoute + '/route-a': typeof PathlessLayoutNestedLayoutRouteARoute + '/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute + '/posts/$postId/deep': typeof PostsPostIdDeepRoute +} + +export interface FileRoutesById { + __root__: typeof rootRoute + '/': typeof IndexRoute + '/_pathlessLayout': typeof PathlessLayoutRouteWithChildren + '/deferred': typeof DeferredRoute + '/posts': typeof PostsRouteWithChildren + '/redirect': typeof RedirectRoute + '/users': typeof UsersRouteWithChildren + '/_pathlessLayout/_nested-layout': typeof PathlessLayoutNestedLayoutRouteWithChildren + '/posts/$postId': typeof PostsPostIdRoute + '/users/$userId': typeof UsersUserIdRoute + '/posts/': typeof PostsIndexRoute + '/users/': typeof UsersIndexRoute + '/_pathlessLayout/_nested-layout/route-a': typeof PathlessLayoutNestedLayoutRouteARoute + '/_pathlessLayout/_nested-layout/route-b': typeof PathlessLayoutNestedLayoutRouteBRoute + '/posts_/$postId/deep': typeof PostsPostIdDeepRoute +} + +export interface FileRouteTypes { + fileRoutesByFullPath: FileRoutesByFullPath + fullPaths: + | '/' + | '' + | '/deferred' + | '/posts' + | '/redirect' + | '/users' + | '/posts/$postId' + | '/users/$userId' + | '/posts/' + | '/users/' + | '/route-a' + | '/route-b' + | '/posts/$postId/deep' + fileRoutesByTo: FileRoutesByTo + to: + | '/' + | '' + | '/deferred' + | '/redirect' + | '/posts/$postId' + | '/users/$userId' + | '/posts' + | '/users' + | '/route-a' + | '/route-b' + | '/posts/$postId/deep' + id: + | '__root__' + | '/' + | '/_pathlessLayout' + | '/deferred' + | '/posts' + | '/redirect' + | '/users' + | '/_pathlessLayout/_nested-layout' + | '/posts/$postId' + | '/users/$userId' + | '/posts/' + | '/users/' + | '/_pathlessLayout/_nested-layout/route-a' + | '/_pathlessLayout/_nested-layout/route-b' + | '/posts_/$postId/deep' + fileRoutesById: FileRoutesById +} + +export interface RootRouteChildren { + IndexRoute: typeof IndexRoute + PathlessLayoutRoute: typeof PathlessLayoutRouteWithChildren + DeferredRoute: typeof DeferredRoute + PostsRoute: typeof PostsRouteWithChildren + RedirectRoute: typeof RedirectRoute + UsersRoute: typeof UsersRouteWithChildren + PostsPostIdDeepRoute: typeof PostsPostIdDeepRoute +} + +const rootRouteChildren: RootRouteChildren = { + IndexRoute: IndexRoute, + PathlessLayoutRoute: PathlessLayoutRouteWithChildren, + DeferredRoute: DeferredRoute, + PostsRoute: PostsRouteWithChildren, + RedirectRoute: RedirectRoute, + UsersRoute: UsersRouteWithChildren, + PostsPostIdDeepRoute: PostsPostIdDeepRoute, +} + +export const routeTree = rootRoute + ._addFileChildren(rootRouteChildren) + ._addFileTypes() + +/* ROUTE_MANIFEST_START +{ + "routes": { + "__root__": { + "filePath": "__root.tsx", + "children": [ + "/", + "/_pathlessLayout", + "/deferred", + "/posts", + "/redirect", + "/users", + "/posts_/$postId/deep" + ] + }, + "/": { + "filePath": "index.tsx" + }, + "/_pathlessLayout": { + "filePath": "_pathlessLayout.tsx", + "children": [ + "/_pathlessLayout/_nested-layout" + ] + }, + "/deferred": { + "filePath": "deferred.tsx" + }, + "/posts": { + "filePath": "posts.tsx", + "children": [ + "/posts/$postId", + "/posts/" + ] + }, + "/redirect": { + "filePath": "redirect.tsx" + }, + "/users": { + "filePath": "users.tsx", + "children": [ + "/users/$userId", + "/users/" + ] + }, + "/_pathlessLayout/_nested-layout": { + "filePath": "_pathlessLayout/_nested-layout.tsx", + "parent": "/_pathlessLayout", + "children": [ + "/_pathlessLayout/_nested-layout/route-a", + "/_pathlessLayout/_nested-layout/route-b" + ] + }, + "/posts/$postId": { + "filePath": "posts.$postId.tsx", + "parent": "/posts" + }, + "/users/$userId": { + "filePath": "users.$userId.tsx", + "parent": "/users" + }, + "/posts/": { + "filePath": "posts.index.tsx", + "parent": "/posts" + }, + "/users/": { + "filePath": "users.index.tsx", + "parent": "/users" + }, + "/_pathlessLayout/_nested-layout/route-a": { + "filePath": "_pathlessLayout/_nested-layout/route-a.tsx", + "parent": "/_pathlessLayout/_nested-layout" + }, + "/_pathlessLayout/_nested-layout/route-b": { + "filePath": "_pathlessLayout/_nested-layout/route-b.tsx", + "parent": "/_pathlessLayout/_nested-layout" + }, + "/posts_/$postId/deep": { + "filePath": "posts_.$postId.deep.tsx" + } + } +} +ROUTE_MANIFEST_END */ diff --git a/examples/solid/start-basic/src/router.tsx b/examples/solid/start-basic/src/router.tsx new file mode 100644 index 0000000000..c45bed4758 --- /dev/null +++ b/examples/solid/start-basic/src/router.tsx @@ -0,0 +1,22 @@ +import { createRouter as createTanStackRouter } from '@tanstack/solid-router' +import { routeTree } from './routeTree.gen' +import { DefaultCatchBoundary } from './components/DefaultCatchBoundary' +import { NotFound } from './components/NotFound' + +export function createRouter() { + const router = createTanStackRouter({ + routeTree, + defaultPreload: 'intent', + defaultErrorComponent: DefaultCatchBoundary, + defaultNotFoundComponent: () => , + scrollRestoration: true, + }) + + return router +} + +declare module '@tanstack/solid-router' { + interface Register { + router: ReturnType + } +} diff --git a/examples/solid/start-basic/src/routes/__root.tsx b/examples/solid/start-basic/src/routes/__root.tsx new file mode 100644 index 0000000000..c3e395041f --- /dev/null +++ b/examples/solid/start-basic/src/routes/__root.tsx @@ -0,0 +1,139 @@ +import { + HeadContent, + Link, + Outlet, + Scripts, + createRootRoute, +} from '@tanstack/solid-router' +import { TanStackRouterDevtools } from '@tanstack/solid-router-devtools' +import * as Solid from 'solid-js' +import { DefaultCatchBoundary } from '~/components/DefaultCatchBoundary' +import { NotFound } from '~/components/NotFound' +import appCss from '~/styles/app.css?url' +import { seo } from '~/utils/seo' + +export const Route = createRootRoute({ + head: () => ({ + meta: [ + { + charset: 'utf-8', + }, + { + name: 'viewport', + content: 'width=device-width, initial-scale=1', + }, + ...seo({ + title: + 'TanStack Start | Type-Safe, Client-First, Full-Stack React Framework', + description: `TanStack Start is a type-safe, client-first, full-stack React framework. `, + }), + ], + links: [ + { rel: 'stylesheet', href: appCss }, + { + rel: 'apple-touch-icon', + sizes: '180x180', + href: '/apple-touch-icon.png', + }, + { + rel: 'icon', + type: 'image/png', + sizes: '32x32', + href: '/favicon-32x32.png', + }, + { + rel: 'icon', + type: 'image/png', + sizes: '16x16', + href: '/favicon-16x16.png', + }, + { rel: 'manifest', href: '/site.webmanifest', color: '#fffff' }, + { rel: 'icon', href: '/favicon.ico' }, + ], + }), + errorComponent: (props) => { + return ( + + + + ) + }, + notFoundComponent: () => , + component: RootComponent, +}) + +function RootComponent() { + return ( + + + + ) +} + +function RootDocument({ children }: { children: Solid.JSX.Element }) { + return ( + + + + + +
+ + Home + {' '} + + Posts + {' '} + + Users + {' '} + + Pathless Layout + {' '} + + Deferred + {' '} + + This Route Does Not Exist + +
+
+ {children} + + + + + ) +} diff --git a/examples/solid/start-basic/src/routes/_pathlessLayout.tsx b/examples/solid/start-basic/src/routes/_pathlessLayout.tsx new file mode 100644 index 0000000000..af197bc038 --- /dev/null +++ b/examples/solid/start-basic/src/routes/_pathlessLayout.tsx @@ -0,0 +1,16 @@ +import { Outlet, createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/_pathlessLayout')({ + component: LayoutComponent, +}) + +function LayoutComponent() { + return ( +
+
I'm a layout
+
+ +
+
+ ) +} diff --git a/examples/solid/start-basic/src/routes/_pathlessLayout/_nested-layout.tsx b/examples/solid/start-basic/src/routes/_pathlessLayout/_nested-layout.tsx new file mode 100644 index 0000000000..24e4b2545b --- /dev/null +++ b/examples/solid/start-basic/src/routes/_pathlessLayout/_nested-layout.tsx @@ -0,0 +1,34 @@ +import { Link, Outlet, createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/_pathlessLayout/_nested-layout')({ + component: LayoutComponent, +}) + +function LayoutComponent() { + return ( +
+
I'm a nested layout
+
+ + Go to route A + + + Go to route B + +
+
+ +
+
+ ) +} diff --git a/examples/solid/start-basic/src/routes/_pathlessLayout/_nested-layout/route-a.tsx b/examples/solid/start-basic/src/routes/_pathlessLayout/_nested-layout/route-a.tsx new file mode 100644 index 0000000000..a22902a271 --- /dev/null +++ b/examples/solid/start-basic/src/routes/_pathlessLayout/_nested-layout/route-a.tsx @@ -0,0 +1,11 @@ +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/_pathlessLayout/_nested-layout/route-a')( + { + component: LayoutAComponent, + }, +) + +function LayoutAComponent() { + return
I'm A!
+} diff --git a/examples/solid/start-basic/src/routes/_pathlessLayout/_nested-layout/route-b.tsx b/examples/solid/start-basic/src/routes/_pathlessLayout/_nested-layout/route-b.tsx new file mode 100644 index 0000000000..36231d2153 --- /dev/null +++ b/examples/solid/start-basic/src/routes/_pathlessLayout/_nested-layout/route-b.tsx @@ -0,0 +1,11 @@ +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/_pathlessLayout/_nested-layout/route-b')( + { + component: LayoutBComponent, + }, +) + +function LayoutBComponent() { + return
I'm B!
+} diff --git a/examples/solid/start-basic/src/routes/api/users.$id.ts b/examples/solid/start-basic/src/routes/api/users.$id.ts new file mode 100644 index 0000000000..b1797e7917 --- /dev/null +++ b/examples/solid/start-basic/src/routes/api/users.$id.ts @@ -0,0 +1,24 @@ +import { json } from '@tanstack/react-start' +import { createAPIFileRoute } from '@tanstack/react-start/api' +import axios from 'redaxios' +import type { User } from '../../utils/users' + +export const APIRoute = createAPIFileRoute('/api/users/$id')({ + GET: async ({ request, params }) => { + console.info(`Fetching users by id=${params.id}... @`, request.url) + try { + const res = await axios.get( + 'https://jsonplaceholder.typicode.com/users/' + params.id, + ) + + return json({ + id: res.data.id, + name: res.data.name, + email: res.data.email, + }) + } catch (e) { + console.error(e) + return json({ error: 'User not found' }, { status: 404 }) + } + }, +}) diff --git a/examples/solid/start-basic/src/routes/api/users.ts b/examples/solid/start-basic/src/routes/api/users.ts new file mode 100644 index 0000000000..679eb9e8ab --- /dev/null +++ b/examples/solid/start-basic/src/routes/api/users.ts @@ -0,0 +1,17 @@ +import { json } from '@tanstack/react-start' +import { createAPIFileRoute } from '@tanstack/react-start/api' +import axios from 'redaxios' +import type { User } from '../../utils/users' + +export const APIRoute = createAPIFileRoute('/api/users')({ + GET: async ({ request }) => { + console.info('Fetching users... @', request.url) + const res = await axios.get>( + 'https://jsonplaceholder.typicode.com/users', + ) + + const list = res.data.slice(0, 10) + + return json(list.map((u) => ({ id: u.id, name: u.name, email: u.email }))) + }, +}) diff --git a/examples/solid/start-basic/src/routes/deferred.tsx b/examples/solid/start-basic/src/routes/deferred.tsx new file mode 100644 index 0000000000..48f11f2450 --- /dev/null +++ b/examples/solid/start-basic/src/routes/deferred.tsx @@ -0,0 +1,62 @@ +import { Await, createFileRoute } from '@tanstack/solid-router' +import { createServerFn } from '@tanstack/react-start' +import { createSignal, Suspense } from 'solid-js' + +const personServerFn = createServerFn({ method: 'GET' }) + .validator((d: string) => d) + .handler(({ data: name }) => { + return { name, randomNumber: Math.floor(Math.random() * 100) } + }) + +const slowServerFn = createServerFn({ method: 'GET' }) + .validator((d: string) => d) + .handler(async ({ data: name }) => { + await new Promise((r) => setTimeout(r, 1000)) + return { name, randomNumber: Math.floor(Math.random() * 100) } + }) + +export const Route = createFileRoute('/deferred')({ + loader: async () => { + return { + deferredStuff: new Promise((r) => + setTimeout(() => r('Hello deferred!'), 2000), + ), + deferredPerson: slowServerFn({ data: 'Tanner Linsley' }), + person: await personServerFn({ data: 'John Doe' }), + } + }, + component: Deferred, +}) + +function Deferred() { + const [count, setCount] = createSignal(0) + const loaderData = Route.useLoaderData() + + return ( +
+
+ {loaderData().person.name} - {loaderData().person.randomNumber} +
+ Loading person...
}> + ( +
+ {data.name} - {data.randomNumber} +
+ )} + /> + + Loading stuff...}> +

{data}

} + /> +
+
Count: {count()}
+
+ +
+ + ) +} diff --git a/examples/solid/start-basic/src/routes/index.tsx b/examples/solid/start-basic/src/routes/index.tsx new file mode 100644 index 0000000000..a128aeca0e --- /dev/null +++ b/examples/solid/start-basic/src/routes/index.tsx @@ -0,0 +1,13 @@ +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/')({ + component: Home, +}) + +function Home() { + return ( +
+

Welcome Home!!!

+
+ ) +} diff --git a/examples/solid/start-basic/src/routes/posts.$postId.tsx b/examples/solid/start-basic/src/routes/posts.$postId.tsx new file mode 100644 index 0000000000..d13735a4db --- /dev/null +++ b/examples/solid/start-basic/src/routes/posts.$postId.tsx @@ -0,0 +1,34 @@ +import { Link, createFileRoute } from '@tanstack/solid-router' +import { fetchPost } from '../utils/posts' +import { NotFound } from '~/components/NotFound' +import { PostErrorComponent } from '~/components/PostError' + +export const Route = createFileRoute('/posts/$postId')({ + loader: ({ params: { postId } }) => fetchPost({ data: postId }), + errorComponent: PostErrorComponent, + component: PostComponent, + notFoundComponent: () => { + return Post not found + }, +}) + +function PostComponent() { + const post = Route.useLoaderData() + + return ( +
+

{post().title}

+
{post().body}
+ + Deep View + +
+ ) +} diff --git a/examples/solid/start-basic/src/routes/posts.index.tsx b/examples/solid/start-basic/src/routes/posts.index.tsx new file mode 100644 index 0000000000..33d0386c19 --- /dev/null +++ b/examples/solid/start-basic/src/routes/posts.index.tsx @@ -0,0 +1,9 @@ +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/posts/')({ + component: PostsIndexComponent, +}) + +function PostsIndexComponent() { + return
Select a post.
+} diff --git a/examples/solid/start-basic/src/routes/posts.tsx b/examples/solid/start-basic/src/routes/posts.tsx new file mode 100644 index 0000000000..326372478f --- /dev/null +++ b/examples/solid/start-basic/src/routes/posts.tsx @@ -0,0 +1,38 @@ +import { Link, Outlet, createFileRoute } from '@tanstack/solid-router' +import { fetchPosts } from '../utils/posts' + +export const Route = createFileRoute('/posts')({ + loader: async () => fetchPosts(), + component: PostsComponent, +}) + +function PostsComponent() { + const posts = Route.useLoaderData() + + return ( +
+
    + {[...posts(), { id: 'i-do-not-exist', title: 'Non-existent Post' }].map( + (post) => { + return ( +
  • + +
    {post.title.substring(0, 20)}
    + +
  • + ) + }, + )} +
+
+ +
+ ) +} diff --git a/examples/solid/start-basic/src/routes/posts_.$postId.deep.tsx b/examples/solid/start-basic/src/routes/posts_.$postId.deep.tsx new file mode 100644 index 0000000000..4125a77f94 --- /dev/null +++ b/examples/solid/start-basic/src/routes/posts_.$postId.deep.tsx @@ -0,0 +1,29 @@ +import { Link, createFileRoute } from '@tanstack/solid-router' +import { fetchPost } from '../utils/posts' +import { PostErrorComponent } from '~/components/PostError' + +export const Route = createFileRoute('/posts_/$postId/deep')({ + loader: async ({ params: { postId } }) => + fetchPost({ + data: postId, + }), + errorComponent: PostErrorComponent, + component: PostDeepComponent, +}) + +function PostDeepComponent() { + const post = Route.useLoaderData() + + return ( +
+ + ← All Posts + +

{post().title}

+
{post().body}
+
+ ) +} diff --git a/examples/solid/start-basic/src/routes/redirect.tsx b/examples/solid/start-basic/src/routes/redirect.tsx new file mode 100644 index 0000000000..ca017f0635 --- /dev/null +++ b/examples/solid/start-basic/src/routes/redirect.tsx @@ -0,0 +1,9 @@ +import { createFileRoute, redirect } from '@tanstack/solid-router' + +export const Route = createFileRoute('/redirect')({ + beforeLoad: async () => { + throw redirect({ + to: '/posts', + }) + }, +}) diff --git a/examples/solid/start-basic/src/routes/users.$userId.tsx b/examples/solid/start-basic/src/routes/users.$userId.tsx new file mode 100644 index 0000000000..a2d99fbf6b --- /dev/null +++ b/examples/solid/start-basic/src/routes/users.$userId.tsx @@ -0,0 +1,33 @@ +import { createFileRoute } from '@tanstack/solid-router' +import axios from 'redaxios' +import type { User } from '~/utils/users' +import { DEPLOY_URL } from '~/utils/users' +import { NotFound } from '~/components/NotFound' +import { UserErrorComponent } from '~/components/UserError' + +export const Route = createFileRoute('/users/$userId')({ + loader: async ({ params: { userId } }) => { + return await axios + .get(DEPLOY_URL + '/api/users/' + userId) + .then((r) => r.data) + .catch(() => { + throw new Error('Failed to fetch user') + }) + }, + errorComponent: UserErrorComponent, + component: UserComponent, + notFoundComponent: () => { + return User not found + }, +}) + +function UserComponent() { + const user = Route.useLoaderData() + + return ( +
+

{user().name}

+
{user().email}
+
+ ) +} diff --git a/examples/solid/start-basic/src/routes/users.index.tsx b/examples/solid/start-basic/src/routes/users.index.tsx new file mode 100644 index 0000000000..bbc96801a9 --- /dev/null +++ b/examples/solid/start-basic/src/routes/users.index.tsx @@ -0,0 +1,9 @@ +import { createFileRoute } from '@tanstack/solid-router' + +export const Route = createFileRoute('/users/')({ + component: UsersIndexComponent, +}) + +function UsersIndexComponent() { + return
Select a user.
+} diff --git a/examples/solid/start-basic/src/routes/users.tsx b/examples/solid/start-basic/src/routes/users.tsx new file mode 100644 index 0000000000..2caca046e0 --- /dev/null +++ b/examples/solid/start-basic/src/routes/users.tsx @@ -0,0 +1,48 @@ +import { Link, Outlet, createFileRoute } from '@tanstack/solid-router' +import axios from 'redaxios' +import { DEPLOY_URL } from '../utils/users' +import type { User } from '../utils/users' + +export const Route = createFileRoute('/users')({ + loader: async () => { + return await axios + .get>(DEPLOY_URL + '/api/users') + .then((r) => r.data) + .catch(() => { + throw new Error('Failed to fetch users') + }) + }, + component: UsersComponent, +}) + +function UsersComponent() { + const users = Route.useLoaderData() + + return ( +
+
    + {[ + ...users(), + { id: 'i-do-not-exist', name: 'Non-existent User', email: '' }, + ].map((user) => { + return ( +
  • + +
    {user.name}
    + +
  • + ) + })} +
+
+ +
+ ) +} diff --git a/examples/solid/start-basic/src/styles/app.css b/examples/solid/start-basic/src/styles/app.css new file mode 100644 index 0000000000..c53c870665 --- /dev/null +++ b/examples/solid/start-basic/src/styles/app.css @@ -0,0 +1,22 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@layer base { + html { + color-scheme: light dark; + } + + * { + @apply border-gray-200 dark:border-gray-800; + } + + html, + body { + @apply text-gray-900 bg-gray-50 dark:bg-gray-950 dark:text-gray-200; + } + + .using-mouse * { + outline: none !important; + } +} diff --git a/examples/solid/start-basic/src/utils/loggingMiddleware.tsx b/examples/solid/start-basic/src/utils/loggingMiddleware.tsx new file mode 100644 index 0000000000..d743ba5340 --- /dev/null +++ b/examples/solid/start-basic/src/utils/loggingMiddleware.tsx @@ -0,0 +1,41 @@ +import { createMiddleware } from '@tanstack/react-start' + +const preLogMiddleware = createMiddleware() + .client(async (ctx) => { + const clientTime = new Date() + + return ctx.next({ + context: { + clientTime, + }, + sendContext: { + clientTime, + }, + }) + }) + .server(async (ctx) => { + const serverTime = new Date() + + return ctx.next({ + sendContext: { + serverTime, + durationToServer: + serverTime.getTime() - ctx.context.clientTime.getTime(), + }, + }) + }) + +export const logMiddleware = createMiddleware() + .middleware([preLogMiddleware]) + .client(async (ctx) => { + const res = await ctx.next() + + const now = new Date() + console.log('Client Req/Res:', { + duration: now.getTime() - res.context.clientTime.getTime(), + durationToServer: res.context.durationToServer, + durationFromServer: now.getTime() - res.context.serverTime.getTime(), + }) + + return res + }) diff --git a/examples/solid/start-basic/src/utils/posts.tsx b/examples/solid/start-basic/src/utils/posts.tsx new file mode 100644 index 0000000000..0366131412 --- /dev/null +++ b/examples/solid/start-basic/src/utils/posts.tsx @@ -0,0 +1,36 @@ +import { notFound } from '@tanstack/solid-router' +import { createServerFn } from '@tanstack/react-start' +import axios from 'redaxios' + +export type PostType = { + id: string + title: string + body: string +} + +export const fetchPost = createServerFn({ method: 'GET' }) + .validator((d: string) => d) + .handler(async ({ data }) => { + console.info(`Fetching post with id ${data}...`) + const post = await axios + .get(`https://jsonplaceholder.typicode.com/posts/${data}`) + .then((r) => r.data) + .catch((err) => { + console.error(err) + if (err.status === 404) { + throw notFound() + } + throw err + }) + + return post + }) + +export const fetchPosts = createServerFn({ method: 'GET' }).handler( + async () => { + console.info('Fetching posts...') + return axios + .get>('https://jsonplaceholder.typicode.com/posts') + .then((r) => r.data.slice(0, 10)) + }, +) diff --git a/examples/solid/start-basic/src/utils/seo.ts b/examples/solid/start-basic/src/utils/seo.ts new file mode 100644 index 0000000000..d18ad84b74 --- /dev/null +++ b/examples/solid/start-basic/src/utils/seo.ts @@ -0,0 +1,33 @@ +export const seo = ({ + title, + description, + keywords, + image, +}: { + title: string + description?: string + image?: string + keywords?: string +}) => { + const tags = [ + { title }, + { name: 'description', content: description }, + { name: 'keywords', content: keywords }, + { name: 'twitter:title', content: title }, + { name: 'twitter:description', content: description }, + { name: 'twitter:creator', content: '@tannerlinsley' }, + { name: 'twitter:site', content: '@tannerlinsley' }, + { name: 'og:type', content: 'website' }, + { name: 'og:title', content: title }, + { name: 'og:description', content: description }, + ...(image + ? [ + { name: 'twitter:image', content: image }, + { name: 'twitter:card', content: 'summary_large_image' }, + { name: 'og:image', content: image }, + ] + : []), + ] + + return tags +} diff --git a/examples/solid/start-basic/src/utils/users.tsx b/examples/solid/start-basic/src/utils/users.tsx new file mode 100644 index 0000000000..b810f455fe --- /dev/null +++ b/examples/solid/start-basic/src/utils/users.tsx @@ -0,0 +1,7 @@ +export type User = { + id: number + name: string + email: string +} + +export const DEPLOY_URL = 'http://localhost:3000' diff --git a/examples/solid/start-basic/tailwind.config.mjs b/examples/solid/start-basic/tailwind.config.mjs new file mode 100644 index 0000000000..e49f4eb776 --- /dev/null +++ b/examples/solid/start-basic/tailwind.config.mjs @@ -0,0 +1,4 @@ +/** @type {import('tailwindcss').Config} */ +export default { + content: ['./src/**/*.{js,jsx,ts,tsx}'], +} diff --git a/examples/solid/start-basic/tsconfig.json b/examples/solid/start-basic/tsconfig.json new file mode 100644 index 0000000000..a40235b863 --- /dev/null +++ b/examples/solid/start-basic/tsconfig.json @@ -0,0 +1,23 @@ +{ + "include": ["**/*.ts", "**/*.tsx"], + "compilerOptions": { + "strict": true, + "esModuleInterop": true, + "jsx": "preserve", + "jsxImportSource": "solid-js", + "module": "ESNext", + "moduleResolution": "Bundler", + "lib": ["DOM", "DOM.Iterable", "ES2022"], + "isolatedModules": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "target": "ES2022", + "allowJs": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "paths": { + "~/*": ["./src/*"] + }, + "noEmit": true + } +} diff --git a/examples/solid/start-basic/vite.config.ts b/examples/solid/start-basic/vite.config.ts new file mode 100644 index 0000000000..2171b8ae8c --- /dev/null +++ b/examples/solid/start-basic/vite.config.ts @@ -0,0 +1,19 @@ +import { defineConfig } from 'vite' +import tsConfigPaths from 'vite-tsconfig-paths' +import { TanStackStartVitePlugin } from '@tanstack/solid-start/plugin' + +export default defineConfig({ + server: { + port: 3000, + }, + plugins: [ + tsConfigPaths({ + projects: ['./tsconfig.json'], + }), + TanStackStartVitePlugin({ + server: { + // preset: 'netlify', + }, + }), + ], +}) diff --git a/packages/solid-start-plugin/README.md b/packages/solid-start-plugin/README.md index 798fa094a3..90488bbcd8 100644 --- a/packages/solid-start-plugin/README.md +++ b/packages/solid-start-plugin/README.md @@ -2,4 +2,4 @@ # TanStack Start Vite Plugin -See https://tanstack.com/router/latest/docs/framework/react/guide/file-based-routing +See https://tanstack.com/router/latest/docs/framework/react/routing/file-based-routing diff --git a/packages/solid-start-plugin/package.json b/packages/solid-start-plugin/package.json index bd18553c02..d783bc94e4 100644 --- a/packages/solid-start-plugin/package.json +++ b/packages/solid-start-plugin/package.json @@ -1,7 +1,7 @@ { "name": "@tanstack/solid-start-plugin", - "version": "1.111.2", - "description": "Modern and scalable routing for React applications", + "version": "1.114.12", + "description": "Modern and scalable routing for Solid applications", "author": "Tanner Linsley", "license": "MIT", "repository": { @@ -15,7 +15,7 @@ "url": "https://github.com/sponsors/tannerlinsley" }, "keywords": [ - "react", + "solid", "location", "router", "routing", @@ -72,15 +72,24 @@ "@babel/template": "^7.26.8", "@babel/traverse": "^7.26.8", "@babel/types": "^7.26.8", + "@tanstack/solid-router": "workspace:^", + "@tanstack/router-generator": "workspace:^", + "@tanstack/router-plugin": "workspace:^", "@tanstack/router-utils": "workspace:^", - "babel-dead-code-elimination": "^1.0.9", - "tiny-invariant": "^1.3.3", - "vite": "6.1.0" - }, - "devDependencies": { + "@tanstack/server-functions-plugin": "workspace:^", "@types/babel__code-frame": "^7.0.6", "@types/babel__core": "^7.20.5", "@types/babel__template": "^7.4.4", - "@types/babel__traverse": "^7.20.6" + "@types/babel__traverse": "^7.20.6", + "vite-plugin-solid": "^2.11.6", + "babel-dead-code-elimination": "^1.0.9", + "fast-glob": "^3.3.3", + "h3": "1.13.0", + "import-meta-resolve": "^4.1.0", + "nitropack": "^2.10.4", + "tiny-invariant": "^1.3.3", + "vite": "6.1.0", + "xmlbuilder2": "^3.1.1", + "zod": "^3.24.2" } } diff --git a/packages/solid-start-plugin/src/index.ts b/packages/solid-start-plugin/src/index.ts index 1e856c0bda..e2d8faa19d 100644 --- a/packages/solid-start-plugin/src/index.ts +++ b/packages/solid-start-plugin/src/index.ts @@ -1,129 +1,196 @@ -import { fileURLToPath, pathToFileURL } from 'node:url' import path from 'node:path' -import { existsSync } from 'node:fs' -import { logDiff } from '@tanstack/router-utils' -import { compileStartOutput } from './compilers' -import type { Plugin } from 'vite' +import { TanStackServerFnPluginEnv } from '@tanstack/server-functions-plugin' +import { createNitro } from 'nitropack' +import { TanStackRouterVite } from '@tanstack/router-plugin/vite' +import viteSolid from 'vite-plugin-solid' +import { mergeConfig } from 'vite' +import { getTanStackStartOptions } from './schema.js' +import { nitroPlugin } from './nitro/nitro-plugin.js' +import { startManifestPlugin } from './routesManifestPlugin.js' +import { TanStackStartCompilerPlugin } from './start-compiler-plugin.js' +import type { PluginOption } from 'vite' +import type { TanStackStartInputConfig } from './schema.js' -const debug = - process.env.TSR_VITE_DEBUG && - ['true', 'solid-start-plugin'].includes(process.env.TSR_VITE_DEBUG) +export type { + TanStackStartInputConfig, + TanStackStartOutputConfig, +} from './schema.js' -export type TanStackStartViteOptions = { - globalMiddlewareEntry: string -} +export const clientDistDir = 'node_modules/.tanstack-start/client-dist' -const transformFuncs = [ - 'createServerFn', - 'createMiddleware', - 'serverOnly', - 'clientOnly', - 'createIsomorphicFn', -] -const tokenRegex = new RegExp(transformFuncs.join('|')) -// const eitherFuncRegex = new RegExp( -// `(function ${transformFuncs.join('|function ')})`, -// ) - -export function createTanStackStartPlugin(opts: TanStackStartViteOptions): { - client: Array - ssr: Array - server: Array -} { - const globalMiddlewarePlugin = (): Plugin => { - let entry: string | null = null - let resolvedGlobalMiddlewareEntry: string | null = null - let globalMiddlewareEntryExists = false - let ROOT: string = process.cwd() - return { - name: 'vite-plugin-tanstack-start-ensure-global-middleware', - enforce: 'pre', - configResolved: (config) => { - ROOT = config.root - entry = path.resolve(ROOT, (config as any).router.handler) - resolvedGlobalMiddlewareEntry = path.resolve( - ROOT, - opts.globalMiddlewareEntry, - ) - globalMiddlewareEntryExists = existsSync(resolvedGlobalMiddlewareEntry) +export function TanStackStartVitePlugin( + opts?: TanStackStartInputConfig, +): Array { + const options = getTanStackStartOptions(opts) + + return [ + { + name: 'tss-vite-config-client', + ...options.vite, + async config() { + // Create a dummy nitro app to get the resolved public output path + const dummyNitroApp = await createNitro({ + preset: options.server.preset, + compatibilityDate: '2024-12-01', + }) + + const nitroOutputPublicDir = dummyNitroApp.options.output.publicDir + await dummyNitroApp.close() - if (!entry) { - throw new Error( - '@tanstack/solid-start-plugin: No server entry found!', + return { + environments: { + client: { + build: { + manifest: true, + rollupOptions: { + input: { + main: options.clientEntryPath, + }, + output: { + dir: path.resolve(options.root, clientDistDir), + }, + external: ['node:fs', 'node:path', 'node:os', 'node:crypto'], + }, + }, + }, + server: {}, + }, + resolve: { + noExternal: [ + '@tanstack/start', + '@tanstack/start/server', + '@tanstack/start-client', + '@tanstack/start-client-core', + '@tanstack/start-server', + '@tanstack/start-server-core', + '@tanstack/start-server-functions-fetcher', + '@tanstack/start-server-functions-client', + '@tanstack/start-server-functions-ssr', + '@tanstack/start-server-functions-server', + '@tanstack/start-router-manifest', + '@tanstack/start-config', + '@tanstack/start-api-routes', + '@tanstack/server-functions-plugin', + 'tsr:start-manifest', + 'tsr:server-fn-manifest', + ], + }, + optimizeDeps: { + entries: [], + ...(options.vite?.optimizeDeps || {}), + include: [...(options.vite?.optimizeDeps?.include || [])], + }, + /* prettier-ignore */ + define: { + ...(options.vite?.define || {}), + ...injectDefineEnv('TSS_PUBLIC_BASE', options.routers.public.base), + ...injectDefineEnv('TSS_CLIENT_BASE', options.routers.client.base), + ...injectDefineEnv('TSS_CLIENT_ENTRY', options.clientEntryPath), + ...injectDefineEnv('TSS_SERVER_FN_BASE', options.routers.server.base), + ...injectDefineEnv('TSS_OUTPUT_PUBLIC_DIR', nitroOutputPublicDir), + }, + } + }, + configEnvironment(env, config) { + if (env === 'server') { + } else { + config = mergeConfig( + mergeConfig(config, options.vite || {}), + options.routers.client.vite || {}, ) } + + return config }, - transform(code, id) { - if (entry && id.includes(entry)) { - if (globalMiddlewareEntryExists) { - return { - code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, - map: null, - } - } + resolveId(id) { + if ( + [ + '/~start/default-server-entry', + '/~start/default-client-entry', + ].includes(id) + ) { + return `${id}.tsx` } - return code + + return null }, - } - } + load(id) { + const routerImportPath = JSON.stringify( + path.resolve(options.root, options.tsr.srcDirectory, 'router'), + ) - return { - client: [ - globalMiddlewarePlugin(), - TanStackStartServerFnsAndMiddleware({ ...opts, env: 'client' }), - ], - ssr: [ - globalMiddlewarePlugin(), - TanStackStartServerFnsAndMiddleware({ ...opts, env: 'ssr' }), - ], - server: [ - globalMiddlewarePlugin(), - TanStackStartServerFnsAndMiddleware({ ...opts, env: 'server' }), - ], - } -} + if (id === '/~start/default-client-entry.tsx') { + return ` +import { hydrate } from 'solid-js/web' +import { StartClient } from '@tanstack/solid-start' +import { createRouter } from ${routerImportPath} -export function TanStackStartServerFnsAndMiddleware(opts: { - env: 'server' | 'ssr' | 'client' -}): Plugin { - // let ROOT: string = process.cwd() +const router = createRouter() - return { - name: 'vite-plugin-tanstack-start-create-server-fn', - enforce: 'pre', - configResolved: (_config) => { - // ROOT = config.root - }, - transform(code, id) { - const url = pathToFileURL(id) - url.searchParams.delete('v') - id = fileURLToPath(url).replace(/\\/g, '/') - - const includesToken = tokenRegex.test(code) - // const includesEitherFunc = eitherFuncRegex.test(code) - - if ( - !includesToken - // includesEitherFunc - // /node_modules/.test(id) - ) { - return null - } +hydrate(() => , document.body) - if (debug) console.info(`${opts.env} Compiling Start: `, id) - const compiled = compileStartOutput({ - code, - filename: id, - env: opts.env, - }) +` + } - if (debug) { - logDiff(code, compiled.code) - console.log('Output:\n', compiled.code + '\n\n') - } + if (id === '/~start/default-server-entry.tsx') { + return ` +import { createStartHandler, defaultStreamHandler } from '@tanstack/solid-start/server' +import { createRouter } from ${routerImportPath} - return compiled +export default createStartHandler({ + createRouter, +})(defaultStreamHandler) +` + } + + return null + }, }, - } + TanStackStartCompilerPlugin(), + TanStackServerFnPluginEnv({ + // This is the ID that will be available to look up and import + // our server function manifest and resolve its module + manifestVirtualImportId: 'tsr:server-fn-manifest', + client: { + getRuntimeCode: () => + `import { createClientRpc } from '@tanstack/solid-start/server-functions-client'`, + replacer: (d) => + `createClientRpc('${d.functionId}', '${options.routers.server.base}')`, + }, + server: { + getRuntimeCode: () => + `import { createServerRpc } from '@tanstack/solid-start/server-functions-server'`, + replacer: (d) => + `createServerRpc('${d.functionId}', '${options.routers.server.base}', ${d.fn})`, + }, + }), + startManifestPlugin(options), + TanStackRouterVite({ + ...options.tsr, + target: 'solid', + enableRouteGeneration: true, + __enableAPIRoutesGeneration: true, + autoCodeSplitting: true, + }), + viteSolid(options.solid), + nitroPlugin(options), + ] +} + +function injectDefineEnv( + key: TKey, + value: TValue, +): { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } { + return { + [`process.env.${key}`]: JSON.stringify(value), + [`import.meta.env.${key}`]: JSON.stringify(value), + } as { [P in `process.env.${TKey}` | `import.meta.env.${TKey}`]: TValue } } + +// function isEmptyPrerenderRoutes(options?: Options): boolean { +// if (!options || isArrayWithElements(nitroConfig.prerender?.routes)) { +// return false +// } +// return !options.server.prerender?.routes +// } diff --git a/packages/solid-start-plugin/src/nitro/build-server.ts b/packages/solid-start-plugin/src/nitro/build-server.ts new file mode 100644 index 0000000000..052ffd66dc --- /dev/null +++ b/packages/solid-start-plugin/src/nitro/build-server.ts @@ -0,0 +1,39 @@ +import { + build, + copyPublicAssets, + createNitro, + prepare, + prerender, +} from 'nitropack' + +import type { NitroConfig } from 'nitropack' + +export async function buildServer(nitroConfig: NitroConfig) { + const nitro = await createNitro({ + dev: false, + preset: process.env['BUILD_PRESET'], + ...nitroConfig, + }) + + // if (nitroConfig.prerender?.postRenderingHooks) { + // addPostRenderingHooks(nitro, nitroConfig.prerender.postRenderingHooks) + // } + + await prepare(nitro) + await copyPublicAssets(nitro) + + if ( + nitroConfig.prerender?.routes && + nitroConfig.prerender.routes.length > 0 + ) { + console.log(`Prerendering static pages...`) + await prerender(nitro) + } + + if (!nitroConfig.static) { + console.log('Building Server...') + await build(nitro) + } + + await nitro.close() +} diff --git a/packages/solid-start-plugin/src/nitro/build-sitemap.ts b/packages/solid-start-plugin/src/nitro/build-sitemap.ts new file mode 100644 index 0000000000..c06ed77d0e --- /dev/null +++ b/packages/solid-start-plugin/src/nitro/build-sitemap.ts @@ -0,0 +1,79 @@ +import { writeFileSync } from 'node:fs' +import { resolve } from 'node:path' +import { create } from 'xmlbuilder2' +import type { XMLBuilder } from 'xmlbuilder2/lib/interfaces' + +export type PagesJson = { + page: string + lastMod: string +} + +export async function buildSitemap({ + host, + routes, + outputDir, +}: { + host: string + routes: Array | (() => Promise>) + outputDir: string +}) { + const routeList: Array = await optionHasRoutes(routes) + + if (routeList.length) { + const slash = checkSlash(host) + const sitemapData: Array = routeList.map((page: string) => ({ + page: `${host}${slash}${page.replace(/^\/+/g, '')}`, + lastMod: new Date().toISOString().split('T')[0]!, + })) + + const sitemap = createXml('urlset') + + for (const item of sitemapData) { + const page = sitemap.ele('url') + page.ele('loc').txt(item.page) + page.ele('lastmod').txt(item.lastMod) + } + + const mapPath = `${resolve(outputDir)}/sitemap.xml` + try { + console.log(`Writing sitemap at ${mapPath}`) + writeFileSync(mapPath, sitemap.end({ prettyPrint: true })) + } catch (e) { + console.error(`Unable to write file at ${mapPath}`, e) + } + } +} + +function createXml(elementName: 'urlset' | 'sitemapindex'): XMLBuilder { + return create({ version: '1.0', encoding: 'UTF-8' }) + .ele(elementName, { + xmlns: 'https://www.sitemaps.org/schemas/sitemap/0.9', + }) + .com(`This file was automatically generated by Analog.`) +} + +function checkSlash(host: string): string { + const finalChar = host.slice(-1) + return finalChar === '/' ? '' : '/' +} + +async function optionHasRoutes( + routes: + | Array + | (() => Promise>), +): Promise> { + let routeList: Array + + if (typeof routes === 'function') { + // returns an array or undefined + routeList = await routes() + } else if (Array.isArray(routes)) { + // returns an array of strings + routeList = routes + } else { + // default it to an empty of array + routeList = [] + } + + return routeList.filter(Boolean) as Array +} diff --git a/packages/solid-start-plugin/src/nitro/dev-server-plugin.ts b/packages/solid-start-plugin/src/nitro/dev-server-plugin.ts new file mode 100644 index 0000000000..9f6c156b45 --- /dev/null +++ b/packages/solid-start-plugin/src/nitro/dev-server-plugin.ts @@ -0,0 +1,152 @@ +// SSR dev server, middleware and error page source modified from +// https://github.com/solidjs/solid-start/blob/main/packages/start/dev/server.js + +import { createEvent, getHeader, sendWebResponse } from 'h3' +import { isRunnableDevEnvironment } from 'vite' +import type { Connect, Environment, Plugin, ViteDevServer } from 'vite' +import type { TanStackStartOutputConfig } from '../schema.js' + +export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { + // let config: UserConfig + let isTest = false + + return { + name: 'startjs-dev-ssr-plugin', + config(userConfig, { mode }) { + // config = userConfig + isTest = isTest ? isTest : mode === 'test' + + return { + resolve: { + alias: { + '/~start/ssr-entry': options.serverEntryPath, + }, + }, + } + }, + configureServer(viteDevServer) { + if (isTest) { + return + } + + ;(globalThis as any).viteDevServer = viteDevServer + + return () => { + remove_html_middlewares(viteDevServer.middlewares) + + viteDevServer.middlewares.use(async (req, res) => { + const event = createEvent(req, res) + const serverEnv = viteDevServer.environments['server'] as Environment + + try { + if (!isRunnableDevEnvironment(serverEnv)) { + throw new Error('Server environment not found') + } + + const serverEntry = + await serverEnv.runner.import('/~start/ssr-entry') + + const response = await serverEntry['default'](event) + + sendWebResponse(event, response) + } catch (e) { + console.error(e) + viteDevServer.ssrFixStacktrace(e as Error) + + if ( + getHeader(event, 'content-type')?.includes('application/json') + ) { + return sendWebResponse( + event, + new Response( + JSON.stringify( + { + status: 500, + error: 'Internal Server Error', + message: + 'An unexpected error occurred. Please try again later.', + timestamp: new Date().toISOString(), + }, + null, + 2, + ), + { + status: 500, + headers: { + 'Content-Type': 'application/json', + }, + }, + ), + ) + } + + sendWebResponse( + event, + new Response( + ` + + + + + Error + + + + + + `, + { + status: 500, + }, + ), + ) + } + }) + } + }, + } +} + +/** + * Removes Vite internal middleware + * + * @param server + */ +function remove_html_middlewares(server: ViteDevServer['middlewares']) { + const html_middlewares = [ + 'viteIndexHtmlMiddleware', + 'vite404Middleware', + 'viteSpaFallbackMiddleware', + ] + for (let i = server.stack.length - 1; i > 0; i--) { + if ( + html_middlewares.includes( + // @ts-expect-error + server.stack[i].handle.name, + ) + ) { + server.stack.splice(i, 1) + } + } +} + +/** + * Formats error for SSR message in error overlay + * @param req + * @param error + * @returns + */ +function prepareError(req: Connect.IncomingMessage, error: unknown) { + const e = error as Error + return { + message: `An error occured while server rendering ${req.url}:\n\n\t${ + typeof e === 'string' ? e : e.message + } `, + stack: typeof e === 'string' ? '' : e.stack, + } +} diff --git a/packages/solid-start-plugin/src/nitro/nitro-plugin.ts b/packages/solid-start-plugin/src/nitro/nitro-plugin.ts new file mode 100644 index 0000000000..d179dc95ee --- /dev/null +++ b/packages/solid-start-plugin/src/nitro/nitro-plugin.ts @@ -0,0 +1,191 @@ +import { platform } from 'node:os' +import { promises as fsp } from 'node:fs' +import path from 'node:path' +import { copyPublicAssets, createNitro, prepare } from 'nitropack' +import { version } from 'nitropack/meta' +import { normalizePath } from 'vite' + +import { getRollupConfig } from 'nitropack/rollup' +import { clientDistDir } from '../index.js' +import { devServerPlugin } from './dev-server-plugin.js' +import type { EnvironmentOptions, PluginOption } from 'vite' +import type { Nitro, NitroConfig } from 'nitropack' +import type { TanStackStartOutputConfig } from '../schema.js' + +export type { + TanStackStartInputConfig, + TanStackStartOutputConfig, +} from '../schema.js' + +const isWindows = platform() === 'win32' +const filePrefix = isWindows ? 'file:///' : '' + +export function nitroPlugin( + options: TanStackStartOutputConfig, +): Array { + let nitro: Nitro + let nitroRollupOptions: ReturnType + + const buildPreset = + process.env['BUILD_PRESET'] ?? (options.server.preset as string | undefined) + + const nitroConfig: NitroConfig = { + compatibilityDate: '2024-11-19', + logLevel: options.server.logLevel || 0, + srcDir: normalizePath(options.tsr.srcDirectory), + ...options.server, + preset: buildPreset, + publicAssets: [ + { + dir: path.resolve(options.root, clientDistDir), + }, + ], + typescript: { + generateTsConfig: false, + }, + prerender: { + ...options.server.prerender, + routes: ['/', ...(options.server.prerender?.routes || [])], + }, + renderer: options.serverEntryPath, + } + + return [ + devServerPlugin(options), + { + name: 'tanstack-vite-plugin-nitro', + async configEnvironment(name) { + nitro = await createNitro({ + dev: false, + ...nitroConfig, + }) + + nitroRollupOptions = getRollupConfig(nitro) + + if (name === 'server') { + return { + build: { + commonjsOptions: { + include: [], + }, + ssr: true, + sourcemap: true, + rollupOptions: { + ...nitroRollupOptions, + output: { + ...nitroRollupOptions.output, + sourcemap: undefined, + }, + }, + }, + } satisfies EnvironmentOptions + } + + return null + }, + config() { + return { + builder: { + sharedPlugins: true, + async buildApp(builder) { + if (!builder.environments['client']) { + throw new Error('Client environment not found') + } + + if (!builder.environments['server']) { + throw new Error('SSR environment not found') + } + + await builder.build(builder.environments['client']) + await prepare(nitro) + await copyPublicAssets(nitro) + + // if ( + // nitroConfig.prerender?.routes && + // nitroConfig.prerender.routes.length > 0 + // ) { + // console.log(`Prerendering static pages...`) + // await prerender(nitro) + // } + + await builder.build(builder.environments['server']) + + const buildInfoPath = path.resolve( + nitro.options.output.dir, + 'nitro.json', + ) + + const presetsWithConfig = [ + 'awsAmplify', + 'awsLambda', + 'azure', + 'cloudflare', + 'firebase', + 'netlify', + 'vercel', + ] + + const buildInfo = { + date: /* @__PURE__ */ new Date().toJSON(), + preset: nitro.options.preset, + framework: nitro.options.framework, + versions: { + nitro: version, + }, + commands: { + preview: nitro.options.commands.preview, + deploy: nitro.options.commands.deploy, + }, + config: { + ...Object.fromEntries( + presetsWithConfig.map((key) => [ + key, + (nitro.options as any)[key], + ]), + ), + }, + } + + await fsp.writeFile( + buildInfoPath, + JSON.stringify(buildInfo, null, 2), + ) + + await nitro.close() + + // if (nitroConfig.prerender?.routes?.length && options.sitemap) { + // console.log('Building Sitemap...') + // // sitemap needs to be built after all directories are built + // await buildSitemap({ + // host: options.sitemap.host, + // routes: nitroConfig.prerender.routes, + // outputDir: resolve(options.root, 'dist/public'), + // }) + // } + + // console.log( + // `\n\n✅ Client and server bundles successfully built.`, + // ) + }, + }, + } + }, + // async buildStart() { + // await Promise.all( + // [ + // nitro.options.output.dir, + // nitro.options.output.serverDir, + // nitro.options.output.publicDir, + // ].map((dir) => { + // if (dir) { + // return promises.mkdir(dir, { + // recursive: true, + // }) + // } + // return + // }), + // ) + // }, + }, + ] +} diff --git a/packages/solid-start-plugin/src/nitro/options.ts b/packages/solid-start-plugin/src/nitro/options.ts new file mode 100644 index 0000000000..c8c8a3d15f --- /dev/null +++ b/packages/solid-start-plugin/src/nitro/options.ts @@ -0,0 +1,80 @@ +import { PrerenderRoute } from 'nitropack' + +export interface Options { + ssr?: boolean + ssrBuildDir?: string + /** + * Prerender the static pages without producing the server output. + */ + static?: boolean + prerender?: PrerenderOptions + entryServer?: string + index?: string + workspaceRoot?: string + /** + * Additional page paths to include + */ + additionalPagesDirs?: string[] + /** + * Additional API paths to include + */ + additionalAPIDirs?: string[] + apiPrefix?: string + + /** + * Toggles internal API middleware. + * If disabled, a proxy request is used to route /api + * requests to / in the production server build. + */ + useAPIMiddleware?: boolean +} + +export interface PrerenderOptions { + /** + * Add additional routes to prerender through crawling page links. + */ + discover?: boolean + + /** + * List of routes to prerender resolved statically or dynamically. + */ + routes?: + | (string | PrerenderContentDir)[] + | (() => Promise<(string | PrerenderContentDir | undefined)[]>) + sitemap?: SitemapConfig + /** List of functions that run for each route after pre-rendering is complete. */ + postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[] +} + +export interface SitemapConfig { + host: string +} + +export interface PrerenderContentDir { + /** + * The directory where files should be grabbed from. + * @example `/src/contents/blog` + */ + contentDir: string + /** + * Transform the matching content files path into a route. + * The function is called for each matching content file within the specified contentDir. + * @param file information of the matching file (`path`, `name`, `extension`, `attributes`) + * @returns a string with the route should be returned (e. g. `/blog/`) or the value `false`, when the route should not be prerendered. + */ + transform: (file: PrerenderContentFile) => string | false +} + +/** + * @param path the path to the content file + * @param name the basename of the matching content file without the file extension + * @param extension the file extension + * @param attributes the frontmatter attributes extracted from the frontmatter section of the file + * @returns a string with the route should be returned (e. g. `/blog/`) or the value `false`, when the route should not be prerendered. + */ +export interface PrerenderContentFile { + path: string + attributes: Record + name: string + extension: string +} diff --git a/packages/solid-start-plugin/src/routesManifestPlugin.ts b/packages/solid-start-plugin/src/routesManifestPlugin.ts new file mode 100644 index 0000000000..e2351669fd --- /dev/null +++ b/packages/solid-start-plugin/src/routesManifestPlugin.ts @@ -0,0 +1,187 @@ +import { readFileSync } from 'node:fs' +import path from 'node:path' +import type { PluginOption, ResolvedConfig } from 'vite' +import type { Manifest } from '@tanstack/solid-router' +import type { TanStackStartOutputConfig } from './schema' + +export function startManifestPlugin( + opts: TanStackStartOutputConfig, +): PluginOption { + let config: ResolvedConfig + + return { + name: 'tsr-routes-manifest', + enforce: 'pre', + + configResolved(resolvedConfig) { + config = resolvedConfig + }, + // configEnvironment(env, envConfig) { + // config = envConfig. + // }, + resolveId(id) { + if (id === 'tsr:start-manifest') { + return id + } + return + }, + load(id) { + if (id === 'tsr:start-manifest') { + // If we're in development, return a dummy manifest + + if (config.command === 'serve') { + return `export default () => ({ + entry: "$${process.env.TSS_CLIENT_BASE}/", + routes: {} + })` + } + + const clientViteManifestPath = path.resolve( + opts.root, + 'node_modules/.tanstack-start/client-dist/.vite/manifest.json', + ) + + type ViteManifest = Record< + string, + { + file: string + isEntry: boolean + imports?: Array + } + > + + let manifest: ViteManifest + try { + manifest = JSON.parse(readFileSync(clientViteManifestPath, 'utf-8')) + } catch (err) { + console.error(err) + throw new Error( + `Could not find the production client vite manifest at '${clientViteManifestPath}'!`, + ) + } + + const routeTreePath = path.resolve(opts.tsr.generatedRouteTree) + + let routeTreeContent: string + try { + routeTreeContent = readFileSync(routeTreePath, 'utf-8') + } catch (err) { + console.error(err) + throw new Error( + `Could not find the generated route tree at '${routeTreePath}'!`, + ) + } + + // Extract the routesManifest JSON from the route tree file. + // It's located between the /* ROUTE_MANIFEST_START and ROUTE_MANIFEST_END */ comment block. + + const routerManifest = JSON.parse( + routeTreeContent.match( + /\/\* ROUTE_MANIFEST_START([\s\S]*?)ROUTE_MANIFEST_END \*\//, + )?.[1] || '{ routes: {} }', + ) as Manifest + + const routes = routerManifest.routes + + let entryFile: + | { + file: string + imports?: Array + } + | undefined + + const filesByRouteFilePath: ViteManifest = Object.fromEntries( + Object.entries(manifest).map(([k, v]) => { + if (v.isEntry) { + entryFile = v + } + + const rPath = k.split('?')[0] + + return [rPath, v] + }, {}), + ) + + const routesDirectoryFromRoot = path.relative( + opts.root, + opts.tsr.routesDirectory, + ) + + // Add preloads to the routes from the vite manifest + Object.entries(routes).forEach(([k, v]) => { + const file = + filesByRouteFilePath[ + path.join(routesDirectoryFromRoot, v.filePath as string) + ] + + if (file) { + const preloads = (file.imports ?? []).map((d) => + path.join('/', manifest[d]!.file), + ) + + if (file.file) { + preloads.unshift(path.join('/', file.file)) + } + + routes[k] = { + ...v, + preloads, + } + } + }) + + if (entryFile) { + routes.__root__!.preloads = [ + path.join('/', entryFile.file), + ...(entryFile.imports?.map((d) => + path.join('/', manifest[d]!.file), + ) || []), + ] + routes.__root__!.assets = [ + ...(routes.__root__!.assets || []), + { + tag: 'script', + attrs: { + src: path.join('/', entryFile.file), + type: 'module', + }, + }, + ] + } + + const recurseRoute = ( + route: { + preloads?: Array + children?: Array + }, + seenPreloads = {} as Record, + ) => { + route.preloads = route.preloads?.filter((preload) => { + if (seenPreloads[preload]) { + return false + } + seenPreloads[preload] = true + return true + }) + + if (route.children) { + route.children.forEach((child) => { + const childRoute = routes[child]! + recurseRoute(childRoute, { ...seenPreloads }) + }) + } + } + + // @ts-expect-error + recurseRoute(routes.__root__) + + const routesManifest = { + routes, + } + + return `export default () => (${JSON.stringify(routesManifest)})` + } + return + }, + } +} diff --git a/packages/solid-start-plugin/src/schema.ts b/packages/solid-start-plugin/src/schema.ts new file mode 100644 index 0000000000..428dacdf0a --- /dev/null +++ b/packages/solid-start-plugin/src/schema.ts @@ -0,0 +1,150 @@ +import path from 'node:path' +import { existsSync } from 'node:fs' +import { z } from 'zod' +import { configSchema, getConfig } from '@tanstack/router-generator' +import type { UserConfig } from 'vite' +import type { NitroConfig } from 'nitropack' +import type { Options as ViteSolidOptions } from 'vite-plugin-solid' + +type HTTPSOptions = { + cert?: string + key?: string + pfx?: string + passphrase?: string + validityDays?: number + domains?: Array +} + +type ServerOptions = NitroConfig & { + https?: boolean | HTTPSOptions +} + +export const serverSchema = z.custom().and( + z.object({ + preset: z + .custom() + .optional() + .default('node-server'), + }), +) + +const viteSchema = z.custom() + +const viteSolidSchema = z.custom() + +const routersSchema = z.object({ + ssr: z + .object({ + entry: z.string().optional(), + // middleware: z.string().optional(), + vite: viteSchema.optional(), + }) + .optional() + .default({}), + client: z + .object({ + entry: z.string().optional(), + base: z.string().optional().default('/_build'), + vite: viteSchema.optional(), + }) + .optional() + .default({}), + server: z + .object({ + base: z.string().optional().default('/_server'), + globalMiddlewareEntry: z + .string() + .optional() + .default('global-middleware.ts'), + // middleware: z.string().optional(), + vite: viteSchema.optional(), + }) + .optional() + .default({}), + public: z + .object({ + dir: z.string().optional().default('public'), + base: z.string().optional().default('/'), + }) + .optional() + .default({}), +}) + +const sitemapSchema = z.object({ + host: z.string(), +}) + +const tsrConfig = configSchema.partial().extend({ + srcDirectory: z.string().optional().default('src'), +}) + +const TanStackStartOptionsSchema = z + .object({ + root: z.string().optional().default(process.cwd()), + solid: viteSolidSchema.optional(), + vite: viteSchema.optional(), + tsr: tsrConfig.optional().default({}), + routers: routersSchema.optional().default({}), + server: serverSchema.optional().default({}), + sitemap: sitemapSchema.optional(), + }) + .optional() + .default({}) + +export function getTanStackStartOptions(opts?: TanStackStartInputConfig) { + const options = TanStackStartOptionsSchema.parse(opts) + + const srcDirectory = options.tsr.srcDirectory + + const routesDirectory = + options.tsr.routesDirectory ?? path.join(srcDirectory, 'routes') + + const generatedRouteTree = + options.tsr.generatedRouteTree ?? + path.join(srcDirectory, 'routeTree.gen.ts') + + const clientEntryPath = (() => { + if (options.routers.client.entry) { + return path.join(srcDirectory, options.routers.client.entry) + } + + if (existsSync(path.join(srcDirectory, 'client.tsx'))) { + return path.join(srcDirectory, 'client.tsx') + } + + return '/~start/default-client-entry' + })() + + const serverEntryPath = (() => { + if (options.routers.ssr.entry) { + return path.join(srcDirectory, options.routers.ssr.entry) + } + + if (existsSync(path.join(srcDirectory, 'server.tsx'))) { + return path.join(srcDirectory, 'server.tsx') + } + + return '/~start/default-server-entry' + })() + + return { + ...options, + tsr: { + ...options.tsr, + ...getConfig({ + ...options.tsr, + routesDirectory, + generatedRouteTree, + }), + }, + clientEntryPath, + serverEntryPath, + } +} + +export type TanStackStartInputConfig = z.input< + typeof TanStackStartOptionsSchema +> +export type TanStackStartOutputConfig = ReturnType< + typeof getTanStackStartOptions +> diff --git a/packages/solid-start-plugin/src/start-compiler-plugin.ts b/packages/solid-start-plugin/src/start-compiler-plugin.ts new file mode 100644 index 0000000000..2c42234c10 --- /dev/null +++ b/packages/solid-start-plugin/src/start-compiler-plugin.ts @@ -0,0 +1,150 @@ +import { fileURLToPath, pathToFileURL } from 'node:url' +import { logDiff } from '@tanstack/router-utils' +import { compileStartOutput } from './compilers' + +import type { Plugin } from 'vite' + +const debug = + process.env.TSR_VITE_DEBUG && + ['true', 'start-plugin'].includes(process.env.TSR_VITE_DEBUG) + +export type TanStackStartViteOptions = { + globalMiddlewareEntry: string +} + +const transformFuncs = [ + 'createServerFn', + 'createMiddleware', + 'serverOnly', + 'clientOnly', + 'createIsomorphicFn', +] +const tokenRegex = new RegExp(transformFuncs.join('|')) +// const eitherFuncRegex = new RegExp( +// `(function ${transformFuncs.join('|function ')})`, +// ) + +// TODO: Bring these back +// (() => { +// let entry: string | null = null +// let ROOT: string = process.cwd() +// return { +// name: 'vite-plugin-tanstack-start-server-entry-client', +// enforce: 'pre', +// configResolved: (config) => { +// ROOT = config.root +// entry = path.resolve(ROOT, (config as any).router.handler) + +// if (!entry) { +// throw new Error('@tanstack/start-plugin: No server entry found!') +// } +// }, +// transform(code, id) { +// if (entry && id.includes(entry)) { +// return { +// code: `${code}\n\nimport '${path.resolve(ROOT, opts.globalMiddlewareEntry)}'`, +// map: null, +// } +// } +// return null +// }, +// } +// })(), + +export function TanStackStartCompilerPlugin(opts?: { + client?: { + envName?: string + } + server?: { + envName?: string + } +}): Plugin { + opts = { + client: { + envName: 'client', + ...opts?.client, + }, + server: { + envName: 'server', + ...opts?.server, + }, + } + + return { + name: 'vite-plugin-tanstack-start-create-server-fn', + enforce: 'pre', + applyToEnvironment(env) { + return [opts.client?.envName, opts.server?.envName].includes(env.name) + }, + transform(code, id) { + const env = + this.environment.name === opts.client?.envName + ? 'client' + : this.environment.name === opts.server?.envName + ? 'server' + : (() => { + throw new Error( + `Environment ${this.environment.name} not configured`, + ) + })() + + return transformCode({ + code, + id, + env, + }) + }, + } +} + +function transformCode(opts: { + code: string + id: string + env: 'server' | 'client' +}) { + const { code, env } = opts + let { id } = opts + + const url = pathToFileURL(id) + url.searchParams.delete('v') + id = fileURLToPath(url).replace(/\\/g, '/') + + const includesToken = tokenRegex.test(code) + // const includesEitherFunc = eitherFuncRegex.test(code) + + if ( + !includesToken + // includesEitherFunc + // /node_modules/.test(id) + ) { + return null + } + + if (code.includes('@react-refresh')) { + throw new Error( + `We detected that the '@vitejs/plugin-react' was passed before '@tanstack/start-plugin'. Please make sure that '@tanstack/router-vite-plugin' is passed before '@vitejs/plugin-react' and try again: + e.g. + + plugins: [ + TanStackStartVite(), // Place this before viteReact() + viteReact(), + ] + `, + ) + } + + if (debug) console.info(`${env} Compiling Start: `, id) + + const compiled = compileStartOutput({ + code, + filename: id, + env, + }) + + if (debug) { + logDiff(code, compiled.code) + console.log('Output:\n', compiled.code + '\n\n') + } + + return compiled +} diff --git a/packages/solid-start-plugin/tsconfig.json b/packages/solid-start-plugin/tsconfig.json index 37d21ef6ca..6c8c904b07 100644 --- a/packages/solid-start-plugin/tsconfig.json +++ b/packages/solid-start-plugin/tsconfig.json @@ -3,6 +3,9 @@ "include": ["src", "vite.config.ts", "tests"], "exclude": ["tests/**/test-files/**", "tests/**/snapshots/**"], "compilerOptions": { - "jsx": "react-jsx" + "rootDir": "src", + "outDir": "dist/esm", + "target": "esnext", + "noEmit": false } } diff --git a/packages/solid-start-plugin/vite.config.ts b/packages/solid-start-plugin/vite.config.ts index 5389f0f739..2c711fd181 100644 --- a/packages/solid-start-plugin/vite.config.ts +++ b/packages/solid-start-plugin/vite.config.ts @@ -16,5 +16,6 @@ export default mergeConfig( tanstackViteConfig({ entry: './src/index.ts', srcDir: './src', + outDir: './dist', }), ) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c9f3b4834e..006bbf5b7a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5341,6 +5341,49 @@ importers: specifier: ^5.1.4 version: 5.1.4(typescript@5.8.2)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) + examples/solid/start-basic: + dependencies: + '@tanstack/solid-router': + specifier: ^1.114.17 + version: link:../../../packages/solid-router + '@tanstack/solid-router-devtools': + specifier: workspace:^ + version: link:../../../packages/solid-router-devtools + '@tanstack/solid-start': + specifier: workspace:* + version: link:../../../packages/solid-start + redaxios: + specifier: ^0.5.1 + version: 0.5.1 + solid-js: + specifier: ^1.9.5 + version: 1.9.5 + tailwind-merge: + specifier: ^2.6.0 + version: 2.6.0 + vite: + specifier: 6.1.0 + version: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) + devDependencies: + '@types/node': + specifier: ^22.5.4 + version: 22.13.4 + autoprefixer: + specifier: ^10.4.20 + version: 10.4.20(postcss@8.5.1) + postcss: + specifier: ^8.5.1 + version: 8.5.1 + tailwindcss: + specifier: ^3.4.17 + version: 3.4.17 + typescript: + specifier: ^5.7.2 + version: 5.8.2 + vite-tsconfig-paths: + specifier: ^5.1.4 + version: 5.1.4(typescript@5.8.2)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) + packages/arktype-adapter: devDependencies: '@tanstack/react-router': @@ -6323,19 +6366,21 @@ importers: '@babel/types': specifier: ^7.26.8 version: 7.26.8 + '@tanstack/router-generator': + specifier: workspace:* + version: link:../router-generator + '@tanstack/router-plugin': + specifier: workspace:* + version: link:../router-plugin '@tanstack/router-utils': specifier: workspace:* version: link:../router-utils - babel-dead-code-elimination: - specifier: ^1.0.9 - version: 1.0.9 - tiny-invariant: - specifier: ^1.3.3 - version: 1.3.3 - vite: - specifier: 6.1.0 - version: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) - devDependencies: + '@tanstack/server-functions-plugin': + specifier: workspace:* + version: link:../server-functions-plugin + '@tanstack/solid-router': + specifier: workspace:^ + version: link:../solid-router '@types/babel__code-frame': specifier: ^7.0.6 version: 7.0.6 @@ -6348,6 +6393,36 @@ importers: '@types/babel__traverse': specifier: ^7.20.6 version: 7.20.6 + babel-dead-code-elimination: + specifier: ^1.0.9 + version: 1.0.9 + fast-glob: + specifier: ^3.3.3 + version: 3.3.3 + h3: + specifier: 1.13.0 + version: 1.13.0 + import-meta-resolve: + specifier: ^4.1.0 + version: 4.1.0 + nitropack: + specifier: ^2.10.4 + version: 2.10.4(typescript@5.8.2) + tiny-invariant: + specifier: ^1.3.3 + version: 1.3.3 + vite: + specifier: 6.1.0 + version: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) + vite-plugin-solid: + specifier: ^2.11.6 + version: 2.11.6(@testing-library/jest-dom@6.6.3)(solid-js@1.9.5)(vite@6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0)) + xmlbuilder2: + specifier: ^3.1.1 + version: 3.1.1 + zod: + specifier: ^3.24.2 + version: 3.24.2 packages/solid-start-server: dependencies: From 4c13b84fec6b1928a18d1152f613154d5a408e38 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Wed, 12 Mar 2025 15:30:19 +0100 Subject: [PATCH 046/155] fix workspace - rename to tanstack-solid-start-example-basic --- examples/solid/start-basic/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/solid/start-basic/package.json b/examples/solid/start-basic/package.json index 4695a931f6..24274d7682 100644 --- a/examples/solid/start-basic/package.json +++ b/examples/solid/start-basic/package.json @@ -1,5 +1,5 @@ { - "name": "tanstack-start-example-basic", + "name": "tanstack-solid-start-example-basic", "private": true, "sideEffects": false, "type": "module", From 28bb4b60d6c06669de7a7f2a247d4415d163b31c Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Wed, 12 Mar 2025 15:45:35 +0100 Subject: [PATCH 047/155] fix some imports in solid-start example --- examples/solid/start-basic/src/routes/api/users.$id.ts | 4 ++-- examples/solid/start-basic/src/routes/api/users.ts | 4 ++-- examples/solid/start-basic/src/routes/deferred.tsx | 2 +- examples/solid/start-basic/src/utils/loggingMiddleware.tsx | 2 +- examples/solid/start-basic/src/utils/posts.tsx | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/examples/solid/start-basic/src/routes/api/users.$id.ts b/examples/solid/start-basic/src/routes/api/users.$id.ts index b1797e7917..b1786f6a30 100644 --- a/examples/solid/start-basic/src/routes/api/users.$id.ts +++ b/examples/solid/start-basic/src/routes/api/users.$id.ts @@ -1,5 +1,5 @@ -import { json } from '@tanstack/react-start' -import { createAPIFileRoute } from '@tanstack/react-start/api' +import { json } from '@tanstack/solid-start' +import { createAPIFileRoute } from '@tanstack/solid-start/api' import axios from 'redaxios' import type { User } from '../../utils/users' diff --git a/examples/solid/start-basic/src/routes/api/users.ts b/examples/solid/start-basic/src/routes/api/users.ts index 679eb9e8ab..c10bcfc94a 100644 --- a/examples/solid/start-basic/src/routes/api/users.ts +++ b/examples/solid/start-basic/src/routes/api/users.ts @@ -1,5 +1,5 @@ -import { json } from '@tanstack/react-start' -import { createAPIFileRoute } from '@tanstack/react-start/api' +import { json } from '@tanstack/solid-start' +import { createAPIFileRoute } from '@tanstack/solid-start/api' import axios from 'redaxios' import type { User } from '../../utils/users' diff --git a/examples/solid/start-basic/src/routes/deferred.tsx b/examples/solid/start-basic/src/routes/deferred.tsx index 48f11f2450..1860f3af9a 100644 --- a/examples/solid/start-basic/src/routes/deferred.tsx +++ b/examples/solid/start-basic/src/routes/deferred.tsx @@ -1,5 +1,5 @@ import { Await, createFileRoute } from '@tanstack/solid-router' -import { createServerFn } from '@tanstack/react-start' +import { createServerFn } from '@tanstack/solid-start' import { createSignal, Suspense } from 'solid-js' const personServerFn = createServerFn({ method: 'GET' }) diff --git a/examples/solid/start-basic/src/utils/loggingMiddleware.tsx b/examples/solid/start-basic/src/utils/loggingMiddleware.tsx index d743ba5340..928fedfd25 100644 --- a/examples/solid/start-basic/src/utils/loggingMiddleware.tsx +++ b/examples/solid/start-basic/src/utils/loggingMiddleware.tsx @@ -1,4 +1,4 @@ -import { createMiddleware } from '@tanstack/react-start' +import { createMiddleware } from '@tanstack/solid-start' const preLogMiddleware = createMiddleware() .client(async (ctx) => { diff --git a/examples/solid/start-basic/src/utils/posts.tsx b/examples/solid/start-basic/src/utils/posts.tsx index 0366131412..96eaa78afc 100644 --- a/examples/solid/start-basic/src/utils/posts.tsx +++ b/examples/solid/start-basic/src/utils/posts.tsx @@ -1,5 +1,5 @@ import { notFound } from '@tanstack/solid-router' -import { createServerFn } from '@tanstack/react-start' +import { createServerFn } from '@tanstack/solid-start' import axios from 'redaxios' export type PostType = { From 9d22c535553c93d4724a598c55429e8e4296ad0b Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Wed, 12 Mar 2025 12:27:17 -0600 Subject: [PATCH 048/155] rework schema --- examples/react/start-basic/vite.config.ts | 6 +- packages/react-start-plugin/src/index.ts | 49 +++----- .../src/nitro/build-server.ts | 39 ------ .../src/nitro/nitro-plugin.ts | 9 +- .../react-start-plugin/src/nitro/options.ts | 80 ------------ packages/react-start-plugin/src/schema.ts | 118 ++++++++---------- 6 files changed, 72 insertions(+), 229 deletions(-) delete mode 100644 packages/react-start-plugin/src/nitro/build-server.ts delete mode 100644 packages/react-start-plugin/src/nitro/options.ts diff --git a/examples/react/start-basic/vite.config.ts b/examples/react/start-basic/vite.config.ts index dfee8b17e9..698e4856da 100644 --- a/examples/react/start-basic/vite.config.ts +++ b/examples/react/start-basic/vite.config.ts @@ -10,10 +10,6 @@ export default defineConfig({ tsConfigPaths({ projects: ['./tsconfig.json'], }), - TanStackStartVitePlugin({ - server: { - // preset: 'netlify', - }, - }), + TanStackStartVitePlugin(), ], }) diff --git a/packages/react-start-plugin/src/index.ts b/packages/react-start-plugin/src/index.ts index 1a8c2837d6..cb4b7f9354 100644 --- a/packages/react-start-plugin/src/index.ts +++ b/packages/react-start-plugin/src/index.ts @@ -1,9 +1,8 @@ import path from 'node:path' import { TanStackServerFnPluginEnv } from '@tanstack/server-functions-plugin' -import { createNitro } from 'nitropack' import { TanStackRouterVite } from '@tanstack/router-plugin/vite' import viteReact from '@vitejs/plugin-react' -import { mergeConfig } from 'vite' +import { createNitro } from 'nitropack' import { getTanStackStartOptions } from './schema.js' import { nitroPlugin } from './nitro/nitro-plugin.js' import { startManifestPlugin } from './routesManifestPlugin.js' @@ -26,16 +25,19 @@ export function TanStackStartVitePlugin( return [ { name: 'tss-vite-config-client', - ...options.vite, async config() { - // Create a dummy nitro app to get the resolved public output path - const dummyNitroApp = await createNitro({ - preset: options.server.preset, - compatibilityDate: '2024-12-01', - }) + const nitroOutputPublicDir = await (async () => { + // Create a dummy nitro app to get the resolved public output path + const dummyNitroApp = await createNitro({ + preset: options.target, + compatibilityDate: '2024-12-01', + }) - const nitroOutputPublicDir = dummyNitroApp.options.output.publicDir - await dummyNitroApp.close() + const nitroOutputPublicDir = dummyNitroApp.options.output.publicDir + await dummyNitroApp.close() + + return nitroOutputPublicDir + })() return { environments: { @@ -75,33 +77,16 @@ export function TanStackStartVitePlugin( 'tsr:server-fn-manifest', ], }, - optimizeDeps: { - entries: [], - ...(options.vite?.optimizeDeps || {}), - include: [...(options.vite?.optimizeDeps?.include || [])], - }, /* prettier-ignore */ define: { - ...(options.vite?.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', options.routers.public.base), - ...injectDefineEnv('TSS_CLIENT_BASE', options.routers.client.base), + ...injectDefineEnv('TSS_PUBLIC_BASE', options.public.base), + ...injectDefineEnv('TSS_CLIENT_BASE', options.client.base), ...injectDefineEnv('TSS_CLIENT_ENTRY', options.clientEntryPath), - ...injectDefineEnv('TSS_SERVER_FN_BASE', options.routers.server.base), + ...injectDefineEnv('TSS_SERVER_FN_BASE', options.serverFns.base), ...injectDefineEnv('TSS_OUTPUT_PUBLIC_DIR', nitroOutputPublicDir), }, } }, - configEnvironment(env, config) { - if (env === 'server') { - } else { - config = mergeConfig( - mergeConfig(config, options.vite || {}), - options.routers.client.vite || {}, - ) - } - - return config - }, resolveId(id) { if ( [ @@ -154,13 +139,13 @@ export default createStartHandler({ getRuntimeCode: () => `import { createClientRpc } from '@tanstack/react-start/server-functions-client'`, replacer: (d) => - `createClientRpc('${d.functionId}', '${options.routers.server.base}')`, + `createClientRpc('${d.functionId}', '${options.serverFns.base}')`, }, server: { getRuntimeCode: () => `import { createServerRpc } from '@tanstack/react-start/server-functions-server'`, replacer: (d) => - `createServerRpc('${d.functionId}', '${options.routers.server.base}', ${d.fn})`, + `createServerRpc('${d.functionId}', '${options.serverFns.base}', ${d.fn})`, }, }), startManifestPlugin(options), diff --git a/packages/react-start-plugin/src/nitro/build-server.ts b/packages/react-start-plugin/src/nitro/build-server.ts deleted file mode 100644 index 052ffd66dc..0000000000 --- a/packages/react-start-plugin/src/nitro/build-server.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - build, - copyPublicAssets, - createNitro, - prepare, - prerender, -} from 'nitropack' - -import type { NitroConfig } from 'nitropack' - -export async function buildServer(nitroConfig: NitroConfig) { - const nitro = await createNitro({ - dev: false, - preset: process.env['BUILD_PRESET'], - ...nitroConfig, - }) - - // if (nitroConfig.prerender?.postRenderingHooks) { - // addPostRenderingHooks(nitro, nitroConfig.prerender.postRenderingHooks) - // } - - await prepare(nitro) - await copyPublicAssets(nitro) - - if ( - nitroConfig.prerender?.routes && - nitroConfig.prerender.routes.length > 0 - ) { - console.log(`Prerendering static pages...`) - await prerender(nitro) - } - - if (!nitroConfig.static) { - console.log('Building Server...') - await build(nitro) - } - - await nitro.close() -} diff --git a/packages/react-start-plugin/src/nitro/nitro-plugin.ts b/packages/react-start-plugin/src/nitro/nitro-plugin.ts index d179dc95ee..fb87e1a50b 100644 --- a/packages/react-start-plugin/src/nitro/nitro-plugin.ts +++ b/packages/react-start-plugin/src/nitro/nitro-plugin.ts @@ -27,13 +27,12 @@ export function nitroPlugin( let nitroRollupOptions: ReturnType const buildPreset = - process.env['BUILD_PRESET'] ?? (options.server.preset as string | undefined) + process.env['START_TARGET'] ?? (options.target as string | undefined) const nitroConfig: NitroConfig = { compatibilityDate: '2024-11-19', - logLevel: options.server.logLevel || 0, srcDir: normalizePath(options.tsr.srcDirectory), - ...options.server, + ...options.nitro, preset: buildPreset, publicAssets: [ { @@ -44,8 +43,8 @@ export function nitroPlugin( generateTsConfig: false, }, prerender: { - ...options.server.prerender, - routes: ['/', ...(options.server.prerender?.routes || [])], + ...options.prerender, + routes: options.prerender.routes || [], }, renderer: options.serverEntryPath, } diff --git a/packages/react-start-plugin/src/nitro/options.ts b/packages/react-start-plugin/src/nitro/options.ts deleted file mode 100644 index c8c8a3d15f..0000000000 --- a/packages/react-start-plugin/src/nitro/options.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { PrerenderRoute } from 'nitropack' - -export interface Options { - ssr?: boolean - ssrBuildDir?: string - /** - * Prerender the static pages without producing the server output. - */ - static?: boolean - prerender?: PrerenderOptions - entryServer?: string - index?: string - workspaceRoot?: string - /** - * Additional page paths to include - */ - additionalPagesDirs?: string[] - /** - * Additional API paths to include - */ - additionalAPIDirs?: string[] - apiPrefix?: string - - /** - * Toggles internal API middleware. - * If disabled, a proxy request is used to route /api - * requests to / in the production server build. - */ - useAPIMiddleware?: boolean -} - -export interface PrerenderOptions { - /** - * Add additional routes to prerender through crawling page links. - */ - discover?: boolean - - /** - * List of routes to prerender resolved statically or dynamically. - */ - routes?: - | (string | PrerenderContentDir)[] - | (() => Promise<(string | PrerenderContentDir | undefined)[]>) - sitemap?: SitemapConfig - /** List of functions that run for each route after pre-rendering is complete. */ - postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[] -} - -export interface SitemapConfig { - host: string -} - -export interface PrerenderContentDir { - /** - * The directory where files should be grabbed from. - * @example `/src/contents/blog` - */ - contentDir: string - /** - * Transform the matching content files path into a route. - * The function is called for each matching content file within the specified contentDir. - * @param file information of the matching file (`path`, `name`, `extension`, `attributes`) - * @returns a string with the route should be returned (e. g. `/blog/`) or the value `false`, when the route should not be prerendered. - */ - transform: (file: PrerenderContentFile) => string | false -} - -/** - * @param path the path to the content file - * @param name the basename of the matching content file without the file extension - * @param extension the file extension - * @param attributes the frontmatter attributes extracted from the frontmatter section of the file - * @returns a string with the route should be returned (e. g. `/blog/`) or the value `false`, when the route should not be prerendered. - */ -export interface PrerenderContentFile { - path: string - attributes: Record - name: string - extension: string -} diff --git a/packages/react-start-plugin/src/schema.ts b/packages/react-start-plugin/src/schema.ts index ac120b642d..0e94ac7d27 100644 --- a/packages/react-start-plugin/src/schema.ts +++ b/packages/react-start-plugin/src/schema.ts @@ -2,74 +2,24 @@ import path from 'node:path' import { existsSync } from 'node:fs' import { z } from 'zod' import { configSchema, getConfig } from '@tanstack/router-generator' -import type { UserConfig } from 'vite' import type { NitroConfig } from 'nitropack' import type { Options as ViteReactOptions } from '@vitejs/plugin-react' -type HTTPSOptions = { - cert?: string - key?: string - pfx?: string - passphrase?: string - validityDays?: number - domains?: Array -} - -type ServerOptions = NitroConfig & { - https?: boolean | HTTPSOptions -} +// type HTTPSOptions = { +// cert?: string +// key?: string +// pfx?: string +// passphrase?: string +// validityDays?: number +// domains?: Array +// } -export const serverSchema = z.custom().and( - z.object({ - preset: z - .custom() - .optional() - .default('node-server'), - }), -) - -const viteSchema = z.custom() +// type ServerOptions = NitroConfig & { +// https?: boolean | HTTPSOptions +// } const viteReactSchema = z.custom() -const routersSchema = z.object({ - ssr: z - .object({ - entry: z.string().optional(), - // middleware: z.string().optional(), - vite: viteSchema.optional(), - }) - .optional() - .default({}), - client: z - .object({ - entry: z.string().optional(), - base: z.string().optional().default('/_build'), - vite: viteSchema.optional(), - }) - .optional() - .default({}), - server: z - .object({ - base: z.string().optional().default('/_server'), - globalMiddlewareEntry: z - .string() - .optional() - .default('global-middleware.ts'), - // middleware: z.string().optional(), - vite: viteSchema.optional(), - }) - .optional() - .default({}), - public: z - .object({ - dir: z.string().optional().default('public'), - base: z.string().optional().default('/'), - }) - .optional() - .default({}), -}) - const sitemapSchema = z.object({ host: z.string(), }) @@ -81,12 +31,44 @@ const tsrConfig = configSchema.partial().extend({ const TanStackStartOptionsSchema = z .object({ root: z.string().optional().default(process.cwd()), + target: z.custom().optional(), + nitro: z.custom().optional().default({}), react: viteReactSchema.optional(), - vite: viteSchema.optional(), tsr: tsrConfig.optional().default({}), - routers: routersSchema.optional().default({}), - server: serverSchema.optional().default({}), + client: z + .object({ + entry: z.string().optional(), + base: z.string().optional().default('/_build'), + }) + .optional() + .default({}), + server: z + .object({ + entry: z.string().optional(), + }) + .optional() + .default({}), + serverFns: z + .object({ + base: z.string().optional().default('/_server'), + }) + .optional() + .default({}), + public: z + .object({ + dir: z.string().optional().default('public'), + base: z.string().optional().default('/'), + }) + .optional() + .default({}), sitemap: sitemapSchema.optional(), + prerender: z + .object({ + enabled: z.boolean().optional(), + routes: z.array(z.string()).optional(), + }) + .optional() + .default({}), }) .optional() .default({}) @@ -104,8 +86,8 @@ export function getTanStackStartOptions(opts?: TanStackStartInputConfig) { path.join(srcDirectory, 'routeTree.gen.ts') const clientEntryPath = (() => { - if (options.routers.client.entry) { - return path.join(srcDirectory, options.routers.client.entry) + if (options.client.entry) { + return path.join(srcDirectory, options.client.entry) } if (existsSync(path.join(srcDirectory, 'client.tsx'))) { @@ -116,8 +98,8 @@ export function getTanStackStartOptions(opts?: TanStackStartInputConfig) { })() const serverEntryPath = (() => { - if (options.routers.ssr.entry) { - return path.join(srcDirectory, options.routers.ssr.entry) + if (options.server.entry) { + return path.join(srcDirectory, options.server.entry) } if (existsSync(path.join(srcDirectory, 'server.tsx'))) { From cabada8a1fd465279c1402f9b9027a56053a3733 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Wed, 12 Mar 2025 19:58:44 +0100 Subject: [PATCH 049/155] set Content-Type text/html for error overlay --- packages/react-start-plugin/src/nitro/dev-server-plugin.ts | 3 +++ packages/solid-start-plugin/src/nitro/dev-server-plugin.ts | 3 +++ 2 files changed, 6 insertions(+) diff --git a/packages/react-start-plugin/src/nitro/dev-server-plugin.ts b/packages/react-start-plugin/src/nitro/dev-server-plugin.ts index 9f6c156b45..03a447112c 100644 --- a/packages/react-start-plugin/src/nitro/dev-server-plugin.ts +++ b/packages/react-start-plugin/src/nitro/dev-server-plugin.ts @@ -102,6 +102,9 @@ export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { `, { status: 500, + headers: { + 'Content-Type': 'text/html', + }, }, ), ) diff --git a/packages/solid-start-plugin/src/nitro/dev-server-plugin.ts b/packages/solid-start-plugin/src/nitro/dev-server-plugin.ts index 9f6c156b45..03a447112c 100644 --- a/packages/solid-start-plugin/src/nitro/dev-server-plugin.ts +++ b/packages/solid-start-plugin/src/nitro/dev-server-plugin.ts @@ -102,6 +102,9 @@ export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { `, { status: 500, + headers: { + 'Content-Type': 'text/html', + }, }, ), ) From 5fcd5a8e7afd8359f57744d05992fe09c4c7d4cf Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Wed, 12 Mar 2025 13:38:55 -0600 Subject: [PATCH 050/155] prerendering todo --- .../src/nitro/nitro-plugin.ts | 20 +++++++++---------- packages/react-start-plugin/src/schema.ts | 5 ++++- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/packages/react-start-plugin/src/nitro/nitro-plugin.ts b/packages/react-start-plugin/src/nitro/nitro-plugin.ts index fb87e1a50b..d6f208dcec 100644 --- a/packages/react-start-plugin/src/nitro/nitro-plugin.ts +++ b/packages/react-start-plugin/src/nitro/nitro-plugin.ts @@ -42,10 +42,7 @@ export function nitroPlugin( typescript: { generateTsConfig: false, }, - prerender: { - ...options.prerender, - routes: options.prerender.routes || [], - }, + prerender: undefined, renderer: options.serverEntryPath, } @@ -99,13 +96,14 @@ export function nitroPlugin( await prepare(nitro) await copyPublicAssets(nitro) - // if ( - // nitroConfig.prerender?.routes && - // nitroConfig.prerender.routes.length > 0 - // ) { - // console.log(`Prerendering static pages...`) - // await prerender(nitro) - // } + if ( + options.prerender.routes && + options.prerender.routes.length > 0 + ) { + console.log('Prerendering is not implemented yet.') + // console.log(`Prerendering static pages...`) + // await prerender(nitro) + } await builder.build(builder.environments['server']) diff --git a/packages/react-start-plugin/src/schema.ts b/packages/react-start-plugin/src/schema.ts index 0e94ac7d27..185da14fa1 100644 --- a/packages/react-start-plugin/src/schema.ts +++ b/packages/react-start-plugin/src/schema.ts @@ -32,7 +32,10 @@ const TanStackStartOptionsSchema = z .object({ root: z.string().optional().default(process.cwd()), target: z.custom().optional(), - nitro: z.custom().optional().default({}), + nitro: z + .custom>() + .optional() + .default({}), react: viteReactSchema.optional(), tsr: tsrConfig.optional().default({}), client: z From d03fdcd35fdf5eb0cc8d76713089be1a336e121e Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Wed, 12 Mar 2025 13:43:11 -0600 Subject: [PATCH 051/155] No nitro exposure --- packages/react-start-plugin/src/nitro/nitro-plugin.ts | 7 ++----- packages/react-start-plugin/src/schema.ts | 4 ---- 2 files changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/react-start-plugin/src/nitro/nitro-plugin.ts b/packages/react-start-plugin/src/nitro/nitro-plugin.ts index d6f208dcec..0d3febc0d9 100644 --- a/packages/react-start-plugin/src/nitro/nitro-plugin.ts +++ b/packages/react-start-plugin/src/nitro/nitro-plugin.ts @@ -30,9 +30,9 @@ export function nitroPlugin( process.env['START_TARGET'] ?? (options.target as string | undefined) const nitroConfig: NitroConfig = { + dev: false, compatibilityDate: '2024-11-19', srcDir: normalizePath(options.tsr.srcDirectory), - ...options.nitro, preset: buildPreset, publicAssets: [ { @@ -51,10 +51,7 @@ export function nitroPlugin( { name: 'tanstack-vite-plugin-nitro', async configEnvironment(name) { - nitro = await createNitro({ - dev: false, - ...nitroConfig, - }) + nitro = await createNitro(nitroConfig) nitroRollupOptions = getRollupConfig(nitro) diff --git a/packages/react-start-plugin/src/schema.ts b/packages/react-start-plugin/src/schema.ts index 185da14fa1..fe14504b85 100644 --- a/packages/react-start-plugin/src/schema.ts +++ b/packages/react-start-plugin/src/schema.ts @@ -32,10 +32,6 @@ const TanStackStartOptionsSchema = z .object({ root: z.string().optional().default(process.cwd()), target: z.custom().optional(), - nitro: z - .custom>() - .optional() - .default({}), react: viteReactSchema.optional(), tsr: tsrConfig.optional().default({}), client: z From 630803e58f0976e302a3cf713f48f77919449312 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Wed, 12 Mar 2025 22:34:21 +0100 Subject: [PATCH 052/155] sync solid --- packages/solid-start-plugin/src/index.ts | 49 +++----- .../src/nitro/build-server.ts | 39 ------ .../src/nitro/nitro-plugin.ts | 30 ++--- .../solid-start-plugin/src/nitro/options.ts | 80 ------------ packages/solid-start-plugin/src/schema.ts | 117 ++++++++---------- 5 files changed, 78 insertions(+), 237 deletions(-) delete mode 100644 packages/solid-start-plugin/src/nitro/build-server.ts delete mode 100644 packages/solid-start-plugin/src/nitro/options.ts diff --git a/packages/solid-start-plugin/src/index.ts b/packages/solid-start-plugin/src/index.ts index e2d8faa19d..3311da3ea4 100644 --- a/packages/solid-start-plugin/src/index.ts +++ b/packages/solid-start-plugin/src/index.ts @@ -1,9 +1,8 @@ import path from 'node:path' import { TanStackServerFnPluginEnv } from '@tanstack/server-functions-plugin' -import { createNitro } from 'nitropack' import { TanStackRouterVite } from '@tanstack/router-plugin/vite' import viteSolid from 'vite-plugin-solid' -import { mergeConfig } from 'vite' +import { createNitro } from 'nitropack' import { getTanStackStartOptions } from './schema.js' import { nitroPlugin } from './nitro/nitro-plugin.js' import { startManifestPlugin } from './routesManifestPlugin.js' @@ -26,16 +25,19 @@ export function TanStackStartVitePlugin( return [ { name: 'tss-vite-config-client', - ...options.vite, async config() { - // Create a dummy nitro app to get the resolved public output path - const dummyNitroApp = await createNitro({ - preset: options.server.preset, - compatibilityDate: '2024-12-01', - }) + const nitroOutputPublicDir = await (async () => { + // Create a dummy nitro app to get the resolved public output path + const dummyNitroApp = await createNitro({ + preset: options.target, + compatibilityDate: '2024-12-01', + }) - const nitroOutputPublicDir = dummyNitroApp.options.output.publicDir - await dummyNitroApp.close() + const nitroOutputPublicDir = dummyNitroApp.options.output.publicDir + await dummyNitroApp.close() + + return nitroOutputPublicDir + })() return { environments: { @@ -75,33 +77,16 @@ export function TanStackStartVitePlugin( 'tsr:server-fn-manifest', ], }, - optimizeDeps: { - entries: [], - ...(options.vite?.optimizeDeps || {}), - include: [...(options.vite?.optimizeDeps?.include || [])], - }, /* prettier-ignore */ define: { - ...(options.vite?.define || {}), - ...injectDefineEnv('TSS_PUBLIC_BASE', options.routers.public.base), - ...injectDefineEnv('TSS_CLIENT_BASE', options.routers.client.base), + ...injectDefineEnv('TSS_PUBLIC_BASE', options.public.base), + ...injectDefineEnv('TSS_CLIENT_BASE', options.client.base), ...injectDefineEnv('TSS_CLIENT_ENTRY', options.clientEntryPath), - ...injectDefineEnv('TSS_SERVER_FN_BASE', options.routers.server.base), + ...injectDefineEnv('TSS_SERVER_FN_BASE', options.serverFns.base), ...injectDefineEnv('TSS_OUTPUT_PUBLIC_DIR', nitroOutputPublicDir), }, } }, - configEnvironment(env, config) { - if (env === 'server') { - } else { - config = mergeConfig( - mergeConfig(config, options.vite || {}), - options.routers.client.vite || {}, - ) - } - - return config - }, resolveId(id) { if ( [ @@ -156,13 +141,13 @@ export default createStartHandler({ getRuntimeCode: () => `import { createClientRpc } from '@tanstack/solid-start/server-functions-client'`, replacer: (d) => - `createClientRpc('${d.functionId}', '${options.routers.server.base}')`, + `createClientRpc('${d.functionId}', '${options.serverFns.base}')`, }, server: { getRuntimeCode: () => `import { createServerRpc } from '@tanstack/solid-start/server-functions-server'`, replacer: (d) => - `createServerRpc('${d.functionId}', '${options.routers.server.base}', ${d.fn})`, + `createServerRpc('${d.functionId}', '${options.serverFns.base}', ${d.fn})`, }, }), startManifestPlugin(options), diff --git a/packages/solid-start-plugin/src/nitro/build-server.ts b/packages/solid-start-plugin/src/nitro/build-server.ts deleted file mode 100644 index 052ffd66dc..0000000000 --- a/packages/solid-start-plugin/src/nitro/build-server.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { - build, - copyPublicAssets, - createNitro, - prepare, - prerender, -} from 'nitropack' - -import type { NitroConfig } from 'nitropack' - -export async function buildServer(nitroConfig: NitroConfig) { - const nitro = await createNitro({ - dev: false, - preset: process.env['BUILD_PRESET'], - ...nitroConfig, - }) - - // if (nitroConfig.prerender?.postRenderingHooks) { - // addPostRenderingHooks(nitro, nitroConfig.prerender.postRenderingHooks) - // } - - await prepare(nitro) - await copyPublicAssets(nitro) - - if ( - nitroConfig.prerender?.routes && - nitroConfig.prerender.routes.length > 0 - ) { - console.log(`Prerendering static pages...`) - await prerender(nitro) - } - - if (!nitroConfig.static) { - console.log('Building Server...') - await build(nitro) - } - - await nitro.close() -} diff --git a/packages/solid-start-plugin/src/nitro/nitro-plugin.ts b/packages/solid-start-plugin/src/nitro/nitro-plugin.ts index d179dc95ee..0d3febc0d9 100644 --- a/packages/solid-start-plugin/src/nitro/nitro-plugin.ts +++ b/packages/solid-start-plugin/src/nitro/nitro-plugin.ts @@ -27,13 +27,12 @@ export function nitroPlugin( let nitroRollupOptions: ReturnType const buildPreset = - process.env['BUILD_PRESET'] ?? (options.server.preset as string | undefined) + process.env['START_TARGET'] ?? (options.target as string | undefined) const nitroConfig: NitroConfig = { + dev: false, compatibilityDate: '2024-11-19', - logLevel: options.server.logLevel || 0, srcDir: normalizePath(options.tsr.srcDirectory), - ...options.server, preset: buildPreset, publicAssets: [ { @@ -43,10 +42,7 @@ export function nitroPlugin( typescript: { generateTsConfig: false, }, - prerender: { - ...options.server.prerender, - routes: ['/', ...(options.server.prerender?.routes || [])], - }, + prerender: undefined, renderer: options.serverEntryPath, } @@ -55,10 +51,7 @@ export function nitroPlugin( { name: 'tanstack-vite-plugin-nitro', async configEnvironment(name) { - nitro = await createNitro({ - dev: false, - ...nitroConfig, - }) + nitro = await createNitro(nitroConfig) nitroRollupOptions = getRollupConfig(nitro) @@ -100,13 +93,14 @@ export function nitroPlugin( await prepare(nitro) await copyPublicAssets(nitro) - // if ( - // nitroConfig.prerender?.routes && - // nitroConfig.prerender.routes.length > 0 - // ) { - // console.log(`Prerendering static pages...`) - // await prerender(nitro) - // } + if ( + options.prerender.routes && + options.prerender.routes.length > 0 + ) { + console.log('Prerendering is not implemented yet.') + // console.log(`Prerendering static pages...`) + // await prerender(nitro) + } await builder.build(builder.environments['server']) diff --git a/packages/solid-start-plugin/src/nitro/options.ts b/packages/solid-start-plugin/src/nitro/options.ts deleted file mode 100644 index c8c8a3d15f..0000000000 --- a/packages/solid-start-plugin/src/nitro/options.ts +++ /dev/null @@ -1,80 +0,0 @@ -import { PrerenderRoute } from 'nitropack' - -export interface Options { - ssr?: boolean - ssrBuildDir?: string - /** - * Prerender the static pages without producing the server output. - */ - static?: boolean - prerender?: PrerenderOptions - entryServer?: string - index?: string - workspaceRoot?: string - /** - * Additional page paths to include - */ - additionalPagesDirs?: string[] - /** - * Additional API paths to include - */ - additionalAPIDirs?: string[] - apiPrefix?: string - - /** - * Toggles internal API middleware. - * If disabled, a proxy request is used to route /api - * requests to / in the production server build. - */ - useAPIMiddleware?: boolean -} - -export interface PrerenderOptions { - /** - * Add additional routes to prerender through crawling page links. - */ - discover?: boolean - - /** - * List of routes to prerender resolved statically or dynamically. - */ - routes?: - | (string | PrerenderContentDir)[] - | (() => Promise<(string | PrerenderContentDir | undefined)[]>) - sitemap?: SitemapConfig - /** List of functions that run for each route after pre-rendering is complete. */ - postRenderingHooks?: ((routes: PrerenderRoute) => Promise)[] -} - -export interface SitemapConfig { - host: string -} - -export interface PrerenderContentDir { - /** - * The directory where files should be grabbed from. - * @example `/src/contents/blog` - */ - contentDir: string - /** - * Transform the matching content files path into a route. - * The function is called for each matching content file within the specified contentDir. - * @param file information of the matching file (`path`, `name`, `extension`, `attributes`) - * @returns a string with the route should be returned (e. g. `/blog/`) or the value `false`, when the route should not be prerendered. - */ - transform: (file: PrerenderContentFile) => string | false -} - -/** - * @param path the path to the content file - * @param name the basename of the matching content file without the file extension - * @param extension the file extension - * @param attributes the frontmatter attributes extracted from the frontmatter section of the file - * @returns a string with the route should be returned (e. g. `/blog/`) or the value `false`, when the route should not be prerendered. - */ -export interface PrerenderContentFile { - path: string - attributes: Record - name: string - extension: string -} diff --git a/packages/solid-start-plugin/src/schema.ts b/packages/solid-start-plugin/src/schema.ts index 428dacdf0a..350dfe226d 100644 --- a/packages/solid-start-plugin/src/schema.ts +++ b/packages/solid-start-plugin/src/schema.ts @@ -2,74 +2,24 @@ import path from 'node:path' import { existsSync } from 'node:fs' import { z } from 'zod' import { configSchema, getConfig } from '@tanstack/router-generator' -import type { UserConfig } from 'vite' import type { NitroConfig } from 'nitropack' import type { Options as ViteSolidOptions } from 'vite-plugin-solid' -type HTTPSOptions = { - cert?: string - key?: string - pfx?: string - passphrase?: string - validityDays?: number - domains?: Array -} - -type ServerOptions = NitroConfig & { - https?: boolean | HTTPSOptions -} +// type HTTPSOptions = { +// cert?: string +// key?: string +// pfx?: string +// passphrase?: string +// validityDays?: number +// domains?: Array +// } -export const serverSchema = z.custom().and( - z.object({ - preset: z - .custom() - .optional() - .default('node-server'), - }), -) - -const viteSchema = z.custom() +// type ServerOptions = NitroConfig & { +// https?: boolean | HTTPSOptions +// } const viteSolidSchema = z.custom() -const routersSchema = z.object({ - ssr: z - .object({ - entry: z.string().optional(), - // middleware: z.string().optional(), - vite: viteSchema.optional(), - }) - .optional() - .default({}), - client: z - .object({ - entry: z.string().optional(), - base: z.string().optional().default('/_build'), - vite: viteSchema.optional(), - }) - .optional() - .default({}), - server: z - .object({ - base: z.string().optional().default('/_server'), - globalMiddlewareEntry: z - .string() - .optional() - .default('global-middleware.ts'), - // middleware: z.string().optional(), - vite: viteSchema.optional(), - }) - .optional() - .default({}), - public: z - .object({ - dir: z.string().optional().default('public'), - base: z.string().optional().default('/'), - }) - .optional() - .default({}), -}) - const sitemapSchema = z.object({ host: z.string(), }) @@ -81,12 +31,43 @@ const tsrConfig = configSchema.partial().extend({ const TanStackStartOptionsSchema = z .object({ root: z.string().optional().default(process.cwd()), + target: z.custom().optional(), solid: viteSolidSchema.optional(), - vite: viteSchema.optional(), tsr: tsrConfig.optional().default({}), - routers: routersSchema.optional().default({}), - server: serverSchema.optional().default({}), + client: z + .object({ + entry: z.string().optional(), + base: z.string().optional().default('/_build'), + }) + .optional() + .default({}), + server: z + .object({ + entry: z.string().optional(), + }) + .optional() + .default({}), + serverFns: z + .object({ + base: z.string().optional().default('/_server'), + }) + .optional() + .default({}), + public: z + .object({ + dir: z.string().optional().default('public'), + base: z.string().optional().default('/'), + }) + .optional() + .default({}), sitemap: sitemapSchema.optional(), + prerender: z + .object({ + enabled: z.boolean().optional(), + routes: z.array(z.string()).optional(), + }) + .optional() + .default({}), }) .optional() .default({}) @@ -104,8 +85,8 @@ export function getTanStackStartOptions(opts?: TanStackStartInputConfig) { path.join(srcDirectory, 'routeTree.gen.ts') const clientEntryPath = (() => { - if (options.routers.client.entry) { - return path.join(srcDirectory, options.routers.client.entry) + if (options.client.entry) { + return path.join(srcDirectory, options.client.entry) } if (existsSync(path.join(srcDirectory, 'client.tsx'))) { @@ -116,8 +97,8 @@ export function getTanStackStartOptions(opts?: TanStackStartInputConfig) { })() const serverEntryPath = (() => { - if (options.routers.ssr.entry) { - return path.join(srcDirectory, options.routers.ssr.entry) + if (options.server.entry) { + return path.join(srcDirectory, options.server.entry) } if (existsSync(path.join(srcDirectory, 'server.tsx'))) { From f886dc9f91aa60de340ee54bb3500fafc3974a56 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Wed, 12 Mar 2025 23:44:12 +0100 Subject: [PATCH 053/155] add target react, for easier mirror to solid --- packages/react-start-plugin/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-start-plugin/src/index.ts b/packages/react-start-plugin/src/index.ts index cb4b7f9354..b2fee6c7d0 100644 --- a/packages/react-start-plugin/src/index.ts +++ b/packages/react-start-plugin/src/index.ts @@ -151,6 +151,7 @@ export default createStartHandler({ startManifestPlugin(options), TanStackRouterVite({ ...options.tsr, + target: 'react', enableRouteGeneration: true, __enableAPIRoutesGeneration: true, autoCodeSplitting: true, From 857bc66359a111391c3df29e8e58d9246275a7ea Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Wed, 12 Mar 2025 23:48:16 +0100 Subject: [PATCH 054/155] add ssr true flag to solid vite plugin --- packages/solid-start-plugin/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solid-start-plugin/src/index.ts b/packages/solid-start-plugin/src/index.ts index 3311da3ea4..e5def0ddec 100644 --- a/packages/solid-start-plugin/src/index.ts +++ b/packages/solid-start-plugin/src/index.ts @@ -158,7 +158,7 @@ export default createStartHandler({ __enableAPIRoutesGeneration: true, autoCodeSplitting: true, }), - viteSolid(options.solid), + viteSolid({ ...options.solid, ssr: true }), nitroPlugin(options), ] } From 963d18c460b10262b69f7e2ac7b1308eaca58665 Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Wed, 12 Mar 2025 23:57:54 +0100 Subject: [PATCH 055/155] fix deferred --- examples/solid/start-basic/src/routes/__root.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/examples/solid/start-basic/src/routes/__root.tsx b/examples/solid/start-basic/src/routes/__root.tsx index c3e395041f..3dbf0d19d4 100644 --- a/examples/solid/start-basic/src/routes/__root.tsx +++ b/examples/solid/start-basic/src/routes/__root.tsx @@ -72,11 +72,8 @@ function RootComponent() { function RootDocument({ children }: { children: Solid.JSX.Element }) { return ( - - + <> - -
- - + ) } From dd55500a769793c02f6df2b36c657d14f57c0efc Mon Sep 17 00:00:00 2001 From: Birk Skyum Date: Thu, 13 Mar 2025 00:31:24 +0100 Subject: [PATCH 056/155] fix hydration for solid --- .../src/createStartHandler.ts | 74 ++++++++++++++++++ packages/react-start-server/src/index.tsx | 2 + .../src/router-manifest.ts | 4 - .../src/createStartHandler.ts | 74 ++++++++++++++++++ packages/solid-start-server/src/index.tsx | 2 + .../solid-start-server/src/router-manifest.ts | 75 ++++++++++++++++++ packages/solid-start-server/vite.config.ts | 1 + .../src/createStartHandler.ts | 77 +------------------ packages/start-server-core/src/index.tsx | 6 +- .../src/server-functions-handler.ts | 2 +- 10 files changed, 235 insertions(+), 82 deletions(-) create mode 100644 packages/react-start-server/src/createStartHandler.ts rename packages/{start-server-core => react-start-server}/src/router-manifest.ts (96%) create mode 100644 packages/solid-start-server/src/createStartHandler.ts create mode 100644 packages/solid-start-server/src/router-manifest.ts diff --git a/packages/react-start-server/src/createStartHandler.ts b/packages/react-start-server/src/createStartHandler.ts new file mode 100644 index 0000000000..4a1f53feba --- /dev/null +++ b/packages/react-start-server/src/createStartHandler.ts @@ -0,0 +1,74 @@ +import path from 'node:path' +import { createMemoryHistory } from '@tanstack/history' +import { eventHandler, toWebRequest } from 'h3' +import { attachRouterServerSsrUtils, dehydrateRouter, getStartResponseHeaders, serverFunctionsHandler } from '@tanstack/start-server-core' +import { getStartManifest } from './router-manifest' +import type { EventHandlerResponse } from 'h3' +import type { AnyRouter } from '@tanstack/router-core' +import type { CustomizeStartHandler } from '@tanstack/start-server-core'; + +export function createStartHandler< + TRouter extends AnyRouter, + TResponse extends EventHandlerResponse = EventHandlerResponse, +>({ + createRouter, +}: { + createRouter: () => TRouter +}): CustomizeStartHandler { + return (cb) => { + return eventHandler(async (event) => { + const request = toWebRequest(event) + + const url = new URL(request.url) + const href = url.href.replace(url.origin, '') + + if (!process.env.TSS_SERVER_FN_BASE) { + throw new Error( + 'tanstack/react-start-server: TSS_SERVER_FN_BASE must be defined in your environment for createStartHandler()', + ) + } + + // Handle server functions + if ( + href.startsWith(path.join('/', process.env.TSS_SERVER_FN_BASE, '/')) + ) { + return await serverFunctionsHandler(event) + } + + // Handle API routes + // handleApiRoutes(event) + // if (event.handled) { + // return + // } + + // If no API routes returned, then fallback to SSR on the router + + // Create a history for the router + const history = createMemoryHistory({ + initialEntries: [href], + }) + + const router = createRouter() + + attachRouterServerSsrUtils(router, getStartManifest()) + + // Update the router with the history and context + router.update({ + history, + }) + + await router.load() + + dehydrateRouter(router) + + const responseHeaders = getStartResponseHeaders({ event, router }) + const response = await cb({ + request, + router, + responseHeaders, + }) + + return response + }) + } +} \ No newline at end of file diff --git a/packages/react-start-server/src/index.tsx b/packages/react-start-server/src/index.tsx index f4573955c8..638efaef79 100644 --- a/packages/react-start-server/src/index.tsx +++ b/packages/react-start-server/src/index.tsx @@ -1,4 +1,6 @@ export { StartServer } from './StartServer' export { defaultStreamHandler } from './defaultStreamHandler' export { defaultRenderHandler } from './defaultRenderHandler' +export { createStartHandler } from './createStartHandler' +export { getStartManifest } from './router-manifest' export * from '@tanstack/start-server-core' diff --git a/packages/start-server-core/src/router-manifest.ts b/packages/react-start-server/src/router-manifest.ts similarity index 96% rename from packages/start-server-core/src/router-manifest.ts rename to packages/react-start-server/src/router-manifest.ts index 546342724f..b07af49c89 100644 --- a/packages/start-server-core/src/router-manifest.ts +++ b/packages/react-start-server/src/router-manifest.ts @@ -3,10 +3,6 @@ import path from 'node:path' import tsrStartManifest from 'tsr:start-manifest' import type { Manifest } from '@tanstack/router-core' -function sanitizeBase(base: string) { - return base.replace(/^\/|\/$/g, '') -} - /** * @description Returns the router manifest that should be sent to the client. * This includes only the assets and preloads for the current route and any diff --git a/packages/solid-start-server/src/createStartHandler.ts b/packages/solid-start-server/src/createStartHandler.ts new file mode 100644 index 0000000000..e0062e0da7 --- /dev/null +++ b/packages/solid-start-server/src/createStartHandler.ts @@ -0,0 +1,74 @@ +import path from 'node:path' +import { createMemoryHistory } from '@tanstack/history' +import { eventHandler, toWebRequest } from 'h3' +import { attachRouterServerSsrUtils, dehydrateRouter, getStartResponseHeaders, serverFunctionsHandler } from '@tanstack/start-server-core' +import { getStartManifest } from './router-manifest' +import type { EventHandlerResponse } from 'h3' +import type { AnyRouter } from '@tanstack/router-core' +import type { CustomizeStartHandler } from '@tanstack/start-server-core'; + +export function createStartHandler< + TRouter extends AnyRouter, + TResponse extends EventHandlerResponse = EventHandlerResponse, +>({ + createRouter, +}: { + createRouter: () => TRouter +}): CustomizeStartHandler { + return (cb) => { + return eventHandler(async (event) => { + const request = toWebRequest(event) + + const url = new URL(request.url) + const href = url.href.replace(url.origin, '') + + if (!process.env.TSS_SERVER_FN_BASE) { + throw new Error( + 'tanstack/solid-start-server: TSS_SERVER_FN_BASE must be defined in your environment for createStartHandler()', + ) + } + + // Handle server functions + if ( + href.startsWith(path.join('/', process.env.TSS_SERVER_FN_BASE, '/')) + ) { + return await serverFunctionsHandler(event) + } + + // Handle API routes + // handleApiRoutes(event) + // if (event.handled) { + // return + // } + + // If no API routes returned, then fallback to SSR on the router + + // Create a history for the router + const history = createMemoryHistory({ + initialEntries: [href], + }) + + const router = createRouter() + + attachRouterServerSsrUtils(router, getStartManifest()) + + // Update the router with the history and context + router.update({ + history, + }) + + await router.load() + + dehydrateRouter(router) + + const responseHeaders = getStartResponseHeaders({ event, router }) + const response = await cb({ + request, + router, + responseHeaders, + }) + + return response + }) + } +} \ No newline at end of file diff --git a/packages/solid-start-server/src/index.tsx b/packages/solid-start-server/src/index.tsx index f4573955c8..638efaef79 100644 --- a/packages/solid-start-server/src/index.tsx +++ b/packages/solid-start-server/src/index.tsx @@ -1,4 +1,6 @@ export { StartServer } from './StartServer' export { defaultStreamHandler } from './defaultStreamHandler' export { defaultRenderHandler } from './defaultRenderHandler' +export { createStartHandler } from './createStartHandler' +export { getStartManifest } from './router-manifest' export * from '@tanstack/start-server-core' diff --git a/packages/solid-start-server/src/router-manifest.ts b/packages/solid-start-server/src/router-manifest.ts new file mode 100644 index 0000000000..a5277a6945 --- /dev/null +++ b/packages/solid-start-server/src/router-manifest.ts @@ -0,0 +1,75 @@ +// @ts-expect-error +import tsrStartManifest from 'tsr:start-manifest' +import type { Manifest } from '@tanstack/router-core' + +/** + * @description Returns the router manifest that should be sent to the client. + * This includes only the assets and preloads for the current route and any + * special assets that are needed for the client. It does not include relationships + * between routes or any other data that is not needed for the client. + */ +export function getStartManifest() { + const startManifest = tsrStartManifest() as Manifest + + const rootRoute = (startManifest.routes.__root__ = + startManifest.routes.__root__ || {}) + + rootRoute.assets = rootRoute.assets || [] + + // Get the entry for the client from vinxi + // const vinxiClientManifest = getManifest('client') + + // const importPath = + // vinxiClientManifest.inputs[vinxiClientManifest.handler]?.output.path + // if (!importPath) { + // invariant(importPath, 'Could not find client entry in vinxi manifest') + // } + + if (process.env.NODE_ENV === 'development' && !process.env.TSS_CLIENT_ENTRY) { + throw new Error( + 'tanstack/start-router-manifest: TSS_CLIENT_ENTRY must be defined in your environment for getStartManifest()', + ) + } + + if (process.env.NODE_ENV === 'development') { + // Always fake that HMR is ready + // const CLIENT_BASE = sanitizeBase(process.env.TSS_CLIENT_BASE || '') + + // if (!CLIENT_BASE) { + // throw new Error( + // 'tanstack/start-router-manifest: TSS_CLIENT_BASE must be defined in your environment for getFullRouterManifest()', + // ) + // } + + const script = `import(${JSON.stringify(process.env.TSS_CLIENT_ENTRY)})` + + rootRoute.assets.push({ + tag: 'script', + attrs: { + type: 'module', + suppressHydrationWarning: true, + async: true, + }, + children: script, + }) + } + + const manifest = { + ...startManifest, + routes: Object.fromEntries( + Object.entries(startManifest.routes).map(([k, v]: any) => { + const { preloads, assets } = v + return [ + k, + { + preloads, + assets, + }, + ] + }), + ), + } + + // Strip out anything that isn't needed for the client + return manifest +} diff --git a/packages/solid-start-server/vite.config.ts b/packages/solid-start-server/vite.config.ts index c0a7454291..79bf665097 100644 --- a/packages/solid-start-server/vite.config.ts +++ b/packages/solid-start-server/vite.config.ts @@ -22,5 +22,6 @@ export default mergeConfig( tanstackViteConfig({ srcDir: './src', entry: './src/index.tsx', + externalDeps: ['tsr:server-fn-manifest', 'tsr:start-manifest'], }), ) diff --git a/packages/start-server-core/src/createStartHandler.ts b/packages/start-server-core/src/createStartHandler.ts index b39540c05f..a701c53f3f 100644 --- a/packages/start-server-core/src/createStartHandler.ts +++ b/packages/start-server-core/src/createStartHandler.ts @@ -1,12 +1,7 @@ -import path from 'node:path' -import { createMemoryHistory } from '@tanstack/history' import { mergeHeaders } from '@tanstack/start-client-core' -import { eventHandler, getResponseHeaders, toWebRequest } from 'h3' -import serverFunctionsHandler from './server-functions-handler' -import { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server' -import { getStartManifest } from './router-manifest' +import { getResponseHeaders } from 'h3' import type { HandlerCallback } from './handlerCallback' -import type { EventHandlerResponse, H3Event } from 'h3' +import type { EventHandlerResponse, H3Event, eventHandler } from 'h3' import type { AnyRouter } from '@tanstack/router-core' export type CustomizeStartHandler< @@ -14,73 +9,7 @@ export type CustomizeStartHandler< TResponse extends EventHandlerResponse = EventHandlerResponse, > = (cb: HandlerCallback) => ReturnType -export function createStartHandler< - TRouter extends AnyRouter, - TResponse extends EventHandlerResponse = EventHandlerResponse, ->({ - createRouter, -}: { - createRouter: () => TRouter -}): CustomizeStartHandler { - return (cb) => { - return eventHandler(async (event) => { - const request = toWebRequest(event) - - const url = new URL(request.url) - const href = url.href.replace(url.origin, '') - - if (!process.env.TSS_SERVER_FN_BASE) { - throw new Error( - 'tanstack/react-start-server: TSS_SERVER_FN_BASE must be defined in your environment for createStartHandler()', - ) - } - - // Handle server functions - if ( - href.startsWith(path.join('/', process.env.TSS_SERVER_FN_BASE, '/')) - ) { - return await serverFunctionsHandler(event) - } - - // Handle API routes - // handleApiRoutes(event) - // if (event.handled) { - // return - // } - - // If no API routes returned, then fallback to SSR on the router - - // Create a history for the router - const history = createMemoryHistory({ - initialEntries: [href], - }) - - const router = createRouter() - - attachRouterServerSsrUtils(router, getStartManifest()) - - // Update the router with the history and context - router.update({ - history, - }) - - await router.load() - - dehydrateRouter(router) - - const responseHeaders = getStartResponseHeaders({ event, router }) - const response = await cb({ - request, - router, - responseHeaders, - }) - - return response - }) - } -} - -function getStartResponseHeaders(opts: { event: H3Event; router: AnyRouter }) { +export function getStartResponseHeaders(opts: { event: H3Event; router: AnyRouter }) { let headers = mergeHeaders( getResponseHeaders(opts.event), (opts.event as any).___ssrRpcResponseHeaders, diff --git a/packages/start-server-core/src/index.tsx b/packages/start-server-core/src/index.tsx index 88dccaab53..45bb559d9c 100644 --- a/packages/start-server-core/src/index.tsx +++ b/packages/start-server-core/src/index.tsx @@ -3,14 +3,14 @@ export { transformPipeableStreamWithRouter, } from './transformStreamWithRouter' -export { createStartHandler } from './createStartHandler' +export { getStartResponseHeaders } from './createStartHandler' +export type { CustomizeStartHandler } from './createStartHandler' export { createRequestHandler } from './createRequestHandler' -export { getStartManifest } from './router-manifest' - export { defineHandlerCallback } from './handlerCallback' export type { HandlerCallback } from './handlerCallback' export { attachRouterServerSsrUtils, dehydrateRouter } from './ssr-server' +export { serverFunctionsHandler } from './server-functions-handler' export * from './h3' diff --git a/packages/start-server-core/src/server-functions-handler.ts b/packages/start-server-core/src/server-functions-handler.ts index 3422f5254a..8b3b9afde5 100644 --- a/packages/start-server-core/src/server-functions-handler.ts +++ b/packages/start-server-core/src/server-functions-handler.ts @@ -10,7 +10,7 @@ import type { H3Event } from './h3' // only having a default export. export const dummy = 2 -export default eventHandler(handleServerAction) +export const serverFunctionsHandler = eventHandler(handleServerAction) const serverFnManifest = _serverFnManifest as Record< string, From 8a3d567a95d2213d86db99ab9ec2027cbc850a03 Mon Sep 17 00:00:00 2001 From: Tanner Linsley Date: Thu, 13 Mar 2025 02:10:55 -0600 Subject: [PATCH 057/155] checkpoint prerender --- examples/react/start-basic/vite.config.ts | 6 +- packages/react-start-plugin/package.json | 2 + packages/react-start-plugin/src/createPool.ts | 143 ++++++++++++ .../src/nitro/build-nitro.ts | 48 ++++ .../src/nitro/nitro-plugin.ts | 82 ++----- packages/react-start-plugin/src/prerender.ts | 209 ++++++++++++++++++ packages/react-start-plugin/src/schema.ts | 86 ++++++- pnpm-lock.yaml | 6 + 8 files changed, 517 insertions(+), 65 deletions(-) create mode 100644 packages/react-start-plugin/src/createPool.ts create mode 100644 packages/react-start-plugin/src/nitro/build-nitro.ts create mode 100644 packages/react-start-plugin/src/prerender.ts diff --git a/examples/react/start-basic/vite.config.ts b/examples/react/start-basic/vite.config.ts index 698e4856da..ae0e653220 100644 --- a/examples/react/start-basic/vite.config.ts +++ b/examples/react/start-basic/vite.config.ts @@ -10,6 +10,10 @@ export default defineConfig({ tsConfigPaths({ projects: ['./tsconfig.json'], }), - TanStackStartVitePlugin(), + TanStackStartVitePlugin({ + prerender: { + enabled: true, + }, + }), ], }) diff --git a/packages/react-start-plugin/package.json b/packages/react-start-plugin/package.json index 1f1f812a99..3c855b3805 100644 --- a/packages/react-start-plugin/package.json +++ b/packages/react-start-plugin/package.json @@ -84,10 +84,12 @@ "@vitejs/plugin-react": "^4.3.4", "babel-dead-code-elimination": "^1.0.9", "fast-glob": "^3.3.3", + "get-port": "^7.1.0", "h3": "1.13.0", "import-meta-resolve": "^4.1.0", "nitropack": "^2.10.4", "tiny-invariant": "^1.3.3", + "ufo": "^1.5.4", "vite": "6.1.0", "xmlbuilder2": "^3.1.1", "zod": "^3.24.2" diff --git a/packages/react-start-plugin/src/createPool.ts b/packages/react-start-plugin/src/createPool.ts new file mode 100644 index 0000000000..8a7395801f --- /dev/null +++ b/packages/react-start-plugin/src/createPool.ts @@ -0,0 +1,143 @@ +interface PoolConfig { + concurrency?: number + started?: boolean + tasks?: Array<() => Promise> +} +interface PoolAPI { + add: ( + fn: () => Promise | T, + options?: { priority?: boolean }, + ) => Promise + throttle: (n: number) => void + onSettled: (cb: () => void) => () => void + onError: (cb: (error: any, task: () => Promise) => void) => () => void + onSuccess: (cb: (result: any, task: () => Promise) => void) => () => void + stop: () => void + start: () => Promise + clear: () => void + getActive: () => Array<() => Promise> + getPending: () => Array<() => Promise> + getAll: () => Array<() => Promise> + isRunning: () => boolean + isSettled: () => boolean +} +const defaultConfig: PoolConfig = { + concurrency: 5, + started: false, + tasks: [], +} + +export function createPool(config: PoolConfig = defaultConfig): PoolAPI { + const { concurrency, started, tasks } = { + ...defaultConfig, + ...config, + } + + let onSettles: Array<(res: any, error: any) => void> = [] + let onErrors: Array<(error: any, task: () => Promise) => void> = [] + let onSuccesses: Array<(result: any, task: () => Promise) => void> = [] + let running = started! + let active: Array<() => Promise> = [] + let pending: Array<() => Promise> = tasks as Array<() => Promise> + let currentConcurrency = concurrency! + + const tick = () => { + if (!running) { + return + } + while (active.length < currentConcurrency && pending.length) { + const nextFn = pending.shift() + if (!nextFn) { + throw new Error('Found task that is not a function') + } // Safety check + active.push(nextFn) + ;(async () => { + let success = false + let res!: T + let error: any + try { + res = await nextFn() + success = true + } catch (e) { + error = e + } + active = active.filter((d) => d !== nextFn) + if (success) { + onSuccesses.forEach((d) => d(res, nextFn)) + } else { + onErrors.forEach((d) => d(error, nextFn)) + } + onSettles.forEach((d) => d(res, error)) + tick() + })() + } + } + + const api: PoolAPI = { + add: (fn, { priority } = {}) => { + return new Promise((resolve, reject) => { + const task = () => + Promise.resolve(fn()) + .then((res) => { + resolve(res) + return res + }) + .catch((err) => { + reject(err) + throw err + }) + if (priority) { + pending.unshift(task) + } else { + pending.push(task) + } + tick() + }) + }, + throttle: (n) => { + currentConcurrency = n + }, + onSettled: (cb) => { + onSettles.push(cb) + return () => { + onSettles = onSettles.filter((d) => d !== cb) + } + }, + onError: (cb) => { + onErrors.push(cb) + return () => { + onErrors = onErrors.filter((d) => d !== cb) + } + }, + onSuccess: (cb) => { + onSuccesses.push(cb) + return () => { + onSuccesses = onSuccesses.filter((d) => d !== cb) + } + }, + stop: () => { + running = false + }, + start: () => { + running = true + tick() + return new Promise((resolve) => { + api.onSettled(() => { + if (api.isSettled()) { + resolve() + } + }) + }) + }, + clear: () => { + pending = [] + }, + getActive: () => active, + getPending: () => pending, + getAll: () => [...active, ...pending], + isRunning: () => running, + isSettled: () => !active.length && !pending.length, + } + + return api +} diff --git a/packages/react-start-plugin/src/nitro/build-nitro.ts b/packages/react-start-plugin/src/nitro/build-nitro.ts new file mode 100644 index 0000000000..53c6cdad99 --- /dev/null +++ b/packages/react-start-plugin/src/nitro/build-nitro.ts @@ -0,0 +1,48 @@ +import { promises as fsp } from 'node:fs' +import path from 'node:path' +import { version } from 'nitropack/meta' +import { copyPublicAssets, prepare } from 'nitropack' +import type { Nitro } from 'nitropack' + +export async function buildNitroEnvironment( + nitro: Nitro, + build: () => Promise, +) { + await prepare(nitro) + await copyPublicAssets(nitro) + await build() + + const presetsWithConfig = [ + 'awsAmplify', + 'awsLambda', + 'azure', + 'cloudflare', + 'firebase', + 'netlify', + 'vercel', + ] + + const buildInfo = { + date: /* @__PURE__ */ new Date().toJSON(), + preset: nitro.options.preset, + framework: nitro.options.framework, + versions: { + nitro: version, + }, + commands: { + preview: nitro.options.commands.preview, + deploy: nitro.options.commands.deploy, + }, + config: { + ...Object.fromEntries( + presetsWithConfig.map((key) => [key, (nitro.options as any)[key]]), + ), + }, + } + + const buildInfoPath = path.resolve(nitro.options.output.dir, 'nitro.json') + + await fsp.writeFile(buildInfoPath, JSON.stringify(buildInfo, null, 2)) + + await nitro.close() +} diff --git a/packages/react-start-plugin/src/nitro/nitro-plugin.ts b/packages/react-start-plugin/src/nitro/nitro-plugin.ts index 0d3febc0d9..c54b993748 100644 --- a/packages/react-start-plugin/src/nitro/nitro-plugin.ts +++ b/packages/react-start-plugin/src/nitro/nitro-plugin.ts @@ -1,13 +1,13 @@ import { platform } from 'node:os' -import { promises as fsp } from 'node:fs' import path from 'node:path' -import { copyPublicAssets, createNitro, prepare } from 'nitropack' -import { version } from 'nitropack/meta' +import { createNitro } from 'nitropack' import { normalizePath } from 'vite' import { getRollupConfig } from 'nitropack/rollup' import { clientDistDir } from '../index.js' +import { prerender } from '../prerender.js' import { devServerPlugin } from './dev-server-plugin.js' +import { buildNitroEnvironment } from './build-nitro.js' import type { EnvironmentOptions, PluginOption } from 'vite' import type { Nitro, NitroConfig } from 'nitropack' import type { TanStackStartOutputConfig } from '../schema.js' @@ -81,72 +81,38 @@ export function nitroPlugin( builder: { sharedPlugins: true, async buildApp(builder) { - if (!builder.environments['client']) { + const clientEnv = builder.environments['client'] + const serverEnv = builder.environments['server'] + + if (!clientEnv) { throw new Error('Client environment not found') } - if (!builder.environments['server']) { + if (!serverEnv) { throw new Error('SSR environment not found') } - await builder.build(builder.environments['client']) - await prepare(nitro) - await copyPublicAssets(nitro) + await builder.build(clientEnv) + await buildNitroEnvironment(nitro, () => builder.build(serverEnv)) if ( - options.prerender.routes && - options.prerender.routes.length > 0 + // If prerender is enabled + options.prerender?.enabled || + // or if any page specifically has prerender set but not disabled + options.pages?.some( + (d) => + typeof d === 'object' && + d.prerender && + !d.prerender.enabled, + ) ) { - console.log('Prerendering is not implemented yet.') - // console.log(`Prerendering static pages...`) - // await prerender(nitro) - } - - await builder.build(builder.environments['server']) - - const buildInfoPath = path.resolve( - nitro.options.output.dir, - 'nitro.json', - ) - - const presetsWithConfig = [ - 'awsAmplify', - 'awsLambda', - 'azure', - 'cloudflare', - 'firebase', - 'netlify', - 'vercel', - ] - - const buildInfo = { - date: /* @__PURE__ */ new Date().toJSON(), - preset: nitro.options.preset, - framework: nitro.options.framework, - versions: { - nitro: version, - }, - commands: { - preview: nitro.options.commands.preview, - deploy: nitro.options.commands.deploy, - }, - config: { - ...Object.fromEntries( - presetsWithConfig.map((key) => [ - key, - (nitro.options as any)[key], - ]), - ), - }, + await prerender({ + options, + nitro, + builder, + }) } - await fsp.writeFile( - buildInfoPath, - JSON.stringify(buildInfo, null, 2), - ) - - await nitro.close() - // if (nitroConfig.prerender?.routes?.length && options.sitemap) { // console.log('Building Sitemap...') // // sitemap needs to be built after all directories are built diff --git a/packages/react-start-plugin/src/prerender.ts b/packages/react-start-plugin/src/prerender.ts new file mode 100644 index 0000000000..6d622723d7 --- /dev/null +++ b/packages/react-start-plugin/src/prerender.ts @@ -0,0 +1,209 @@ +import { promises as fsp } from 'node:fs' +import os from 'node:os' +import path from 'node:path' +import { getRollupConfig } from 'nitropack/rollup' +import { createNitro } from 'nitropack' +import { joinURL, withBase, withoutBase } from 'ufo' +import { buildNitroEnvironment } from './nitro/build-nitro.js' +import { createPool } from './createPool.js' +import type { fork } from 'node:child_process' +import type { ViteBuilder } from 'vite' +import type { $Fetch, Nitro } from 'nitropack' +import type { TanStackStartOutputConfig } from './schema.js' + +interface ServerProcess { + process: ReturnType + port: number + baseUrl: string +} + +export async function prerender({ + options, + nitro, + builder, +}: { + options: TanStackStartOutputConfig + nitro: Nitro + builder: ViteBuilder +}) { + console.info('Prendering pages...') + + const serverEnv = builder.environments['server'] + + if (!serverEnv) { + throw new Error(`Vite's "server" environment not found`) + } + + const prerenderOutputDir = path.resolve( + options.root, + 'node_modules/.tanstack-start/prerenderer', + ) + + const nodeNitro = await createNitro({ + ...nitro.options._config, + preset: 'nitro-prerender', + logLevel: 0, + output: { + dir: prerenderOutputDir, + serverDir: path.resolve(prerenderOutputDir, 'server'), + publicDir: path.resolve(prerenderOutputDir, 'public'), + }, + }) + + const nodeNitroRollupOptions = getRollupConfig(nodeNitro) + + const build = serverEnv.config.build + + build.outDir = prerenderOutputDir + + build.rollupOptions = { + ...build.rollupOptions, + ...nodeNitroRollupOptions, + output: { + ...build.rollupOptions.output, + ...nodeNitroRollupOptions.output, + sourcemap: undefined, + }, + } + + await buildNitroEnvironment(nodeNitro, () => builder.build(serverEnv)) + + // Import renderer entry + const serverFilename = + typeof nodeNitro.options.rollupConfig?.output.entryFileNames === 'string' + ? nodeNitro.options.rollupConfig.output.entryFileNames + : 'index.mjs' + + const serverEntrypoint = path.resolve( + nodeNitro.options.output.serverDir, + serverFilename, + ) + + const { closePrerenderer, localFetch } = (await import(serverEntrypoint)) as { + closePrerenderer: () => void + localFetch: $Fetch + } + + try { + // Crawl all pages + const pages = await crawlPages() + + console.info(`Prerendered ${pages.length} pages:`) + pages.forEach((page) => { + console.info(`- ${page}`) + }) + + // TODO: Write the prerendered pages to the output directory + } catch (error) { + console.error(error) + } finally { + // Ensure server is always closed + // server.process.kill() + closePrerenderer() + } + + function extractLinks(html: string): Array { + const linkRegex = /]+href=["']([^"']+)["'][^>]*>/g + const links: Array = [] + let match + + while ((match = linkRegex.exec(html)) !== null) { + const href = match[1] + if (href && (href.startsWith('/') || href.startsWith('./'))) { + links.push(href) + } + } + + return links + } + + async function crawlPages() { + const seen = new Set() + const retriesByPath = new Map() + const initialPages = new Set(['/']) + const concurrency = os.cpus().length + console.info(`Concurrency: ${concurrency}`) + const pool = createPool({ concurrency }) + + for (const pathname of initialPages) { + if (seen.has(pathname)) continue + pool.add(crawlPageTask(pathname)) + } + + await pool.start() + + return Array.from(seen) + + function crawlPageTask(pathname: string) { + seen.add(pathname) + return async () => { + console.info(`Crawling: ${pathname}`) + const retries = retriesByPath.get(pathname) || 0 + try { + // Fetch the route + const encodedRoute = encodeURI(pathname) + + const res = await localFetch( + withBase(encodedRoute, nodeNitro.options.baseURL), + { + headers: { 'x-nitro-prerender': encodedRoute }, + retry: nodeNitro.options.prerender.retry, + retryDelay: nodeNitro.options.prerender.retryDelay, + }, + ) + + if (!res.ok) { + throw new Error(`Failed to fetch ${pathname}: ${res.statusText}`) + } + + // Guess route type and populate fileName + const contentType = res.headers.get('content-type') || '' + const isImplicitHTML = + !pathname.endsWith('.html') && contentType.includes('html') + // && + // !JsonSigRx.test(dataBuff.subarray(0, 32).toString('utf8')) + const routeWithIndex = pathname.endsWith('/') + ? pathname + 'index' + : pathname + + const htmlPath = + pathname.endsWith('/') || nitro.options.prerender.autoSubfolderIndex + ? joinURL(pathname, 'index.html') + : pathname + '.html' + + const filename = withoutBase( + isImplicitHTML ? htmlPath : routeWithIndex, + nitro.options.baseURL, + ) + + const html = await res.text() + + const filepath = path.join(nitro.options.output.publicDir, filename) + + await fsp.mkdir(path.dirname(filepath), { + recursive: true, + }) + + await fsp.writeFile(filepath, html) + + // Find new links + const links = extractLinks(html) + for (const link of links) { + if (!seen.has(link)) { + pool.add(crawlPageTask(link)) + } + } + } catch (error) { + if (retries < 3) { + console.warn(`Encountered error, retrying: ${pathname} in 500ms`) + await new Promise((resolve) => setTimeout(resolve, 500)) + retriesByPath.set(pathname, retries + 1) + pool.add(crawlPageTask(pathname)) + } else { + throw error + } + } + } + } + } +} diff --git a/packages/react-start-plugin/src/schema.ts b/packages/react-start-plugin/src/schema.ts index fe14504b85..184506c9f1 100644 --- a/packages/react-start-plugin/src/schema.ts +++ b/packages/react-start-plugin/src/schema.ts @@ -20,14 +20,70 @@ import type { Options as ViteReactOptions } from '@vitejs/plugin-react' const viteReactSchema = z.custom() -const sitemapSchema = z.object({ - host: z.string(), +const sitemapPageOptionsSchema = z.object({ + exclude: z.boolean().optional(), + priority: z.number().min(0).max(1).optional(), + changefreq: z + .enum(['always', 'hourly', 'daily', 'weekly', 'monthly', 'yearly', 'never']) + .optional(), + lastmod: z.union([z.string(), z.date()]).optional(), + alternateRefs: z + .array( + z.object({ + href: z.string(), + hreflang: z.string(), + }), + ) + .optional(), + images: z + .array( + z.object({ + loc: z.string(), + caption: z.string().optional(), + title: z.string().optional(), + }), + ) + .optional(), + news: z + .object({ + publication: z.object({ + name: z.string(), + language: z.string(), + }), + publicationDate: z.union([z.string(), z.date()]), + title: z.string(), + }) + .optional(), }) const tsrConfig = configSchema.partial().extend({ srcDirectory: z.string().optional().default('src'), }) +const pageSitemapOptionsSchema = z.union([ + z.boolean(), + sitemapPageOptionsSchema, +]) + +const pagePrerenderOptionsSchema = z.object({ + enabled: z.boolean().optional(), + autoSubfolderIndex: z.boolean().optional().default(true), + interval: z.number().optional().default(0), + failOnError: z.boolean().optional().default(false), + crawlLinks: z.boolean().optional().default(false), + filterLinks: z + .function() + .args( + z.object({ + url: z.string(), + }), + ) + .returns(z.any()) + .optional(), + retry: z.number().optional().default(3), + retryDelay: z.number().optional().default(500), +}) + const TanStackStartOptionsSchema = z .object({ root: z.string().optional().default(process.cwd()), @@ -60,14 +116,32 @@ const TanStackStartOptionsSchema = z }) .optional() .default({}), - sitemap: sitemapSchema.optional(), + pages: z + .array( + z.union([ + z.string(), + z.object({ + path: z.string(), + prerender: pagePrerenderOptionsSchema.optional(), + sitemap: pageSitemapOptionsSchema.optional(), + }), + ]), + ) + .optional(), + sitemap: pagePrerenderOptionsSchema.optional().and( + z + .object({ + host: z.string().optional(), + }) + .optional(), + ), prerender: z .object({ enabled: z.boolean().optional(), - routes: z.array(z.string()).optional(), + concurrency: z.number().optional().default(1), }) - .optional() - .default({}), + .and(pagePrerenderOptionsSchema.optional()) + .optional(), }) .optional() .default({}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 006bbf5b7a..534ae31936 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -5873,6 +5873,9 @@ importers: fast-glob: specifier: ^3.3.3 version: 3.3.3 + get-port: + specifier: ^7.1.0 + version: 7.1.0 h3: specifier: 1.13.0 version: 1.13.0 @@ -5885,6 +5888,9 @@ importers: tiny-invariant: specifier: ^1.3.3 version: 1.3.3 + ufo: + specifier: ^1.5.4 + version: 1.5.4 vite: specifier: 6.1.0 version: 6.1.0(@types/node@22.13.4)(jiti@2.4.2)(lightningcss@1.29.1)(terser@5.37.0)(tsx@4.19.2)(yaml@2.7.0) From d646e4f6f20b64767c254a1a962af6f59884a2b7 Mon Sep 17 00:00:00 2001 From: SeanCassiere <33615041+SeanCassiere@users.noreply.github.com> Date: Thu, 13 Mar 2025 23:03:54 +1300 Subject: [PATCH 058/155] extract plugin add-ons to the head using `viteServer.transformIndexHtml`, extract the HMR add-ons used by `plugin-react` and inject them using `.injectHtml()`. no more having to "fake HMR" --- packages/react-router/src/index.tsx | 5 + .../src/nitro/dev-server-plugin.ts | 21 ++- .../react-start-server/src/router-manifest.ts | 8 +- packages/router-core/src/dev-html.ts | 151 ++++++++++++++++++ packages/router-core/src/index.ts | 2 + packages/solid-router/src/index.tsx | 5 + .../src/nitro/dev-server-plugin.ts | 2 +- packages/start-server-core/src/ssr-server.ts | 15 ++ 8 files changed, 200 insertions(+), 9 deletions(-) create mode 100644 packages/router-core/src/dev-html.ts diff --git a/packages/react-router/src/index.tsx b/packages/react-router/src/index.tsx index 374fc2916a..15d6a75fe2 100644 --- a/packages/react-router/src/index.tsx +++ b/packages/react-router/src/index.tsx @@ -359,6 +359,11 @@ export type { ValidateUseParamsResult, } from '@tanstack/router-core' +export { + __internal_devHtmlUtils, + type ExtractedHtmlTagInfo, +} from '@tanstack/router-core' + export { ScriptOnce } from './ScriptOnce' export { Asset } from './Asset' export { HeadContent } from './HeadContent' diff --git a/packages/react-start-plugin/src/nitro/dev-server-plugin.ts b/packages/react-start-plugin/src/nitro/dev-server-plugin.ts index 03a447112c..8aa6c242b8 100644 --- a/packages/react-start-plugin/src/nitro/dev-server-plugin.ts +++ b/packages/react-start-plugin/src/nitro/dev-server-plugin.ts @@ -3,15 +3,22 @@ import { createEvent, getHeader, sendWebResponse } from 'h3' import { isRunnableDevEnvironment } from 'vite' +import { __internal_devHtmlUtils } from '@tanstack/react-router' +import type { ExtractedHtmlTagInfo } from '@tanstack/react-router' import type { Connect, Environment, Plugin, ViteDevServer } from 'vite' import type { TanStackStartOutputConfig } from '../schema.js' +declare global { + // eslint-disable-next-line no-var + var TSS_INJECTED_HEAD_SCRIPTS_INFO: Array | undefined +} + export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { // let config: UserConfig let isTest = false return { - name: 'startjs-dev-ssr-plugin', + name: 'start-dev-ssr-plugin', config(userConfig, { mode }) { // config = userConfig isTest = isTest ? isTest : mode === 'test' @@ -43,6 +50,18 @@ export function devServerPlugin(options: TanStackStartOutputConfig): Plugin { throw new Error('Server environment not found') } + const templateHtml = `` + const transformedHtml = await viteDevServer.transformIndexHtml( + req.url || '/', + templateHtml, + ) + + const headScripts = __internal_devHtmlUtils.extractHtmlTagInfo( + 'script', + __internal_devHtmlUtils.extractHeadContent(transformedHtml), + ) + globalThis.TSS_INJECTED_HEAD_SCRIPTS_INFO = headScripts + const serverEntry = await serverEnv.runner.import('/~start/ssr-entry') diff --git a/packages/react-start-server/src/router-manifest.ts b/packages/react-start-server/src/router-manifest.ts index b07af49c89..a5277a6945 100644 --- a/packages/react-start-server/src/router-manifest.ts +++ b/packages/react-start-server/src/router-manifest.ts @@ -1,4 +1,3 @@ -import path from 'node:path' // @ts-expect-error import tsrStartManifest from 'tsr:start-manifest' import type { Manifest } from '@tanstack/router-core' @@ -42,12 +41,7 @@ export function getStartManifest() { // ) // } - const script = `import RefreshRuntime from "${path.join('/', '@react-refresh')}"; - RefreshRuntime.injectIntoGlobalHook(window) - window.$RefreshReg$ = () => {} - window.$RefreshSig$ = () => (type) => type - window.__vite_plugin_react_preamble_installed__ = true; - import(${JSON.stringify(process.env.TSS_CLIENT_ENTRY)})` + const script = `import(${JSON.stringify(process.env.TSS_CLIENT_ENTRY)})` rootRoute.assets.push({ tag: 'script', diff --git a/packages/router-core/src/dev-html.ts b/packages/router-core/src/dev-html.ts new file mode 100644 index 0000000000..ab6db327c1 --- /dev/null +++ b/packages/router-core/src/dev-html.ts @@ -0,0 +1,151 @@ +export interface ExtractedHtmlTagInfo { + attributes: Record + content: string +} + +/** + * Extracts specified HTML tags from content along with their attributes and inner content + * @internal + * @param tagName - Name of the HTML tag to extract (e.g., 'script', 'meta', 'div') + * @param htmlContent - String containing HTML content + * @returns Array of objects with tag attributes and content + */ +function extractHtmlTagInfo( + tagName: string, + htmlContent: string, +): Array { + const tags: Array = [] + // Create a regex pattern based on the provided tag name + // This regex will match both self-closing tags and tags with content + const tagRegex = new RegExp( + `<${tagName}\\b([^>]*?)(?:>([\\s\\S]*?)|\\s*/?>)`, + 'gi', + ) + + let match + while ((match = tagRegex.exec(htmlContent)) !== null) { + const attributesString = match[1] || '' + // For self-closing tags or tags with no content, this will be undefined + const content = match[2] || '' + + // Parse attributes + const attributes: Record = {} + const attributeRegex = /(\w+)(?:=(?:"([^"]*)"|'([^']*)'|([^\s>]*))?)?/g + let attrMatch + + while ((attrMatch = attributeRegex.exec(attributesString)) !== null) { + const attrName = attrMatch[1] + if (!attrName) { + continue + } + + // Check if this is a valueless attribute (no value or empty string) + if ( + attrMatch[2] === undefined && + attrMatch[3] === undefined && + attrMatch[4] === undefined + ) { + // Valueless attribute with no value, like