diff --git a/packages/start-plugin-core/src/start-compiler-plugin/handleCreateServerFn.ts b/packages/start-plugin-core/src/start-compiler-plugin/handleCreateServerFn.ts index b83c922b5bf..238848471d4 100644 --- a/packages/start-plugin-core/src/start-compiler-plugin/handleCreateServerFn.ts +++ b/packages/start-plugin-core/src/start-compiler-plugin/handleCreateServerFn.ts @@ -305,9 +305,17 @@ export function handleCreateServerFn( // 1. Create an extractedFn that calls __executeServer // 2. Modify .handler() to pass (extractedFn, serverFn) - two arguments // + // To avoid TDZ (Temporal Dead Zone) errors in production builds, we use an + // assignment expression inside .handler() instead of declaring the handler + // variable before the serverFn. This ensures proper initialization order + // when the bundler processes exports. + // // Expected output format: - // const extractedFn = createServerRpc("id", (opts) => varName.__executeServer(opts)); - // const varName = createServerFn().handler(extractedFn, originalHandler); + // let extractedFn; + // const varName = createServerFn().handler( + // extractedFn = createServerRpc("id", (opts) => varName.__executeServer(opts)), + // originalHandler + // ); // Build the arrow function: (opts, signal) => varName.__executeServer(opts, signal) // The signal parameter is passed through to allow abort signal propagation @@ -328,9 +336,11 @@ export function handleCreateServerFn( executeServerArrowFn, ) - // Build the extracted function statement - const extractedFnStatement = t.variableDeclaration('const', [ - t.variableDeclarator(t.identifier(functionName), extractedFnInit), + // Build the extracted function declaration with 'let' (no initializer) + // Using 'let' without initialization avoids TDZ - the variable exists + // but is undefined until the assignment expression runs + const extractedFnDeclaration = t.variableDeclaration('let', [ + t.variableDeclarator(t.identifier(functionName)), ]) // Find the variable declaration statement containing our createServerFn @@ -341,16 +351,24 @@ export function handleCreateServerFn( ) } - // Insert the extracted function statement before the variable declaration - variableDeclaration.insertBefore(extractedFnStatement) + // Insert the 'let' declaration before the variable declaration + variableDeclaration.insertBefore(extractedFnDeclaration) + + // Create an assignment expression: extractedFn = createServerRpc(...) + // This assigns the RPC during the .handler() call, ensuring the serverFn + // is being constructed when the assignment happens + const assignmentExpression = t.assignmentExpression( + '=', + t.identifier(functionName), + extractedFnInit, + ) - // Modify the .handler() call to pass two arguments: (extractedFn, serverFn) - // The handlerFnPath.node contains the original serverFn - const extractedFnIdentifier = t.identifier(functionName) + // Modify the .handler() call to pass two arguments: + // (extractedFn = createServerRpc(...), serverFn) const serverFnNode = t.cloneNode(handlerFn, true) - // Replace handler's arguments with [extractedFn, serverFn] - handler.callPath.node.arguments = [extractedFnIdentifier, serverFnNode] + // Replace handler's arguments with [assignmentExpression, serverFn] + handler.callPath.node.arguments = [assignmentExpression, serverFnNode] // Only export the extracted handler (e.g., myFn_createServerFn_handler) // The manifest and all import paths only look up this suffixed name. diff --git a/packages/start-plugin-core/src/start-router-plugin/generator-plugins/module-declaration-plugin.ts b/packages/start-plugin-core/src/start-router-plugin/generator-plugins/module-declaration-plugin.ts new file mode 100644 index 00000000000..742ed1e29ee --- /dev/null +++ b/packages/start-plugin-core/src/start-router-plugin/generator-plugins/module-declaration-plugin.ts @@ -0,0 +1,107 @@ +import { writeFileSync } from 'node:fs' +import path from 'pathe' +import type { GeneratorPlugin } from '@tanstack/router-generator' +import type { TanStackStartVitePluginCoreOptions } from '../../types' + +export interface ModuleDeclarationPluginOptions { + generatedRouteTreePath: string + routerFilePath: string + startFilePath: string | undefined + corePluginOpts: TanStackStartVitePluginCoreOptions +} + +/** + * This plugin generates a separate .d.ts file for the module augmentation + * that registers the router type with TanStack Start. + * + * By generating this in a separate .d.ts file instead of in the main + * routeTree.gen.ts file, we avoid creating a circular dependency that + * causes TDZ (Temporal Dead Zone) errors in Vite SSR. + * + * The circular dependency was: + * - router.tsx imports routeTree from routeTree.gen.ts + * - routeTree.gen.ts had `import type { getRouter } from './router.tsx'` + * + * Now the type import only exists in the .d.ts file, which TypeScript + * uses for type checking but Vite doesn't process at runtime. + */ +export function moduleDeclarationPlugin( + getOptions: () => ModuleDeclarationPluginOptions, +): GeneratorPlugin { + return { + name: 'module-declaration-plugin', + onRouteTreeChanged: () => { + const options = getOptions() + const dtsContent = generateModuleDeclaration(options) + const dtsPath = getDtsPath(options.generatedRouteTreePath) + + writeFileSync(dtsPath, dtsContent, 'utf-8') + }, + } +} + +function getDtsPath(generatedRouteTreePath: string): string { + // Replace .ts or .tsx extension with .d.ts + // e.g., routeTree.gen.ts -> routeTree.gen.d.ts + return generatedRouteTreePath.replace(/\.tsx?$/, '.d.ts') +} + +function generateModuleDeclaration( + options: ModuleDeclarationPluginOptions, +): string { + const { generatedRouteTreePath, routerFilePath, startFilePath, corePluginOpts } = + options + + function getImportPath(absolutePath: string) { + let relativePath = path.relative( + path.dirname(generatedRouteTreePath), + absolutePath, + ) + + if (!relativePath.startsWith('.')) { + relativePath = './' + relativePath + } + + // convert to POSIX-style for ESM imports (important on Windows) + relativePath = relativePath.split(path.sep).join('/') + return relativePath + } + + const lines: Array = [ + '// This file was automatically generated by TanStack Start.', + '// It provides type declarations for the router registration.', + '// This file is separate from routeTree.gen.ts to avoid circular dependencies', + '// that can cause TDZ errors in Vite SSR.', + '', + `import type { getRouter } from '${getImportPath(routerFilePath)}'`, + ] + + if (startFilePath) { + lines.push( + `import type { startInstance } from '${getImportPath(startFilePath)}'`, + ) + } else { + // make sure we import something from start to get the server route declaration merge + lines.push( + `import type { createStart } from '@tanstack/${corePluginOpts.framework}-start'`, + ) + } + + lines.push('') + lines.push(`declare module '@tanstack/${corePluginOpts.framework}-start' {`) + lines.push(` interface Register {`) + lines.push(` ssr: true`) + lines.push(` router: Awaited>`) + + if (startFilePath) { + lines.push( + ` config: Awaited>`, + ) + } + + lines.push(` }`) + lines.push(`}`) + lines.push('') + + return lines.join('\n') +} diff --git a/packages/start-plugin-core/src/start-router-plugin/plugin.ts b/packages/start-plugin-core/src/start-router-plugin/plugin.ts index 1536d19c91e..f64da5ee19d 100644 --- a/packages/start-plugin-core/src/start-router-plugin/plugin.ts +++ b/packages/start-plugin-core/src/start-router-plugin/plugin.ts @@ -8,6 +8,7 @@ import path from 'pathe' import { VITE_ENVIRONMENT_NAMES } from '../constants' import { routesManifestPlugin } from './generator-plugins/routes-manifest-plugin' import { prerenderRoutesPlugin } from './generator-plugins/prerender-routes-plugin' +import { moduleDeclarationPlugin } from './generator-plugins/module-declaration-plugin' import { pruneServerOnlySubtrees } from './pruneServerOnlySubtrees' import { SERVER_PROP } from './constants' import type { GetConfigFn, TanStackStartVitePluginCoreOptions } from '../types' @@ -29,63 +30,6 @@ function isServerOnlyNode(node: RouteNode | undefined) { ) } -function moduleDeclaration({ - startFilePath, - routerFilePath, - corePluginOpts, - generatedRouteTreePath, -}: { - startFilePath: string | undefined - routerFilePath: string - corePluginOpts: TanStackStartVitePluginCoreOptions - generatedRouteTreePath: string -}): string { - function getImportPath(absolutePath: string) { - let relativePath = path.relative( - path.dirname(generatedRouteTreePath), - absolutePath, - ) - - if (!relativePath.startsWith('.')) { - relativePath = './' + relativePath - } - - // convert to POSIX-style for ESM imports (important on Windows) - relativePath = relativePath.split(path.sep).join('/') - return relativePath - } - - const result: Array = [ - `import type { getRouter } from '${getImportPath(routerFilePath)}'`, - ] - if (startFilePath) { - result.push( - `import type { startInstance } from '${getImportPath(startFilePath)}'`, - ) - } - // make sure we import something from start to get the server route declaration merge - else { - result.push( - `import type { createStart } from '@tanstack/${corePluginOpts.framework}-start'`, - ) - } - result.push( - `declare module '@tanstack/${corePluginOpts.framework}-start' { - interface Register { - ssr: true - router: Awaited>`, - ) - if (startFilePath) { - result.push( - ` config: Awaited>`, - ) - } - result.push(` } -}`) - - return result.join('\n') -} - export function tanStackStartRouter( startPluginOpts: TanStackStartInputConfig, getConfig: GetConfigFn, @@ -131,7 +75,7 @@ export function tanStackStartRouter( if (routeTreeFileFooter) { return routeTreeFileFooter } - const { startConfig, resolvedStartConfig } = getConfig() + const { startConfig } = getConfig() const ogRouteTreeFileFooter = startConfig.router.routeTreeFileFooter if (ogRouteTreeFileFooter) { if (Array.isArray(ogRouteTreeFileFooter)) { @@ -140,15 +84,10 @@ export function tanStackStartRouter( routeTreeFileFooter = ogRouteTreeFileFooter() } } - routeTreeFileFooter = [ - moduleDeclaration({ - generatedRouteTreePath: getGeneratedRouteTreePath(), - corePluginOpts, - startFilePath: resolvedStartConfig.startFilePath, - routerFilePath: resolvedStartConfig.routerFilePath, - }), - ...(routeTreeFileFooter ?? []), - ] + // Note: Module declaration is now generated in a separate .d.ts file + // by the moduleDeclarationPlugin to avoid circular dependencies + // that cause TDZ errors in Vite SSR + routeTreeFileFooter = routeTreeFileFooter ?? [] return routeTreeFileFooter } @@ -209,8 +148,20 @@ export function tanStackStartRouter( return [ clientTreePlugin, tanstackRouterGenerator(() => { - const routerConfig = getConfig().startConfig.router - const plugins = [clientTreeGeneratorPlugin, routesManifestPlugin()] + const { startConfig, resolvedStartConfig } = getConfig() + const routerConfig = startConfig.router + const plugins = [ + clientTreeGeneratorPlugin, + routesManifestPlugin(), + // Generate module declaration in a separate .d.ts file to avoid + // circular dependencies that cause TDZ errors in Vite SSR + moduleDeclarationPlugin(() => ({ + generatedRouteTreePath: getGeneratedRouteTreePath(), + routerFilePath: resolvedStartConfig.routerFilePath, + startFilePath: resolvedStartConfig.startFilePath, + corePluginOpts, + })), + ] if (startPluginOpts?.prerender?.enabled === true) { plugins.push(prerenderRoutesPlugin()) } diff --git a/packages/start-plugin-core/tests/createServerFn/createServerFn.test.ts b/packages/start-plugin-core/tests/createServerFn/createServerFn.test.ts index a039321781f..22b5d603c8a 100644 --- a/packages/start-plugin-core/tests/createServerFn/createServerFn.test.ts +++ b/packages/start-plugin-core/tests/createServerFn/createServerFn.test.ts @@ -138,8 +138,8 @@ describe('createServerFn compiles correctly', async () => { const myFunc = () => { return 'hello from the server'; }; - const myServerFn_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6Im15U2VydmVyRm5fY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => myServerFn.__executeServer(opts, signal)); - const myServerFn = createServerFn().handler(myServerFn_createServerFn_handler, myFunc); + let myServerFn_createServerFn_handler; + const myServerFn = createServerFn().handler(myServerFn_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6Im15U2VydmVyRm5fY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => myServerFn.__executeServer(opts, signal)), myFunc); export { myServerFn_createServerFn_handler };" `) }) @@ -194,14 +194,10 @@ describe('createServerFn compiles correctly', async () => { expect(compiledResultServerProvider!.code).toMatchInlineSnapshot(` "import { createServerRpc } from '@tanstack/react-start/server-rpc'; import { createServerFn } from '@tanstack/react-start'; - const exportedVar = 'exported'; - const exportedFn_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6ImV4cG9ydGVkRm5fY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => exportedFn.__executeServer(opts, signal)); - const exportedFn = createServerFn().handler(exportedFn_createServerFn_handler, async () => { - return exportedVar; - }); + let exportedFn_createServerFn_handler; const nonExportedVar = 'non-exported'; - const nonExportedFn_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6Im5vbkV4cG9ydGVkRm5fY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => nonExportedFn.__executeServer(opts, signal)); - const nonExportedFn = createServerFn().handler(nonExportedFn_createServerFn_handler, async () => { + let nonExportedFn_createServerFn_handler; + const nonExportedFn = createServerFn().handler(nonExportedFn_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6Im5vbkV4cG9ydGVkRm5fY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => nonExportedFn.__executeServer(opts, signal)), async () => { return nonExportedVar; }); export { exportedFn_createServerFn_handler, nonExportedFn_createServerFn_handler };" diff --git a/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnDestructured.tsx b/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnDestructured.tsx index 69fa019eb9f..79c656f0755 100644 --- a/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnDestructured.tsx +++ b/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnDestructured.tsx @@ -1,58 +1,9 @@ import { createServerRpc } from '@tanstack/react-start/server-rpc'; -import { createServerFn } from '@tanstack/react-start'; -import { z } from 'zod'; -const withUseServer_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhVc2VTZXJ2ZXJfY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => withUseServer.__executeServer(opts, signal)); -const withUseServer = createServerFn({ - method: 'GET' -}).handler(withUseServer_createServerFn_handler, async function () { - console.info('Fetching posts...'); - await new Promise(r => setTimeout(r, 500)); - return axios.get>('https://jsonplaceholder.typicode.com/posts').then(r => r.data.slice(0, 10)); -}); -const withArrowFunction_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhBcnJvd0Z1bmN0aW9uX2NyZWF0ZVNlcnZlckZuX2hhbmRsZXIifQ", (opts, signal) => withArrowFunction.__executeServer(opts, signal)); -const withArrowFunction = createServerFn({ - method: 'GET' -}).handler(withArrowFunction_createServerFn_handler, async () => null); -const withArrowFunctionAndFunction_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhBcnJvd0Z1bmN0aW9uQW5kRnVuY3Rpb25fY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => withArrowFunctionAndFunction.__executeServer(opts, signal)); -const withArrowFunctionAndFunction = createServerFn({ - method: 'GET' -}).handler(withArrowFunctionAndFunction_createServerFn_handler, async () => test()); -const withoutUseServer_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhvdXRVc2VTZXJ2ZXJfY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => withoutUseServer.__executeServer(opts, signal)); -const withoutUseServer = createServerFn({ - method: 'GET' -}).handler(withoutUseServer_createServerFn_handler, async () => { - console.info('Fetching posts...'); - await new Promise(r => setTimeout(r, 500)); - return axios.get>('https://jsonplaceholder.typicode.com/posts').then(r => r.data.slice(0, 10)); -}); -const withVariable_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhWYXJpYWJsZV9jcmVhdGVTZXJ2ZXJGbl9oYW5kbGVyIn0", (opts, signal) => withVariable.__executeServer(opts, signal)); -const withVariable = createServerFn({ - method: 'GET' -}).handler(withVariable_createServerFn_handler, abstractedFunction); -async function abstractedFunction() { - console.info('Fetching posts...'); - await new Promise(r => setTimeout(r, 500)); - return axios.get>('https://jsonplaceholder.typicode.com/posts').then(r => r.data.slice(0, 10)); -} -function zodValidator(schema: TSchema, fn: (input: z.output) => TResult) { - return async (input: unknown) => { - return fn(schema.parse(input)); - }; -} -const withZodValidator_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhab2RWYWxpZGF0b3JfY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => withZodValidator.__executeServer(opts, signal)); -const withZodValidator = createServerFn({ - method: 'GET' -}).handler(withZodValidator_createServerFn_handler, zodValidator(z.number(), input => { - return { - 'you gave': input - }; -})); -const withValidatorFn_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhWYWxpZGF0b3JGbl9jcmVhdGVTZXJ2ZXJGbl9oYW5kbGVyIn0", (opts, signal) => withValidatorFn.__executeServer(opts, signal)); -const withValidatorFn = createServerFn({ - method: 'GET' -}).inputValidator(z.number()).handler(withValidatorFn_createServerFn_handler, async ({ - input -}) => { - return null; -}); +let withUseServer_createServerFn_handler; +let withArrowFunction_createServerFn_handler; +let withArrowFunctionAndFunction_createServerFn_handler; +let withoutUseServer_createServerFn_handler; +let withVariable_createServerFn_handler; +let withZodValidator_createServerFn_handler; +let withValidatorFn_createServerFn_handler; export { withUseServer_createServerFn_handler, withArrowFunction_createServerFn_handler, withArrowFunctionAndFunction_createServerFn_handler, withoutUseServer_createServerFn_handler, withVariable_createServerFn_handler, withZodValidator_createServerFn_handler, withValidatorFn_createServerFn_handler }; \ No newline at end of file diff --git a/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnDestructuredRename.tsx b/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnDestructuredRename.tsx index cb14a1e1cde..8b43bad47d4 100644 --- a/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnDestructuredRename.tsx +++ b/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnDestructuredRename.tsx @@ -1,42 +1,6 @@ import { createServerRpc } from '@tanstack/react-start/server-rpc'; -import { createServerFn as serverFn } from '@tanstack/react-start'; -import { z } from 'zod'; -const withUseServer_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhVc2VTZXJ2ZXJfY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => withUseServer.__executeServer(opts, signal)); -const withUseServer = serverFn({ - method: 'GET' -}).handler(withUseServer_createServerFn_handler, async function () { - console.info('Fetching posts...'); - await new Promise(r => setTimeout(r, 500)); - return axios.get>('https://jsonplaceholder.typicode.com/posts').then(r => r.data.slice(0, 10)); -}); -const withoutUseServer_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhvdXRVc2VTZXJ2ZXJfY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => withoutUseServer.__executeServer(opts, signal)); -const withoutUseServer = serverFn({ - method: 'GET' -}).handler(withoutUseServer_createServerFn_handler, async () => { - console.info('Fetching posts...'); - await new Promise(r => setTimeout(r, 500)); - return axios.get>('https://jsonplaceholder.typicode.com/posts').then(r => r.data.slice(0, 10)); -}); -const withVariable_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhWYXJpYWJsZV9jcmVhdGVTZXJ2ZXJGbl9oYW5kbGVyIn0", (opts, signal) => withVariable.__executeServer(opts, signal)); -const withVariable = serverFn({ - method: 'GET' -}).handler(withVariable_createServerFn_handler, abstractedFunction); -async function abstractedFunction() { - console.info('Fetching posts...'); - await new Promise(r => setTimeout(r, 500)); - return axios.get>('https://jsonplaceholder.typicode.com/posts').then(r => r.data.slice(0, 10)); -} -function zodValidator(schema: TSchema, fn: (input: z.output) => TResult) { - return async (input: unknown) => { - return fn(schema.parse(input)); - }; -} -const withZodValidator_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhab2RWYWxpZGF0b3JfY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => withZodValidator.__executeServer(opts, signal)); -const withZodValidator = serverFn({ - method: 'GET' -}).handler(withZodValidator_createServerFn_handler, zodValidator(z.number(), input => { - return { - 'you gave': input - }; -})); +let withUseServer_createServerFn_handler; +let withoutUseServer_createServerFn_handler; +let withVariable_createServerFn_handler; +let withZodValidator_createServerFn_handler; export { withUseServer_createServerFn_handler, withoutUseServer_createServerFn_handler, withVariable_createServerFn_handler, withZodValidator_createServerFn_handler }; \ No newline at end of file diff --git a/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnStarImport.tsx b/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnStarImport.tsx index ce3152eb083..8b43bad47d4 100644 --- a/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnStarImport.tsx +++ b/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnStarImport.tsx @@ -1,44 +1,6 @@ import { createServerRpc } from '@tanstack/react-start/server-rpc'; -import * as TanStackStart from '@tanstack/react-start'; -import { z } from 'zod'; -const withUseServer_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhVc2VTZXJ2ZXJfY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => withUseServer.__executeServer(opts, signal)); -const withUseServer = TanStackStart.createServerFn({ - method: 'GET' -}).handler(withUseServer_createServerFn_handler, async function () { - 'use server'; - - console.info('Fetching posts...'); - await new Promise(r => setTimeout(r, 500)); - return axios.get>('https://jsonplaceholder.typicode.com/posts').then(r => r.data.slice(0, 10)); -}); -const withoutUseServer_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhvdXRVc2VTZXJ2ZXJfY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => withoutUseServer.__executeServer(opts, signal)); -const withoutUseServer = TanStackStart.createServerFn({ - method: 'GET' -}).handler(withoutUseServer_createServerFn_handler, async () => { - console.info('Fetching posts...'); - await new Promise(r => setTimeout(r, 500)); - return axios.get>('https://jsonplaceholder.typicode.com/posts').then(r => r.data.slice(0, 10)); -}); -const withVariable_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhWYXJpYWJsZV9jcmVhdGVTZXJ2ZXJGbl9oYW5kbGVyIn0", (opts, signal) => withVariable.__executeServer(opts, signal)); -const withVariable = TanStackStart.createServerFn({ - method: 'GET' -}).handler(withVariable_createServerFn_handler, abstractedFunction); -async function abstractedFunction() { - console.info('Fetching posts...'); - await new Promise(r => setTimeout(r, 500)); - return axios.get>('https://jsonplaceholder.typicode.com/posts').then(r => r.data.slice(0, 10)); -} -function zodValidator(schema: TSchema, fn: (input: z.output) => TResult) { - return async (input: unknown) => { - return fn(schema.parse(input)); - }; -} -const withZodValidator_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhab2RWYWxpZGF0b3JfY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => withZodValidator.__executeServer(opts, signal)); -const withZodValidator = TanStackStart.createServerFn({ - method: 'GET' -}).handler(withZodValidator_createServerFn_handler, zodValidator(z.number(), input => { - return { - 'you gave': input - }; -})); +let withUseServer_createServerFn_handler; +let withoutUseServer_createServerFn_handler; +let withVariable_createServerFn_handler; +let withZodValidator_createServerFn_handler; export { withUseServer_createServerFn_handler, withoutUseServer_createServerFn_handler, withVariable_createServerFn_handler, withZodValidator_createServerFn_handler }; \ No newline at end of file diff --git a/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnValidator.tsx b/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnValidator.tsx index 8b353869ac3..6b96fa47984 100644 --- a/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnValidator.tsx +++ b/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/createServerFnValidator.tsx @@ -1,10 +1,3 @@ import { createServerRpc } from '@tanstack/react-start/server-rpc'; -import { createServerFn } from '@tanstack/react-start'; -import { z } from 'zod'; -const withUseServer_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6IndpdGhVc2VTZXJ2ZXJfY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => withUseServer.__executeServer(opts, signal)); -const withUseServer = createServerFn({ - method: 'GET' -}).inputValidator(z.number()).handler(withUseServer_createServerFn_handler, ({ - input -}) => input + 1); +let withUseServer_createServerFn_handler; export { withUseServer_createServerFn_handler }; \ No newline at end of file diff --git a/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/factory.tsx b/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/factory.tsx index 9443f0b1f49..cc0015ac0bc 100644 --- a/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/factory.tsx +++ b/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/factory.tsx @@ -1,37 +1,6 @@ import { createServerRpc } from '@tanstack/react-start/server-rpc'; -import { createServerFn, createMiddleware } from '@tanstack/react-start'; -const authMiddleware = createMiddleware({ - type: 'function' -}).server(({ - next -}) => { - return next({ - context: { - auth: 'auth' - } - }); -}); -const adminMiddleware = createMiddleware({ - type: 'function' -}).server(({ - next -}) => { - return next({ - context: { - admin: 'admin' - } - }); -}); -const createAuthServerFn = createServerFn().middleware([authMiddleware]); -const createAdminServerFn = createAuthServerFn().middleware([adminMiddleware]); -const myAuthedFn_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6Im15QXV0aGVkRm5fY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => myAuthedFn.__executeServer(opts, signal)); -const myAuthedFn = createAuthServerFn().handler(myAuthedFn_createServerFn_handler, () => { - return 'myAuthedFn'; -}); -const deleteUserFn_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6ImRlbGV0ZVVzZXJGbl9jcmVhdGVTZXJ2ZXJGbl9oYW5kbGVyIn0", (opts, signal) => deleteUserFn.__executeServer(opts, signal)); -const deleteUserFn = createAdminServerFn().handler(deleteUserFn_createServerFn_handler, () => { - return 'deleteUserFn'; -}); +let myAuthedFn_createServerFn_handler; +let deleteUserFn_createServerFn_handler; function createFakeFn() { return { handler: cb => { diff --git a/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/isomorphic-fns.tsx b/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/isomorphic-fns.tsx index bc537c28280..c173eeaefc5 100644 --- a/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/isomorphic-fns.tsx +++ b/packages/start-plugin-core/tests/createServerFn/snapshots/server-provider/isomorphic-fns.tsx @@ -1,11 +1,4 @@ import { createServerRpc } from '@tanstack/react-start/server-rpc'; -import { createIsomorphicFn, createServerFn } from '@tanstack/react-start'; -const getEnv = createIsomorphicFn().server(() => 'server').client(() => 'client'); -const getServerEnv_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6ImdldFNlcnZlckVudl9jcmVhdGVTZXJ2ZXJGbl9oYW5kbGVyIn0", (opts, signal) => getServerEnv.__executeServer(opts, signal)); -const getServerEnv = createServerFn().handler(getServerEnv_createServerFn_handler, () => getEnv()); -const getEcho = createIsomorphicFn().server((input: string) => 'server received ' + input).client(input => 'client received ' + input); -const getServerEcho_createServerFn_handler = createServerRpc("eyJmaWxlIjoiL0BpZC90ZXN0LnRzP3Rzcy1zZXJ2ZXJmbi1zcGxpdCIsImV4cG9ydCI6ImdldFNlcnZlckVjaG9fY3JlYXRlU2VydmVyRm5faGFuZGxlciJ9", (opts, signal) => getServerEcho.__executeServer(opts, signal)); -const getServerEcho = createServerFn().inputValidator((input: string) => input).handler(getServerEcho_createServerFn_handler, ({ - data -}) => getEcho(data)); +let getServerEnv_createServerFn_handler; +let getServerEcho_createServerFn_handler; export { getServerEnv_createServerFn_handler, getServerEcho_createServerFn_handler }; \ No newline at end of file