@tanstack/start-client-core 1.167.22 → 1.168.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,21 @@
1
1
  import { TSS_SERVER_FUNCTION_FACTORY, ClientFnMeta, ServerFnMeta, TSS_SERVER_FUNCTION } from './constants.js';
2
2
  import { AnyValidator, Constrain, Expand, Register, RegisteredSerializableInput, ResolveValidatorInput, ValidateSerializable, ValidateSerializableInput, Validator } from '@tanstack/router-core';
3
3
  import { AnyFunctionMiddleware, AnyRequestMiddleware, AssignAllServerFnContext, IntersectAllValidatorInputs, IntersectAllValidatorOutputs } from './createMiddleware.js';
4
- export type CreateServerFn<TRegister> = <TMethod extends Method, TResponse = unknown, TMiddlewares = undefined, TInputValidator = undefined>(options?: {
4
+ export type ServerFnStrict = boolean | {
5
+ input?: boolean;
6
+ output?: boolean;
7
+ };
8
+ export interface ServerFnOptions<TMethod extends Method = Method, TStrict extends ServerFnStrict = true> {
5
9
  method?: TMethod;
6
- }, __opts?: ServerFnBaseOptions<TRegister, TMethod, TResponse, TMiddlewares, TInputValidator>) => ServerFnBuilder<TRegister, TMethod>;
10
+ strict?: TStrict;
11
+ }
12
+ export type ServerFnStrictInput<TStrict extends ServerFnStrict> = TStrict extends false ? false : TStrict extends {
13
+ input: infer TInput extends boolean;
14
+ } ? TInput : true;
15
+ export type ServerFnStrictOutput<TStrict extends ServerFnStrict> = TStrict extends false ? false : TStrict extends {
16
+ output: infer TOutput extends boolean;
17
+ } ? TOutput : true;
18
+ export type CreateServerFn<TRegister> = <TMethod extends Method, TStrict extends ServerFnStrict = true, TResponse = unknown, TMiddlewares = undefined, TInputValidator = undefined>(options?: ServerFnOptions<TMethod, TStrict>, __opts?: ServerFnBaseOptions<TRegister, TMethod, TResponse, TMiddlewares, TInputValidator, TStrict>) => ServerFnBuilder<TRegister, TMethod, TStrict>;
7
19
  export declare const createServerFn: CreateServerFn<Register>;
8
20
  export declare function executeMiddleware(middlewares: Array<AnyFunctionMiddleware | AnyRequestMiddleware>, env: 'client' | 'server', opts: ServerFnMiddlewareOptions): Promise<ServerFnMiddlewareResult>;
9
21
  export type CompiledFetcherFnOptions = {
@@ -48,8 +60,8 @@ export type RscStream<T> = {
48
60
  __cacheState: T;
49
61
  };
50
62
  export type Method = 'GET' | 'POST';
51
- export type ServerFnReturnType<TRegister, TResponse> = TResponse extends PromiseLike<infer U> ? Promise<ServerFnReturnType<TRegister, U>> : TResponse extends Response ? TResponse : ValidateSerializableInput<TRegister, TResponse>;
52
- export type ServerFn<TRegister, TMethod, TMiddlewares, TInputValidator, TResponse> = (ctx: ServerFnCtx<TRegister, TMethod, TMiddlewares, TInputValidator>) => ServerFnReturnType<TRegister, TResponse>;
63
+ export type ServerFnReturnType<TRegister, TResponse, TStrict extends ServerFnStrict = true> = ServerFnStrictOutput<TStrict> extends false ? TResponse : TResponse extends PromiseLike<infer U> ? Promise<ServerFnReturnType<TRegister, U, TStrict>> : TResponse extends Response ? TResponse : ValidateSerializableInput<TRegister, TResponse>;
64
+ export type ServerFn<TRegister, TMethod, TMiddlewares, TInputValidator, TResponse, TStrict extends ServerFnStrict = true> = (ctx: ServerFnCtx<TRegister, TMethod, TMiddlewares, TInputValidator>) => ServerFnReturnType<TRegister, TResponse, TStrict>;
53
65
  export interface ServerFnCtx<TRegister, TMethod, TMiddlewares, TInputValidator> {
54
66
  data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TInputValidator>>;
55
67
  serverFnMeta: ServerFnMeta;
@@ -61,47 +73,48 @@ export type CompiledFetcherFn<TRegister, TResponse> = {
61
73
  url: string;
62
74
  serverFnMeta: ServerFnMeta;
63
75
  };
64
- export type ServerFnBaseOptions<TRegister, TMethod extends Method = 'GET', TResponse = unknown, TMiddlewares = unknown, TInputValidator = unknown> = {
76
+ export type ServerFnBaseOptions<TRegister, TMethod extends Method = 'GET', TResponse = unknown, TMiddlewares = unknown, TInputValidator = unknown, TStrict extends ServerFnStrict = true> = {
65
77
  method: TMethod;
78
+ strict?: TStrict;
66
79
  middleware?: Constrain<TMiddlewares, ReadonlyArray<AnyFunctionMiddleware | AnyRequestMiddleware>>;
67
- inputValidator?: ConstrainValidator<TRegister, TMethod, TInputValidator>;
80
+ inputValidator?: ConstrainValidator<TRegister, TMethod, TInputValidator, TStrict>;
68
81
  extractedFn?: CompiledFetcherFn<TRegister, TResponse>;
69
- serverFn?: ServerFn<TRegister, TMethod, TMiddlewares, TInputValidator, TResponse>;
82
+ serverFn?: ServerFn<TRegister, TMethod, TMiddlewares, TInputValidator, TResponse, TStrict>;
70
83
  };
71
- export type ValidateValidatorInput<TRegister, TMethod extends Method, TInputValidator> = TMethod extends 'POST' ? ResolveValidatorInput<TInputValidator> extends FormData ? ResolveValidatorInput<TInputValidator> : ValidateSerializable<ResolveValidatorInput<TInputValidator>, RegisteredSerializableInput<TRegister>> : ValidateSerializable<ResolveValidatorInput<TInputValidator>, RegisteredSerializableInput<TRegister>>;
72
- export type ValidateValidator<TRegister, TMethod extends Method, TInputValidator> = ValidateValidatorInput<TRegister, TMethod, TInputValidator> extends infer TInput ? Validator<TInput, any> : never;
73
- export type ConstrainValidator<TRegister, TMethod extends Method, TInputValidator> = (unknown extends TInputValidator ? TInputValidator : ResolveValidatorInput<TInputValidator> extends ValidateValidator<TRegister, TMethod, TInputValidator> ? TInputValidator : never) | ValidateValidator<TRegister, TMethod, TInputValidator>;
84
+ export type ValidateValidatorInput<TRegister, TMethod extends Method, TInputValidator, TStrict extends ServerFnStrict = true> = ServerFnStrictInput<TStrict> extends false ? ResolveValidatorInput<TInputValidator> : TMethod extends 'POST' ? ResolveValidatorInput<TInputValidator> extends FormData ? ResolveValidatorInput<TInputValidator> : ValidateSerializable<ResolveValidatorInput<TInputValidator>, RegisteredSerializableInput<TRegister>> : ValidateSerializable<ResolveValidatorInput<TInputValidator>, RegisteredSerializableInput<TRegister>>;
85
+ export type ValidateValidator<TRegister, TMethod extends Method, TInputValidator, TStrict extends ServerFnStrict = true> = ValidateValidatorInput<TRegister, TMethod, TInputValidator, TStrict> extends infer TInput ? Validator<TInput, any> : never;
86
+ export type ConstrainValidator<TRegister, TMethod extends Method, TInputValidator, TStrict extends ServerFnStrict = true> = (unknown extends TInputValidator ? TInputValidator : ResolveValidatorInput<TInputValidator> extends ValidateValidator<TRegister, TMethod, TInputValidator, TStrict> ? TInputValidator : never) | ValidateValidator<TRegister, TMethod, TInputValidator, TStrict>;
74
87
  export type AppendMiddlewares<TMiddlewares, TNewMiddlewares> = TMiddlewares extends ReadonlyArray<any> ? TNewMiddlewares extends ReadonlyArray<any> ? readonly [...TMiddlewares, ...TNewMiddlewares] : TMiddlewares : TNewMiddlewares;
75
- export interface ServerFnMiddleware<TRegister, TMethod extends Method, TMiddlewares, TInputValidator> {
76
- middleware: <const TNewMiddlewares>(middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyFunctionMiddleware | AnyRequestMiddleware | AnyServerFn>>) => ServerFnAfterMiddleware<TRegister, TMethod, AppendMiddlewares<TMiddlewares, TNewMiddlewares>, TInputValidator>;
88
+ export interface ServerFnMiddleware<TRegister, TMethod extends Method, TMiddlewares, TInputValidator, TStrict extends ServerFnStrict> {
89
+ middleware: <const TNewMiddlewares>(middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyFunctionMiddleware | AnyRequestMiddleware | AnyServerFn>>) => ServerFnAfterMiddleware<TRegister, TMethod, AppendMiddlewares<TMiddlewares, TNewMiddlewares>, TInputValidator, TStrict>;
77
90
  }
78
- export interface ServerFnAfterMiddleware<TRegister, TMethod extends Method, TMiddlewares, TInputValidator> extends ServerFnWithTypes<TRegister, TMethod, TMiddlewares, TInputValidator, undefined>, ServerFnMiddleware<TRegister, TMethod, TMiddlewares, undefined>, ServerFnValidator<TRegister, TMethod, TMiddlewares>, ServerFnHandler<TRegister, TMethod, TMiddlewares, TInputValidator> {
79
- <TNewMethod extends Method = TMethod>(options?: {
80
- method?: TNewMethod;
81
- }): ServerFnAfterMiddleware<TRegister, TNewMethod, TMiddlewares, TInputValidator>;
91
+ export interface ServerFnAfterMiddleware<TRegister, TMethod extends Method, TMiddlewares, TInputValidator, TStrict extends ServerFnStrict> extends ServerFnWithTypes<TRegister, TMethod, TMiddlewares, TInputValidator, undefined, TStrict>, ServerFnMiddleware<TRegister, TMethod, TMiddlewares, undefined, TStrict>, ServerFnValidator<TRegister, TMethod, TMiddlewares, TStrict>, ServerFnHandler<TRegister, TMethod, TMiddlewares, TInputValidator, TStrict> {
92
+ <TNewMethod extends Method = TMethod, TNewStrict extends ServerFnStrict = TStrict>(options?: ServerFnOptions<TNewMethod, TNewStrict>): ServerFnAfterMiddleware<TRegister, TNewMethod, TMiddlewares, TInputValidator, TNewStrict>;
82
93
  }
83
- export type ValidatorFn<TRegister, TMethod extends Method, TMiddlewares> = <TInputValidator>(inputValidator: ConstrainValidator<TRegister, TMethod, TInputValidator>) => ServerFnAfterValidator<TRegister, TMethod, TMiddlewares, TInputValidator>;
84
- export interface ServerFnValidator<TRegister, TMethod extends Method, TMiddlewares> {
85
- inputValidator: ValidatorFn<TRegister, TMethod, TMiddlewares>;
94
+ export type ValidatorFn<TRegister, TMethod extends Method, TMiddlewares, TStrict extends ServerFnStrict> = <TInputValidator>(inputValidator: ConstrainValidator<TRegister, TMethod, TInputValidator, TStrict>) => ServerFnAfterValidator<TRegister, TMethod, TMiddlewares, TInputValidator, TStrict>;
95
+ export interface ServerFnValidator<TRegister, TMethod extends Method, TMiddlewares, TStrict extends ServerFnStrict> {
96
+ inputValidator: ValidatorFn<TRegister, TMethod, TMiddlewares, TStrict>;
86
97
  }
87
- export interface ServerFnAfterValidator<TRegister, TMethod extends Method, TMiddlewares, TInputValidator> extends ServerFnWithTypes<TRegister, TMethod, TMiddlewares, TInputValidator, undefined>, ServerFnMiddleware<TRegister, TMethod, TMiddlewares, TInputValidator>, ServerFnHandler<TRegister, TMethod, TMiddlewares, TInputValidator> {
98
+ export interface ServerFnAfterValidator<TRegister, TMethod extends Method, TMiddlewares, TInputValidator, TStrict extends ServerFnStrict> extends ServerFnWithTypes<TRegister, TMethod, TMiddlewares, TInputValidator, undefined, TStrict>, ServerFnMiddleware<TRegister, TMethod, TMiddlewares, TInputValidator, TStrict>, ServerFnHandler<TRegister, TMethod, TMiddlewares, TInputValidator, TStrict> {
88
99
  }
89
- export interface ServerFnAfterTyper<TRegister, TMethod extends Method, TMiddlewares, TInputValidator> extends ServerFnWithTypes<TRegister, TMethod, TMiddlewares, TInputValidator, undefined>, ServerFnHandler<TRegister, TMethod, TMiddlewares, TInputValidator> {
100
+ export interface ServerFnAfterTyper<TRegister, TMethod extends Method, TMiddlewares, TInputValidator, TStrict extends ServerFnStrict> extends ServerFnWithTypes<TRegister, TMethod, TMiddlewares, TInputValidator, undefined, TStrict>, ServerFnHandler<TRegister, TMethod, TMiddlewares, TInputValidator, TStrict> {
90
101
  }
91
- export interface ServerFnHandler<TRegister, TMethod extends Method, TMiddlewares, TInputValidator> {
92
- handler: <TNewResponse>(fn?: ServerFn<TRegister, TMethod, TMiddlewares, TInputValidator, TNewResponse>) => Fetcher<TMiddlewares, TInputValidator, TNewResponse>;
102
+ export interface ServerFnHandler<TRegister, TMethod extends Method, TMiddlewares, TInputValidator, TStrict extends ServerFnStrict> {
103
+ handler: <TNewResponse>(fn?: ServerFn<TRegister, TMethod, TMiddlewares, TInputValidator, TNewResponse, TStrict>) => Fetcher<TMiddlewares, TInputValidator, TNewResponse>;
93
104
  }
94
- export interface ServerFnBuilder<TRegister, TMethod extends Method = 'GET'> extends ServerFnWithTypes<TRegister, TMethod, undefined, undefined, undefined>, ServerFnMiddleware<TRegister, TMethod, undefined, undefined>, ServerFnValidator<TRegister, TMethod, undefined>, ServerFnHandler<TRegister, TMethod, undefined, undefined> {
95
- options: ServerFnBaseOptions<TRegister, TMethod, unknown, undefined, undefined>;
105
+ export interface ServerFnBuilder<TRegister, TMethod extends Method = 'GET', TStrict extends ServerFnStrict = true> extends ServerFnWithTypes<TRegister, TMethod, undefined, undefined, undefined, TStrict>, ServerFnMiddleware<TRegister, TMethod, undefined, undefined, TStrict>, ServerFnValidator<TRegister, TMethod, undefined, TStrict>, ServerFnHandler<TRegister, TMethod, undefined, undefined, TStrict> {
106
+ <TNewMethod extends Method = TMethod, TNewStrict extends ServerFnStrict = TStrict>(options?: ServerFnOptions<TNewMethod, TNewStrict>): ServerFnBuilder<TRegister, TNewMethod, TNewStrict>;
107
+ options: ServerFnBaseOptions<TRegister, TMethod, unknown, undefined, undefined, TStrict>;
96
108
  }
97
- export interface ServerFnWithTypes<in out TRegister, in out TMethod extends Method, in out TMiddlewares, in out TInputValidator, in out TResponse> {
98
- '~types': ServerFnTypes<TRegister, TMethod, TMiddlewares, TInputValidator, TResponse>;
99
- options: ServerFnBaseOptions<TRegister, TMethod, unknown, undefined, undefined>;
109
+ export interface ServerFnWithTypes<in out TRegister, in out TMethod extends Method, in out TMiddlewares, in out TInputValidator, in out TResponse, in out TStrict extends ServerFnStrict> {
110
+ '~types': ServerFnTypes<TRegister, TMethod, TMiddlewares, TInputValidator, TResponse, TStrict>;
111
+ options: ServerFnBaseOptions<TRegister, TMethod, unknown, undefined, undefined, TStrict>;
100
112
  [TSS_SERVER_FUNCTION_FACTORY]: true;
101
113
  }
102
- export type AnyServerFn = ServerFnWithTypes<any, any, any, any, any>;
103
- export interface ServerFnTypes<in out TRegister, in out TMethod extends Method, in out TMiddlewares, in out TInputValidator, in out TResponse> {
114
+ export type AnyServerFn = ServerFnWithTypes<any, any, any, any, any, any>;
115
+ export interface ServerFnTypes<in out TRegister, in out TMethod extends Method, in out TMiddlewares, in out TInputValidator, in out TResponse, in out TStrict extends ServerFnStrict> {
104
116
  method: TMethod;
117
+ strict: TStrict;
105
118
  middlewares: TMiddlewares;
106
119
  inputValidator: TInputValidator;
107
120
  response: TResponse;
@@ -1 +1 @@
1
- {"version":3,"file":"createServerFn.js","names":[],"sources":["../../src/createServerFn.ts"],"sourcesContent":["import { mergeHeaders } from '@tanstack/router-core/ssr/client'\n\nimport { isRedirect, parseRedirect } from '@tanstack/router-core'\nimport { TSS_SERVER_FUNCTION_FACTORY } from './constants'\nimport { getStartOptions } from './getStartOptions'\nimport { getStartContextServerOnly } from './getStartContextServerOnly'\nimport { createNullProtoObject, safeObjectMerge } from './safeObjectMerge'\nimport type {\n ClientFnMeta,\n ServerFnMeta,\n TSS_SERVER_FUNCTION,\n} from './constants'\nimport type {\n AnyValidator,\n Constrain,\n Expand,\n Register,\n RegisteredSerializableInput,\n ResolveValidatorInput,\n ValidateSerializable,\n ValidateSerializableInput,\n Validator,\n} from '@tanstack/router-core'\nimport type {\n AnyFunctionMiddleware,\n AnyRequestMiddleware,\n AssignAllServerFnContext,\n FunctionMiddlewareServerFnResult,\n IntersectAllValidatorInputs,\n IntersectAllValidatorOutputs,\n} from './createMiddleware'\n\ntype TODO = any\n\nexport type CreateServerFn<TRegister> = <\n TMethod extends Method,\n TResponse = unknown,\n TMiddlewares = undefined,\n TInputValidator = undefined,\n>(\n options?: {\n method?: TMethod\n },\n __opts?: ServerFnBaseOptions<\n TRegister,\n TMethod,\n TResponse,\n TMiddlewares,\n TInputValidator\n >,\n) => ServerFnBuilder<TRegister, TMethod>\n\nexport const createServerFn: CreateServerFn<Register> = (options, __opts) => {\n const resolvedOptions = (__opts || options || {}) as ServerFnBaseOptions<\n any,\n any,\n any,\n any,\n any\n >\n\n if (typeof resolvedOptions.method === 'undefined') {\n resolvedOptions.method = 'GET' as Method\n }\n\n const res: ServerFnBuilder<Register, Method> = {\n options: resolvedOptions,\n middleware: (middleware) => {\n // multiple calls to `middleware()` merge the middlewares with the previously supplied ones\n // this is primarily useful for letting users create their own abstractions on top of `createServerFn`\n\n const newMiddleware = [...(resolvedOptions.middleware || [])]\n middleware.map((m) => {\n if (TSS_SERVER_FUNCTION_FACTORY in m) {\n if (m.options.middleware) {\n newMiddleware.push(...m.options.middleware)\n }\n } else {\n newMiddleware.push(m)\n }\n })\n\n const newOptions = {\n ...resolvedOptions,\n middleware: newMiddleware,\n }\n const res = createServerFn(undefined, newOptions) as any\n res[TSS_SERVER_FUNCTION_FACTORY] = true\n return res\n },\n inputValidator: (inputValidator) => {\n const newOptions = { ...resolvedOptions, inputValidator }\n return createServerFn(undefined, newOptions) as any\n },\n handler: (...args) => {\n // This function signature changes due to AST transformations\n // in the babel plugin. We need to cast it to the correct\n // function signature post-transformation\n const [extractedFn, serverFn] = args as unknown as [\n CompiledFetcherFn<Register, any>,\n ServerFn<Register, Method, any, any, any>,\n ]\n\n // Keep the original function around so we can use it\n // in the server environment\n const newOptions = { ...resolvedOptions, extractedFn, serverFn }\n\n const resolvedMiddleware = [\n ...(newOptions.middleware || []),\n serverFnBaseToMiddleware(newOptions),\n ]\n\n // We want to make sure the new function has the same\n // properties as the original function\n\n // Propagate the declared HTTP method onto the extracted handler\n // so the manifest-exported symbol (resolved by getServerFnById)\n // carries `method`, enabling the server handler to reject\n // mismatched HTTP methods before parsing request payloads.\n ;(extractedFn as any).method = resolvedOptions.method\n\n return Object.assign(\n async (opts?: CompiledFetcherFnOptions) => {\n // Start by executing the client-side middleware chain\n const result = await executeMiddleware(resolvedMiddleware, 'client', {\n ...extractedFn,\n ...newOptions,\n data: opts?.data as any,\n headers: opts?.headers,\n signal: opts?.signal,\n fetch: opts?.fetch,\n context: createNullProtoObject(),\n })\n\n const redirect = parseRedirect(result.error)\n if (redirect) {\n throw redirect\n }\n\n if (result.error) throw result.error\n return result.result\n },\n {\n // This copies over the URL, function ID\n ...extractedFn,\n // Expose the declared HTTP method so the server handler\n // can reject mismatched methods before parsing payloads\n method: resolvedOptions.method,\n // The extracted function on the server-side calls\n // this function\n __executeServer: async (opts: any) => {\n const startContext = getStartContextServerOnly()\n const serverContextAfterGlobalMiddlewares =\n startContext.contextAfterGlobalMiddlewares\n const ctx = {\n ...extractedFn,\n ...opts,\n // Ensure we use the full serverFnMeta from the provider file's extractedFn\n // (which has id, name, filename) rather than the partial one from SSR/client\n // callers (which only has id)\n serverFnMeta: extractedFn.serverFnMeta,\n // Merge client context first so trusted server middleware context wins.\n context: safeObjectMerge(\n opts.context,\n serverContextAfterGlobalMiddlewares,\n ),\n request: startContext.request,\n }\n\n const result = await executeMiddleware(\n resolvedMiddleware,\n 'server',\n ctx,\n ).then((d) => ({\n // Only send the result and sendContext back to the client\n result: d.result,\n error: d.error,\n context: d.sendContext,\n }))\n\n return result\n },\n },\n ) as any\n },\n } as ServerFnBuilder<Register, Method>\n const fun = (options?: { method?: Method }) => {\n const newOptions = {\n ...resolvedOptions,\n ...options,\n }\n return createServerFn(undefined, newOptions) as any\n }\n return Object.assign(fun, res) as any\n}\n\nexport async function executeMiddleware(\n middlewares: Array<AnyFunctionMiddleware | AnyRequestMiddleware>,\n env: 'client' | 'server',\n opts: ServerFnMiddlewareOptions,\n): Promise<ServerFnMiddlewareResult> {\n const globalMiddlewares = getStartOptions()?.functionMiddleware || []\n let flattenedMiddlewares = flattenMiddlewares([\n ...globalMiddlewares,\n ...middlewares,\n ])\n\n // On server, filter out middlewares that already executed in the request phase\n // to prevent duplicate execution (issue #5239)\n if (env === 'server') {\n const startContext = getStartContextServerOnly({ throwIfNotFound: false })\n if (startContext?.executedRequestMiddlewares) {\n flattenedMiddlewares = flattenedMiddlewares.filter(\n (m) => !startContext.executedRequestMiddlewares.has(m),\n )\n }\n }\n\n const callNextMiddleware: NextFn = async (ctx) => {\n // Get the next middleware\n const nextMiddleware = flattenedMiddlewares.shift()\n\n // If there are no more middlewares, return the context\n if (!nextMiddleware) {\n return ctx\n }\n\n // Execute the middleware\n try {\n if (\n 'inputValidator' in nextMiddleware.options &&\n nextMiddleware.options.inputValidator &&\n env === 'server'\n ) {\n // Execute the middleware's input function\n ctx.data = await execValidator(\n nextMiddleware.options.inputValidator,\n ctx.data,\n )\n }\n\n let middlewareFn: MiddlewareFn | undefined = undefined\n if (env === 'client') {\n if ('client' in nextMiddleware.options) {\n middlewareFn = nextMiddleware.options.client as\n | MiddlewareFn\n | undefined\n }\n }\n // env === 'server'\n else if ('server' in nextMiddleware.options) {\n middlewareFn = nextMiddleware.options.server as MiddlewareFn | undefined\n }\n\n if (middlewareFn) {\n const userNext = async (\n userCtx: ServerFnMiddlewareResult | undefined = {} as any,\n ) => {\n // Return the next middleware\n // Use safeObjectMerge for context objects to prevent prototype pollution\n const nextCtx = {\n ...ctx,\n ...userCtx,\n context: safeObjectMerge(ctx.context, userCtx.context),\n sendContext: safeObjectMerge(ctx.sendContext, userCtx.sendContext),\n headers: mergeHeaders(ctx.headers, userCtx.headers),\n _callSiteFetch: ctx._callSiteFetch,\n fetch: ctx._callSiteFetch ?? userCtx.fetch ?? ctx.fetch,\n result:\n userCtx.result !== undefined\n ? userCtx.result\n : userCtx instanceof Response\n ? userCtx\n : (ctx as any).result,\n error: userCtx.error ?? (ctx as any).error,\n }\n\n const result = await callNextMiddleware(nextCtx)\n\n if (result.error) {\n throw result.error\n }\n\n return result\n }\n\n // Execute the middleware\n const result = await middlewareFn({\n ...ctx,\n next: userNext,\n })\n\n // If result is NOT a ctx object, we need to return it as\n // the { result }\n if (isRedirect(result)) {\n return {\n ...ctx,\n error: result,\n }\n }\n\n if (result instanceof Response) {\n return {\n ...ctx,\n result,\n }\n }\n\n if (!(result as any)) {\n throw new Error(\n 'User middleware returned undefined. You must call next() or return a result in your middlewares.',\n )\n }\n\n return result\n }\n\n return callNextMiddleware(ctx)\n } catch (error: any) {\n return {\n ...ctx,\n error,\n }\n }\n }\n\n // Start the middleware chain\n return callNextMiddleware({\n ...opts,\n headers: opts.headers || {},\n sendContext: opts.sendContext || {},\n context: opts.context || createNullProtoObject(),\n _callSiteFetch: opts.fetch,\n })\n}\n\nexport type CompiledFetcherFnOptions = {\n method: Method\n data: unknown\n headers?: HeadersInit\n signal?: AbortSignal\n fetch?: CustomFetch\n context?: any\n}\n\nexport type Fetcher<TMiddlewares, TInputValidator, TResponse> =\n undefined extends IntersectAllValidatorInputs<TMiddlewares, TInputValidator>\n ? OptionalFetcher<TMiddlewares, TInputValidator, TResponse>\n : RequiredFetcher<TMiddlewares, TInputValidator, TResponse>\n\nexport interface FetcherBase {\n [TSS_SERVER_FUNCTION]: true\n url: string\n method: Method\n __executeServer: (opts: {\n method: Method\n data: unknown\n headers?: HeadersInit\n context?: any\n }) => Promise<unknown>\n}\n\nexport interface OptionalFetcher<\n TMiddlewares,\n TInputValidator,\n TResponse,\n> extends FetcherBase {\n (\n options?: OptionalFetcherDataOptions<TMiddlewares, TInputValidator>,\n ): Promise<Awaited<TResponse>>\n}\n\nexport interface RequiredFetcher<\n TMiddlewares,\n TInputValidator,\n TResponse,\n> extends FetcherBase {\n (\n opts: RequiredFetcherDataOptions<TMiddlewares, TInputValidator>,\n ): Promise<Awaited<TResponse>>\n}\n\n// Ideally, this type should just be `export type CustomFetch = typeof globalThis.fetch`, but that conflicts with the type overrides the `bun-types` package - a dependency of unplugin.\n// Relevant bun issues:\n// - https://github.com/oven-sh/bun/issues/23500\n// - https://github.com/oven-sh/bun/issues/23741\nexport type CustomFetch = typeof fetch extends (...args: infer A) => infer R\n ? (...args: A) => R\n : never\n\nexport type FetcherBaseOptions = {\n headers?: HeadersInit\n signal?: AbortSignal\n fetch?: CustomFetch\n}\n\nexport interface OptionalFetcherDataOptions<\n TMiddlewares,\n TInputValidator,\n> extends FetcherBaseOptions {\n data?: Expand<IntersectAllValidatorInputs<TMiddlewares, TInputValidator>>\n}\n\nexport interface RequiredFetcherDataOptions<\n TMiddlewares,\n TInputValidator,\n> extends FetcherBaseOptions {\n data: Expand<IntersectAllValidatorInputs<TMiddlewares, TInputValidator>>\n}\n\nexport type RscStream<T> = {\n __cacheState: T\n}\n\nexport type Method = 'GET' | 'POST'\n\nexport type ServerFnReturnType<TRegister, TResponse> =\n TResponse extends PromiseLike<infer U>\n ? Promise<ServerFnReturnType<TRegister, U>>\n : TResponse extends Response\n ? TResponse\n : ValidateSerializableInput<TRegister, TResponse>\n\nexport type ServerFn<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TResponse,\n> = (\n ctx: ServerFnCtx<TRegister, TMethod, TMiddlewares, TInputValidator>,\n) => ServerFnReturnType<TRegister, TResponse>\n\nexport interface ServerFnCtx<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n> {\n data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TInputValidator>>\n serverFnMeta: ServerFnMeta\n context: Expand<AssignAllServerFnContext<TRegister, TMiddlewares, {}>>\n method: TMethod\n}\n\nexport type CompiledFetcherFn<TRegister, TResponse> = {\n (\n opts: CompiledFetcherFnOptions & ServerFnBaseOptions<TRegister, Method>,\n ): Promise<TResponse>\n url: string\n serverFnMeta: ServerFnMeta\n}\n\nexport type ServerFnBaseOptions<\n TRegister,\n TMethod extends Method = 'GET',\n TResponse = unknown,\n TMiddlewares = unknown,\n TInputValidator = unknown,\n> = {\n method: TMethod\n middleware?: Constrain<\n TMiddlewares,\n ReadonlyArray<AnyFunctionMiddleware | AnyRequestMiddleware>\n >\n inputValidator?: ConstrainValidator<TRegister, TMethod, TInputValidator>\n extractedFn?: CompiledFetcherFn<TRegister, TResponse>\n serverFn?: ServerFn<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TResponse\n >\n}\n\nexport type ValidateValidatorInput<\n TRegister,\n TMethod extends Method,\n TInputValidator,\n> = TMethod extends 'POST'\n ? ResolveValidatorInput<TInputValidator> extends FormData\n ? ResolveValidatorInput<TInputValidator>\n : ValidateSerializable<\n ResolveValidatorInput<TInputValidator>,\n RegisteredSerializableInput<TRegister>\n >\n : ValidateSerializable<\n ResolveValidatorInput<TInputValidator>,\n RegisteredSerializableInput<TRegister>\n >\n\nexport type ValidateValidator<\n TRegister,\n TMethod extends Method,\n TInputValidator,\n> =\n ValidateValidatorInput<\n TRegister,\n TMethod,\n TInputValidator\n > extends infer TInput\n ? Validator<TInput, any>\n : never\n\nexport type ConstrainValidator<\n TRegister,\n TMethod extends Method,\n TInputValidator,\n> =\n | (unknown extends TInputValidator\n ? TInputValidator\n : ResolveValidatorInput<TInputValidator> extends ValidateValidator<\n TRegister,\n TMethod,\n TInputValidator\n >\n ? TInputValidator\n : never)\n | ValidateValidator<TRegister, TMethod, TInputValidator>\n\nexport type AppendMiddlewares<TMiddlewares, TNewMiddlewares> =\n TMiddlewares extends ReadonlyArray<any>\n ? TNewMiddlewares extends ReadonlyArray<any>\n ? readonly [...TMiddlewares, ...TNewMiddlewares]\n : TMiddlewares\n : TNewMiddlewares\n\nexport interface ServerFnMiddleware<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n> {\n middleware: <const TNewMiddlewares>(\n middlewares: Constrain<\n TNewMiddlewares,\n ReadonlyArray<AnyFunctionMiddleware | AnyRequestMiddleware | AnyServerFn>\n >,\n ) => ServerFnAfterMiddleware<\n TRegister,\n TMethod,\n AppendMiddlewares<TMiddlewares, TNewMiddlewares>,\n TInputValidator\n >\n}\n\nexport interface ServerFnAfterMiddleware<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n undefined\n >,\n ServerFnMiddleware<TRegister, TMethod, TMiddlewares, undefined>,\n ServerFnValidator<TRegister, TMethod, TMiddlewares>,\n ServerFnHandler<TRegister, TMethod, TMiddlewares, TInputValidator> {\n <TNewMethod extends Method = TMethod>(options?: {\n method?: TNewMethod\n }): ServerFnAfterMiddleware<\n TRegister,\n TNewMethod,\n TMiddlewares,\n TInputValidator\n >\n}\n\nexport type ValidatorFn<TRegister, TMethod extends Method, TMiddlewares> = <\n TInputValidator,\n>(\n inputValidator: ConstrainValidator<TRegister, TMethod, TInputValidator>,\n) => ServerFnAfterValidator<TRegister, TMethod, TMiddlewares, TInputValidator>\n\nexport interface ServerFnValidator<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n> {\n inputValidator: ValidatorFn<TRegister, TMethod, TMiddlewares>\n}\n\nexport interface ServerFnAfterValidator<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n undefined\n >,\n ServerFnMiddleware<TRegister, TMethod, TMiddlewares, TInputValidator>,\n ServerFnHandler<TRegister, TMethod, TMiddlewares, TInputValidator> {}\n\nexport interface ServerFnAfterTyper<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n undefined\n >,\n ServerFnHandler<TRegister, TMethod, TMiddlewares, TInputValidator> {}\n\n// Handler\nexport interface ServerFnHandler<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n> {\n handler: <TNewResponse>(\n fn?: ServerFn<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TNewResponse\n >,\n ) => Fetcher<TMiddlewares, TInputValidator, TNewResponse>\n}\n\nexport interface ServerFnBuilder<TRegister, TMethod extends Method = 'GET'>\n extends\n ServerFnWithTypes<TRegister, TMethod, undefined, undefined, undefined>,\n ServerFnMiddleware<TRegister, TMethod, undefined, undefined>,\n ServerFnValidator<TRegister, TMethod, undefined>,\n ServerFnHandler<TRegister, TMethod, undefined, undefined> {\n options: ServerFnBaseOptions<\n TRegister,\n TMethod,\n unknown,\n undefined,\n undefined\n >\n}\n\nexport interface ServerFnWithTypes<\n in out TRegister,\n in out TMethod extends Method,\n in out TMiddlewares,\n in out TInputValidator,\n in out TResponse,\n> {\n '~types': ServerFnTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TResponse\n >\n options: ServerFnBaseOptions<\n TRegister,\n TMethod,\n unknown,\n undefined,\n undefined\n >\n [TSS_SERVER_FUNCTION_FACTORY]: true\n}\n\nexport type AnyServerFn = ServerFnWithTypes<any, any, any, any, any>\n\nexport interface ServerFnTypes<\n in out TRegister,\n in out TMethod extends Method,\n in out TMiddlewares,\n in out TInputValidator,\n in out TResponse,\n> {\n method: TMethod\n middlewares: TMiddlewares\n inputValidator: TInputValidator\n response: TResponse\n allServerContext: AssignAllServerFnContext<TRegister, TMiddlewares>\n allInput: IntersectAllValidatorInputs<TMiddlewares, TInputValidator>\n allOutput: IntersectAllValidatorOutputs<TMiddlewares, TInputValidator>\n}\n\nexport function flattenMiddlewares<\n T extends AnyFunctionMiddleware | AnyRequestMiddleware,\n>(middlewares: Array<T>, maxDepth: number = 100): Array<T> {\n const seen = new Set<T>()\n const flattened: Array<T> = []\n\n const recurse = (middleware: Array<T>, depth: number) => {\n if (depth > maxDepth) {\n throw new Error(\n `Middleware nesting depth exceeded maximum of ${maxDepth}. Check for circular references.`,\n )\n }\n middleware.forEach((m) => {\n if (m.options.middleware) {\n recurse(m.options.middleware as Array<T>, depth + 1)\n }\n\n if (!seen.has(m)) {\n seen.add(m)\n flattened.push(m)\n }\n })\n }\n\n recurse(middlewares, 0)\n\n return flattened\n}\n\nexport type ServerFnMiddlewareOptions = {\n method: Method\n data: any\n headers?: HeadersInit\n signal?: AbortSignal\n sendContext?: any\n context?: any\n serverFnMeta: ClientFnMeta\n fetch?: CustomFetch\n /** @internal - Preserves the call-site fetch to ensure it has highest priority over middleware */\n _callSiteFetch?: CustomFetch\n}\n\nexport type ServerFnMiddlewareResult = ServerFnMiddlewareOptions & {\n result?: unknown\n error?: unknown\n}\n\nexport type NextFn = (\n ctx: ServerFnMiddlewareResult,\n) => Promise<ServerFnMiddlewareResult>\n\nexport type MiddlewareFn = (\n ctx: ServerFnMiddlewareOptions & {\n next: NextFn\n },\n) => Promise<ServerFnMiddlewareResult>\n\nexport async function execValidator(\n validator: AnyValidator,\n input: unknown,\n): Promise<unknown> {\n if (validator == null) return {}\n\n if ('~standard' in validator) {\n const result = await validator['~standard'].validate(input)\n\n if (result.issues)\n throw new Error(JSON.stringify(result.issues, undefined, 2))\n\n return result.value\n }\n\n if ('parse' in validator) {\n return validator.parse(input)\n }\n\n if (typeof validator === 'function') {\n return validator(input)\n }\n\n throw new Error('Invalid validator type!')\n}\n\nfunction serverFnBaseToMiddleware(\n options: ServerFnBaseOptions<any, any, any, any, any>,\n): AnyFunctionMiddleware {\n return {\n '~types': undefined!,\n options: {\n inputValidator: options.inputValidator,\n client: async ({ next, sendContext, fetch, ...ctx }) => {\n const payload = {\n ...ctx,\n // switch the sendContext over to context\n context: sendContext,\n fetch,\n } as any\n\n // Execute the extracted function\n // but not before serializing the context\n const res = await options.extractedFn?.(payload)\n\n return next(res)\n },\n server: async ({ next, ...ctx }) => {\n // Execute the server function\n const result = await options.serverFn?.(ctx as TODO)\n\n return next({\n ...ctx,\n result,\n } as any) as unknown as FunctionMiddlewareServerFnResult<\n any,\n any,\n any,\n any,\n any\n >\n },\n },\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"createServerFn.js","names":[],"sources":["../../src/createServerFn.ts"],"sourcesContent":["import { mergeHeaders } from '@tanstack/router-core/ssr/client'\n\nimport { isRedirect, parseRedirect } from '@tanstack/router-core'\nimport { TSS_SERVER_FUNCTION_FACTORY } from './constants'\nimport { getStartOptions } from './getStartOptions'\nimport { getStartContextServerOnly } from './getStartContextServerOnly'\nimport { createNullProtoObject, safeObjectMerge } from './safeObjectMerge'\nimport type {\n ClientFnMeta,\n ServerFnMeta,\n TSS_SERVER_FUNCTION,\n} from './constants'\nimport type {\n AnyValidator,\n Constrain,\n Expand,\n Register,\n RegisteredSerializableInput,\n ResolveValidatorInput,\n ValidateSerializable,\n ValidateSerializableInput,\n Validator,\n} from '@tanstack/router-core'\nimport type {\n AnyFunctionMiddleware,\n AnyRequestMiddleware,\n AssignAllServerFnContext,\n FunctionMiddlewareServerFnResult,\n IntersectAllValidatorInputs,\n IntersectAllValidatorOutputs,\n} from './createMiddleware'\n\ntype TODO = any\n\nexport type ServerFnStrict = boolean | { input?: boolean; output?: boolean }\n\nexport interface ServerFnOptions<\n TMethod extends Method = Method,\n TStrict extends ServerFnStrict = true,\n> {\n method?: TMethod\n strict?: TStrict\n}\n\nexport type ServerFnStrictInput<TStrict extends ServerFnStrict> =\n TStrict extends false\n ? false\n : TStrict extends { input: infer TInput extends boolean }\n ? TInput\n : true\n\nexport type ServerFnStrictOutput<TStrict extends ServerFnStrict> =\n TStrict extends false\n ? false\n : TStrict extends { output: infer TOutput extends boolean }\n ? TOutput\n : true\n\nexport type CreateServerFn<TRegister> = <\n TMethod extends Method,\n TStrict extends ServerFnStrict = true,\n TResponse = unknown,\n TMiddlewares = undefined,\n TInputValidator = undefined,\n>(\n options?: ServerFnOptions<TMethod, TStrict>,\n __opts?: ServerFnBaseOptions<\n TRegister,\n TMethod,\n TResponse,\n TMiddlewares,\n TInputValidator,\n TStrict\n >,\n) => ServerFnBuilder<TRegister, TMethod, TStrict>\n\nexport const createServerFn: CreateServerFn<Register> = (options, __opts) => {\n const resolvedOptions = (__opts || options || {}) as ServerFnBaseOptions<\n any,\n any,\n any,\n any,\n any,\n any\n >\n\n if (typeof resolvedOptions.method === 'undefined') {\n resolvedOptions.method = 'GET' as Method\n }\n\n const res: ServerFnBuilder<Register, Method, ServerFnStrict> = {\n options: resolvedOptions,\n middleware: (middleware) => {\n // multiple calls to `middleware()` merge the middlewares with the previously supplied ones\n // this is primarily useful for letting users create their own abstractions on top of `createServerFn`\n\n const newMiddleware = [...(resolvedOptions.middleware || [])]\n middleware.map((m) => {\n if (TSS_SERVER_FUNCTION_FACTORY in m) {\n if (m.options.middleware) {\n newMiddleware.push(...m.options.middleware)\n }\n } else {\n newMiddleware.push(m)\n }\n })\n\n const newOptions = {\n ...resolvedOptions,\n middleware: newMiddleware,\n }\n const res = createServerFn(undefined, newOptions) as any\n res[TSS_SERVER_FUNCTION_FACTORY] = true\n return res\n },\n inputValidator: (inputValidator) => {\n const newOptions = { ...resolvedOptions, inputValidator }\n return createServerFn(undefined, newOptions) as any\n },\n handler: (...args) => {\n // This function signature changes due to AST transformations\n // in the babel plugin. We need to cast it to the correct\n // function signature post-transformation\n const [extractedFn, serverFn] = args as unknown as [\n CompiledFetcherFn<Register, any>,\n ServerFn<Register, Method, any, any, any>,\n ]\n\n // Keep the original function around so we can use it\n // in the server environment\n const newOptions = { ...resolvedOptions, extractedFn, serverFn }\n\n const resolvedMiddleware = [\n ...(newOptions.middleware || []),\n serverFnBaseToMiddleware(newOptions),\n ]\n\n // We want to make sure the new function has the same\n // properties as the original function\n\n // Propagate the declared HTTP method onto the extracted handler\n // so the manifest-exported symbol (resolved by getServerFnById)\n // carries `method`, enabling the server handler to reject\n // mismatched HTTP methods before parsing request payloads.\n ;(extractedFn as any).method = resolvedOptions.method\n\n return Object.assign(\n async (opts?: CompiledFetcherFnOptions) => {\n // Start by executing the client-side middleware chain\n const result = await executeMiddleware(resolvedMiddleware, 'client', {\n ...extractedFn,\n ...newOptions,\n data: opts?.data as any,\n headers: opts?.headers,\n signal: opts?.signal,\n fetch: opts?.fetch,\n context: createNullProtoObject(),\n })\n\n const redirect = parseRedirect(result.error)\n if (redirect) {\n throw redirect\n }\n\n if (result.error) throw result.error\n return result.result\n },\n {\n // This copies over the URL, function ID\n ...extractedFn,\n // Expose the declared HTTP method so the server handler\n // can reject mismatched methods before parsing payloads\n method: resolvedOptions.method,\n // The extracted function on the server-side calls\n // this function\n __executeServer: async (opts: any) => {\n const startContext = getStartContextServerOnly()\n const serverContextAfterGlobalMiddlewares =\n startContext.contextAfterGlobalMiddlewares\n const ctx = {\n ...extractedFn,\n ...opts,\n // Ensure we use the full serverFnMeta from the provider file's extractedFn\n // (which has id, name, filename) rather than the partial one from SSR/client\n // callers (which only has id)\n serverFnMeta: extractedFn.serverFnMeta,\n // Merge client context first so trusted server middleware context wins.\n context: safeObjectMerge(\n opts.context,\n serverContextAfterGlobalMiddlewares,\n ),\n request: startContext.request,\n }\n\n const result = await executeMiddleware(\n resolvedMiddleware,\n 'server',\n ctx,\n ).then((d) => ({\n // Only send the result and sendContext back to the client\n result: d.result,\n error: d.error,\n context: d.sendContext,\n }))\n\n return result\n },\n },\n ) as any\n },\n } as ServerFnBuilder<Register, Method, ServerFnStrict>\n const fun = (options?: ServerFnOptions<Method, ServerFnStrict>) => {\n const newOptions = {\n ...resolvedOptions,\n ...options,\n }\n return createServerFn(undefined, newOptions) as any\n }\n return Object.assign(fun, res) as any\n}\n\nexport async function executeMiddleware(\n middlewares: Array<AnyFunctionMiddleware | AnyRequestMiddleware>,\n env: 'client' | 'server',\n opts: ServerFnMiddlewareOptions,\n): Promise<ServerFnMiddlewareResult> {\n const globalMiddlewares = getStartOptions()?.functionMiddleware || []\n let flattenedMiddlewares = flattenMiddlewares([\n ...globalMiddlewares,\n ...middlewares,\n ])\n\n // On server, filter out middlewares that already executed in the request phase\n // to prevent duplicate execution (issue #5239)\n if (env === 'server') {\n const startContext = getStartContextServerOnly({ throwIfNotFound: false })\n if (startContext?.executedRequestMiddlewares) {\n flattenedMiddlewares = flattenedMiddlewares.filter(\n (m) => !startContext.executedRequestMiddlewares.has(m),\n )\n }\n }\n\n const callNextMiddleware: NextFn = async (ctx) => {\n // Get the next middleware\n const nextMiddleware = flattenedMiddlewares.shift()\n\n // If there are no more middlewares, return the context\n if (!nextMiddleware) {\n return ctx\n }\n\n // Execute the middleware\n try {\n if (\n 'inputValidator' in nextMiddleware.options &&\n nextMiddleware.options.inputValidator &&\n env === 'server'\n ) {\n // Execute the middleware's input function\n ctx.data = await execValidator(\n nextMiddleware.options.inputValidator,\n ctx.data,\n )\n }\n\n let middlewareFn: MiddlewareFn | undefined = undefined\n if (env === 'client') {\n if ('client' in nextMiddleware.options) {\n middlewareFn = nextMiddleware.options.client as\n | MiddlewareFn\n | undefined\n }\n }\n // env === 'server'\n else if ('server' in nextMiddleware.options) {\n middlewareFn = nextMiddleware.options.server as MiddlewareFn | undefined\n }\n\n if (middlewareFn) {\n const userNext = async (\n userCtx: ServerFnMiddlewareResult | undefined = {} as any,\n ) => {\n // Return the next middleware\n // Use safeObjectMerge for context objects to prevent prototype pollution\n const nextCtx = {\n ...ctx,\n ...userCtx,\n context: safeObjectMerge(ctx.context, userCtx.context),\n sendContext: safeObjectMerge(ctx.sendContext, userCtx.sendContext),\n headers: mergeHeaders(ctx.headers, userCtx.headers),\n _callSiteFetch: ctx._callSiteFetch,\n fetch: ctx._callSiteFetch ?? userCtx.fetch ?? ctx.fetch,\n result:\n userCtx.result !== undefined\n ? userCtx.result\n : userCtx instanceof Response\n ? userCtx\n : (ctx as any).result,\n error: userCtx.error ?? (ctx as any).error,\n }\n\n const result = await callNextMiddleware(nextCtx)\n\n if (result.error) {\n throw result.error\n }\n\n return result\n }\n\n // Execute the middleware\n const result = await middlewareFn({\n ...ctx,\n next: userNext,\n })\n\n // If result is NOT a ctx object, we need to return it as\n // the { result }\n if (isRedirect(result)) {\n return {\n ...ctx,\n error: result,\n }\n }\n\n if (result instanceof Response) {\n return {\n ...ctx,\n result,\n }\n }\n\n if (!(result as any)) {\n throw new Error(\n 'User middleware returned undefined. You must call next() or return a result in your middlewares.',\n )\n }\n\n return result\n }\n\n return callNextMiddleware(ctx)\n } catch (error: any) {\n return {\n ...ctx,\n error,\n }\n }\n }\n\n // Start the middleware chain\n return callNextMiddleware({\n ...opts,\n headers: opts.headers || {},\n sendContext: opts.sendContext || {},\n context: opts.context || createNullProtoObject(),\n _callSiteFetch: opts.fetch,\n })\n}\n\nexport type CompiledFetcherFnOptions = {\n method: Method\n data: unknown\n headers?: HeadersInit\n signal?: AbortSignal\n fetch?: CustomFetch\n context?: any\n}\n\nexport type Fetcher<TMiddlewares, TInputValidator, TResponse> =\n undefined extends IntersectAllValidatorInputs<TMiddlewares, TInputValidator>\n ? OptionalFetcher<TMiddlewares, TInputValidator, TResponse>\n : RequiredFetcher<TMiddlewares, TInputValidator, TResponse>\n\nexport interface FetcherBase {\n [TSS_SERVER_FUNCTION]: true\n url: string\n method: Method\n __executeServer: (opts: {\n method: Method\n data: unknown\n headers?: HeadersInit\n context?: any\n }) => Promise<unknown>\n}\n\nexport interface OptionalFetcher<\n TMiddlewares,\n TInputValidator,\n TResponse,\n> extends FetcherBase {\n (\n options?: OptionalFetcherDataOptions<TMiddlewares, TInputValidator>,\n ): Promise<Awaited<TResponse>>\n}\n\nexport interface RequiredFetcher<\n TMiddlewares,\n TInputValidator,\n TResponse,\n> extends FetcherBase {\n (\n opts: RequiredFetcherDataOptions<TMiddlewares, TInputValidator>,\n ): Promise<Awaited<TResponse>>\n}\n\n// Ideally, this type should just be `export type CustomFetch = typeof globalThis.fetch`, but that conflicts with the type overrides the `bun-types` package - a dependency of unplugin.\n// Relevant bun issues:\n// - https://github.com/oven-sh/bun/issues/23500\n// - https://github.com/oven-sh/bun/issues/23741\nexport type CustomFetch = typeof fetch extends (...args: infer A) => infer R\n ? (...args: A) => R\n : never\n\nexport type FetcherBaseOptions = {\n headers?: HeadersInit\n signal?: AbortSignal\n fetch?: CustomFetch\n}\n\nexport interface OptionalFetcherDataOptions<\n TMiddlewares,\n TInputValidator,\n> extends FetcherBaseOptions {\n data?: Expand<IntersectAllValidatorInputs<TMiddlewares, TInputValidator>>\n}\n\nexport interface RequiredFetcherDataOptions<\n TMiddlewares,\n TInputValidator,\n> extends FetcherBaseOptions {\n data: Expand<IntersectAllValidatorInputs<TMiddlewares, TInputValidator>>\n}\n\nexport type RscStream<T> = {\n __cacheState: T\n}\n\nexport type Method = 'GET' | 'POST'\n\nexport type ServerFnReturnType<\n TRegister,\n TResponse,\n TStrict extends ServerFnStrict = true,\n> =\n ServerFnStrictOutput<TStrict> extends false\n ? TResponse\n : TResponse extends PromiseLike<infer U>\n ? Promise<ServerFnReturnType<TRegister, U, TStrict>>\n : TResponse extends Response\n ? TResponse\n : ValidateSerializableInput<TRegister, TResponse>\n\nexport type ServerFn<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TResponse,\n TStrict extends ServerFnStrict = true,\n> = (\n ctx: ServerFnCtx<TRegister, TMethod, TMiddlewares, TInputValidator>,\n) => ServerFnReturnType<TRegister, TResponse, TStrict>\n\nexport interface ServerFnCtx<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n> {\n data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TInputValidator>>\n serverFnMeta: ServerFnMeta\n context: Expand<AssignAllServerFnContext<TRegister, TMiddlewares, {}>>\n method: TMethod\n}\n\nexport type CompiledFetcherFn<TRegister, TResponse> = {\n (\n opts: CompiledFetcherFnOptions & ServerFnBaseOptions<TRegister, Method>,\n ): Promise<TResponse>\n url: string\n serverFnMeta: ServerFnMeta\n}\n\nexport type ServerFnBaseOptions<\n TRegister,\n TMethod extends Method = 'GET',\n TResponse = unknown,\n TMiddlewares = unknown,\n TInputValidator = unknown,\n TStrict extends ServerFnStrict = true,\n> = {\n method: TMethod\n strict?: TStrict\n middleware?: Constrain<\n TMiddlewares,\n ReadonlyArray<AnyFunctionMiddleware | AnyRequestMiddleware>\n >\n inputValidator?: ConstrainValidator<\n TRegister,\n TMethod,\n TInputValidator,\n TStrict\n >\n extractedFn?: CompiledFetcherFn<TRegister, TResponse>\n serverFn?: ServerFn<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TResponse,\n TStrict\n >\n}\n\nexport type ValidateValidatorInput<\n TRegister,\n TMethod extends Method,\n TInputValidator,\n TStrict extends ServerFnStrict = true,\n> =\n ServerFnStrictInput<TStrict> extends false\n ? ResolveValidatorInput<TInputValidator>\n : TMethod extends 'POST'\n ? ResolveValidatorInput<TInputValidator> extends FormData\n ? ResolveValidatorInput<TInputValidator>\n : ValidateSerializable<\n ResolveValidatorInput<TInputValidator>,\n RegisteredSerializableInput<TRegister>\n >\n : ValidateSerializable<\n ResolveValidatorInput<TInputValidator>,\n RegisteredSerializableInput<TRegister>\n >\n\nexport type ValidateValidator<\n TRegister,\n TMethod extends Method,\n TInputValidator,\n TStrict extends ServerFnStrict = true,\n> =\n ValidateValidatorInput<\n TRegister,\n TMethod,\n TInputValidator,\n TStrict\n > extends infer TInput\n ? Validator<TInput, any>\n : never\n\nexport type ConstrainValidator<\n TRegister,\n TMethod extends Method,\n TInputValidator,\n TStrict extends ServerFnStrict = true,\n> =\n | (unknown extends TInputValidator\n ? TInputValidator\n : ResolveValidatorInput<TInputValidator> extends ValidateValidator<\n TRegister,\n TMethod,\n TInputValidator,\n TStrict\n >\n ? TInputValidator\n : never)\n | ValidateValidator<TRegister, TMethod, TInputValidator, TStrict>\n\nexport type AppendMiddlewares<TMiddlewares, TNewMiddlewares> =\n TMiddlewares extends ReadonlyArray<any>\n ? TNewMiddlewares extends ReadonlyArray<any>\n ? readonly [...TMiddlewares, ...TNewMiddlewares]\n : TMiddlewares\n : TNewMiddlewares\n\nexport interface ServerFnMiddleware<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n> {\n middleware: <const TNewMiddlewares>(\n middlewares: Constrain<\n TNewMiddlewares,\n ReadonlyArray<AnyFunctionMiddleware | AnyRequestMiddleware | AnyServerFn>\n >,\n ) => ServerFnAfterMiddleware<\n TRegister,\n TMethod,\n AppendMiddlewares<TMiddlewares, TNewMiddlewares>,\n TInputValidator,\n TStrict\n >\n}\n\nexport interface ServerFnAfterMiddleware<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n undefined,\n TStrict\n >,\n ServerFnMiddleware<TRegister, TMethod, TMiddlewares, undefined, TStrict>,\n ServerFnValidator<TRegister, TMethod, TMiddlewares, TStrict>,\n ServerFnHandler<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n > {\n <\n TNewMethod extends Method = TMethod,\n TNewStrict extends ServerFnStrict = TStrict,\n >(\n options?: ServerFnOptions<TNewMethod, TNewStrict>,\n ): ServerFnAfterMiddleware<\n TRegister,\n TNewMethod,\n TMiddlewares,\n TInputValidator,\n TNewStrict\n >\n}\n\nexport type ValidatorFn<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TStrict extends ServerFnStrict,\n> = <TInputValidator>(\n inputValidator: ConstrainValidator<\n TRegister,\n TMethod,\n TInputValidator,\n TStrict\n >,\n) => ServerFnAfterValidator<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n>\n\nexport interface ServerFnValidator<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TStrict extends ServerFnStrict,\n> {\n inputValidator: ValidatorFn<TRegister, TMethod, TMiddlewares, TStrict>\n}\n\nexport interface ServerFnAfterValidator<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n undefined,\n TStrict\n >,\n ServerFnMiddleware<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n >,\n ServerFnHandler<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n > {}\n\nexport interface ServerFnAfterTyper<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n undefined,\n TStrict\n >,\n ServerFnHandler<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TStrict\n > {}\n\n// Handler\nexport interface ServerFnHandler<\n TRegister,\n TMethod extends Method,\n TMiddlewares,\n TInputValidator,\n TStrict extends ServerFnStrict,\n> {\n handler: <TNewResponse>(\n fn?: ServerFn<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TNewResponse,\n TStrict\n >,\n ) => Fetcher<TMiddlewares, TInputValidator, TNewResponse>\n}\n\nexport interface ServerFnBuilder<\n TRegister,\n TMethod extends Method = 'GET',\n TStrict extends ServerFnStrict = true,\n>\n extends\n ServerFnWithTypes<\n TRegister,\n TMethod,\n undefined,\n undefined,\n undefined,\n TStrict\n >,\n ServerFnMiddleware<TRegister, TMethod, undefined, undefined, TStrict>,\n ServerFnValidator<TRegister, TMethod, undefined, TStrict>,\n ServerFnHandler<TRegister, TMethod, undefined, undefined, TStrict> {\n <\n TNewMethod extends Method = TMethod,\n TNewStrict extends ServerFnStrict = TStrict,\n >(\n options?: ServerFnOptions<TNewMethod, TNewStrict>,\n ): ServerFnBuilder<TRegister, TNewMethod, TNewStrict>\n options: ServerFnBaseOptions<\n TRegister,\n TMethod,\n unknown,\n undefined,\n undefined,\n TStrict\n >\n}\n\nexport interface ServerFnWithTypes<\n in out TRegister,\n in out TMethod extends Method,\n in out TMiddlewares,\n in out TInputValidator,\n in out TResponse,\n in out TStrict extends ServerFnStrict,\n> {\n '~types': ServerFnTypes<\n TRegister,\n TMethod,\n TMiddlewares,\n TInputValidator,\n TResponse,\n TStrict\n >\n options: ServerFnBaseOptions<\n TRegister,\n TMethod,\n unknown,\n undefined,\n undefined,\n TStrict\n >\n [TSS_SERVER_FUNCTION_FACTORY]: true\n}\n\nexport type AnyServerFn = ServerFnWithTypes<any, any, any, any, any, any>\n\nexport interface ServerFnTypes<\n in out TRegister,\n in out TMethod extends Method,\n in out TMiddlewares,\n in out TInputValidator,\n in out TResponse,\n in out TStrict extends ServerFnStrict,\n> {\n method: TMethod\n strict: TStrict\n middlewares: TMiddlewares\n inputValidator: TInputValidator\n response: TResponse\n allServerContext: AssignAllServerFnContext<TRegister, TMiddlewares>\n allInput: IntersectAllValidatorInputs<TMiddlewares, TInputValidator>\n allOutput: IntersectAllValidatorOutputs<TMiddlewares, TInputValidator>\n}\n\nexport function flattenMiddlewares<\n T extends AnyFunctionMiddleware | AnyRequestMiddleware,\n>(middlewares: Array<T>, maxDepth: number = 100): Array<T> {\n const seen = new Set<T>()\n const flattened: Array<T> = []\n\n const recurse = (middleware: Array<T>, depth: number) => {\n if (depth > maxDepth) {\n throw new Error(\n `Middleware nesting depth exceeded maximum of ${maxDepth}. Check for circular references.`,\n )\n }\n middleware.forEach((m) => {\n if (m.options.middleware) {\n recurse(m.options.middleware as Array<T>, depth + 1)\n }\n\n if (!seen.has(m)) {\n seen.add(m)\n flattened.push(m)\n }\n })\n }\n\n recurse(middlewares, 0)\n\n return flattened\n}\n\nexport type ServerFnMiddlewareOptions = {\n method: Method\n data: any\n headers?: HeadersInit\n signal?: AbortSignal\n sendContext?: any\n context?: any\n serverFnMeta: ClientFnMeta\n fetch?: CustomFetch\n /** @internal - Preserves the call-site fetch to ensure it has highest priority over middleware */\n _callSiteFetch?: CustomFetch\n}\n\nexport type ServerFnMiddlewareResult = ServerFnMiddlewareOptions & {\n result?: unknown\n error?: unknown\n}\n\nexport type NextFn = (\n ctx: ServerFnMiddlewareResult,\n) => Promise<ServerFnMiddlewareResult>\n\nexport type MiddlewareFn = (\n ctx: ServerFnMiddlewareOptions & {\n next: NextFn\n },\n) => Promise<ServerFnMiddlewareResult>\n\nexport async function execValidator(\n validator: AnyValidator,\n input: unknown,\n): Promise<unknown> {\n if (validator == null) return {}\n\n if ('~standard' in validator) {\n const result = await validator['~standard'].validate(input)\n\n if (result.issues)\n throw new Error(JSON.stringify(result.issues, undefined, 2))\n\n return result.value\n }\n\n if ('parse' in validator) {\n return validator.parse(input)\n }\n\n if (typeof validator === 'function') {\n return validator(input)\n }\n\n throw new Error('Invalid validator type!')\n}\n\nfunction serverFnBaseToMiddleware(\n options: ServerFnBaseOptions<any, any, any, any, any>,\n): AnyFunctionMiddleware {\n return {\n '~types': undefined!,\n options: {\n inputValidator: options.inputValidator,\n client: async ({ next, sendContext, fetch, ...ctx }) => {\n const payload = {\n ...ctx,\n // switch the sendContext over to context\n context: sendContext,\n fetch,\n } as any\n\n // Execute the extracted function\n // but not before serializing the context\n const res = await options.extractedFn?.(payload)\n\n return next(res)\n },\n server: async ({ next, ...ctx }) => {\n // Execute the server function\n const result = await options.serverFn?.(ctx as TODO)\n\n return next({\n ...ctx,\n result,\n } as any) as unknown as FunctionMiddlewareServerFnResult<\n any,\n any,\n any,\n any,\n any\n >\n },\n },\n }\n}\n"],"mappings":";;;;;;;AA4EA,IAAa,kBAA4C,SAAS,WAAW;CAC3E,MAAM,kBAAmB,UAAU,WAAW,EAAE;AAShD,KAAI,OAAO,gBAAgB,WAAW,YACpC,iBAAgB,SAAS;CAG3B,MAAM,MAAyD;EAC7D,SAAS;EACT,aAAa,eAAe;GAI1B,MAAM,gBAAgB,CAAC,GAAI,gBAAgB,cAAc,EAAE,CAAE;AAC7D,cAAW,KAAK,MAAM;AACpB,QAAI,+BAA+B;SAC7B,EAAE,QAAQ,WACZ,eAAc,KAAK,GAAG,EAAE,QAAQ,WAAW;UAG7C,eAAc,KAAK,EAAE;KAEvB;GAMF,MAAM,MAAM,eAAe,KAAA,GAJR;IACjB,GAAG;IACH,YAAY;IACb,CACgD;AACjD,OAAI,+BAA+B;AACnC,UAAO;;EAET,iBAAiB,mBAAmB;AAElC,UAAO,eAAe,KAAA,GADH;IAAE,GAAG;IAAiB;IAAgB,CACb;;EAE9C,UAAU,GAAG,SAAS;GAIpB,MAAM,CAAC,aAAa,YAAY;GAOhC,MAAM,aAAa;IAAE,GAAG;IAAiB;IAAa;IAAU;GAEhE,MAAM,qBAAqB,CACzB,GAAI,WAAW,cAAc,EAAE,EAC/B,yBAAyB,WAAW,CACrC;AASC,eAAoB,SAAS,gBAAgB;AAE/C,UAAO,OAAO,OACZ,OAAO,SAAoC;IAEzC,MAAM,SAAS,MAAM,kBAAkB,oBAAoB,UAAU;KACnE,GAAG;KACH,GAAG;KACH,MAAM,MAAM;KACZ,SAAS,MAAM;KACf,QAAQ,MAAM;KACd,OAAO,MAAM;KACb,SAAS,uBAAuB;KACjC,CAAC;IAEF,MAAM,WAAW,cAAc,OAAO,MAAM;AAC5C,QAAI,SACF,OAAM;AAGR,QAAI,OAAO,MAAO,OAAM,OAAO;AAC/B,WAAO,OAAO;MAEhB;IAEE,GAAG;IAGH,QAAQ,gBAAgB;IAGxB,iBAAiB,OAAO,SAAc;KACpC,MAAM,eAAe,2BAA2B;KAChD,MAAM,sCACJ,aAAa;AA2Bf,YAXe,MAAM,kBACnB,oBACA,UAjBU;MACV,GAAG;MACH,GAAG;MAIH,cAAc,YAAY;MAE1B,SAAS,gBACP,KAAK,SACL,oCACD;MACD,SAAS,aAAa;MACvB,CAMA,CAAC,MAAM,OAAO;MAEb,QAAQ,EAAE;MACV,OAAO,EAAE;MACT,SAAS,EAAE;MACZ,EAAE;;IAIN,CACF;;EAEJ;CACD,MAAM,OAAO,YAAsD;AAKjE,SAAO,eAAe,KAAA,GAJH;GACjB,GAAG;GACH,GAAG;GACJ,CAC2C;;AAE9C,QAAO,OAAO,OAAO,KAAK,IAAI;;AAGhC,eAAsB,kBACpB,aACA,KACA,MACmC;CAEnC,IAAI,uBAAuB,mBAAmB,CAC5C,GAFwB,iBAAiB,EAAE,sBAAsB,EAAE,EAGnE,GAAG,YACJ,CAAC;AAIF,KAAI,QAAQ,UAAU;EACpB,MAAM,eAAe,0BAA0B,EAAE,iBAAiB,OAAO,CAAC;AAC1E,MAAI,cAAc,2BAChB,wBAAuB,qBAAqB,QACzC,MAAM,CAAC,aAAa,2BAA2B,IAAI,EAAE,CACvD;;CAIL,MAAM,qBAA6B,OAAO,QAAQ;EAEhD,MAAM,iBAAiB,qBAAqB,OAAO;AAGnD,MAAI,CAAC,eACH,QAAO;AAIT,MAAI;AACF,OACE,oBAAoB,eAAe,WACnC,eAAe,QAAQ,kBACvB,QAAQ,SAGR,KAAI,OAAO,MAAM,cACf,eAAe,QAAQ,gBACvB,IAAI,KACL;GAGH,IAAI,eAAyC,KAAA;AAC7C,OAAI,QAAQ;QACN,YAAY,eAAe,QAC7B,gBAAe,eAAe,QAAQ;cAMjC,YAAY,eAAe,QAClC,gBAAe,eAAe,QAAQ;AAGxC,OAAI,cAAc;IAChB,MAAM,WAAW,OACf,UAAgD,EAAE,KAC/C;KAoBH,MAAM,SAAS,MAAM,mBAjBL;MACd,GAAG;MACH,GAAG;MACH,SAAS,gBAAgB,IAAI,SAAS,QAAQ,QAAQ;MACtD,aAAa,gBAAgB,IAAI,aAAa,QAAQ,YAAY;MAClE,SAAS,aAAa,IAAI,SAAS,QAAQ,QAAQ;MACnD,gBAAgB,IAAI;MACpB,OAAO,IAAI,kBAAkB,QAAQ,SAAS,IAAI;MAClD,QACE,QAAQ,WAAW,KAAA,IACf,QAAQ,SACR,mBAAmB,WACjB,UACC,IAAY;MACrB,OAAO,QAAQ,SAAU,IAAY;MACtC,CAE+C;AAEhD,SAAI,OAAO,MACT,OAAM,OAAO;AAGf,YAAO;;IAIT,MAAM,SAAS,MAAM,aAAa;KAChC,GAAG;KACH,MAAM;KACP,CAAC;AAIF,QAAI,WAAW,OAAO,CACpB,QAAO;KACL,GAAG;KACH,OAAO;KACR;AAGH,QAAI,kBAAkB,SACpB,QAAO;KACL,GAAG;KACH;KACD;AAGH,QAAI,CAAE,OACJ,OAAM,IAAI,MACR,mGACD;AAGH,WAAO;;AAGT,UAAO,mBAAmB,IAAI;WACvB,OAAY;AACnB,UAAO;IACL,GAAG;IACH;IACD;;;AAKL,QAAO,mBAAmB;EACxB,GAAG;EACH,SAAS,KAAK,WAAW,EAAE;EAC3B,aAAa,KAAK,eAAe,EAAE;EACnC,SAAS,KAAK,WAAW,uBAAuB;EAChD,gBAAgB,KAAK;EACtB,CAAC;;AA8cJ,SAAgB,mBAEd,aAAuB,WAAmB,KAAe;CACzD,MAAM,uBAAO,IAAI,KAAQ;CACzB,MAAM,YAAsB,EAAE;CAE9B,MAAM,WAAW,YAAsB,UAAkB;AACvD,MAAI,QAAQ,SACV,OAAM,IAAI,MACR,gDAAgD,SAAS,kCAC1D;AAEH,aAAW,SAAS,MAAM;AACxB,OAAI,EAAE,QAAQ,WACZ,SAAQ,EAAE,QAAQ,YAAwB,QAAQ,EAAE;AAGtD,OAAI,CAAC,KAAK,IAAI,EAAE,EAAE;AAChB,SAAK,IAAI,EAAE;AACX,cAAU,KAAK,EAAE;;IAEnB;;AAGJ,SAAQ,aAAa,EAAE;AAEvB,QAAO;;AA+BT,eAAsB,cACpB,WACA,OACkB;AAClB,KAAI,aAAa,KAAM,QAAO,EAAE;AAEhC,KAAI,eAAe,WAAW;EAC5B,MAAM,SAAS,MAAM,UAAU,aAAa,SAAS,MAAM;AAE3D,MAAI,OAAO,OACT,OAAM,IAAI,MAAM,KAAK,UAAU,OAAO,QAAQ,KAAA,GAAW,EAAE,CAAC;AAE9D,SAAO,OAAO;;AAGhB,KAAI,WAAW,UACb,QAAO,UAAU,MAAM,MAAM;AAG/B,KAAI,OAAO,cAAc,WACvB,QAAO,UAAU,MAAM;AAGzB,OAAM,IAAI,MAAM,0BAA0B;;AAG5C,SAAS,yBACP,SACuB;AACvB,QAAO;EACL,UAAU,KAAA;EACV,SAAS;GACP,gBAAgB,QAAQ;GACxB,QAAQ,OAAO,EAAE,MAAM,aAAa,OAAO,GAAG,UAAU;IACtD,MAAM,UAAU;KACd,GAAG;KAEH,SAAS;KACT;KACD;AAMD,WAAO,KAFK,MAAM,QAAQ,cAAc,QAAQ,CAEhC;;GAElB,QAAQ,OAAO,EAAE,MAAM,GAAG,UAAU;IAElC,MAAM,SAAS,MAAM,QAAQ,WAAW,IAAY;AAEpD,WAAO,KAAK;KACV,GAAG;KACH;KACD,CAAQ;;GAQZ;EACF"}
@@ -5,7 +5,7 @@ export type { OnRawStreamCallback } from '@tanstack/router-core';
5
5
  export { createIsomorphicFn, createServerOnlyFn, createClientOnlyFn, type IsomorphicFn, type ServerOnlyFn, type ClientOnlyFn, type IsomorphicFnBase, } from '@tanstack/start-fn-stubs';
6
6
  export { createServerFn } from './createServerFn.js';
7
7
  export { createMiddleware, type IntersectAllValidatorInputs, type IntersectAllValidatorOutputs, type FunctionMiddlewareServerFn, type AnyFunctionMiddleware, type FunctionMiddlewareOptions, type FunctionMiddlewareWithTypes, type FunctionMiddlewareValidator, type FunctionMiddlewareServer, type FunctionMiddlewareAfterClient, type FunctionMiddlewareAfterServer, type FunctionMiddleware, type FunctionMiddlewareAfterMiddleware, type FunctionMiddlewareClientFnOptions, type FunctionMiddlewareClientFnResult, type FunctionMiddlewareClientNextFn, type FunctionClientResultWithContext, type AssignAllClientContextBeforeNext, type AssignAllMiddleware, type FunctionMiddlewareAfterValidator, type FunctionMiddlewareClientFn, type FunctionMiddlewareServerFnResult, type FunctionMiddlewareClient, type FunctionMiddlewareServerFnOptions, type FunctionMiddlewareServerNextFn, type FunctionServerResultWithContext, type AnyRequestMiddleware, type RequestMiddlewareOptions, type RequestMiddlewareWithTypes, type RequestMiddlewareServer, type RequestMiddlewareAfterServer, type RequestMiddleware, type RequestMiddlewareAfterMiddleware, type RequestServerFn, type RequestMiddlewareServerFnResult, type RequestServerOptions, type RequestServerNextFn, type RequestServerNextFnOptions, type RequestServerResult, } from './createMiddleware.js';
8
- export type { CompiledFetcherFnOptions, CompiledFetcherFn, CustomFetch, Fetcher, RscStream, FetcherBaseOptions, ServerFn, ServerFnCtx, MiddlewareFn, ServerFnMiddlewareOptions, ServerFnMiddlewareResult, ServerFnBuilder, ServerFnBaseOptions, NextFn, Method, OptionalFetcher, RequiredFetcher, } from './createServerFn.js';
8
+ export type { CompiledFetcherFnOptions, CompiledFetcherFn, CustomFetch, Fetcher, RscStream, FetcherBaseOptions, ServerFn, ServerFnCtx, ServerFnOptions, ServerFnStrict, ServerFnStrictInput, ServerFnStrictOutput, MiddlewareFn, ServerFnMiddlewareOptions, ServerFnMiddlewareResult, ServerFnBuilder, ServerFnBaseOptions, NextFn, Method, OptionalFetcher, RequiredFetcher, } from './createServerFn.js';
9
9
  export { execValidator, flattenMiddlewares, executeMiddleware, } from './createServerFn.js';
10
10
  export { TSS_FORMDATA_CONTEXT, TSS_SERVER_FUNCTION, TSS_CONTENT_TYPE_FRAMED, TSS_CONTENT_TYPE_FRAMED_VERSIONED, TSS_FRAMED_PROTOCOL_VERSION, FrameType, FRAME_HEADER_SIZE, X_TSS_SERIALIZED, X_TSS_RAW_RESPONSE, X_TSS_CONTEXT, validateFramedProtocolVersion, } from './constants.js';
11
11
  export type { FrameType as FrameTypeValue, ClientFnMeta, ServerFnMeta, } from './constants.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/start-client-core",
3
- "version": "1.167.22",
3
+ "version": "1.168.0",
4
4
  "description": "Modern and scalable routing for React applications",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -32,23 +32,47 @@ import type {
32
32
 
33
33
  type TODO = any
34
34
 
35
+ export type ServerFnStrict = boolean | { input?: boolean; output?: boolean }
36
+
37
+ export interface ServerFnOptions<
38
+ TMethod extends Method = Method,
39
+ TStrict extends ServerFnStrict = true,
40
+ > {
41
+ method?: TMethod
42
+ strict?: TStrict
43
+ }
44
+
45
+ export type ServerFnStrictInput<TStrict extends ServerFnStrict> =
46
+ TStrict extends false
47
+ ? false
48
+ : TStrict extends { input: infer TInput extends boolean }
49
+ ? TInput
50
+ : true
51
+
52
+ export type ServerFnStrictOutput<TStrict extends ServerFnStrict> =
53
+ TStrict extends false
54
+ ? false
55
+ : TStrict extends { output: infer TOutput extends boolean }
56
+ ? TOutput
57
+ : true
58
+
35
59
  export type CreateServerFn<TRegister> = <
36
60
  TMethod extends Method,
61
+ TStrict extends ServerFnStrict = true,
37
62
  TResponse = unknown,
38
63
  TMiddlewares = undefined,
39
64
  TInputValidator = undefined,
40
65
  >(
41
- options?: {
42
- method?: TMethod
43
- },
66
+ options?: ServerFnOptions<TMethod, TStrict>,
44
67
  __opts?: ServerFnBaseOptions<
45
68
  TRegister,
46
69
  TMethod,
47
70
  TResponse,
48
71
  TMiddlewares,
49
- TInputValidator
72
+ TInputValidator,
73
+ TStrict
50
74
  >,
51
- ) => ServerFnBuilder<TRegister, TMethod>
75
+ ) => ServerFnBuilder<TRegister, TMethod, TStrict>
52
76
 
53
77
  export const createServerFn: CreateServerFn<Register> = (options, __opts) => {
54
78
  const resolvedOptions = (__opts || options || {}) as ServerFnBaseOptions<
@@ -56,6 +80,7 @@ export const createServerFn: CreateServerFn<Register> = (options, __opts) => {
56
80
  any,
57
81
  any,
58
82
  any,
83
+ any,
59
84
  any
60
85
  >
61
86
 
@@ -63,7 +88,7 @@ export const createServerFn: CreateServerFn<Register> = (options, __opts) => {
63
88
  resolvedOptions.method = 'GET' as Method
64
89
  }
65
90
 
66
- const res: ServerFnBuilder<Register, Method> = {
91
+ const res: ServerFnBuilder<Register, Method, ServerFnStrict> = {
67
92
  options: resolvedOptions,
68
93
  middleware: (middleware) => {
69
94
  // multiple calls to `middleware()` merge the middlewares with the previously supplied ones
@@ -183,8 +208,8 @@ export const createServerFn: CreateServerFn<Register> = (options, __opts) => {
183
208
  },
184
209
  ) as any
185
210
  },
186
- } as ServerFnBuilder<Register, Method>
187
- const fun = (options?: { method?: Method }) => {
211
+ } as ServerFnBuilder<Register, Method, ServerFnStrict>
212
+ const fun = (options?: ServerFnOptions<Method, ServerFnStrict>) => {
188
213
  const newOptions = {
189
214
  ...resolvedOptions,
190
215
  ...options,
@@ -414,12 +439,18 @@ export type RscStream<T> = {
414
439
 
415
440
  export type Method = 'GET' | 'POST'
416
441
 
417
- export type ServerFnReturnType<TRegister, TResponse> =
418
- TResponse extends PromiseLike<infer U>
419
- ? Promise<ServerFnReturnType<TRegister, U>>
420
- : TResponse extends Response
421
- ? TResponse
422
- : ValidateSerializableInput<TRegister, TResponse>
442
+ export type ServerFnReturnType<
443
+ TRegister,
444
+ TResponse,
445
+ TStrict extends ServerFnStrict = true,
446
+ > =
447
+ ServerFnStrictOutput<TStrict> extends false
448
+ ? TResponse
449
+ : TResponse extends PromiseLike<infer U>
450
+ ? Promise<ServerFnReturnType<TRegister, U, TStrict>>
451
+ : TResponse extends Response
452
+ ? TResponse
453
+ : ValidateSerializableInput<TRegister, TResponse>
423
454
 
424
455
  export type ServerFn<
425
456
  TRegister,
@@ -427,9 +458,10 @@ export type ServerFn<
427
458
  TMiddlewares,
428
459
  TInputValidator,
429
460
  TResponse,
461
+ TStrict extends ServerFnStrict = true,
430
462
  > = (
431
463
  ctx: ServerFnCtx<TRegister, TMethod, TMiddlewares, TInputValidator>,
432
- ) => ServerFnReturnType<TRegister, TResponse>
464
+ ) => ServerFnReturnType<TRegister, TResponse, TStrict>
433
465
 
434
466
  export interface ServerFnCtx<
435
467
  TRegister,
@@ -457,20 +489,28 @@ export type ServerFnBaseOptions<
457
489
  TResponse = unknown,
458
490
  TMiddlewares = unknown,
459
491
  TInputValidator = unknown,
492
+ TStrict extends ServerFnStrict = true,
460
493
  > = {
461
494
  method: TMethod
495
+ strict?: TStrict
462
496
  middleware?: Constrain<
463
497
  TMiddlewares,
464
498
  ReadonlyArray<AnyFunctionMiddleware | AnyRequestMiddleware>
465
499
  >
466
- inputValidator?: ConstrainValidator<TRegister, TMethod, TInputValidator>
500
+ inputValidator?: ConstrainValidator<
501
+ TRegister,
502
+ TMethod,
503
+ TInputValidator,
504
+ TStrict
505
+ >
467
506
  extractedFn?: CompiledFetcherFn<TRegister, TResponse>
468
507
  serverFn?: ServerFn<
469
508
  TRegister,
470
509
  TMethod,
471
510
  TMiddlewares,
472
511
  TInputValidator,
473
- TResponse
512
+ TResponse,
513
+ TStrict
474
514
  >
475
515
  }
476
516
 
@@ -478,27 +518,33 @@ export type ValidateValidatorInput<
478
518
  TRegister,
479
519
  TMethod extends Method,
480
520
  TInputValidator,
481
- > = TMethod extends 'POST'
482
- ? ResolveValidatorInput<TInputValidator> extends FormData
521
+ TStrict extends ServerFnStrict = true,
522
+ > =
523
+ ServerFnStrictInput<TStrict> extends false
483
524
  ? ResolveValidatorInput<TInputValidator>
484
- : ValidateSerializable<
485
- ResolveValidatorInput<TInputValidator>,
486
- RegisteredSerializableInput<TRegister>
487
- >
488
- : ValidateSerializable<
489
- ResolveValidatorInput<TInputValidator>,
490
- RegisteredSerializableInput<TRegister>
491
- >
525
+ : TMethod extends 'POST'
526
+ ? ResolveValidatorInput<TInputValidator> extends FormData
527
+ ? ResolveValidatorInput<TInputValidator>
528
+ : ValidateSerializable<
529
+ ResolveValidatorInput<TInputValidator>,
530
+ RegisteredSerializableInput<TRegister>
531
+ >
532
+ : ValidateSerializable<
533
+ ResolveValidatorInput<TInputValidator>,
534
+ RegisteredSerializableInput<TRegister>
535
+ >
492
536
 
493
537
  export type ValidateValidator<
494
538
  TRegister,
495
539
  TMethod extends Method,
496
540
  TInputValidator,
541
+ TStrict extends ServerFnStrict = true,
497
542
  > =
498
543
  ValidateValidatorInput<
499
544
  TRegister,
500
545
  TMethod,
501
- TInputValidator
546
+ TInputValidator,
547
+ TStrict
502
548
  > extends infer TInput
503
549
  ? Validator<TInput, any>
504
550
  : never
@@ -507,17 +553,19 @@ export type ConstrainValidator<
507
553
  TRegister,
508
554
  TMethod extends Method,
509
555
  TInputValidator,
556
+ TStrict extends ServerFnStrict = true,
510
557
  > =
511
558
  | (unknown extends TInputValidator
512
559
  ? TInputValidator
513
560
  : ResolveValidatorInput<TInputValidator> extends ValidateValidator<
514
561
  TRegister,
515
562
  TMethod,
516
- TInputValidator
563
+ TInputValidator,
564
+ TStrict
517
565
  >
518
566
  ? TInputValidator
519
567
  : never)
520
- | ValidateValidator<TRegister, TMethod, TInputValidator>
568
+ | ValidateValidator<TRegister, TMethod, TInputValidator, TStrict>
521
569
 
522
570
  export type AppendMiddlewares<TMiddlewares, TNewMiddlewares> =
523
571
  TMiddlewares extends ReadonlyArray<any>
@@ -531,6 +579,7 @@ export interface ServerFnMiddleware<
531
579
  TMethod extends Method,
532
580
  TMiddlewares,
533
581
  TInputValidator,
582
+ TStrict extends ServerFnStrict,
534
583
  > {
535
584
  middleware: <const TNewMiddlewares>(
536
585
  middlewares: Constrain<
@@ -541,7 +590,8 @@ export interface ServerFnMiddleware<
541
590
  TRegister,
542
591
  TMethod,
543
592
  AppendMiddlewares<TMiddlewares, TNewMiddlewares>,
544
- TInputValidator
593
+ TInputValidator,
594
+ TStrict
545
595
  >
546
596
  }
547
597
 
@@ -550,6 +600,7 @@ export interface ServerFnAfterMiddleware<
550
600
  TMethod extends Method,
551
601
  TMiddlewares,
552
602
  TInputValidator,
603
+ TStrict extends ServerFnStrict,
553
604
  >
554
605
  extends
555
606
  ServerFnWithTypes<
@@ -557,33 +608,59 @@ export interface ServerFnAfterMiddleware<
557
608
  TMethod,
558
609
  TMiddlewares,
559
610
  TInputValidator,
560
- undefined
611
+ undefined,
612
+ TStrict
561
613
  >,
562
- ServerFnMiddleware<TRegister, TMethod, TMiddlewares, undefined>,
563
- ServerFnValidator<TRegister, TMethod, TMiddlewares>,
564
- ServerFnHandler<TRegister, TMethod, TMiddlewares, TInputValidator> {
565
- <TNewMethod extends Method = TMethod>(options?: {
566
- method?: TNewMethod
567
- }): ServerFnAfterMiddleware<
614
+ ServerFnMiddleware<TRegister, TMethod, TMiddlewares, undefined, TStrict>,
615
+ ServerFnValidator<TRegister, TMethod, TMiddlewares, TStrict>,
616
+ ServerFnHandler<
617
+ TRegister,
618
+ TMethod,
619
+ TMiddlewares,
620
+ TInputValidator,
621
+ TStrict
622
+ > {
623
+ <
624
+ TNewMethod extends Method = TMethod,
625
+ TNewStrict extends ServerFnStrict = TStrict,
626
+ >(
627
+ options?: ServerFnOptions<TNewMethod, TNewStrict>,
628
+ ): ServerFnAfterMiddleware<
568
629
  TRegister,
569
630
  TNewMethod,
570
631
  TMiddlewares,
571
- TInputValidator
632
+ TInputValidator,
633
+ TNewStrict
572
634
  >
573
635
  }
574
636
 
575
- export type ValidatorFn<TRegister, TMethod extends Method, TMiddlewares> = <
637
+ export type ValidatorFn<
638
+ TRegister,
639
+ TMethod extends Method,
640
+ TMiddlewares,
641
+ TStrict extends ServerFnStrict,
642
+ > = <TInputValidator>(
643
+ inputValidator: ConstrainValidator<
644
+ TRegister,
645
+ TMethod,
646
+ TInputValidator,
647
+ TStrict
648
+ >,
649
+ ) => ServerFnAfterValidator<
650
+ TRegister,
651
+ TMethod,
652
+ TMiddlewares,
576
653
  TInputValidator,
577
- >(
578
- inputValidator: ConstrainValidator<TRegister, TMethod, TInputValidator>,
579
- ) => ServerFnAfterValidator<TRegister, TMethod, TMiddlewares, TInputValidator>
654
+ TStrict
655
+ >
580
656
 
581
657
  export interface ServerFnValidator<
582
658
  TRegister,
583
659
  TMethod extends Method,
584
660
  TMiddlewares,
661
+ TStrict extends ServerFnStrict,
585
662
  > {
586
- inputValidator: ValidatorFn<TRegister, TMethod, TMiddlewares>
663
+ inputValidator: ValidatorFn<TRegister, TMethod, TMiddlewares, TStrict>
587
664
  }
588
665
 
589
666
  export interface ServerFnAfterValidator<
@@ -591,6 +668,7 @@ export interface ServerFnAfterValidator<
591
668
  TMethod extends Method,
592
669
  TMiddlewares,
593
670
  TInputValidator,
671
+ TStrict extends ServerFnStrict,
594
672
  >
595
673
  extends
596
674
  ServerFnWithTypes<
@@ -598,16 +676,30 @@ export interface ServerFnAfterValidator<
598
676
  TMethod,
599
677
  TMiddlewares,
600
678
  TInputValidator,
601
- undefined
679
+ undefined,
680
+ TStrict
602
681
  >,
603
- ServerFnMiddleware<TRegister, TMethod, TMiddlewares, TInputValidator>,
604
- ServerFnHandler<TRegister, TMethod, TMiddlewares, TInputValidator> {}
682
+ ServerFnMiddleware<
683
+ TRegister,
684
+ TMethod,
685
+ TMiddlewares,
686
+ TInputValidator,
687
+ TStrict
688
+ >,
689
+ ServerFnHandler<
690
+ TRegister,
691
+ TMethod,
692
+ TMiddlewares,
693
+ TInputValidator,
694
+ TStrict
695
+ > {}
605
696
 
606
697
  export interface ServerFnAfterTyper<
607
698
  TRegister,
608
699
  TMethod extends Method,
609
700
  TMiddlewares,
610
701
  TInputValidator,
702
+ TStrict extends ServerFnStrict,
611
703
  >
612
704
  extends
613
705
  ServerFnWithTypes<
@@ -615,9 +707,16 @@ export interface ServerFnAfterTyper<
615
707
  TMethod,
616
708
  TMiddlewares,
617
709
  TInputValidator,
618
- undefined
710
+ undefined,
711
+ TStrict
619
712
  >,
620
- ServerFnHandler<TRegister, TMethod, TMiddlewares, TInputValidator> {}
713
+ ServerFnHandler<
714
+ TRegister,
715
+ TMethod,
716
+ TMiddlewares,
717
+ TInputValidator,
718
+ TStrict
719
+ > {}
621
720
 
622
721
  // Handler
623
722
  export interface ServerFnHandler<
@@ -625,6 +724,7 @@ export interface ServerFnHandler<
625
724
  TMethod extends Method,
626
725
  TMiddlewares,
627
726
  TInputValidator,
727
+ TStrict extends ServerFnStrict,
628
728
  > {
629
729
  handler: <TNewResponse>(
630
730
  fn?: ServerFn<
@@ -632,23 +732,42 @@ export interface ServerFnHandler<
632
732
  TMethod,
633
733
  TMiddlewares,
634
734
  TInputValidator,
635
- TNewResponse
735
+ TNewResponse,
736
+ TStrict
636
737
  >,
637
738
  ) => Fetcher<TMiddlewares, TInputValidator, TNewResponse>
638
739
  }
639
740
 
640
- export interface ServerFnBuilder<TRegister, TMethod extends Method = 'GET'>
741
+ export interface ServerFnBuilder<
742
+ TRegister,
743
+ TMethod extends Method = 'GET',
744
+ TStrict extends ServerFnStrict = true,
745
+ >
641
746
  extends
642
- ServerFnWithTypes<TRegister, TMethod, undefined, undefined, undefined>,
643
- ServerFnMiddleware<TRegister, TMethod, undefined, undefined>,
644
- ServerFnValidator<TRegister, TMethod, undefined>,
645
- ServerFnHandler<TRegister, TMethod, undefined, undefined> {
747
+ ServerFnWithTypes<
748
+ TRegister,
749
+ TMethod,
750
+ undefined,
751
+ undefined,
752
+ undefined,
753
+ TStrict
754
+ >,
755
+ ServerFnMiddleware<TRegister, TMethod, undefined, undefined, TStrict>,
756
+ ServerFnValidator<TRegister, TMethod, undefined, TStrict>,
757
+ ServerFnHandler<TRegister, TMethod, undefined, undefined, TStrict> {
758
+ <
759
+ TNewMethod extends Method = TMethod,
760
+ TNewStrict extends ServerFnStrict = TStrict,
761
+ >(
762
+ options?: ServerFnOptions<TNewMethod, TNewStrict>,
763
+ ): ServerFnBuilder<TRegister, TNewMethod, TNewStrict>
646
764
  options: ServerFnBaseOptions<
647
765
  TRegister,
648
766
  TMethod,
649
767
  unknown,
650
768
  undefined,
651
- undefined
769
+ undefined,
770
+ TStrict
652
771
  >
653
772
  }
654
773
 
@@ -658,25 +777,28 @@ export interface ServerFnWithTypes<
658
777
  in out TMiddlewares,
659
778
  in out TInputValidator,
660
779
  in out TResponse,
780
+ in out TStrict extends ServerFnStrict,
661
781
  > {
662
782
  '~types': ServerFnTypes<
663
783
  TRegister,
664
784
  TMethod,
665
785
  TMiddlewares,
666
786
  TInputValidator,
667
- TResponse
787
+ TResponse,
788
+ TStrict
668
789
  >
669
790
  options: ServerFnBaseOptions<
670
791
  TRegister,
671
792
  TMethod,
672
793
  unknown,
673
794
  undefined,
674
- undefined
795
+ undefined,
796
+ TStrict
675
797
  >
676
798
  [TSS_SERVER_FUNCTION_FACTORY]: true
677
799
  }
678
800
 
679
- export type AnyServerFn = ServerFnWithTypes<any, any, any, any, any>
801
+ export type AnyServerFn = ServerFnWithTypes<any, any, any, any, any, any>
680
802
 
681
803
  export interface ServerFnTypes<
682
804
  in out TRegister,
@@ -684,8 +806,10 @@ export interface ServerFnTypes<
684
806
  in out TMiddlewares,
685
807
  in out TInputValidator,
686
808
  in out TResponse,
809
+ in out TStrict extends ServerFnStrict,
687
810
  > {
688
811
  method: TMethod
812
+ strict: TStrict
689
813
  middlewares: TMiddlewares
690
814
  inputValidator: TInputValidator
691
815
  response: TResponse
package/src/index.tsx CHANGED
@@ -65,6 +65,10 @@ export type {
65
65
  FetcherBaseOptions,
66
66
  ServerFn,
67
67
  ServerFnCtx,
68
+ ServerFnOptions,
69
+ ServerFnStrict,
70
+ ServerFnStrictInput,
71
+ ServerFnStrictOutput,
68
72
  MiddlewareFn,
69
73
  ServerFnMiddlewareOptions,
70
74
  ServerFnMiddlewareResult,
@@ -518,6 +518,131 @@ test('createServerFn cannot return function', () => {
518
518
  }>()
519
519
  })
520
520
 
521
+ test('createServerFn strict false can validate and return function', () => {
522
+ const fn = createServerFn({ method: 'GET', strict: false })
523
+ .inputValidator((input: { func: () => 'input' }) => ({
524
+ output: input.func(),
525
+ }))
526
+ .handler(({ data }) => {
527
+ expectTypeOf(data).toEqualTypeOf<{ output: 'input' }>()
528
+
529
+ return {
530
+ func: () => 'func' as const,
531
+ }
532
+ })
533
+
534
+ expectTypeOf(fn).parameter(0).toEqualTypeOf<{
535
+ data: { func: () => 'input' }
536
+ headers?: HeadersInit
537
+ signal?: AbortSignal
538
+ fetch?: CustomFetch
539
+ }>()
540
+
541
+ expectTypeOf(fn({ data: { func: () => 'input' } })).toEqualTypeOf<
542
+ Promise<{
543
+ func: () => 'func'
544
+ }>
545
+ >()
546
+ })
547
+
548
+ test('createServerFn strict false factory preserves strictness', () => {
549
+ const createServerFnWithoutSerializationCheck = createServerFn({
550
+ strict: false,
551
+ })
552
+
553
+ const myServerFn = createServerFnWithoutSerializationCheck()
554
+ .inputValidator((input: { func: () => 'input' }) => ({
555
+ output: input.func(),
556
+ }))
557
+ .handler(({ data }) => {
558
+ expectTypeOf(data).toEqualTypeOf<{ output: 'input' }>()
559
+
560
+ return {
561
+ func: () => 'func' as const,
562
+ }
563
+ })
564
+
565
+ expectTypeOf(myServerFn).parameter(0).toEqualTypeOf<{
566
+ data: { func: () => 'input' }
567
+ headers?: HeadersInit
568
+ signal?: AbortSignal
569
+ fetch?: CustomFetch
570
+ }>()
571
+
572
+ expectTypeOf(myServerFn({ data: { func: () => 'input' } })).toEqualTypeOf<
573
+ Promise<{
574
+ func: () => 'func'
575
+ }>
576
+ >()
577
+ })
578
+
579
+ test('createServerFn strict input false can validate function', () => {
580
+ const fn = createServerFn({ strict: { input: false } })
581
+ .inputValidator((input: { func: () => 'input' }) => ({
582
+ output: input.func(),
583
+ }))
584
+ .handler(({ data }) => {
585
+ expectTypeOf(data).toEqualTypeOf<{ output: 'input' }>()
586
+
587
+ return {
588
+ value: 'serializable' as const,
589
+ }
590
+ })
591
+
592
+ expectTypeOf(fn).parameter(0).toEqualTypeOf<{
593
+ data: { func: () => 'input' }
594
+ headers?: HeadersInit
595
+ signal?: AbortSignal
596
+ fetch?: CustomFetch
597
+ }>()
598
+
599
+ expectTypeOf(fn({ data: { func: () => 'input' } })).toEqualTypeOf<
600
+ Promise<{
601
+ value: 'serializable'
602
+ }>
603
+ >()
604
+ })
605
+
606
+ test('createServerFn strict output false can return function', () => {
607
+ const fn = createServerFn({ strict: { output: false } }).handler(() => ({
608
+ func: () => 'func' as const,
609
+ }))
610
+
611
+ expectTypeOf(fn()).toEqualTypeOf<
612
+ Promise<{
613
+ func: () => 'func'
614
+ }>
615
+ >()
616
+
617
+ const promiseFn = createServerFn({ strict: { output: false } }).handler(() =>
618
+ Promise.resolve({
619
+ func: () => 'func' as const,
620
+ }),
621
+ )
622
+
623
+ expectTypeOf(promiseFn()).toEqualTypeOf<
624
+ Promise<{
625
+ func: () => 'func'
626
+ }>
627
+ >()
628
+ })
629
+
630
+ test('ServerFnReturnType skips serialization when strict is false', () => {
631
+ expectTypeOf<
632
+ ServerFnReturnType<Register, { func: () => 'func' }, false>
633
+ >().toEqualTypeOf<{
634
+ func: () => 'func'
635
+ }>()
636
+ })
637
+
638
+ test('ServerFnReturnType skips serialization when strict output is false', () => {
639
+ expectTypeOf<
640
+ ServerFnReturnType<Register, { func: () => 'func' }, { output: false }>
641
+ >().toEqualTypeOf<{
642
+ func: () => 'func'
643
+ }>()
644
+ })
645
+
521
646
  test('createServerFn cannot validate function', () => {
522
647
  const validator = createServerFn().inputValidator<
523
648
  (input: { func: () => 'string' }) => { output: 'string' }
@@ -536,6 +661,25 @@ test('createServerFn cannot validate function', () => {
536
661
  >()
537
662
  })
538
663
 
664
+ test('createServerFn strict output false still checks input', () => {
665
+ const validator = createServerFn({
666
+ method: 'GET',
667
+ strict: { output: false },
668
+ }).inputValidator<(input: { func: () => 'string' }) => { output: 'string' }>
669
+
670
+ expectTypeOf(validator)
671
+ .parameter(0)
672
+ .toEqualTypeOf<
673
+ Constrain<
674
+ (input: { func: () => 'string' }) => { output: 'string' },
675
+ Validator<
676
+ { func: SerializationError<'Function may not be serializable'> },
677
+ any
678
+ >
679
+ >
680
+ >()
681
+ })
682
+
539
683
  test('createServerFn can validate Date', () => {
540
684
  const validator = createServerFn().inputValidator<
541
685
  (input: Date) => { output: 'string' }