From d02c2714a0dd92d43691e7848d2e6b863a07fbb2 Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Sat, 27 Sep 2025 23:23:56 +0200 Subject: [PATCH 1/3] fix: createServerFn fetcher has TSS_SERVER_FUNCTION symbol prop --- packages/start-client-core/src/createServerFn.ts | 3 ++- .../start-client-core/src/tests/createServerFn.test-d.ts | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/packages/start-client-core/src/createServerFn.ts b/packages/start-client-core/src/createServerFn.ts index 5315dbe24a4..1cdf189cc30 100644 --- a/packages/start-client-core/src/createServerFn.ts +++ b/packages/start-client-core/src/createServerFn.ts @@ -1,7 +1,7 @@ import { isNotFound, isRedirect } from '@tanstack/router-core' import { mergeHeaders } from '@tanstack/router-core/ssr/client' -import { TSS_SERVER_FUNCTION_FACTORY } from './constants' +import { TSS_SERVER_FUNCTION, TSS_SERVER_FUNCTION_FACTORY } from './constants' import { getServerContextAfterGlobalMiddlewares } from './getServerContextAfterGlobalMiddlewares' import { getStartOptions } from './getStartOptions' import type { @@ -248,6 +248,7 @@ export type Fetcher = : RequiredFetcher export interface FetcherBase { + [TSS_SERVER_FUNCTION]: true url: string __executeServer: (opts: { method: Method diff --git a/packages/start-client-core/src/tests/createServerFn.test-d.ts b/packages/start-client-core/src/tests/createServerFn.test-d.ts index b0fdc619281..8e6d7063274 100644 --- a/packages/start-client-core/src/tests/createServerFn.test-d.ts +++ b/packages/start-client-core/src/tests/createServerFn.test-d.ts @@ -3,6 +3,7 @@ import { createMiddleware } from '../createMiddleware' import { createServerFn } from '../createServerFn' import type { Constrain, Register, Validator } from '@tanstack/router-core' import type { ConstrainValidator } from '../createServerFn' +import { TSS_SERVER_FUNCTION } from '../constants' test('createServerFn method with autocomplete', () => { createServerFn().handler((options) => { @@ -586,3 +587,9 @@ test('createServerFn with inputValidator and request middleware', () => { Promise >() }) + +test('createServerFn has TSS_SERVER_FUNCTION symbol set', () => { + const fn = createServerFn().handler(() => ({})) + expectTypeOf(fn).toHaveProperty(TSS_SERVER_FUNCTION) + expectTypeOf(fn[TSS_SERVER_FUNCTION]).toEqualTypeOf() +}) From 0272efbc2341af6a58fcfd2b7b388f5b0e756e1e Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Sat, 27 Sep 2025 23:45:32 +0200 Subject: [PATCH 2/3] add serializer extension, register server functions to be serializable --- packages/router-core/src/index.ts | 3 +++ .../src/ssr/serializer/transformer.ts | 21 ++++++++++++------- .../start-client-core/src/createServerFn.ts | 3 ++- packages/start-client-core/src/createStart.ts | 5 +++-- .../src/tests/createServerFn.test-d.ts | 7 ++++++- 5 files changed, 27 insertions(+), 12 deletions(-) diff --git a/packages/router-core/src/index.ts b/packages/router-core/src/index.ts index 92b7592d399..ab822a51e73 100644 --- a/packages/router-core/src/index.ts +++ b/packages/router-core/src/index.ts @@ -420,6 +420,9 @@ export type { SerializerExtensions, ValidateSerializable, RegisteredSerializableInput, + SerializableExtensions, + DefaultSerializable, + Serializable, } from './ssr/serializer/transformer' export { diff --git a/packages/router-core/src/ssr/serializer/transformer.ts b/packages/router-core/src/ssr/serializer/transformer.ts index 9e8b2b11309..cf58b4f596e 100644 --- a/packages/router-core/src/ssr/serializer/transformer.ts +++ b/packages/router-core/src/ssr/serializer/transformer.ts @@ -9,14 +9,19 @@ import type { import type { LooseReturnType } from '../../utils' import type { AnyRoute, ResolveAllSSR } from '../../route' -export type Serializable = - | number - | string - | boolean - | null - | undefined - | bigint - | Date +export interface DefaultSerializable { + number: number + string: string + boolean: boolean + null: null + undefined: undefined + bigint: bigint + Date: Date +} + +export interface SerializableExtensions extends DefaultSerializable {} + +export type Serializable = SerializableExtensions[keyof SerializableExtensions] export function createSerializationAdapter< TInput = unknown, diff --git a/packages/start-client-core/src/createServerFn.ts b/packages/start-client-core/src/createServerFn.ts index 1cdf189cc30..3ae9a3682cc 100644 --- a/packages/start-client-core/src/createServerFn.ts +++ b/packages/start-client-core/src/createServerFn.ts @@ -1,9 +1,10 @@ import { isNotFound, isRedirect } from '@tanstack/router-core' import { mergeHeaders } from '@tanstack/router-core/ssr/client' -import { TSS_SERVER_FUNCTION, TSS_SERVER_FUNCTION_FACTORY } from './constants' +import { TSS_SERVER_FUNCTION_FACTORY } from './constants' import { getServerContextAfterGlobalMiddlewares } from './getServerContextAfterGlobalMiddlewares' import { getStartOptions } from './getStartOptions' +import type { TSS_SERVER_FUNCTION } from './constants' import type { AnyValidator, Constrain, diff --git a/packages/start-client-core/src/createStart.ts b/packages/start-client-core/src/createStart.ts index 16ca284976e..ac90efaeaf5 100644 --- a/packages/start-client-core/src/createStart.ts +++ b/packages/start-client-core/src/createStart.ts @@ -1,4 +1,5 @@ import { createMiddleware } from './createMiddleware' +import type { TSS_SERVER_FUNCTION } from './constants' import type { AnyFunctionMiddleware, AnyRequestMiddleware, @@ -116,7 +117,7 @@ export type AnyStartInstance = StartInstance export type AnyStartInstanceOptions = StartInstanceOptions declare module '@tanstack/router-core' { - interface Register { - ssr: true + interface SerializableExtensions { + serverFn: { [TSS_SERVER_FUNCTION]: true } } } diff --git a/packages/start-client-core/src/tests/createServerFn.test-d.ts b/packages/start-client-core/src/tests/createServerFn.test-d.ts index 8e6d7063274..177c679774c 100644 --- a/packages/start-client-core/src/tests/createServerFn.test-d.ts +++ b/packages/start-client-core/src/tests/createServerFn.test-d.ts @@ -1,9 +1,9 @@ import { describe, expectTypeOf, test } from 'vitest' import { createMiddleware } from '../createMiddleware' import { createServerFn } from '../createServerFn' +import { TSS_SERVER_FUNCTION } from '../constants' import type { Constrain, Register, Validator } from '@tanstack/router-core' import type { ConstrainValidator } from '../createServerFn' -import { TSS_SERVER_FUNCTION } from '../constants' test('createServerFn method with autocomplete', () => { createServerFn().handler((options) => { @@ -593,3 +593,8 @@ test('createServerFn has TSS_SERVER_FUNCTION symbol set', () => { expectTypeOf(fn).toHaveProperty(TSS_SERVER_FUNCTION) expectTypeOf(fn[TSS_SERVER_FUNCTION]).toEqualTypeOf() }) + +test('createServerFn fetcher itself is serializable', () => { + const fn1 = createServerFn().handler(() => ({})) + const fn2 = createServerFn().handler(() => fn1) +}) From eca3de42a8b210f7e5314c357eb57817a304a7bf Mon Sep 17 00:00:00 2001 From: Manuel Schiller Date: Sat, 27 Sep 2025 23:59:28 +0200 Subject: [PATCH 3/3] remove cast --- .../server-functions/src/routes/middleware/send-serverFn.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/e2e/react-start/server-functions/src/routes/middleware/send-serverFn.tsx b/e2e/react-start/server-functions/src/routes/middleware/send-serverFn.tsx index 73bba934b04..15fe6c80dc7 100644 --- a/e2e/react-start/server-functions/src/routes/middleware/send-serverFn.tsx +++ b/e2e/react-start/server-functions/src/routes/middleware/send-serverFn.tsx @@ -6,7 +6,7 @@ const middleware = createMiddleware({ type: 'function' }).client( async ({ next }) => { return next({ sendContext: { - serverFn: barFn as any, + serverFn: barFn, }, }) },