- Spec files
npm-tanstack--react-start
Describes: pkg:npm/@tanstack/react-start@1.131.x
- Description
- SSR, Streaming, Server Functions, API Routes, bundling and more powered by TanStack Router and Vite. Ready to deploy to your favorite hosting provider.
- Author
- tessl
- Last updated
How to use
npx @tessl/cli registry install tessl/npm-tanstack--react-start@1.131.0
server-functions.md docs/
1# Server Functions23Type-safe server function system enabling seamless RPC-style communication between client and server code with middleware support, validation, automatic serialization, and full TypeScript integration throughout the stack.45## Capabilities67### Server Function Creation89Core functionality for creating server functions that can be called from client-side code with full type safety.1011```typescript { .api }12/**13* Creates a server function with optional validation and middleware14* @param options - Optional configuration for method, validation, and middleware15* @returns Server function builder for chaining configuration16*/17function createServerFn<TValidator = undefined, TMiddleware = []>(18options?: ServerFnBaseOptions<TValidator, TMiddleware>19): ServerFnBuilder<TValidator, TMiddleware>;2021interface ServerFnBuilder<TValidator, TMiddleware> {22/** Configure HTTP method for the server function (default: POST) */23method<TMethod extends Method>(method: TMethod): ServerFnBuilder<TValidator, TMiddleware>;2425/** Add input validation to the server function */26validator<V>(validator: V): ServerFnBuilder<V, TMiddleware>;2728/** Add middleware to the server function */29middleware<M extends AnyFunctionMiddleware>(30middleware: M31): ServerFnBuilder<TValidator, [...TMiddleware, M]>;3233/** Define the handler function that runs on the server */34handler<THandlerFn extends Function>(35handlerFn: THandlerFn36): CompiledFetcherFn<THandlerFn>;37}3839interface ServerFnBaseOptions<TValidator, TMiddleware> {40method?: Method;41validator?: TValidator;42middleware?: TMiddleware;43}4445type Method = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH';4647interface CompiledFetcherFn<THandlerFn> extends Function {48(...args: Parameters<THandlerFn>): Promise<ReturnType<THandlerFn>>;49url: string;50functionId: string;51}52```5354**Usage Examples:**5556```typescript57import { createServerFn } from '@tanstack/react-start';58import { z } from 'zod';5960// Simple server function61const getUsers = createServerFn()62.handler(async () => {63return await database.users.findMany();64});6566// Server function with validation67const createUser = createServerFn()68.validator(z.object({69name: z.string().min(1),70email: z.string().email(),71}))72.handler(async (input) => {73// input is fully typed based on validator74return await database.users.create({ data: input });75});7677// Server function with middleware78const authMiddleware = createMiddleware({79server: async ({ context, next }) => {80const auth = await validateAuth(context.request);81return next({ context: { ...context, user: auth.user } });82},83});8485const deleteUser = createServerFn()86.middleware(authMiddleware)87.handler(async (userId: string, { context }) => {88// context.user is available from middleware89return await database.users.delete({90where: { id: userId, ownerId: context.user.id }91});92});93```9495### Isomorphic Functions9697Functions that can execute different logic on client and server environments.9899```typescript { .api }100/**101* Creates a function that runs different implementations on client vs server102* @param clientFn - Function implementation for client-side execution103* @param serverFn - Function implementation for server-side execution104* @returns Isomorphic function that automatically chooses correct implementation105*/106function createIsomorphicFn<TArgs extends Array<any>, TReturn>(107clientFn: (...args: TArgs) => TReturn,108serverFn: (...args: TArgs) => TReturn109): IsomorphicFn<TArgs, TReturn>;110111interface IsomorphicFn<TArgs extends Array<any>, TReturn> {112(...args: TArgs): TReturn;113}114115interface IsomorphicFnBase<TArgs extends Array<any>, TReturn> {116clientFn: (...args: TArgs) => TReturn;117serverFn: (...args: TArgs) => TReturn;118}119```120121**Usage Example:**122123```typescript124import { createIsomorphicFn } from '@tanstack/react-start';125126const getEnvironment = createIsomorphicFn(127// Client implementation128() => ({129platform: 'browser',130userAgent: navigator.userAgent,131url: window.location.href,132}),133// Server implementation134() => ({135platform: 'node',136version: process.version,137env: process.env.NODE_ENV,138})139);140141console.log(getEnvironment()); // Different output on client vs server142```143144### Middleware System145146Comprehensive middleware system for server functions with validation, context passing, and lifecycle hooks.147148```typescript { .api }149/**150* Creates middleware for server functions with optional validation and lifecycle hooks151* @param options - Middleware configuration with client, server, and after hooks152* @returns Configured middleware function153*/154function createMiddleware<TOptions extends FunctionMiddlewareOptions>(155options: TOptions156): FunctionMiddlewareWithTypes<TOptions>;157158interface FunctionMiddlewareOptions {159/** Validation schema for middleware inputs */160validator?: any;161162/** Server-side middleware function */163server?: FunctionMiddlewareServer;164165/** Client-side middleware function */166client?: FunctionMiddlewareClient;167168/** After middleware hook for cleanup or additional processing */169after?: FunctionMiddlewareAfterServer | FunctionMiddlewareAfterClient;170}171172interface FunctionMiddlewareServer<TValidator = any, TContext = any> {173(options: FunctionMiddlewareServerFnOptions<TValidator, TContext>):174Promise<FunctionMiddlewareServerFnResult<any, TContext>>;175}176177interface FunctionMiddlewareClient<TValidator = any, TContext = any> {178(options: FunctionMiddlewareClientFnOptions<TValidator, TContext>):179Promise<FunctionMiddlewareClientFnResult<any, TContext>>;180}181182interface FunctionMiddlewareAfterServer<TValidator = any, TContext = any> {183(options: FunctionMiddlewareServerFnOptions<TValidator, TContext>):184Promise<void> | void;185}186187interface FunctionMiddlewareAfterClient<TValidator = any, TContext = any> {188(options: FunctionMiddlewareClientFnOptions<TValidator, TContext>):189Promise<void> | void;190}191```192193**Usage Examples:**194195```typescript196import { createMiddleware, createServerFn } from '@tanstack/react-start';197198// Authentication middleware199const authMiddleware = createMiddleware({200server: async ({ context, next }) => {201const token = context.request.headers.get('Authorization');202if (!token) throw new Error('Authentication required');203204const user = await validateToken(token);205return next({ context: { ...context, user } });206},207});208209// Logging middleware210const loggingMiddleware = createMiddleware({211server: async ({ context, next }) => {212console.log(`Server function called: ${context.request.url}`);213const start = Date.now();214215const result = await next();216217console.log(`Server function completed in ${Date.now() - start}ms`);218return result;219},220});221222// Using middleware in server functions223const protectedFunction = createServerFn()224.middleware(authMiddleware)225.middleware(loggingMiddleware)226.handler(async (data: any, { context }) => {227// context.user is available from authMiddleware228return await processDataForUser(data, context.user);229});230```231232### Global Middleware233234System for registering middleware that applies to all server functions.235236```typescript { .api }237/**238* Registers middleware globally for all server functions239* @param middleware - Middleware function to apply globally240*/241function registerGlobalMiddleware(middleware: AnyFunctionMiddleware): void;242243/** Global middleware registry containing all registered global middleware */244const globalMiddleware: Array<AnyFunctionMiddleware>;245246type AnyFunctionMiddleware = FunctionMiddleware<any, any, any>;247248interface FunctionMiddleware<TValidator, TContext, TResult> {249validator?: TValidator;250server?: FunctionMiddlewareServer<TValidator, TContext>;251client?: FunctionMiddlewareClient<TValidator, TResult>;252after?: FunctionMiddlewareAfterValidator<TValidator, TContext>;253}254```255256### Server Function Runtime (Client)257258Client-side runtime for making RPC calls to server functions.259260```typescript { .api }261/**262* Creates client-side RPC function for calling server functions263* @param functionId - Unique identifier for the server function264* @param serverBase - Base URL for server function endpoints265* @returns Client-side function that calls the server function266*/267function createClientRpc(functionId: string, serverBase: string): ClientRpcFunction;268269interface ClientRpcFunction {270(...args: Array<any>): Promise<any>;271url: string;272functionId: string;273}274```275276### Server Function Runtime (Server)277278Server-side runtime for handling server function calls.279280```typescript { .api }281/**282* Creates server-side RPC handler for processing server function calls283* @param functionId - Unique identifier for the server function284* @param serverBase - Base URL for server function endpoints285* @param splitImportFn - Dynamic import function for loading server function code286* @returns Server-side function handler287*/288function createServerRpc(289functionId: string,290serverBase: string,291splitImportFn: () => Promise<any>292): ServerRpcFunction;293294interface ServerRpcFunction {295(...args: Array<any>): Promise<any>;296url: string;297functionId: string;298}299```300301### Server Function Utilities302303Utility functions for server function processing, middleware execution, and data handling.304305```typescript { .api }306/**307* Applies middleware to a server function execution chain308* @param middlewares - Array of middleware functions to apply309* @param context - Execution context310* @returns Processed result with middleware applied311*/312function applyMiddleware<TContext, TResult>(313middlewares: Array<AnyFunctionMiddleware>,314context: TContext315): Promise<TResult>;316317/**318* Executes validation on server function inputs319* @param validator - Validation schema or function320* @param data - Data to validate321* @returns Validated data or throws validation error322*/323function execValidator<TValidator, TData>(324validator: TValidator,325data: TData326): TData;327328/**329* Converts server function base configuration to middleware330* @param options - Server function base options331* @returns Middleware function332*/333function serverFnBaseToMiddleware<TOptions extends ServerFnBaseOptions<any, any>>(334options: TOptions335): AnyFunctionMiddleware;336337/**338* Extracts form data context from request339* @param request - HTTP request containing form data340* @returns Extracted form data and metadata341*/342function extractFormDataContext(request: Request): Promise<{343data: FormData;344contentType: string;345}>;346347/**348* Flattens nested middleware arrays into a single array349* @param middlewares - Nested middleware arrays350* @returns Flattened middleware array351*/352function flattenMiddlewares(353middlewares: Array<AnyFunctionMiddleware | Array<AnyFunctionMiddleware>>354): Array<AnyFunctionMiddleware>;355356/**357* Static cache for server function results358* @param key - Cache key359* @param value - Value to cache (optional, retrieves if not provided)360* @returns Cached value or undefined361*/362function serverFnStaticCache<T>(key: string, value?: T): T | undefined;363364/**365* Executes middleware with proper error handling and context passing366* @param middleware - Middleware function to execute367* @param context - Execution context368* @returns Promise resolving to middleware result369*/370function executeMiddleware<TContext, TResult>(371middleware: AnyFunctionMiddleware,372context: TContext373): Promise<TResult>;374```375376### Response Utilities377378Utilities for creating and handling server function responses.379380```typescript { .api }381/**382* Creates a JSON response with proper headers383* @param data - Data to serialize as JSON384* @param init - Optional response initialization options385* @returns Response object with JSON content386*/387function json<T = any>(data: T, init?: ResponseInit): JsonResponse<T>;388389interface JsonResponse<T = any> extends Response {390json(): Promise<T>;391}392393type ServerFnResponseType = Response | any;394```395396## Core Types397398```typescript { .api }399interface ServerFn<TValidator = any, TMiddleware = any, THandler = any> {400validator?: TValidator;401middleware?: TMiddleware;402handler: THandler;403method: Method;404url: string;405functionId: string;406}407408interface ServerFnCtx {409request: Request;410params: Record<string, string>;411data: FormData | any;412}413414interface ServerFnType<TInput = any, TOutput = any> {415input: TInput;416output: TOutput;417}418419interface MiddlewareFn<TContext = any, TResult = any> {420(context: TContext): Promise<TResult> | TResult;421}422423interface ServerFnMiddlewareOptions<TValidator, TContext> {424validator: TValidator;425context: TContext;426request: Request;427next: NextFn;428}429430interface ServerFnMiddlewareResult<TResult, TContext> {431result: TResult;432context: TContext;433}434435interface NextFn {436(context?: any): Promise<any>;437}438439interface StaticCachedResult<T> {440value: T;441timestamp: number;442key: string;443}444445// Fetcher types446interface Fetcher<TData = any, TError = any> {447data?: TData;448error?: TError;449isLoading: boolean;450isFetching: boolean;451isSuccess: boolean;452isError: boolean;453}454455interface OptionalFetcher<TData, TError> extends Fetcher<TData, TError> {456data?: TData;457}458459interface RequiredFetcher<TData, TError> extends Fetcher<TData, TError> {460data: TData;461}462463interface FetcherData<T = any> {464data: T;465error?: Error;466isLoading: boolean;467}468469interface FetcherBaseOptions {470retry?: number;471retryDelayMs?: number;472timeout?: number;473}474475interface CompiledFetcherFnOptions extends FetcherBaseOptions {476method?: Method;477headers?: HeadersInit;478}479480// Middleware types481interface FunctionMiddlewareWithTypes<TOptions> {482validator: TOptions extends { validator: infer V } ? V : undefined;483server: TOptions extends { server: infer S } ? S : undefined;484client: TOptions extends { client: infer C } ? C : undefined;485after: TOptions extends { after: infer A } ? A : undefined;486}487488interface FunctionMiddlewareValidator<TInput = any, TOutput = any> {489(input: TInput): TOutput | Promise<TOutput>;490}491492interface FunctionMiddlewareServerFnOptions<TValidator, TContext> {493validator: TValidator;494context: TContext;495request: Request;496data: any;497next: FunctionMiddlewareServerNextFn;498}499500interface FunctionMiddlewareServerFnResult<TResult, TContext> {501result: TResult;502context: TContext;503}504505interface FunctionMiddlewareServerNextFn {506(context?: any): Promise<any>;507}508509interface FunctionMiddlewareClientFnOptions<TValidator, TContext> {510validator: TValidator;511context: TContext;512next: FunctionMiddlewareClientNextFn;513}514515interface FunctionMiddlewareClientFnResult<TResult, TContext> {516result: TResult;517context: TContext;518}519520interface FunctionMiddlewareClientNextFn {521(): Promise<any>;522}523524interface FunctionClientResultWithContext<TResult, TContext> {525result: TResult;526context: TContext;527}528529interface FunctionServerResultWithContext<TResult, TContext> {530result: TResult;531context: TContext;532}533534interface FunctionMiddlewareAfterValidator<TValidator, TContext> {535(options: FunctionMiddlewareServerFnOptions<TValidator, TContext>): void | Promise<void>;536}537538interface FunctionMiddlewareClientFn<TValidator, TContext, TResult> {539(options: FunctionMiddlewareClientFnOptions<TValidator, TContext>):540Promise<FunctionMiddlewareClientFnResult<TResult, TContext>>;541}542543// Type utility types544type IntersectAllValidatorInputs<T extends Array<any>> =545T extends [infer Head, ...infer Tail]546? (Head extends { validator: { input: infer Input } } ? Input : {}) &547IntersectAllValidatorInputs<Tail>548: {};549550type IntersectAllValidatorOutputs<T extends Array<any>> =551T extends [infer Head, ...infer Tail]552? (Head extends { validator: { output: infer Output } } ? Output : {}) &553IntersectAllValidatorOutputs<Tail>554: {};555556type AssignAllClientContextBeforeNext<T extends Array<any>> =557T extends [infer Head, ...infer Tail]558? (Head extends { client: { context: infer Context } } ? Context : {}) &559AssignAllClientContextBeforeNext<Tail>560: {};561562type AssignAllMiddleware<T extends Array<any>> =563T extends [infer Head, ...infer Tail]564? Head & AssignAllMiddleware<Tail>565: {};566567type AssignAllServerContext<T extends Array<any>> =568T extends [infer Head, ...infer Tail]569? (Head extends { server: { context: infer Context } } ? Context : {}) &570AssignAllServerContext<Tail>571: {};572573interface FunctionMiddlewareServerFn<TInput, TOutput, TContext> {574(input: TInput, context: TContext): Promise<TOutput>;575}576577interface AnyRequestMiddleware {578(request: Request): Promise<Request> | Request;579}580```581582### Advanced Server Function Utilities583584Core server function fetching utility used internally for RPC communication. Useful for advanced users who need custom server function handling.585586```typescript { .api }587/**588* Core server function fetcher that handles HTTP requests for server functions589* Used internally by the RPC system, but can be used for custom implementations590* @param url - The server function endpoint URL591* @param args - Arguments to pass to the server function592* @param handler - HTTP handler function for making the actual request593* @returns Promise resolving to the server function result594*/595function serverFnFetcher(596url: string,597args: Array<any>,598handler: (url: string, requestInit: RequestInit) => Promise<Response>599): Promise<any>;600```601602**Usage Example:**603604```typescript605import { serverFnFetcher } from '@tanstack/react-start/server-functions-client';606607// Custom server function handler608const customHandler = async (url: string, requestInit: RequestInit) => {609// Add custom headers or logging610const customInit = {611...requestInit,612headers: {613...requestInit.headers,614'X-Custom-Header': 'my-value',615},616};617618console.log('Making server function call to:', url);619return fetch(url, customInit);620};621622// Use the fetcher directly623const result = await serverFnFetcher(624'/api/my-server-function',625[userId, options],626customHandler627);628```629```