You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@tanstack/start-client-core

Package Overview
Dependencies
Maintainers
2
Versions
343
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@tanstack/start-client-core - npm Package Compare versions

Comparing version
1.114.4
to
1.114.5
+7
dist/cjs/createIsomorphicFn.cjs
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
function createIsomorphicFn() {
return null;
}
exports.createIsomorphicFn = createIsomorphicFn;
//# sourceMappingURL=createIsomorphicFn.cjs.map
{"version":3,"file":"createIsomorphicFn.cjs","sources":["../../src/createIsomorphicFn.ts"],"sourcesContent":["// a function that can have different implementations on the client and server.\n// implementations not provided will default to a no-op function.\n\nexport type IsomorphicFn<\n TArgs extends Array<any> = [],\n TServer = undefined,\n TClient = undefined,\n> = (...args: TArgs) => TServer | TClient\n\nexport interface ServerOnlyFn<TArgs extends Array<any>, TServer>\n extends IsomorphicFn<TArgs, TServer> {\n client: <TClient>(\n clientImpl: (...args: TArgs) => TClient,\n ) => IsomorphicFn<TArgs, TServer, TClient>\n}\n\nexport interface ClientOnlyFn<TArgs extends Array<any>, TClient>\n extends IsomorphicFn<TArgs, undefined, TClient> {\n server: <TServer>(\n serverImpl: (...args: TArgs) => TServer,\n ) => IsomorphicFn<TArgs, TServer, TClient>\n}\n\nexport interface IsomorphicFnBase extends IsomorphicFn {\n server: <TArgs extends Array<any>, TServer>(\n serverImpl: (...args: TArgs) => TServer,\n ) => ServerOnlyFn<TArgs, TServer>\n client: <TArgs extends Array<any>, TClient>(\n clientImpl: (...args: TArgs) => TClient,\n ) => ClientOnlyFn<TArgs, TClient>\n}\n\n// this is a dummy function, it will be replaced by the transformer\nexport function createIsomorphicFn(): IsomorphicFnBase {\n return null!\n}\n"],"names":[],"mappings":";;AAiCO,SAAS,qBAAuC;AAC9C,SAAA;AACT;;"}
export type IsomorphicFn<TArgs extends Array<any> = [], TServer = undefined, TClient = undefined> = (...args: TArgs) => TServer | TClient;
export interface ServerOnlyFn<TArgs extends Array<any>, TServer> extends IsomorphicFn<TArgs, TServer> {
client: <TClient>(clientImpl: (...args: TArgs) => TClient) => IsomorphicFn<TArgs, TServer, TClient>;
}
export interface ClientOnlyFn<TArgs extends Array<any>, TClient> extends IsomorphicFn<TArgs, undefined, TClient> {
server: <TServer>(serverImpl: (...args: TArgs) => TServer) => IsomorphicFn<TArgs, TServer, TClient>;
}
export interface IsomorphicFnBase extends IsomorphicFn {
server: <TArgs extends Array<any>, TServer>(serverImpl: (...args: TArgs) => TServer) => ServerOnlyFn<TArgs, TServer>;
client: <TArgs extends Array<any>, TClient>(clientImpl: (...args: TArgs) => TClient) => ClientOnlyFn<TArgs, TClient>;
}
export declare function createIsomorphicFn(): IsomorphicFnBase;
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
function createMiddleware(options, __opts) {
const resolvedOptions = __opts || (options || {});
return {
options: resolvedOptions,
middleware: (middleware) => {
return createMiddleware(
void 0,
Object.assign(resolvedOptions, { middleware })
);
},
validator: (validator) => {
return createMiddleware(
void 0,
Object.assign(resolvedOptions, { validator })
);
},
client: (client) => {
return createMiddleware(
void 0,
Object.assign(resolvedOptions, { client })
);
},
server: (server) => {
return createMiddleware(
void 0,
Object.assign(resolvedOptions, { server })
);
}
};
}
exports.createMiddleware = createMiddleware;
//# sourceMappingURL=createMiddleware.cjs.map
{"version":3,"file":"createMiddleware.cjs","sources":["../../src/createMiddleware.ts"],"sourcesContent":["import type {\n ConstrainValidator,\n Method,\n ServerFnResponseType,\n ServerFnTypeOrTypeFn,\n} from './createServerFn'\nimport type {\n Assign,\n Constrain,\n Expand,\n IntersectAssign,\n ResolveValidatorInput,\n ResolveValidatorOutput,\n SerializerStringify,\n} from '@tanstack/router-core'\n\nexport type AssignAllMiddleware<\n TMiddlewares,\n TType extends keyof AnyMiddleware['_types'],\n TAcc = undefined,\n> = TMiddlewares extends readonly [\n infer TMiddleware extends AnyMiddleware,\n ...infer TRest,\n]\n ? AssignAllMiddleware<\n TRest,\n TType,\n Assign<TAcc, TMiddleware['_types'][TType]>\n >\n : TAcc\n\n/**\n * Recursively resolve the client context type produced by a sequence of middleware\n */\nexport type AssignAllClientContextBeforeNext<\n TMiddlewares,\n TClientContext = undefined,\n> = unknown extends TClientContext\n ? TClientContext\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allClientContextBeforeNext'>,\n TClientContext\n >\n\nexport type AssignAllClientSendContext<\n TMiddlewares,\n TSendContext = undefined,\n> = unknown extends TSendContext\n ? TSendContext\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allClientSendContext'>,\n TSendContext\n >\n\nexport type AssignAllClientContextAfterNext<\n TMiddlewares,\n TClientContext = undefined,\n TSendContext = undefined,\n> = unknown extends TClientContext\n ? Assign<TClientContext, TSendContext>\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allClientContextAfterNext'>,\n Assign<TClientContext, TSendContext>\n >\n\n/**\n * Recursively resolve the server context type produced by a sequence of middleware\n */\nexport type AssignAllServerContext<\n TMiddlewares,\n TSendContext = undefined,\n TServerContext = undefined,\n> = unknown extends TSendContext\n ? Assign<TSendContext, TServerContext>\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allServerContext'>,\n Assign<TSendContext, TServerContext>\n >\n\nexport type AssignAllServerSendContext<\n TMiddlewares,\n TSendContext = undefined,\n> = unknown extends TSendContext\n ? TSendContext\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allServerSendContext'>,\n TSendContext\n >\n\nexport type IntersectAllMiddleware<\n TMiddlewares,\n TType extends keyof AnyMiddleware['_types'],\n TAcc = undefined,\n> = TMiddlewares extends readonly [\n infer TMiddleware extends AnyMiddleware,\n ...infer TRest,\n]\n ? IntersectAllMiddleware<\n TRest,\n TType,\n IntersectAssign<TAcc, TMiddleware['_types'][TType]>\n >\n : TAcc\n\n/**\n * Recursively resolve the input type produced by a sequence of middleware\n */\nexport type IntersectAllValidatorInputs<TMiddlewares, TValidator> =\n unknown extends TValidator\n ? TValidator\n : IntersectAssign<\n IntersectAllMiddleware<TMiddlewares, 'allInput'>,\n TValidator extends undefined\n ? undefined\n : ResolveValidatorInput<TValidator>\n >\n/**\n * Recursively merge the output type produced by a sequence of middleware\n */\nexport type IntersectAllValidatorOutputs<TMiddlewares, TValidator> =\n unknown extends TValidator\n ? TValidator\n : IntersectAssign<\n IntersectAllMiddleware<TMiddlewares, 'allOutput'>,\n TValidator extends undefined\n ? undefined\n : ResolveValidatorOutput<TValidator>\n >\n\nexport interface MiddlewareOptions<\n in out TMiddlewares,\n in out TValidator,\n in out TServerContext,\n in out TClientContext,\n in out TServerFnResponseType extends ServerFnResponseType,\n> {\n validateClient?: boolean\n middleware?: TMiddlewares\n validator?: ConstrainValidator<TValidator>\n client?: MiddlewareClientFn<\n TMiddlewares,\n TValidator,\n TServerContext,\n TClientContext,\n TServerFnResponseType\n >\n server?: MiddlewareServerFn<\n TMiddlewares,\n TValidator,\n TServerContext,\n unknown,\n unknown,\n TServerFnResponseType\n >\n}\n\nexport type MiddlewareServerNextFn<TMiddlewares, TServerSendContext> = <\n TNewServerContext = undefined,\n TSendContext = undefined,\n>(ctx?: {\n context?: TNewServerContext\n sendContext?: SerializerStringify<TSendContext>\n}) => Promise<\n ServerResultWithContext<\n TMiddlewares,\n TServerSendContext,\n TNewServerContext,\n TSendContext\n >\n>\n\nexport interface MiddlewareServerFnOptions<\n in out TMiddlewares,\n in out TValidator,\n in out TServerSendContext,\n in out TServerFnResponseType,\n> {\n data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TValidator>>\n context: Expand<AssignAllServerContext<TMiddlewares, TServerSendContext>>\n next: MiddlewareServerNextFn<TMiddlewares, TServerSendContext>\n response: TServerFnResponseType\n method: Method\n filename: string\n functionId: string\n signal: AbortSignal\n}\n\nexport type MiddlewareServerFn<\n TMiddlewares,\n TValidator,\n TServerSendContext,\n TNewServerContext,\n TSendContext,\n TServerFnResponseType extends ServerFnResponseType,\n> = (\n options: MiddlewareServerFnOptions<\n TMiddlewares,\n TValidator,\n TServerSendContext,\n TServerFnResponseType\n >,\n) => MiddlewareServerFnResult<\n TMiddlewares,\n TServerSendContext,\n TNewServerContext,\n TSendContext\n>\n\nexport type MiddlewareServerFnResult<\n TMiddlewares,\n TServerSendContext,\n TServerContext,\n TSendContext,\n> =\n | Promise<\n ServerResultWithContext<\n TMiddlewares,\n TServerSendContext,\n TServerContext,\n TSendContext\n >\n >\n | ServerResultWithContext<\n TMiddlewares,\n TServerSendContext,\n TServerContext,\n TSendContext\n >\n\nexport type MiddlewareClientNextFn<TMiddlewares> = <\n TSendContext = undefined,\n TNewClientContext = undefined,\n>(ctx?: {\n context?: TNewClientContext\n sendContext?: SerializerStringify<TSendContext>\n headers?: HeadersInit\n}) => Promise<\n ClientResultWithContext<TMiddlewares, TSendContext, TNewClientContext>\n>\n\nexport interface MiddlewareClientFnOptions<\n in out TMiddlewares,\n in out TValidator,\n in out TServerFnResponseType extends ServerFnResponseType,\n> {\n data: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>\n context: Expand<AssignAllClientContextBeforeNext<TMiddlewares>>\n sendContext: Expand<AssignAllServerSendContext<TMiddlewares>>\n method: Method\n response: TServerFnResponseType\n signal: AbortSignal\n next: MiddlewareClientNextFn<TMiddlewares>\n filename: string\n functionId: string\n type: ServerFnTypeOrTypeFn<\n Method,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n >\n}\n\nexport type MiddlewareClientFn<\n TMiddlewares,\n TValidator,\n TSendContext,\n TClientContext,\n TServerFnResponseType extends ServerFnResponseType,\n> = (\n options: MiddlewareClientFnOptions<\n TMiddlewares,\n TValidator,\n TServerFnResponseType\n >,\n) => MiddlewareClientFnResult<TMiddlewares, TSendContext, TClientContext>\n\nexport type MiddlewareClientFnResult<\n TMiddlewares,\n TSendContext,\n TClientContext,\n> =\n | Promise<ClientResultWithContext<TMiddlewares, TSendContext, TClientContext>>\n | ClientResultWithContext<TMiddlewares, TSendContext, TClientContext>\n\nexport type ServerResultWithContext<\n in out TMiddlewares,\n in out TServerSendContext,\n in out TServerContext,\n in out TSendContext,\n> = {\n 'use functions must return the result of next()': true\n _types: {\n context: TServerContext\n sendContext: TSendContext\n }\n context: Expand<\n AssignAllServerContext<TMiddlewares, TServerSendContext, TServerContext>\n >\n sendContext: Expand<AssignAllClientSendContext<TMiddlewares, TSendContext>>\n}\n\nexport type ClientResultWithContext<\n in out TMiddlewares,\n in out TSendContext,\n in out TClientContext,\n> = {\n 'use functions must return the result of next()': true\n context: Expand<AssignAllClientContextAfterNext<TMiddlewares, TClientContext>>\n sendContext: Expand<AssignAllServerSendContext<TMiddlewares, TSendContext>>\n headers: HeadersInit\n}\n\nexport type AnyMiddleware = MiddlewareWithTypes<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n\nexport interface MiddlewareTypes<\n in out TMiddlewares,\n in out TValidator,\n in out TServerContext,\n in out TServerSendContext,\n in out TClientContext,\n in out TClientSendContext,\n> {\n middlewares: TMiddlewares\n input: ResolveValidatorInput<TValidator>\n allInput: IntersectAllValidatorInputs<TMiddlewares, TValidator>\n output: ResolveValidatorOutput<TValidator>\n allOutput: IntersectAllValidatorOutputs<TMiddlewares, TValidator>\n clientContext: TClientContext\n allClientContextBeforeNext: AssignAllClientContextBeforeNext<\n TMiddlewares,\n TClientContext\n >\n allClientContextAfterNext: AssignAllClientContextAfterNext<\n TMiddlewares,\n TClientContext,\n TClientSendContext\n >\n serverContext: TServerContext\n serverSendContext: TServerSendContext\n allServerSendContext: AssignAllServerSendContext<\n TMiddlewares,\n TServerSendContext\n >\n allServerContext: AssignAllServerContext<\n TMiddlewares,\n TServerSendContext,\n TServerContext\n >\n clientSendContext: TClientSendContext\n allClientSendContext: AssignAllClientSendContext<\n TMiddlewares,\n TClientSendContext\n >\n validator: TValidator\n}\n\nexport interface MiddlewareWithTypes<\n TMiddlewares,\n TValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext,\n TServerFnResponseType extends ServerFnResponseType,\n> {\n _types: MiddlewareTypes<\n TMiddlewares,\n TValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext\n >\n options: MiddlewareOptions<\n TMiddlewares,\n TValidator,\n TServerContext,\n TClientContext,\n TServerFnResponseType\n >\n}\n\nexport interface MiddlewareAfterValidator<\n TMiddlewares,\n TValidator,\n TServerFnResponseType extends ServerFnResponseType,\n> extends MiddlewareWithTypes<\n TMiddlewares,\n TValidator,\n undefined,\n undefined,\n undefined,\n undefined,\n ServerFnResponseType\n >,\n MiddlewareServer<\n TMiddlewares,\n TValidator,\n undefined,\n undefined,\n TServerFnResponseType\n >,\n MiddlewareClient<TMiddlewares, TValidator, ServerFnResponseType> {}\n\nexport interface MiddlewareValidator<\n TMiddlewares,\n TServerFnResponseType extends ServerFnResponseType,\n> {\n validator: <TNewValidator>(\n input: ConstrainValidator<TNewValidator>,\n ) => MiddlewareAfterValidator<\n TMiddlewares,\n TNewValidator,\n TServerFnResponseType\n >\n}\n\nexport interface MiddlewareAfterServer<\n TMiddlewares,\n TValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext,\n TServerFnResponseType extends ServerFnResponseType,\n> extends MiddlewareWithTypes<\n TMiddlewares,\n TValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext,\n TServerFnResponseType\n > {}\n\nexport interface MiddlewareServer<\n TMiddlewares,\n TValidator,\n TServerSendContext,\n TClientContext,\n TServerFnResponseType extends ServerFnResponseType,\n> {\n server: <TNewServerContext = undefined, TSendContext = undefined>(\n server: MiddlewareServerFn<\n TMiddlewares,\n TValidator,\n TServerSendContext,\n TNewServerContext,\n TSendContext,\n TServerFnResponseType\n >,\n ) => MiddlewareAfterServer<\n TMiddlewares,\n TValidator,\n TNewServerContext,\n TServerSendContext,\n TClientContext,\n TSendContext,\n ServerFnResponseType\n >\n}\n\nexport interface MiddlewareAfterClient<\n TMiddlewares,\n TValidator,\n TServerSendContext,\n TClientContext,\n TServerFnResponseType extends ServerFnResponseType,\n> extends MiddlewareWithTypes<\n TMiddlewares,\n TValidator,\n undefined,\n TServerSendContext,\n TClientContext,\n undefined,\n TServerFnResponseType\n >,\n MiddlewareServer<\n TMiddlewares,\n TValidator,\n TServerSendContext,\n TClientContext,\n TServerFnResponseType\n > {}\n\nexport interface MiddlewareClient<\n TMiddlewares,\n TValidator,\n TServerFnResponseType extends ServerFnResponseType,\n> {\n client: <TSendServerContext = undefined, TNewClientContext = undefined>(\n client: MiddlewareClientFn<\n TMiddlewares,\n TValidator,\n TSendServerContext,\n TNewClientContext,\n TServerFnResponseType\n >,\n ) => MiddlewareAfterClient<\n TMiddlewares,\n TValidator,\n TSendServerContext,\n TNewClientContext,\n ServerFnResponseType\n >\n}\n\nexport interface MiddlewareAfterMiddleware<\n TMiddlewares,\n TServerFnResponseType extends ServerFnResponseType,\n> extends MiddlewareWithTypes<\n TMiddlewares,\n undefined,\n undefined,\n undefined,\n undefined,\n undefined,\n TServerFnResponseType\n >,\n MiddlewareServer<\n TMiddlewares,\n undefined,\n undefined,\n undefined,\n TServerFnResponseType\n >,\n MiddlewareClient<TMiddlewares, undefined, TServerFnResponseType>,\n MiddlewareValidator<TMiddlewares, TServerFnResponseType> {}\n\nexport interface Middleware<TServerFnResponseType extends ServerFnResponseType>\n extends MiddlewareAfterMiddleware<unknown, TServerFnResponseType> {\n middleware: <const TNewMiddlewares = undefined>(\n middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>,\n ) => MiddlewareAfterMiddleware<TNewMiddlewares, TServerFnResponseType>\n}\n\nexport function createMiddleware(\n options?: {\n validateClient?: boolean\n },\n __opts?: MiddlewareOptions<\n unknown,\n undefined,\n undefined,\n undefined,\n ServerFnResponseType\n >,\n): Middleware<ServerFnResponseType> {\n // const resolvedOptions = (__opts || options) as MiddlewareOptions<\n const resolvedOptions =\n __opts ||\n ((options || {}) as MiddlewareOptions<\n unknown,\n undefined,\n undefined,\n undefined,\n ServerFnResponseType\n >)\n\n return {\n options: resolvedOptions as any,\n middleware: (middleware: any) => {\n return createMiddleware(\n undefined,\n Object.assign(resolvedOptions, { middleware }),\n ) as any\n },\n validator: (validator: any) => {\n return createMiddleware(\n undefined,\n Object.assign(resolvedOptions, { validator }),\n ) as any\n },\n client: (client: any) => {\n return createMiddleware(\n undefined,\n Object.assign(resolvedOptions, { client }),\n ) as any\n },\n server: (server: any) => {\n return createMiddleware(\n undefined,\n Object.assign(resolvedOptions, { server }),\n ) as any\n },\n } as unknown as Middleware<ServerFnResponseType>\n}\n"],"names":[],"mappings":";;AAgiBgB,SAAA,iBACd,SAGA,QAOkC;AAE5B,QAAA,kBACJ,WACE,WAAW;AAQR,SAAA;AAAA,IACL,SAAS;AAAA,IACT,YAAY,CAAC,eAAoB;AACxB,aAAA;AAAA,QACL;AAAA,QACA,OAAO,OAAO,iBAAiB,EAAE,WAAY,CAAA;AAAA,MAC/C;AAAA,IACF;AAAA,IACA,WAAW,CAAC,cAAmB;AACtB,aAAA;AAAA,QACL;AAAA,QACA,OAAO,OAAO,iBAAiB,EAAE,UAAW,CAAA;AAAA,MAC9C;AAAA,IACF;AAAA,IACA,QAAQ,CAAC,WAAgB;AAChB,aAAA;AAAA,QACL;AAAA,QACA,OAAO,OAAO,iBAAiB,EAAE,OAAQ,CAAA;AAAA,MAC3C;AAAA,IACF;AAAA,IACA,QAAQ,CAAC,WAAgB;AAChB,aAAA;AAAA,QACL;AAAA,QACA,OAAO,OAAO,iBAAiB,EAAE,OAAQ,CAAA;AAAA,MAC3C;AAAA,IAAA;AAAA,EAEJ;AACF;;"}
import { ConstrainValidator, Method, ServerFnResponseType, ServerFnTypeOrTypeFn } from './createServerFn.cjs';
import { Assign, Constrain, Expand, IntersectAssign, ResolveValidatorInput, ResolveValidatorOutput, SerializerStringify } from '@tanstack/router-core';
export type AssignAllMiddleware<TMiddlewares, TType extends keyof AnyMiddleware['_types'], TAcc = undefined> = TMiddlewares extends readonly [
infer TMiddleware extends AnyMiddleware,
...infer TRest
] ? AssignAllMiddleware<TRest, TType, Assign<TAcc, TMiddleware['_types'][TType]>> : TAcc;
/**
* Recursively resolve the client context type produced by a sequence of middleware
*/
export type AssignAllClientContextBeforeNext<TMiddlewares, TClientContext = undefined> = unknown extends TClientContext ? TClientContext : Assign<AssignAllMiddleware<TMiddlewares, 'allClientContextBeforeNext'>, TClientContext>;
export type AssignAllClientSendContext<TMiddlewares, TSendContext = undefined> = unknown extends TSendContext ? TSendContext : Assign<AssignAllMiddleware<TMiddlewares, 'allClientSendContext'>, TSendContext>;
export type AssignAllClientContextAfterNext<TMiddlewares, TClientContext = undefined, TSendContext = undefined> = unknown extends TClientContext ? Assign<TClientContext, TSendContext> : Assign<AssignAllMiddleware<TMiddlewares, 'allClientContextAfterNext'>, Assign<TClientContext, TSendContext>>;
/**
* Recursively resolve the server context type produced by a sequence of middleware
*/
export type AssignAllServerContext<TMiddlewares, TSendContext = undefined, TServerContext = undefined> = unknown extends TSendContext ? Assign<TSendContext, TServerContext> : Assign<AssignAllMiddleware<TMiddlewares, 'allServerContext'>, Assign<TSendContext, TServerContext>>;
export type AssignAllServerSendContext<TMiddlewares, TSendContext = undefined> = unknown extends TSendContext ? TSendContext : Assign<AssignAllMiddleware<TMiddlewares, 'allServerSendContext'>, TSendContext>;
export type IntersectAllMiddleware<TMiddlewares, TType extends keyof AnyMiddleware['_types'], TAcc = undefined> = TMiddlewares extends readonly [
infer TMiddleware extends AnyMiddleware,
...infer TRest
] ? IntersectAllMiddleware<TRest, TType, IntersectAssign<TAcc, TMiddleware['_types'][TType]>> : TAcc;
/**
* Recursively resolve the input type produced by a sequence of middleware
*/
export type IntersectAllValidatorInputs<TMiddlewares, TValidator> = unknown extends TValidator ? TValidator : IntersectAssign<IntersectAllMiddleware<TMiddlewares, 'allInput'>, TValidator extends undefined ? undefined : ResolveValidatorInput<TValidator>>;
/**
* Recursively merge the output type produced by a sequence of middleware
*/
export type IntersectAllValidatorOutputs<TMiddlewares, TValidator> = unknown extends TValidator ? TValidator : IntersectAssign<IntersectAllMiddleware<TMiddlewares, 'allOutput'>, TValidator extends undefined ? undefined : ResolveValidatorOutput<TValidator>>;
export interface MiddlewareOptions<in out TMiddlewares, in out TValidator, in out TServerContext, in out TClientContext, in out TServerFnResponseType extends ServerFnResponseType> {
validateClient?: boolean;
middleware?: TMiddlewares;
validator?: ConstrainValidator<TValidator>;
client?: MiddlewareClientFn<TMiddlewares, TValidator, TServerContext, TClientContext, TServerFnResponseType>;
server?: MiddlewareServerFn<TMiddlewares, TValidator, TServerContext, unknown, unknown, TServerFnResponseType>;
}
export type MiddlewareServerNextFn<TMiddlewares, TServerSendContext> = <TNewServerContext = undefined, TSendContext = undefined>(ctx?: {
context?: TNewServerContext;
sendContext?: SerializerStringify<TSendContext>;
}) => Promise<ServerResultWithContext<TMiddlewares, TServerSendContext, TNewServerContext, TSendContext>>;
export interface MiddlewareServerFnOptions<in out TMiddlewares, in out TValidator, in out TServerSendContext, in out TServerFnResponseType> {
data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TValidator>>;
context: Expand<AssignAllServerContext<TMiddlewares, TServerSendContext>>;
next: MiddlewareServerNextFn<TMiddlewares, TServerSendContext>;
response: TServerFnResponseType;
method: Method;
filename: string;
functionId: string;
signal: AbortSignal;
}
export type MiddlewareServerFn<TMiddlewares, TValidator, TServerSendContext, TNewServerContext, TSendContext, TServerFnResponseType extends ServerFnResponseType> = (options: MiddlewareServerFnOptions<TMiddlewares, TValidator, TServerSendContext, TServerFnResponseType>) => MiddlewareServerFnResult<TMiddlewares, TServerSendContext, TNewServerContext, TSendContext>;
export type MiddlewareServerFnResult<TMiddlewares, TServerSendContext, TServerContext, TSendContext> = Promise<ServerResultWithContext<TMiddlewares, TServerSendContext, TServerContext, TSendContext>> | ServerResultWithContext<TMiddlewares, TServerSendContext, TServerContext, TSendContext>;
export type MiddlewareClientNextFn<TMiddlewares> = <TSendContext = undefined, TNewClientContext = undefined>(ctx?: {
context?: TNewClientContext;
sendContext?: SerializerStringify<TSendContext>;
headers?: HeadersInit;
}) => Promise<ClientResultWithContext<TMiddlewares, TSendContext, TNewClientContext>>;
export interface MiddlewareClientFnOptions<in out TMiddlewares, in out TValidator, in out TServerFnResponseType extends ServerFnResponseType> {
data: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>;
context: Expand<AssignAllClientContextBeforeNext<TMiddlewares>>;
sendContext: Expand<AssignAllServerSendContext<TMiddlewares>>;
method: Method;
response: TServerFnResponseType;
signal: AbortSignal;
next: MiddlewareClientNextFn<TMiddlewares>;
filename: string;
functionId: string;
type: ServerFnTypeOrTypeFn<Method, TServerFnResponseType, TMiddlewares, TValidator>;
}
export type MiddlewareClientFn<TMiddlewares, TValidator, TSendContext, TClientContext, TServerFnResponseType extends ServerFnResponseType> = (options: MiddlewareClientFnOptions<TMiddlewares, TValidator, TServerFnResponseType>) => MiddlewareClientFnResult<TMiddlewares, TSendContext, TClientContext>;
export type MiddlewareClientFnResult<TMiddlewares, TSendContext, TClientContext> = Promise<ClientResultWithContext<TMiddlewares, TSendContext, TClientContext>> | ClientResultWithContext<TMiddlewares, TSendContext, TClientContext>;
export type ServerResultWithContext<in out TMiddlewares, in out TServerSendContext, in out TServerContext, in out TSendContext> = {
'use functions must return the result of next()': true;
_types: {
context: TServerContext;
sendContext: TSendContext;
};
context: Expand<AssignAllServerContext<TMiddlewares, TServerSendContext, TServerContext>>;
sendContext: Expand<AssignAllClientSendContext<TMiddlewares, TSendContext>>;
};
export type ClientResultWithContext<in out TMiddlewares, in out TSendContext, in out TClientContext> = {
'use functions must return the result of next()': true;
context: Expand<AssignAllClientContextAfterNext<TMiddlewares, TClientContext>>;
sendContext: Expand<AssignAllServerSendContext<TMiddlewares, TSendContext>>;
headers: HeadersInit;
};
export type AnyMiddleware = MiddlewareWithTypes<any, any, any, any, any, any, any>;
export interface MiddlewareTypes<in out TMiddlewares, in out TValidator, in out TServerContext, in out TServerSendContext, in out TClientContext, in out TClientSendContext> {
middlewares: TMiddlewares;
input: ResolveValidatorInput<TValidator>;
allInput: IntersectAllValidatorInputs<TMiddlewares, TValidator>;
output: ResolveValidatorOutput<TValidator>;
allOutput: IntersectAllValidatorOutputs<TMiddlewares, TValidator>;
clientContext: TClientContext;
allClientContextBeforeNext: AssignAllClientContextBeforeNext<TMiddlewares, TClientContext>;
allClientContextAfterNext: AssignAllClientContextAfterNext<TMiddlewares, TClientContext, TClientSendContext>;
serverContext: TServerContext;
serverSendContext: TServerSendContext;
allServerSendContext: AssignAllServerSendContext<TMiddlewares, TServerSendContext>;
allServerContext: AssignAllServerContext<TMiddlewares, TServerSendContext, TServerContext>;
clientSendContext: TClientSendContext;
allClientSendContext: AssignAllClientSendContext<TMiddlewares, TClientSendContext>;
validator: TValidator;
}
export interface MiddlewareWithTypes<TMiddlewares, TValidator, TServerContext, TServerSendContext, TClientContext, TClientSendContext, TServerFnResponseType extends ServerFnResponseType> {
_types: MiddlewareTypes<TMiddlewares, TValidator, TServerContext, TServerSendContext, TClientContext, TClientSendContext>;
options: MiddlewareOptions<TMiddlewares, TValidator, TServerContext, TClientContext, TServerFnResponseType>;
}
export interface MiddlewareAfterValidator<TMiddlewares, TValidator, TServerFnResponseType extends ServerFnResponseType> extends MiddlewareWithTypes<TMiddlewares, TValidator, undefined, undefined, undefined, undefined, ServerFnResponseType>, MiddlewareServer<TMiddlewares, TValidator, undefined, undefined, TServerFnResponseType>, MiddlewareClient<TMiddlewares, TValidator, ServerFnResponseType> {
}
export interface MiddlewareValidator<TMiddlewares, TServerFnResponseType extends ServerFnResponseType> {
validator: <TNewValidator>(input: ConstrainValidator<TNewValidator>) => MiddlewareAfterValidator<TMiddlewares, TNewValidator, TServerFnResponseType>;
}
export interface MiddlewareAfterServer<TMiddlewares, TValidator, TServerContext, TServerSendContext, TClientContext, TClientSendContext, TServerFnResponseType extends ServerFnResponseType> extends MiddlewareWithTypes<TMiddlewares, TValidator, TServerContext, TServerSendContext, TClientContext, TClientSendContext, TServerFnResponseType> {
}
export interface MiddlewareServer<TMiddlewares, TValidator, TServerSendContext, TClientContext, TServerFnResponseType extends ServerFnResponseType> {
server: <TNewServerContext = undefined, TSendContext = undefined>(server: MiddlewareServerFn<TMiddlewares, TValidator, TServerSendContext, TNewServerContext, TSendContext, TServerFnResponseType>) => MiddlewareAfterServer<TMiddlewares, TValidator, TNewServerContext, TServerSendContext, TClientContext, TSendContext, ServerFnResponseType>;
}
export interface MiddlewareAfterClient<TMiddlewares, TValidator, TServerSendContext, TClientContext, TServerFnResponseType extends ServerFnResponseType> extends MiddlewareWithTypes<TMiddlewares, TValidator, undefined, TServerSendContext, TClientContext, undefined, TServerFnResponseType>, MiddlewareServer<TMiddlewares, TValidator, TServerSendContext, TClientContext, TServerFnResponseType> {
}
export interface MiddlewareClient<TMiddlewares, TValidator, TServerFnResponseType extends ServerFnResponseType> {
client: <TSendServerContext = undefined, TNewClientContext = undefined>(client: MiddlewareClientFn<TMiddlewares, TValidator, TSendServerContext, TNewClientContext, TServerFnResponseType>) => MiddlewareAfterClient<TMiddlewares, TValidator, TSendServerContext, TNewClientContext, ServerFnResponseType>;
}
export interface MiddlewareAfterMiddleware<TMiddlewares, TServerFnResponseType extends ServerFnResponseType> extends MiddlewareWithTypes<TMiddlewares, undefined, undefined, undefined, undefined, undefined, TServerFnResponseType>, MiddlewareServer<TMiddlewares, undefined, undefined, undefined, TServerFnResponseType>, MiddlewareClient<TMiddlewares, undefined, TServerFnResponseType>, MiddlewareValidator<TMiddlewares, TServerFnResponseType> {
}
export interface Middleware<TServerFnResponseType extends ServerFnResponseType> extends MiddlewareAfterMiddleware<unknown, TServerFnResponseType> {
middleware: <const TNewMiddlewares = undefined>(middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>) => MiddlewareAfterMiddleware<TNewMiddlewares, TServerFnResponseType>;
}
export declare function createMiddleware(options?: {
validateClient?: boolean;
}, __opts?: MiddlewareOptions<unknown, undefined, undefined, undefined, ServerFnResponseType>): Middleware<ServerFnResponseType>;
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const invariant = require("tiny-invariant");
const warning = require("tiny-warning");
const serializer = require("./serializer.cjs");
const headers = require("./headers.cjs");
exports.serverFnStaticCache = void 0;
function setServerFnStaticCache(cache) {
const previousCache = exports.serverFnStaticCache;
exports.serverFnStaticCache = typeof cache === "function" ? cache() : cache;
return () => {
exports.serverFnStaticCache = previousCache;
};
}
function createServerFnStaticCache(serverFnStaticCache2) {
return serverFnStaticCache2;
}
setServerFnStaticCache(() => {
const getStaticCacheUrl = (options, hash) => {
return `/__tsr/staticServerFnCache/${options.functionId}__${hash}.json`;
};
const jsonToFilenameSafeString = (json) => {
const sortedKeysReplacer = (key, value) => value && typeof value === "object" && !Array.isArray(value) ? Object.keys(value).sort().reduce((acc, curr) => {
acc[curr] = value[curr];
return acc;
}, {}) : value;
const jsonString = JSON.stringify(json ?? "", sortedKeysReplacer);
return jsonString.replace(/[/\\?%*:|"<>]/g, "-").replace(/\s+/g, "_");
};
const staticClientCache = typeof document !== "undefined" ? /* @__PURE__ */ new Map() : null;
return createServerFnStaticCache({
getItem: async (ctx) => {
if (typeof document === "undefined") {
const hash = jsonToFilenameSafeString(ctx.data);
const url = getStaticCacheUrl(ctx, hash);
const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR;
const { promises: fs } = await import("node:fs");
const path = await import("node:path");
const filePath = path.join(publicUrl, url);
const [cachedResult, readError] = await fs.readFile(filePath, "utf-8").then((c) => [
serializer.startSerializer.parse(c),
null
]).catch((e) => [null, e]);
if (readError && readError.code !== "ENOENT") {
throw readError;
}
return cachedResult;
}
return void 0;
},
setItem: async (ctx, response) => {
const { promises: fs } = await import("node:fs");
const path = await import("node:path");
const hash = jsonToFilenameSafeString(ctx.data);
const url = getStaticCacheUrl(ctx, hash);
const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR;
const filePath = path.join(publicUrl, url);
await fs.mkdir(path.dirname(filePath), { recursive: true });
await fs.writeFile(filePath, serializer.startSerializer.stringify(response));
},
fetchItem: async (ctx) => {
const hash = jsonToFilenameSafeString(ctx.data);
const url = getStaticCacheUrl(ctx, hash);
let result = staticClientCache == null ? void 0 : staticClientCache.get(url);
if (!result) {
result = await fetch(url, {
method: "GET"
}).then((r) => r.text()).then((d) => serializer.startSerializer.parse(d));
staticClientCache == null ? void 0 : staticClientCache.set(url, result);
}
return result;
}
});
});
function extractFormDataContext(formData) {
const serializedContext = formData.get("__TSR_CONTEXT");
formData.delete("__TSR_CONTEXT");
if (typeof serializedContext !== "string") {
return {
context: {},
data: formData
};
}
try {
const context = serializer.startSerializer.parse(serializedContext);
return {
context,
data: formData
};
} catch {
return {
data: formData
};
}
}
function flattenMiddlewares(middlewares) {
const seen = /* @__PURE__ */ new Set();
const flattened = [];
const recurse = (middleware) => {
middleware.forEach((m) => {
if (m.options.middleware) {
recurse(m.options.middleware);
}
if (!seen.has(m)) {
seen.add(m);
flattened.push(m);
}
});
};
recurse(middlewares);
return flattened;
}
const applyMiddleware = async (middlewareFn, ctx, nextFn) => {
return middlewareFn({
...ctx,
next: async (userCtx = {}) => {
return nextFn({
...ctx,
...userCtx,
context: {
...ctx.context,
...userCtx.context
},
sendContext: {
...ctx.sendContext,
...userCtx.sendContext ?? {}
},
headers: headers.mergeHeaders(ctx.headers, userCtx.headers),
result: userCtx.result !== void 0 ? userCtx.result : ctx.response === "raw" ? userCtx : ctx.result,
error: userCtx.error ?? ctx.error
});
}
});
};
function execValidator(validator, input) {
if (validator == null) return {};
if ("~standard" in validator) {
const result = validator["~standard"].validate(input);
if (result instanceof Promise)
throw new Error("Async validation not supported");
if (result.issues)
throw new Error(JSON.stringify(result.issues, void 0, 2));
return result.value;
}
if ("parse" in validator) {
return validator.parse(input);
}
if (typeof validator === "function") {
return validator(input);
}
throw new Error("Invalid validator type!");
}
function serverFnBaseToMiddleware(options) {
return {
_types: void 0,
options: {
validator: options.validator,
validateClient: options.validateClient,
client: async ({ next, sendContext, ...ctx }) => {
var _a;
const payload = {
...ctx,
// switch the sendContext over to context
context: sendContext,
type: typeof ctx.type === "function" ? ctx.type(ctx) : ctx.type
};
if (ctx.type === "static" && process.env.NODE_ENV === "production" && typeof document !== "undefined") {
invariant(
exports.serverFnStaticCache,
"serverFnStaticCache.fetchItem is not available!"
);
const result = await exports.serverFnStaticCache.fetchItem(payload);
if (result) {
if (result.error) {
throw result.error;
}
return next(result.ctx);
}
warning(
result,
`No static cache item found for ${payload.functionId}__${JSON.stringify(payload.data)}, falling back to server function...`
);
}
const res = await ((_a = options.extractedFn) == null ? void 0 : _a.call(options, payload));
return next(res);
},
server: async ({ next, ...ctx }) => {
var _a;
const result = await ((_a = options.serverFn) == null ? void 0 : _a.call(options, ctx));
return next({
...ctx,
result
});
}
}
};
}
exports.applyMiddleware = applyMiddleware;
exports.createServerFnStaticCache = createServerFnStaticCache;
exports.execValidator = execValidator;
exports.extractFormDataContext = extractFormDataContext;
exports.flattenMiddlewares = flattenMiddlewares;
exports.serverFnBaseToMiddleware = serverFnBaseToMiddleware;
exports.setServerFnStaticCache = setServerFnStaticCache;
//# sourceMappingURL=createServerFn.cjs.map
{"version":3,"file":"createServerFn.cjs","sources":["../../src/createServerFn.ts"],"sourcesContent":["import { default as invariant } from 'tiny-invariant'\nimport { default as warning } from 'tiny-warning'\nimport { startSerializer } from './serializer'\nimport { mergeHeaders } from './headers'\nimport type { Readable } from 'node:stream'\nimport type {\n AnyValidator,\n Constrain,\n Expand,\n ResolveValidatorInput,\n SerializerParse,\n SerializerStringify,\n SerializerStringifyBy,\n Validator,\n} from '@tanstack/router-core'\nimport type {\n AnyMiddleware,\n AssignAllClientSendContext,\n AssignAllServerContext,\n IntersectAllValidatorInputs,\n IntersectAllValidatorOutputs,\n MiddlewareClientFnResult,\n MiddlewareServerFnResult,\n} from './createMiddleware'\n\nexport interface JsonResponse<TData> extends Response {\n json: () => Promise<TData>\n}\n\nexport type CompiledFetcherFnOptions = {\n method: Method\n data: unknown\n response?: ServerFnResponseType\n headers?: HeadersInit\n signal?: AbortSignal\n context?: any\n}\n\nexport type Fetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> =\n undefined extends IntersectAllValidatorInputs<TMiddlewares, TValidator>\n ? OptionalFetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType\n >\n : RequiredFetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType\n >\n\nexport interface FetcherBase {\n url: string\n __executeServer: (opts: {\n method: Method\n response?: ServerFnResponseType\n data: unknown\n headers?: HeadersInit\n context?: any\n signal: AbortSignal\n }) => Promise<unknown>\n}\n\nexport type FetchResult<\n TMiddlewares,\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> = TServerFnResponseType extends 'raw'\n ? Promise<Response>\n : TServerFnResponseType extends 'full'\n ? Promise<FullFetcherData<TMiddlewares, TResponse>>\n : Promise<FetcherData<TResponse>>\n\nexport interface OptionalFetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> extends FetcherBase {\n (\n options?: OptionalFetcherDataOptions<TMiddlewares, TValidator>,\n ): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>\n}\n\nexport interface RequiredFetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> extends FetcherBase {\n (\n opts: RequiredFetcherDataOptions<TMiddlewares, TValidator>,\n ): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>\n}\n\nexport type FetcherBaseOptions = {\n headers?: HeadersInit\n type?: ServerFnType\n signal?: AbortSignal\n}\n\nexport type ServerFnType = 'static' | 'dynamic'\n\nexport interface OptionalFetcherDataOptions<TMiddlewares, TValidator>\n extends FetcherBaseOptions {\n data?: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>\n}\n\nexport interface RequiredFetcherDataOptions<TMiddlewares, TValidator>\n extends FetcherBaseOptions {\n data: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>\n}\n\nexport interface FullFetcherData<TMiddlewares, TResponse> {\n error: unknown\n result: FetcherData<TResponse>\n context: AssignAllClientSendContext<TMiddlewares>\n}\n\nexport type FetcherData<TResponse> =\n TResponse extends JsonResponse<any>\n ? SerializerParse<ReturnType<TResponse['json']>>\n : SerializerParse<TResponse>\n\nexport type RscStream<T> = {\n __cacheState: T\n}\n\nexport type Method = 'GET' | 'POST'\nexport type ServerFnResponseType = 'data' | 'full' | 'raw'\n\n// see https://h3.unjs.io/guide/event-handler#responses-types\nexport type RawResponse = Response | ReadableStream | Readable | null | string\n\nexport type ServerFnReturnType<\n TServerFnResponseType extends ServerFnResponseType,\n TResponse,\n> = TServerFnResponseType extends 'raw'\n ? RawResponse | Promise<RawResponse>\n : Promise<SerializerStringify<TResponse>> | SerializerStringify<TResponse>\nexport type ServerFn<\n TMethod,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n TResponse,\n> = (\n ctx: ServerFnCtx<TMethod, TServerFnResponseType, TMiddlewares, TValidator>,\n) => ServerFnReturnType<TServerFnResponseType, TResponse>\n\nexport interface ServerFnCtx<\n TMethod,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> {\n method: TMethod\n response: TServerFnResponseType\n data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TValidator>>\n context: Expand<AssignAllServerContext<TMiddlewares>>\n signal: AbortSignal\n}\n\nexport type CompiledFetcherFn<\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> = {\n (\n opts: CompiledFetcherFnOptions &\n ServerFnBaseOptions<Method, TServerFnResponseType>,\n ): Promise<TResponse>\n url: string\n}\n\nexport type ServerFnBaseOptions<\n TMethod extends Method = 'GET',\n TServerFnResponseType extends ServerFnResponseType = 'data',\n TResponse = unknown,\n TMiddlewares = unknown,\n TInput = unknown,\n> = {\n method: TMethod\n response?: TServerFnResponseType\n validateClient?: boolean\n middleware?: Constrain<TMiddlewares, ReadonlyArray<AnyMiddleware>>\n validator?: ConstrainValidator<TInput>\n extractedFn?: CompiledFetcherFn<TResponse, TServerFnResponseType>\n serverFn?: ServerFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TInput,\n TResponse\n >\n functionId: string\n type: ServerFnTypeOrTypeFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n AnyValidator\n >\n}\n\nexport type ValidatorSerializerStringify<TValidator> = Validator<\n SerializerStringifyBy<\n ResolveValidatorInput<TValidator>,\n Date | undefined | FormData\n >,\n any\n>\n\nexport type ConstrainValidator<TValidator> = unknown extends TValidator\n ? TValidator\n : Constrain<TValidator, ValidatorSerializerStringify<TValidator>>\n\nexport interface ServerFnMiddleware<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TValidator,\n> {\n middleware: <const TNewMiddlewares = undefined>(\n middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>,\n ) => ServerFnAfterMiddleware<\n TMethod,\n TServerFnResponseType,\n TNewMiddlewares,\n TValidator\n >\n}\n\nexport interface ServerFnAfterMiddleware<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> extends ServerFnValidator<TMethod, TServerFnResponseType, TMiddlewares>,\n ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>,\n ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {}\n\nexport type ValidatorFn<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n> = <TValidator>(\n validator: ConstrainValidator<TValidator>,\n) => ServerFnAfterValidator<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n>\n\nexport interface ServerFnValidator<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n> {\n validator: ValidatorFn<TMethod, TServerFnResponseType, TMiddlewares>\n}\n\nexport interface ServerFnAfterValidator<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> extends ServerFnMiddleware<TMethod, TServerFnResponseType, TValidator>,\n ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>,\n ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {}\n\n// Typer\nexport interface ServerFnTyper<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> {\n type: (\n typer: ServerFnTypeOrTypeFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n >,\n ) => ServerFnAfterTyper<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n >\n}\n\nexport type ServerFnTypeOrTypeFn<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> =\n | ServerFnType\n | ((\n ctx: ServerFnCtx<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n >,\n ) => ServerFnType)\n\nexport interface ServerFnAfterTyper<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> extends ServerFnHandler<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n > {}\n\n// Handler\nexport interface ServerFnHandler<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> {\n handler: <TNewResponse>(\n fn?: ServerFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator,\n TNewResponse\n >,\n ) => Fetcher<TMiddlewares, TValidator, TNewResponse, TServerFnResponseType>\n}\n\nexport interface ServerFnBuilder<\n TMethod extends Method = 'GET',\n TServerFnResponseType extends ServerFnResponseType = 'data',\n> extends ServerFnMiddleware<TMethod, TServerFnResponseType, undefined>,\n ServerFnValidator<TMethod, TServerFnResponseType, undefined>,\n ServerFnTyper<TMethod, TServerFnResponseType, undefined, undefined>,\n ServerFnHandler<TMethod, TServerFnResponseType, undefined, undefined> {\n options: ServerFnBaseOptions<\n TMethod,\n TServerFnResponseType,\n unknown,\n undefined,\n undefined\n >\n}\n\nexport type StaticCachedResult = {\n ctx?: {\n result: any\n context: any\n }\n error?: any\n}\n\nexport type ServerFnStaticCache = {\n getItem: (\n ctx: ServerFnMiddlewareResult,\n ) => StaticCachedResult | Promise<StaticCachedResult | undefined>\n setItem: (\n ctx: ServerFnMiddlewareResult,\n response: StaticCachedResult,\n ) => Promise<void>\n fetchItem: (\n ctx: ServerFnMiddlewareResult,\n ) => StaticCachedResult | Promise<StaticCachedResult | undefined>\n}\n\nexport let serverFnStaticCache: ServerFnStaticCache | undefined\n\nexport function setServerFnStaticCache(\n cache?: ServerFnStaticCache | (() => ServerFnStaticCache | undefined),\n) {\n const previousCache = serverFnStaticCache\n serverFnStaticCache = typeof cache === 'function' ? cache() : cache\n\n return () => {\n serverFnStaticCache = previousCache\n }\n}\n\nexport function createServerFnStaticCache(\n serverFnStaticCache: ServerFnStaticCache,\n) {\n return serverFnStaticCache\n}\n\nsetServerFnStaticCache(() => {\n const getStaticCacheUrl = (\n options: ServerFnMiddlewareResult,\n hash: string,\n ) => {\n return `/__tsr/staticServerFnCache/${options.functionId}__${hash}.json`\n }\n\n const jsonToFilenameSafeString = (json: any) => {\n // Custom replacer to sort keys\n const sortedKeysReplacer = (key: string, value: any) =>\n value && typeof value === 'object' && !Array.isArray(value)\n ? Object.keys(value)\n .sort()\n .reduce((acc: any, curr: string) => {\n acc[curr] = value[curr]\n return acc\n }, {})\n : value\n\n // Convert JSON to string with sorted keys\n const jsonString = JSON.stringify(json ?? '', sortedKeysReplacer)\n\n // Replace characters invalid in filenames\n return jsonString\n .replace(/[/\\\\?%*:|\"<>]/g, '-') // Replace invalid characters with a dash\n .replace(/\\s+/g, '_') // Optionally replace whitespace with underscores\n }\n\n const staticClientCache =\n typeof document !== 'undefined' ? new Map<string, any>() : null\n\n return createServerFnStaticCache({\n getItem: async (ctx) => {\n if (typeof document === 'undefined') {\n const hash = jsonToFilenameSafeString(ctx.data)\n const url = getStaticCacheUrl(ctx, hash)\n const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR!\n\n // Use fs instead of fetch to read from filesystem\n const { promises: fs } = await import('node:fs')\n const path = await import('node:path')\n const filePath = path.join(publicUrl, url)\n\n const [cachedResult, readError] = await fs\n .readFile(filePath, 'utf-8')\n .then((c) => [\n startSerializer.parse(c) as {\n ctx: unknown\n error: any\n },\n null,\n ])\n .catch((e) => [null, e])\n\n if (readError && readError.code !== 'ENOENT') {\n throw readError\n }\n\n return cachedResult as StaticCachedResult\n }\n\n return undefined\n },\n setItem: async (ctx, response) => {\n const { promises: fs } = await import('node:fs')\n const path = await import('node:path')\n\n const hash = jsonToFilenameSafeString(ctx.data)\n const url = getStaticCacheUrl(ctx, hash)\n const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR!\n const filePath = path.join(publicUrl, url)\n\n // Ensure the directory exists\n await fs.mkdir(path.dirname(filePath), { recursive: true })\n\n // Store the result with fs\n await fs.writeFile(filePath, startSerializer.stringify(response))\n },\n fetchItem: async (ctx) => {\n const hash = jsonToFilenameSafeString(ctx.data)\n const url = getStaticCacheUrl(ctx, hash)\n\n let result: any = staticClientCache?.get(url)\n\n if (!result) {\n result = await fetch(url, {\n method: 'GET',\n })\n .then((r) => r.text())\n .then((d) => startSerializer.parse(d))\n\n staticClientCache?.set(url, result)\n }\n\n return result\n },\n })\n})\n\nexport function extractFormDataContext(formData: FormData) {\n const serializedContext = formData.get('__TSR_CONTEXT')\n formData.delete('__TSR_CONTEXT')\n\n if (typeof serializedContext !== 'string') {\n return {\n context: {},\n data: formData,\n }\n }\n\n try {\n const context = startSerializer.parse(serializedContext)\n return {\n context,\n data: formData,\n }\n } catch {\n return {\n data: formData,\n }\n }\n}\n\nexport function flattenMiddlewares(\n middlewares: Array<AnyMiddleware>,\n): Array<AnyMiddleware> {\n const seen = new Set<AnyMiddleware>()\n const flattened: Array<AnyMiddleware> = []\n\n const recurse = (middleware: Array<AnyMiddleware>) => {\n middleware.forEach((m) => {\n if (m.options.middleware) {\n recurse(m.options.middleware)\n }\n\n if (!seen.has(m)) {\n seen.add(m)\n flattened.push(m)\n }\n })\n }\n\n recurse(middlewares)\n\n return flattened\n}\n\nexport type ServerFnMiddlewareOptions = {\n method: Method\n response?: ServerFnResponseType\n data: any\n headers?: HeadersInit\n signal?: AbortSignal\n sendContext?: any\n context?: any\n type: ServerFnTypeOrTypeFn<any, any, any, any>\n functionId: string\n}\n\nexport type ServerFnMiddlewareResult = ServerFnMiddlewareOptions & {\n result?: unknown\n error?: unknown\n type: ServerFnTypeOrTypeFn<any, any, any, any>\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 const applyMiddleware = async (\n middlewareFn: MiddlewareFn,\n ctx: ServerFnMiddlewareOptions,\n nextFn: NextFn,\n) => {\n return middlewareFn({\n ...ctx,\n next: (async (\n userCtx: ServerFnMiddlewareResult | undefined = {} as any,\n ) => {\n // Return the next middleware\n return nextFn({\n ...ctx,\n ...userCtx,\n context: {\n ...ctx.context,\n ...userCtx.context,\n },\n sendContext: {\n ...ctx.sendContext,\n ...(userCtx.sendContext ?? {}),\n },\n headers: mergeHeaders(ctx.headers, userCtx.headers),\n result:\n userCtx.result !== undefined\n ? userCtx.result\n : ctx.response === 'raw'\n ? userCtx\n : (ctx as any).result,\n error: userCtx.error ?? (ctx as any).error,\n })\n }) as any,\n } as any)\n}\n\nexport function execValidator(\n validator: AnyValidator,\n input: unknown,\n): unknown {\n if (validator == null) return {}\n\n if ('~standard' in validator) {\n const result = validator['~standard'].validate(input)\n\n if (result instanceof Promise)\n throw new Error('Async validation not supported')\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\nexport function serverFnBaseToMiddleware(\n options: ServerFnBaseOptions<any, any, any, any, any>,\n): AnyMiddleware {\n return {\n _types: undefined!,\n options: {\n validator: options.validator,\n validateClient: options.validateClient,\n client: async ({ next, sendContext, ...ctx }) => {\n const payload = {\n ...ctx,\n // switch the sendContext over to context\n context: sendContext,\n type: typeof ctx.type === 'function' ? ctx.type(ctx) : ctx.type,\n } as any\n\n if (\n ctx.type === 'static' &&\n process.env.NODE_ENV === 'production' &&\n typeof document !== 'undefined'\n ) {\n invariant(\n serverFnStaticCache,\n 'serverFnStaticCache.fetchItem is not available!',\n )\n\n const result = await serverFnStaticCache.fetchItem(payload)\n\n if (result) {\n if (result.error) {\n throw result.error\n }\n\n return next(result.ctx)\n }\n\n warning(\n result,\n `No static cache item found for ${payload.functionId}__${JSON.stringify(payload.data)}, falling back to server function...`,\n )\n }\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) as unknown as MiddlewareClientFnResult<any, any, any>\n },\n server: async ({ next, ...ctx }) => {\n // Execute the server function\n const result = await options.serverFn?.(ctx)\n\n return next({\n ...ctx,\n result,\n } as any) as unknown as MiddlewareServerFnResult<any, any, any, any>\n },\n },\n }\n}\n"],"names":["serverFnStaticCache","startSerializer","mergeHeaders"],"mappings":"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"}
import { Readable } from 'node:stream';
import { AnyValidator, Constrain, Expand, ResolveValidatorInput, SerializerParse, SerializerStringify, SerializerStringifyBy, Validator } from '@tanstack/router-core';
import { AnyMiddleware, AssignAllClientSendContext, AssignAllServerContext, IntersectAllValidatorInputs, IntersectAllValidatorOutputs } from './createMiddleware.cjs';
export interface JsonResponse<TData> extends Response {
json: () => Promise<TData>;
}
export type CompiledFetcherFnOptions = {
method: Method;
data: unknown;
response?: ServerFnResponseType;
headers?: HeadersInit;
signal?: AbortSignal;
context?: any;
};
export type Fetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType extends ServerFnResponseType> = undefined extends IntersectAllValidatorInputs<TMiddlewares, TValidator> ? OptionalFetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType> : RequiredFetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType>;
export interface FetcherBase {
url: string;
__executeServer: (opts: {
method: Method;
response?: ServerFnResponseType;
data: unknown;
headers?: HeadersInit;
context?: any;
signal: AbortSignal;
}) => Promise<unknown>;
}
export type FetchResult<TMiddlewares, TResponse, TServerFnResponseType extends ServerFnResponseType> = TServerFnResponseType extends 'raw' ? Promise<Response> : TServerFnResponseType extends 'full' ? Promise<FullFetcherData<TMiddlewares, TResponse>> : Promise<FetcherData<TResponse>>;
export interface OptionalFetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType extends ServerFnResponseType> extends FetcherBase {
(options?: OptionalFetcherDataOptions<TMiddlewares, TValidator>): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>;
}
export interface RequiredFetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType extends ServerFnResponseType> extends FetcherBase {
(opts: RequiredFetcherDataOptions<TMiddlewares, TValidator>): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>;
}
export type FetcherBaseOptions = {
headers?: HeadersInit;
type?: ServerFnType;
signal?: AbortSignal;
};
export type ServerFnType = 'static' | 'dynamic';
export interface OptionalFetcherDataOptions<TMiddlewares, TValidator> extends FetcherBaseOptions {
data?: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>;
}
export interface RequiredFetcherDataOptions<TMiddlewares, TValidator> extends FetcherBaseOptions {
data: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>;
}
export interface FullFetcherData<TMiddlewares, TResponse> {
error: unknown;
result: FetcherData<TResponse>;
context: AssignAllClientSendContext<TMiddlewares>;
}
export type FetcherData<TResponse> = TResponse extends JsonResponse<any> ? SerializerParse<ReturnType<TResponse['json']>> : SerializerParse<TResponse>;
export type RscStream<T> = {
__cacheState: T;
};
export type Method = 'GET' | 'POST';
export type ServerFnResponseType = 'data' | 'full' | 'raw';
export type RawResponse = Response | ReadableStream | Readable | null | string;
export type ServerFnReturnType<TServerFnResponseType extends ServerFnResponseType, TResponse> = TServerFnResponseType extends 'raw' ? RawResponse | Promise<RawResponse> : Promise<SerializerStringify<TResponse>> | SerializerStringify<TResponse>;
export type ServerFn<TMethod, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator, TResponse> = (ctx: ServerFnCtx<TMethod, TServerFnResponseType, TMiddlewares, TValidator>) => ServerFnReturnType<TServerFnResponseType, TResponse>;
export interface ServerFnCtx<TMethod, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> {
method: TMethod;
response: TServerFnResponseType;
data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TValidator>>;
context: Expand<AssignAllServerContext<TMiddlewares>>;
signal: AbortSignal;
}
export type CompiledFetcherFn<TResponse, TServerFnResponseType extends ServerFnResponseType> = {
(opts: CompiledFetcherFnOptions & ServerFnBaseOptions<Method, TServerFnResponseType>): Promise<TResponse>;
url: string;
};
export type ServerFnBaseOptions<TMethod extends Method = 'GET', TServerFnResponseType extends ServerFnResponseType = 'data', TResponse = unknown, TMiddlewares = unknown, TInput = unknown> = {
method: TMethod;
response?: TServerFnResponseType;
validateClient?: boolean;
middleware?: Constrain<TMiddlewares, ReadonlyArray<AnyMiddleware>>;
validator?: ConstrainValidator<TInput>;
extractedFn?: CompiledFetcherFn<TResponse, TServerFnResponseType>;
serverFn?: ServerFn<TMethod, TServerFnResponseType, TMiddlewares, TInput, TResponse>;
functionId: string;
type: ServerFnTypeOrTypeFn<TMethod, TServerFnResponseType, TMiddlewares, AnyValidator>;
};
export type ValidatorSerializerStringify<TValidator> = Validator<SerializerStringifyBy<ResolveValidatorInput<TValidator>, Date | undefined | FormData>, any>;
export type ConstrainValidator<TValidator> = unknown extends TValidator ? TValidator : Constrain<TValidator, ValidatorSerializerStringify<TValidator>>;
export interface ServerFnMiddleware<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TValidator> {
middleware: <const TNewMiddlewares = undefined>(middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>) => ServerFnAfterMiddleware<TMethod, TServerFnResponseType, TNewMiddlewares, TValidator>;
}
export interface ServerFnAfterMiddleware<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> extends ServerFnValidator<TMethod, TServerFnResponseType, TMiddlewares>, ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>, ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {
}
export type ValidatorFn<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares> = <TValidator>(validator: ConstrainValidator<TValidator>) => ServerFnAfterValidator<TMethod, TServerFnResponseType, TMiddlewares, TValidator>;
export interface ServerFnValidator<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares> {
validator: ValidatorFn<TMethod, TServerFnResponseType, TMiddlewares>;
}
export interface ServerFnAfterValidator<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> extends ServerFnMiddleware<TMethod, TServerFnResponseType, TValidator>, ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>, ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {
}
export interface ServerFnTyper<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> {
type: (typer: ServerFnTypeOrTypeFn<TMethod, TServerFnResponseType, TMiddlewares, TValidator>) => ServerFnAfterTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>;
}
export type ServerFnTypeOrTypeFn<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> = ServerFnType | ((ctx: ServerFnCtx<TMethod, TServerFnResponseType, TMiddlewares, TValidator>) => ServerFnType);
export interface ServerFnAfterTyper<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> extends ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {
}
export interface ServerFnHandler<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> {
handler: <TNewResponse>(fn?: ServerFn<TMethod, TServerFnResponseType, TMiddlewares, TValidator, TNewResponse>) => Fetcher<TMiddlewares, TValidator, TNewResponse, TServerFnResponseType>;
}
export interface ServerFnBuilder<TMethod extends Method = 'GET', TServerFnResponseType extends ServerFnResponseType = 'data'> extends ServerFnMiddleware<TMethod, TServerFnResponseType, undefined>, ServerFnValidator<TMethod, TServerFnResponseType, undefined>, ServerFnTyper<TMethod, TServerFnResponseType, undefined, undefined>, ServerFnHandler<TMethod, TServerFnResponseType, undefined, undefined> {
options: ServerFnBaseOptions<TMethod, TServerFnResponseType, unknown, undefined, undefined>;
}
export type StaticCachedResult = {
ctx?: {
result: any;
context: any;
};
error?: any;
};
export type ServerFnStaticCache = {
getItem: (ctx: ServerFnMiddlewareResult) => StaticCachedResult | Promise<StaticCachedResult | undefined>;
setItem: (ctx: ServerFnMiddlewareResult, response: StaticCachedResult) => Promise<void>;
fetchItem: (ctx: ServerFnMiddlewareResult) => StaticCachedResult | Promise<StaticCachedResult | undefined>;
};
export declare let serverFnStaticCache: ServerFnStaticCache | undefined;
export declare function setServerFnStaticCache(cache?: ServerFnStaticCache | (() => ServerFnStaticCache | undefined)): () => void;
export declare function createServerFnStaticCache(serverFnStaticCache: ServerFnStaticCache): ServerFnStaticCache;
export declare function extractFormDataContext(formData: FormData): {
context: unknown;
data: FormData;
} | {
data: FormData;
context?: undefined;
};
export declare function flattenMiddlewares(middlewares: Array<AnyMiddleware>): Array<AnyMiddleware>;
export type ServerFnMiddlewareOptions = {
method: Method;
response?: ServerFnResponseType;
data: any;
headers?: HeadersInit;
signal?: AbortSignal;
sendContext?: any;
context?: any;
type: ServerFnTypeOrTypeFn<any, any, any, any>;
functionId: string;
};
export type ServerFnMiddlewareResult = ServerFnMiddlewareOptions & {
result?: unknown;
error?: unknown;
type: ServerFnTypeOrTypeFn<any, any, any, any>;
};
export type NextFn = (ctx: ServerFnMiddlewareResult) => Promise<ServerFnMiddlewareResult>;
export type MiddlewareFn = (ctx: ServerFnMiddlewareOptions & {
next: NextFn;
}) => Promise<ServerFnMiddlewareResult>;
export declare const applyMiddleware: (middlewareFn: MiddlewareFn, ctx: ServerFnMiddlewareOptions, nextFn: NextFn) => Promise<ServerFnMiddlewareResult>;
export declare function execValidator(validator: AnyValidator, input: unknown): unknown;
export declare function serverFnBaseToMiddleware(options: ServerFnBaseOptions<any, any, any, any, any>): AnyMiddleware;
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const serverOnly = (fn) => fn;
const clientOnly = (fn) => fn;
exports.clientOnly = clientOnly;
exports.serverOnly = serverOnly;
//# sourceMappingURL=envOnly.cjs.map
{"version":3,"file":"envOnly.cjs","sources":["../../src/envOnly.ts"],"sourcesContent":["type EnvOnlyFn = <TFn extends (...args: Array<any>) => any>(fn: TFn) => TFn\n\n// A function that will only be available in the server build\n// If called on the client, it will throw an error\nexport const serverOnly: EnvOnlyFn = (fn) => fn\n\n// A function that will only be available in the client build\n// If called on the server, it will throw an error\nexport const clientOnly: EnvOnlyFn = (fn) => fn\n"],"names":[],"mappings":";;AAIa,MAAA,aAAwB,CAAC,OAAO;AAIhC,MAAA,aAAwB,CAAC,OAAO;;;"}
type EnvOnlyFn = <TFn extends (...args: Array<any>) => any>(fn: TFn) => TFn;
export declare const serverOnly: EnvOnlyFn;
export declare const clientOnly: EnvOnlyFn;
export {};
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const headers = require("./headers.cjs");
function json(payload, init) {
return new Response(JSON.stringify(payload), {
...init,
headers: headers.mergeHeaders(
{ "content-type": "application/json" },
init == null ? void 0 : init.headers
)
});
}
exports.json = json;
//# sourceMappingURL=json.cjs.map
{"version":3,"file":"json.cjs","sources":["../../src/json.ts"],"sourcesContent":["import { mergeHeaders } from './headers'\nimport type { JsonResponse } from './createServerFn'\n\nexport function json<TData>(\n payload: TData,\n init?: ResponseInit,\n): JsonResponse<TData> {\n return new Response(JSON.stringify(payload), {\n ...init,\n headers: mergeHeaders(\n { 'content-type': 'application/json' },\n init?.headers,\n ),\n })\n}\n"],"names":["mergeHeaders"],"mappings":";;;AAGgB,SAAA,KACd,SACA,MACqB;AACrB,SAAO,IAAI,SAAS,KAAK,UAAU,OAAO,GAAG;AAAA,IAC3C,GAAG;AAAA,IACH,SAASA,QAAA;AAAA,MACP,EAAE,gBAAgB,mBAAmB;AAAA,MACrC,6BAAM;AAAA,IAAA;AAAA,EACR,CACD;AACH;;"}
import { JsonResponse } from './createServerFn.cjs';
export declare function json<TData>(payload: TData, init?: ResponseInit): JsonResponse<TData>;
"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const globalMiddleware = [];
function registerGlobalMiddleware(options) {
globalMiddleware.push(...options.middleware);
}
exports.globalMiddleware = globalMiddleware;
exports.registerGlobalMiddleware = registerGlobalMiddleware;
//# sourceMappingURL=registerGlobalMiddleware.cjs.map
{"version":3,"file":"registerGlobalMiddleware.cjs","sources":["../../src/registerGlobalMiddleware.ts"],"sourcesContent":["import type { AnyMiddleware } from './createMiddleware'\n\nexport const globalMiddleware: Array<AnyMiddleware> = []\n\nexport function registerGlobalMiddleware(options: {\n middleware: Array<AnyMiddleware>\n}) {\n globalMiddleware.push(...options.middleware)\n}\n"],"names":[],"mappings":";;AAEO,MAAM,mBAAyC,CAAA;AAE/C,SAAS,yBAAyB,SAEtC;AACgB,mBAAA,KAAK,GAAG,QAAQ,UAAU;AAC7C;;;"}
import { AnyMiddleware } from './createMiddleware.cjs';
export declare const globalMiddleware: Array<AnyMiddleware>;
export declare function registerGlobalMiddleware(options: {
middleware: Array<AnyMiddleware>;
}): void;
export type IsomorphicFn<TArgs extends Array<any> = [], TServer = undefined, TClient = undefined> = (...args: TArgs) => TServer | TClient;
export interface ServerOnlyFn<TArgs extends Array<any>, TServer> extends IsomorphicFn<TArgs, TServer> {
client: <TClient>(clientImpl: (...args: TArgs) => TClient) => IsomorphicFn<TArgs, TServer, TClient>;
}
export interface ClientOnlyFn<TArgs extends Array<any>, TClient> extends IsomorphicFn<TArgs, undefined, TClient> {
server: <TServer>(serverImpl: (...args: TArgs) => TServer) => IsomorphicFn<TArgs, TServer, TClient>;
}
export interface IsomorphicFnBase extends IsomorphicFn {
server: <TArgs extends Array<any>, TServer>(serverImpl: (...args: TArgs) => TServer) => ServerOnlyFn<TArgs, TServer>;
client: <TArgs extends Array<any>, TClient>(clientImpl: (...args: TArgs) => TClient) => ClientOnlyFn<TArgs, TClient>;
}
export declare function createIsomorphicFn(): IsomorphicFnBase;
function createIsomorphicFn() {
return null;
}
export {
createIsomorphicFn
};
//# sourceMappingURL=createIsomorphicFn.js.map
{"version":3,"file":"createIsomorphicFn.js","sources":["../../src/createIsomorphicFn.ts"],"sourcesContent":["// a function that can have different implementations on the client and server.\n// implementations not provided will default to a no-op function.\n\nexport type IsomorphicFn<\n TArgs extends Array<any> = [],\n TServer = undefined,\n TClient = undefined,\n> = (...args: TArgs) => TServer | TClient\n\nexport interface ServerOnlyFn<TArgs extends Array<any>, TServer>\n extends IsomorphicFn<TArgs, TServer> {\n client: <TClient>(\n clientImpl: (...args: TArgs) => TClient,\n ) => IsomorphicFn<TArgs, TServer, TClient>\n}\n\nexport interface ClientOnlyFn<TArgs extends Array<any>, TClient>\n extends IsomorphicFn<TArgs, undefined, TClient> {\n server: <TServer>(\n serverImpl: (...args: TArgs) => TServer,\n ) => IsomorphicFn<TArgs, TServer, TClient>\n}\n\nexport interface IsomorphicFnBase extends IsomorphicFn {\n server: <TArgs extends Array<any>, TServer>(\n serverImpl: (...args: TArgs) => TServer,\n ) => ServerOnlyFn<TArgs, TServer>\n client: <TArgs extends Array<any>, TClient>(\n clientImpl: (...args: TArgs) => TClient,\n ) => ClientOnlyFn<TArgs, TClient>\n}\n\n// this is a dummy function, it will be replaced by the transformer\nexport function createIsomorphicFn(): IsomorphicFnBase {\n return null!\n}\n"],"names":[],"mappings":"AAiCO,SAAS,qBAAuC;AAC9C,SAAA;AACT;"}
import { ConstrainValidator, Method, ServerFnResponseType, ServerFnTypeOrTypeFn } from './createServerFn.js';
import { Assign, Constrain, Expand, IntersectAssign, ResolveValidatorInput, ResolveValidatorOutput, SerializerStringify } from '@tanstack/router-core';
export type AssignAllMiddleware<TMiddlewares, TType extends keyof AnyMiddleware['_types'], TAcc = undefined> = TMiddlewares extends readonly [
infer TMiddleware extends AnyMiddleware,
...infer TRest
] ? AssignAllMiddleware<TRest, TType, Assign<TAcc, TMiddleware['_types'][TType]>> : TAcc;
/**
* Recursively resolve the client context type produced by a sequence of middleware
*/
export type AssignAllClientContextBeforeNext<TMiddlewares, TClientContext = undefined> = unknown extends TClientContext ? TClientContext : Assign<AssignAllMiddleware<TMiddlewares, 'allClientContextBeforeNext'>, TClientContext>;
export type AssignAllClientSendContext<TMiddlewares, TSendContext = undefined> = unknown extends TSendContext ? TSendContext : Assign<AssignAllMiddleware<TMiddlewares, 'allClientSendContext'>, TSendContext>;
export type AssignAllClientContextAfterNext<TMiddlewares, TClientContext = undefined, TSendContext = undefined> = unknown extends TClientContext ? Assign<TClientContext, TSendContext> : Assign<AssignAllMiddleware<TMiddlewares, 'allClientContextAfterNext'>, Assign<TClientContext, TSendContext>>;
/**
* Recursively resolve the server context type produced by a sequence of middleware
*/
export type AssignAllServerContext<TMiddlewares, TSendContext = undefined, TServerContext = undefined> = unknown extends TSendContext ? Assign<TSendContext, TServerContext> : Assign<AssignAllMiddleware<TMiddlewares, 'allServerContext'>, Assign<TSendContext, TServerContext>>;
export type AssignAllServerSendContext<TMiddlewares, TSendContext = undefined> = unknown extends TSendContext ? TSendContext : Assign<AssignAllMiddleware<TMiddlewares, 'allServerSendContext'>, TSendContext>;
export type IntersectAllMiddleware<TMiddlewares, TType extends keyof AnyMiddleware['_types'], TAcc = undefined> = TMiddlewares extends readonly [
infer TMiddleware extends AnyMiddleware,
...infer TRest
] ? IntersectAllMiddleware<TRest, TType, IntersectAssign<TAcc, TMiddleware['_types'][TType]>> : TAcc;
/**
* Recursively resolve the input type produced by a sequence of middleware
*/
export type IntersectAllValidatorInputs<TMiddlewares, TValidator> = unknown extends TValidator ? TValidator : IntersectAssign<IntersectAllMiddleware<TMiddlewares, 'allInput'>, TValidator extends undefined ? undefined : ResolveValidatorInput<TValidator>>;
/**
* Recursively merge the output type produced by a sequence of middleware
*/
export type IntersectAllValidatorOutputs<TMiddlewares, TValidator> = unknown extends TValidator ? TValidator : IntersectAssign<IntersectAllMiddleware<TMiddlewares, 'allOutput'>, TValidator extends undefined ? undefined : ResolveValidatorOutput<TValidator>>;
export interface MiddlewareOptions<in out TMiddlewares, in out TValidator, in out TServerContext, in out TClientContext, in out TServerFnResponseType extends ServerFnResponseType> {
validateClient?: boolean;
middleware?: TMiddlewares;
validator?: ConstrainValidator<TValidator>;
client?: MiddlewareClientFn<TMiddlewares, TValidator, TServerContext, TClientContext, TServerFnResponseType>;
server?: MiddlewareServerFn<TMiddlewares, TValidator, TServerContext, unknown, unknown, TServerFnResponseType>;
}
export type MiddlewareServerNextFn<TMiddlewares, TServerSendContext> = <TNewServerContext = undefined, TSendContext = undefined>(ctx?: {
context?: TNewServerContext;
sendContext?: SerializerStringify<TSendContext>;
}) => Promise<ServerResultWithContext<TMiddlewares, TServerSendContext, TNewServerContext, TSendContext>>;
export interface MiddlewareServerFnOptions<in out TMiddlewares, in out TValidator, in out TServerSendContext, in out TServerFnResponseType> {
data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TValidator>>;
context: Expand<AssignAllServerContext<TMiddlewares, TServerSendContext>>;
next: MiddlewareServerNextFn<TMiddlewares, TServerSendContext>;
response: TServerFnResponseType;
method: Method;
filename: string;
functionId: string;
signal: AbortSignal;
}
export type MiddlewareServerFn<TMiddlewares, TValidator, TServerSendContext, TNewServerContext, TSendContext, TServerFnResponseType extends ServerFnResponseType> = (options: MiddlewareServerFnOptions<TMiddlewares, TValidator, TServerSendContext, TServerFnResponseType>) => MiddlewareServerFnResult<TMiddlewares, TServerSendContext, TNewServerContext, TSendContext>;
export type MiddlewareServerFnResult<TMiddlewares, TServerSendContext, TServerContext, TSendContext> = Promise<ServerResultWithContext<TMiddlewares, TServerSendContext, TServerContext, TSendContext>> | ServerResultWithContext<TMiddlewares, TServerSendContext, TServerContext, TSendContext>;
export type MiddlewareClientNextFn<TMiddlewares> = <TSendContext = undefined, TNewClientContext = undefined>(ctx?: {
context?: TNewClientContext;
sendContext?: SerializerStringify<TSendContext>;
headers?: HeadersInit;
}) => Promise<ClientResultWithContext<TMiddlewares, TSendContext, TNewClientContext>>;
export interface MiddlewareClientFnOptions<in out TMiddlewares, in out TValidator, in out TServerFnResponseType extends ServerFnResponseType> {
data: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>;
context: Expand<AssignAllClientContextBeforeNext<TMiddlewares>>;
sendContext: Expand<AssignAllServerSendContext<TMiddlewares>>;
method: Method;
response: TServerFnResponseType;
signal: AbortSignal;
next: MiddlewareClientNextFn<TMiddlewares>;
filename: string;
functionId: string;
type: ServerFnTypeOrTypeFn<Method, TServerFnResponseType, TMiddlewares, TValidator>;
}
export type MiddlewareClientFn<TMiddlewares, TValidator, TSendContext, TClientContext, TServerFnResponseType extends ServerFnResponseType> = (options: MiddlewareClientFnOptions<TMiddlewares, TValidator, TServerFnResponseType>) => MiddlewareClientFnResult<TMiddlewares, TSendContext, TClientContext>;
export type MiddlewareClientFnResult<TMiddlewares, TSendContext, TClientContext> = Promise<ClientResultWithContext<TMiddlewares, TSendContext, TClientContext>> | ClientResultWithContext<TMiddlewares, TSendContext, TClientContext>;
export type ServerResultWithContext<in out TMiddlewares, in out TServerSendContext, in out TServerContext, in out TSendContext> = {
'use functions must return the result of next()': true;
_types: {
context: TServerContext;
sendContext: TSendContext;
};
context: Expand<AssignAllServerContext<TMiddlewares, TServerSendContext, TServerContext>>;
sendContext: Expand<AssignAllClientSendContext<TMiddlewares, TSendContext>>;
};
export type ClientResultWithContext<in out TMiddlewares, in out TSendContext, in out TClientContext> = {
'use functions must return the result of next()': true;
context: Expand<AssignAllClientContextAfterNext<TMiddlewares, TClientContext>>;
sendContext: Expand<AssignAllServerSendContext<TMiddlewares, TSendContext>>;
headers: HeadersInit;
};
export type AnyMiddleware = MiddlewareWithTypes<any, any, any, any, any, any, any>;
export interface MiddlewareTypes<in out TMiddlewares, in out TValidator, in out TServerContext, in out TServerSendContext, in out TClientContext, in out TClientSendContext> {
middlewares: TMiddlewares;
input: ResolveValidatorInput<TValidator>;
allInput: IntersectAllValidatorInputs<TMiddlewares, TValidator>;
output: ResolveValidatorOutput<TValidator>;
allOutput: IntersectAllValidatorOutputs<TMiddlewares, TValidator>;
clientContext: TClientContext;
allClientContextBeforeNext: AssignAllClientContextBeforeNext<TMiddlewares, TClientContext>;
allClientContextAfterNext: AssignAllClientContextAfterNext<TMiddlewares, TClientContext, TClientSendContext>;
serverContext: TServerContext;
serverSendContext: TServerSendContext;
allServerSendContext: AssignAllServerSendContext<TMiddlewares, TServerSendContext>;
allServerContext: AssignAllServerContext<TMiddlewares, TServerSendContext, TServerContext>;
clientSendContext: TClientSendContext;
allClientSendContext: AssignAllClientSendContext<TMiddlewares, TClientSendContext>;
validator: TValidator;
}
export interface MiddlewareWithTypes<TMiddlewares, TValidator, TServerContext, TServerSendContext, TClientContext, TClientSendContext, TServerFnResponseType extends ServerFnResponseType> {
_types: MiddlewareTypes<TMiddlewares, TValidator, TServerContext, TServerSendContext, TClientContext, TClientSendContext>;
options: MiddlewareOptions<TMiddlewares, TValidator, TServerContext, TClientContext, TServerFnResponseType>;
}
export interface MiddlewareAfterValidator<TMiddlewares, TValidator, TServerFnResponseType extends ServerFnResponseType> extends MiddlewareWithTypes<TMiddlewares, TValidator, undefined, undefined, undefined, undefined, ServerFnResponseType>, MiddlewareServer<TMiddlewares, TValidator, undefined, undefined, TServerFnResponseType>, MiddlewareClient<TMiddlewares, TValidator, ServerFnResponseType> {
}
export interface MiddlewareValidator<TMiddlewares, TServerFnResponseType extends ServerFnResponseType> {
validator: <TNewValidator>(input: ConstrainValidator<TNewValidator>) => MiddlewareAfterValidator<TMiddlewares, TNewValidator, TServerFnResponseType>;
}
export interface MiddlewareAfterServer<TMiddlewares, TValidator, TServerContext, TServerSendContext, TClientContext, TClientSendContext, TServerFnResponseType extends ServerFnResponseType> extends MiddlewareWithTypes<TMiddlewares, TValidator, TServerContext, TServerSendContext, TClientContext, TClientSendContext, TServerFnResponseType> {
}
export interface MiddlewareServer<TMiddlewares, TValidator, TServerSendContext, TClientContext, TServerFnResponseType extends ServerFnResponseType> {
server: <TNewServerContext = undefined, TSendContext = undefined>(server: MiddlewareServerFn<TMiddlewares, TValidator, TServerSendContext, TNewServerContext, TSendContext, TServerFnResponseType>) => MiddlewareAfterServer<TMiddlewares, TValidator, TNewServerContext, TServerSendContext, TClientContext, TSendContext, ServerFnResponseType>;
}
export interface MiddlewareAfterClient<TMiddlewares, TValidator, TServerSendContext, TClientContext, TServerFnResponseType extends ServerFnResponseType> extends MiddlewareWithTypes<TMiddlewares, TValidator, undefined, TServerSendContext, TClientContext, undefined, TServerFnResponseType>, MiddlewareServer<TMiddlewares, TValidator, TServerSendContext, TClientContext, TServerFnResponseType> {
}
export interface MiddlewareClient<TMiddlewares, TValidator, TServerFnResponseType extends ServerFnResponseType> {
client: <TSendServerContext = undefined, TNewClientContext = undefined>(client: MiddlewareClientFn<TMiddlewares, TValidator, TSendServerContext, TNewClientContext, TServerFnResponseType>) => MiddlewareAfterClient<TMiddlewares, TValidator, TSendServerContext, TNewClientContext, ServerFnResponseType>;
}
export interface MiddlewareAfterMiddleware<TMiddlewares, TServerFnResponseType extends ServerFnResponseType> extends MiddlewareWithTypes<TMiddlewares, undefined, undefined, undefined, undefined, undefined, TServerFnResponseType>, MiddlewareServer<TMiddlewares, undefined, undefined, undefined, TServerFnResponseType>, MiddlewareClient<TMiddlewares, undefined, TServerFnResponseType>, MiddlewareValidator<TMiddlewares, TServerFnResponseType> {
}
export interface Middleware<TServerFnResponseType extends ServerFnResponseType> extends MiddlewareAfterMiddleware<unknown, TServerFnResponseType> {
middleware: <const TNewMiddlewares = undefined>(middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>) => MiddlewareAfterMiddleware<TNewMiddlewares, TServerFnResponseType>;
}
export declare function createMiddleware(options?: {
validateClient?: boolean;
}, __opts?: MiddlewareOptions<unknown, undefined, undefined, undefined, ServerFnResponseType>): Middleware<ServerFnResponseType>;
function createMiddleware(options, __opts) {
const resolvedOptions = __opts || (options || {});
return {
options: resolvedOptions,
middleware: (middleware) => {
return createMiddleware(
void 0,
Object.assign(resolvedOptions, { middleware })
);
},
validator: (validator) => {
return createMiddleware(
void 0,
Object.assign(resolvedOptions, { validator })
);
},
client: (client) => {
return createMiddleware(
void 0,
Object.assign(resolvedOptions, { client })
);
},
server: (server) => {
return createMiddleware(
void 0,
Object.assign(resolvedOptions, { server })
);
}
};
}
export {
createMiddleware
};
//# sourceMappingURL=createMiddleware.js.map
{"version":3,"file":"createMiddleware.js","sources":["../../src/createMiddleware.ts"],"sourcesContent":["import type {\n ConstrainValidator,\n Method,\n ServerFnResponseType,\n ServerFnTypeOrTypeFn,\n} from './createServerFn'\nimport type {\n Assign,\n Constrain,\n Expand,\n IntersectAssign,\n ResolveValidatorInput,\n ResolveValidatorOutput,\n SerializerStringify,\n} from '@tanstack/router-core'\n\nexport type AssignAllMiddleware<\n TMiddlewares,\n TType extends keyof AnyMiddleware['_types'],\n TAcc = undefined,\n> = TMiddlewares extends readonly [\n infer TMiddleware extends AnyMiddleware,\n ...infer TRest,\n]\n ? AssignAllMiddleware<\n TRest,\n TType,\n Assign<TAcc, TMiddleware['_types'][TType]>\n >\n : TAcc\n\n/**\n * Recursively resolve the client context type produced by a sequence of middleware\n */\nexport type AssignAllClientContextBeforeNext<\n TMiddlewares,\n TClientContext = undefined,\n> = unknown extends TClientContext\n ? TClientContext\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allClientContextBeforeNext'>,\n TClientContext\n >\n\nexport type AssignAllClientSendContext<\n TMiddlewares,\n TSendContext = undefined,\n> = unknown extends TSendContext\n ? TSendContext\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allClientSendContext'>,\n TSendContext\n >\n\nexport type AssignAllClientContextAfterNext<\n TMiddlewares,\n TClientContext = undefined,\n TSendContext = undefined,\n> = unknown extends TClientContext\n ? Assign<TClientContext, TSendContext>\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allClientContextAfterNext'>,\n Assign<TClientContext, TSendContext>\n >\n\n/**\n * Recursively resolve the server context type produced by a sequence of middleware\n */\nexport type AssignAllServerContext<\n TMiddlewares,\n TSendContext = undefined,\n TServerContext = undefined,\n> = unknown extends TSendContext\n ? Assign<TSendContext, TServerContext>\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allServerContext'>,\n Assign<TSendContext, TServerContext>\n >\n\nexport type AssignAllServerSendContext<\n TMiddlewares,\n TSendContext = undefined,\n> = unknown extends TSendContext\n ? TSendContext\n : Assign<\n AssignAllMiddleware<TMiddlewares, 'allServerSendContext'>,\n TSendContext\n >\n\nexport type IntersectAllMiddleware<\n TMiddlewares,\n TType extends keyof AnyMiddleware['_types'],\n TAcc = undefined,\n> = TMiddlewares extends readonly [\n infer TMiddleware extends AnyMiddleware,\n ...infer TRest,\n]\n ? IntersectAllMiddleware<\n TRest,\n TType,\n IntersectAssign<TAcc, TMiddleware['_types'][TType]>\n >\n : TAcc\n\n/**\n * Recursively resolve the input type produced by a sequence of middleware\n */\nexport type IntersectAllValidatorInputs<TMiddlewares, TValidator> =\n unknown extends TValidator\n ? TValidator\n : IntersectAssign<\n IntersectAllMiddleware<TMiddlewares, 'allInput'>,\n TValidator extends undefined\n ? undefined\n : ResolveValidatorInput<TValidator>\n >\n/**\n * Recursively merge the output type produced by a sequence of middleware\n */\nexport type IntersectAllValidatorOutputs<TMiddlewares, TValidator> =\n unknown extends TValidator\n ? TValidator\n : IntersectAssign<\n IntersectAllMiddleware<TMiddlewares, 'allOutput'>,\n TValidator extends undefined\n ? undefined\n : ResolveValidatorOutput<TValidator>\n >\n\nexport interface MiddlewareOptions<\n in out TMiddlewares,\n in out TValidator,\n in out TServerContext,\n in out TClientContext,\n in out TServerFnResponseType extends ServerFnResponseType,\n> {\n validateClient?: boolean\n middleware?: TMiddlewares\n validator?: ConstrainValidator<TValidator>\n client?: MiddlewareClientFn<\n TMiddlewares,\n TValidator,\n TServerContext,\n TClientContext,\n TServerFnResponseType\n >\n server?: MiddlewareServerFn<\n TMiddlewares,\n TValidator,\n TServerContext,\n unknown,\n unknown,\n TServerFnResponseType\n >\n}\n\nexport type MiddlewareServerNextFn<TMiddlewares, TServerSendContext> = <\n TNewServerContext = undefined,\n TSendContext = undefined,\n>(ctx?: {\n context?: TNewServerContext\n sendContext?: SerializerStringify<TSendContext>\n}) => Promise<\n ServerResultWithContext<\n TMiddlewares,\n TServerSendContext,\n TNewServerContext,\n TSendContext\n >\n>\n\nexport interface MiddlewareServerFnOptions<\n in out TMiddlewares,\n in out TValidator,\n in out TServerSendContext,\n in out TServerFnResponseType,\n> {\n data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TValidator>>\n context: Expand<AssignAllServerContext<TMiddlewares, TServerSendContext>>\n next: MiddlewareServerNextFn<TMiddlewares, TServerSendContext>\n response: TServerFnResponseType\n method: Method\n filename: string\n functionId: string\n signal: AbortSignal\n}\n\nexport type MiddlewareServerFn<\n TMiddlewares,\n TValidator,\n TServerSendContext,\n TNewServerContext,\n TSendContext,\n TServerFnResponseType extends ServerFnResponseType,\n> = (\n options: MiddlewareServerFnOptions<\n TMiddlewares,\n TValidator,\n TServerSendContext,\n TServerFnResponseType\n >,\n) => MiddlewareServerFnResult<\n TMiddlewares,\n TServerSendContext,\n TNewServerContext,\n TSendContext\n>\n\nexport type MiddlewareServerFnResult<\n TMiddlewares,\n TServerSendContext,\n TServerContext,\n TSendContext,\n> =\n | Promise<\n ServerResultWithContext<\n TMiddlewares,\n TServerSendContext,\n TServerContext,\n TSendContext\n >\n >\n | ServerResultWithContext<\n TMiddlewares,\n TServerSendContext,\n TServerContext,\n TSendContext\n >\n\nexport type MiddlewareClientNextFn<TMiddlewares> = <\n TSendContext = undefined,\n TNewClientContext = undefined,\n>(ctx?: {\n context?: TNewClientContext\n sendContext?: SerializerStringify<TSendContext>\n headers?: HeadersInit\n}) => Promise<\n ClientResultWithContext<TMiddlewares, TSendContext, TNewClientContext>\n>\n\nexport interface MiddlewareClientFnOptions<\n in out TMiddlewares,\n in out TValidator,\n in out TServerFnResponseType extends ServerFnResponseType,\n> {\n data: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>\n context: Expand<AssignAllClientContextBeforeNext<TMiddlewares>>\n sendContext: Expand<AssignAllServerSendContext<TMiddlewares>>\n method: Method\n response: TServerFnResponseType\n signal: AbortSignal\n next: MiddlewareClientNextFn<TMiddlewares>\n filename: string\n functionId: string\n type: ServerFnTypeOrTypeFn<\n Method,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n >\n}\n\nexport type MiddlewareClientFn<\n TMiddlewares,\n TValidator,\n TSendContext,\n TClientContext,\n TServerFnResponseType extends ServerFnResponseType,\n> = (\n options: MiddlewareClientFnOptions<\n TMiddlewares,\n TValidator,\n TServerFnResponseType\n >,\n) => MiddlewareClientFnResult<TMiddlewares, TSendContext, TClientContext>\n\nexport type MiddlewareClientFnResult<\n TMiddlewares,\n TSendContext,\n TClientContext,\n> =\n | Promise<ClientResultWithContext<TMiddlewares, TSendContext, TClientContext>>\n | ClientResultWithContext<TMiddlewares, TSendContext, TClientContext>\n\nexport type ServerResultWithContext<\n in out TMiddlewares,\n in out TServerSendContext,\n in out TServerContext,\n in out TSendContext,\n> = {\n 'use functions must return the result of next()': true\n _types: {\n context: TServerContext\n sendContext: TSendContext\n }\n context: Expand<\n AssignAllServerContext<TMiddlewares, TServerSendContext, TServerContext>\n >\n sendContext: Expand<AssignAllClientSendContext<TMiddlewares, TSendContext>>\n}\n\nexport type ClientResultWithContext<\n in out TMiddlewares,\n in out TSendContext,\n in out TClientContext,\n> = {\n 'use functions must return the result of next()': true\n context: Expand<AssignAllClientContextAfterNext<TMiddlewares, TClientContext>>\n sendContext: Expand<AssignAllServerSendContext<TMiddlewares, TSendContext>>\n headers: HeadersInit\n}\n\nexport type AnyMiddleware = MiddlewareWithTypes<\n any,\n any,\n any,\n any,\n any,\n any,\n any\n>\n\nexport interface MiddlewareTypes<\n in out TMiddlewares,\n in out TValidator,\n in out TServerContext,\n in out TServerSendContext,\n in out TClientContext,\n in out TClientSendContext,\n> {\n middlewares: TMiddlewares\n input: ResolveValidatorInput<TValidator>\n allInput: IntersectAllValidatorInputs<TMiddlewares, TValidator>\n output: ResolveValidatorOutput<TValidator>\n allOutput: IntersectAllValidatorOutputs<TMiddlewares, TValidator>\n clientContext: TClientContext\n allClientContextBeforeNext: AssignAllClientContextBeforeNext<\n TMiddlewares,\n TClientContext\n >\n allClientContextAfterNext: AssignAllClientContextAfterNext<\n TMiddlewares,\n TClientContext,\n TClientSendContext\n >\n serverContext: TServerContext\n serverSendContext: TServerSendContext\n allServerSendContext: AssignAllServerSendContext<\n TMiddlewares,\n TServerSendContext\n >\n allServerContext: AssignAllServerContext<\n TMiddlewares,\n TServerSendContext,\n TServerContext\n >\n clientSendContext: TClientSendContext\n allClientSendContext: AssignAllClientSendContext<\n TMiddlewares,\n TClientSendContext\n >\n validator: TValidator\n}\n\nexport interface MiddlewareWithTypes<\n TMiddlewares,\n TValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext,\n TServerFnResponseType extends ServerFnResponseType,\n> {\n _types: MiddlewareTypes<\n TMiddlewares,\n TValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext\n >\n options: MiddlewareOptions<\n TMiddlewares,\n TValidator,\n TServerContext,\n TClientContext,\n TServerFnResponseType\n >\n}\n\nexport interface MiddlewareAfterValidator<\n TMiddlewares,\n TValidator,\n TServerFnResponseType extends ServerFnResponseType,\n> extends MiddlewareWithTypes<\n TMiddlewares,\n TValidator,\n undefined,\n undefined,\n undefined,\n undefined,\n ServerFnResponseType\n >,\n MiddlewareServer<\n TMiddlewares,\n TValidator,\n undefined,\n undefined,\n TServerFnResponseType\n >,\n MiddlewareClient<TMiddlewares, TValidator, ServerFnResponseType> {}\n\nexport interface MiddlewareValidator<\n TMiddlewares,\n TServerFnResponseType extends ServerFnResponseType,\n> {\n validator: <TNewValidator>(\n input: ConstrainValidator<TNewValidator>,\n ) => MiddlewareAfterValidator<\n TMiddlewares,\n TNewValidator,\n TServerFnResponseType\n >\n}\n\nexport interface MiddlewareAfterServer<\n TMiddlewares,\n TValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext,\n TServerFnResponseType extends ServerFnResponseType,\n> extends MiddlewareWithTypes<\n TMiddlewares,\n TValidator,\n TServerContext,\n TServerSendContext,\n TClientContext,\n TClientSendContext,\n TServerFnResponseType\n > {}\n\nexport interface MiddlewareServer<\n TMiddlewares,\n TValidator,\n TServerSendContext,\n TClientContext,\n TServerFnResponseType extends ServerFnResponseType,\n> {\n server: <TNewServerContext = undefined, TSendContext = undefined>(\n server: MiddlewareServerFn<\n TMiddlewares,\n TValidator,\n TServerSendContext,\n TNewServerContext,\n TSendContext,\n TServerFnResponseType\n >,\n ) => MiddlewareAfterServer<\n TMiddlewares,\n TValidator,\n TNewServerContext,\n TServerSendContext,\n TClientContext,\n TSendContext,\n ServerFnResponseType\n >\n}\n\nexport interface MiddlewareAfterClient<\n TMiddlewares,\n TValidator,\n TServerSendContext,\n TClientContext,\n TServerFnResponseType extends ServerFnResponseType,\n> extends MiddlewareWithTypes<\n TMiddlewares,\n TValidator,\n undefined,\n TServerSendContext,\n TClientContext,\n undefined,\n TServerFnResponseType\n >,\n MiddlewareServer<\n TMiddlewares,\n TValidator,\n TServerSendContext,\n TClientContext,\n TServerFnResponseType\n > {}\n\nexport interface MiddlewareClient<\n TMiddlewares,\n TValidator,\n TServerFnResponseType extends ServerFnResponseType,\n> {\n client: <TSendServerContext = undefined, TNewClientContext = undefined>(\n client: MiddlewareClientFn<\n TMiddlewares,\n TValidator,\n TSendServerContext,\n TNewClientContext,\n TServerFnResponseType\n >,\n ) => MiddlewareAfterClient<\n TMiddlewares,\n TValidator,\n TSendServerContext,\n TNewClientContext,\n ServerFnResponseType\n >\n}\n\nexport interface MiddlewareAfterMiddleware<\n TMiddlewares,\n TServerFnResponseType extends ServerFnResponseType,\n> extends MiddlewareWithTypes<\n TMiddlewares,\n undefined,\n undefined,\n undefined,\n undefined,\n undefined,\n TServerFnResponseType\n >,\n MiddlewareServer<\n TMiddlewares,\n undefined,\n undefined,\n undefined,\n TServerFnResponseType\n >,\n MiddlewareClient<TMiddlewares, undefined, TServerFnResponseType>,\n MiddlewareValidator<TMiddlewares, TServerFnResponseType> {}\n\nexport interface Middleware<TServerFnResponseType extends ServerFnResponseType>\n extends MiddlewareAfterMiddleware<unknown, TServerFnResponseType> {\n middleware: <const TNewMiddlewares = undefined>(\n middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>,\n ) => MiddlewareAfterMiddleware<TNewMiddlewares, TServerFnResponseType>\n}\n\nexport function createMiddleware(\n options?: {\n validateClient?: boolean\n },\n __opts?: MiddlewareOptions<\n unknown,\n undefined,\n undefined,\n undefined,\n ServerFnResponseType\n >,\n): Middleware<ServerFnResponseType> {\n // const resolvedOptions = (__opts || options) as MiddlewareOptions<\n const resolvedOptions =\n __opts ||\n ((options || {}) as MiddlewareOptions<\n unknown,\n undefined,\n undefined,\n undefined,\n ServerFnResponseType\n >)\n\n return {\n options: resolvedOptions as any,\n middleware: (middleware: any) => {\n return createMiddleware(\n undefined,\n Object.assign(resolvedOptions, { middleware }),\n ) as any\n },\n validator: (validator: any) => {\n return createMiddleware(\n undefined,\n Object.assign(resolvedOptions, { validator }),\n ) as any\n },\n client: (client: any) => {\n return createMiddleware(\n undefined,\n Object.assign(resolvedOptions, { client }),\n ) as any\n },\n server: (server: any) => {\n return createMiddleware(\n undefined,\n Object.assign(resolvedOptions, { server }),\n ) as any\n },\n } as unknown as Middleware<ServerFnResponseType>\n}\n"],"names":[],"mappings":"AAgiBgB,SAAA,iBACd,SAGA,QAOkC;AAE5B,QAAA,kBACJ,WACE,WAAW;AAQR,SAAA;AAAA,IACL,SAAS;AAAA,IACT,YAAY,CAAC,eAAoB;AACxB,aAAA;AAAA,QACL;AAAA,QACA,OAAO,OAAO,iBAAiB,EAAE,WAAY,CAAA;AAAA,MAC/C;AAAA,IACF;AAAA,IACA,WAAW,CAAC,cAAmB;AACtB,aAAA;AAAA,QACL;AAAA,QACA,OAAO,OAAO,iBAAiB,EAAE,UAAW,CAAA;AAAA,MAC9C;AAAA,IACF;AAAA,IACA,QAAQ,CAAC,WAAgB;AAChB,aAAA;AAAA,QACL;AAAA,QACA,OAAO,OAAO,iBAAiB,EAAE,OAAQ,CAAA;AAAA,MAC3C;AAAA,IACF;AAAA,IACA,QAAQ,CAAC,WAAgB;AAChB,aAAA;AAAA,QACL;AAAA,QACA,OAAO,OAAO,iBAAiB,EAAE,OAAQ,CAAA;AAAA,MAC3C;AAAA,IAAA;AAAA,EAEJ;AACF;"}
import { Readable } from 'node:stream';
import { AnyValidator, Constrain, Expand, ResolveValidatorInput, SerializerParse, SerializerStringify, SerializerStringifyBy, Validator } from '@tanstack/router-core';
import { AnyMiddleware, AssignAllClientSendContext, AssignAllServerContext, IntersectAllValidatorInputs, IntersectAllValidatorOutputs } from './createMiddleware.js';
export interface JsonResponse<TData> extends Response {
json: () => Promise<TData>;
}
export type CompiledFetcherFnOptions = {
method: Method;
data: unknown;
response?: ServerFnResponseType;
headers?: HeadersInit;
signal?: AbortSignal;
context?: any;
};
export type Fetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType extends ServerFnResponseType> = undefined extends IntersectAllValidatorInputs<TMiddlewares, TValidator> ? OptionalFetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType> : RequiredFetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType>;
export interface FetcherBase {
url: string;
__executeServer: (opts: {
method: Method;
response?: ServerFnResponseType;
data: unknown;
headers?: HeadersInit;
context?: any;
signal: AbortSignal;
}) => Promise<unknown>;
}
export type FetchResult<TMiddlewares, TResponse, TServerFnResponseType extends ServerFnResponseType> = TServerFnResponseType extends 'raw' ? Promise<Response> : TServerFnResponseType extends 'full' ? Promise<FullFetcherData<TMiddlewares, TResponse>> : Promise<FetcherData<TResponse>>;
export interface OptionalFetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType extends ServerFnResponseType> extends FetcherBase {
(options?: OptionalFetcherDataOptions<TMiddlewares, TValidator>): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>;
}
export interface RequiredFetcher<TMiddlewares, TValidator, TResponse, TServerFnResponseType extends ServerFnResponseType> extends FetcherBase {
(opts: RequiredFetcherDataOptions<TMiddlewares, TValidator>): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>;
}
export type FetcherBaseOptions = {
headers?: HeadersInit;
type?: ServerFnType;
signal?: AbortSignal;
};
export type ServerFnType = 'static' | 'dynamic';
export interface OptionalFetcherDataOptions<TMiddlewares, TValidator> extends FetcherBaseOptions {
data?: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>;
}
export interface RequiredFetcherDataOptions<TMiddlewares, TValidator> extends FetcherBaseOptions {
data: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>;
}
export interface FullFetcherData<TMiddlewares, TResponse> {
error: unknown;
result: FetcherData<TResponse>;
context: AssignAllClientSendContext<TMiddlewares>;
}
export type FetcherData<TResponse> = TResponse extends JsonResponse<any> ? SerializerParse<ReturnType<TResponse['json']>> : SerializerParse<TResponse>;
export type RscStream<T> = {
__cacheState: T;
};
export type Method = 'GET' | 'POST';
export type ServerFnResponseType = 'data' | 'full' | 'raw';
export type RawResponse = Response | ReadableStream | Readable | null | string;
export type ServerFnReturnType<TServerFnResponseType extends ServerFnResponseType, TResponse> = TServerFnResponseType extends 'raw' ? RawResponse | Promise<RawResponse> : Promise<SerializerStringify<TResponse>> | SerializerStringify<TResponse>;
export type ServerFn<TMethod, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator, TResponse> = (ctx: ServerFnCtx<TMethod, TServerFnResponseType, TMiddlewares, TValidator>) => ServerFnReturnType<TServerFnResponseType, TResponse>;
export interface ServerFnCtx<TMethod, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> {
method: TMethod;
response: TServerFnResponseType;
data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TValidator>>;
context: Expand<AssignAllServerContext<TMiddlewares>>;
signal: AbortSignal;
}
export type CompiledFetcherFn<TResponse, TServerFnResponseType extends ServerFnResponseType> = {
(opts: CompiledFetcherFnOptions & ServerFnBaseOptions<Method, TServerFnResponseType>): Promise<TResponse>;
url: string;
};
export type ServerFnBaseOptions<TMethod extends Method = 'GET', TServerFnResponseType extends ServerFnResponseType = 'data', TResponse = unknown, TMiddlewares = unknown, TInput = unknown> = {
method: TMethod;
response?: TServerFnResponseType;
validateClient?: boolean;
middleware?: Constrain<TMiddlewares, ReadonlyArray<AnyMiddleware>>;
validator?: ConstrainValidator<TInput>;
extractedFn?: CompiledFetcherFn<TResponse, TServerFnResponseType>;
serverFn?: ServerFn<TMethod, TServerFnResponseType, TMiddlewares, TInput, TResponse>;
functionId: string;
type: ServerFnTypeOrTypeFn<TMethod, TServerFnResponseType, TMiddlewares, AnyValidator>;
};
export type ValidatorSerializerStringify<TValidator> = Validator<SerializerStringifyBy<ResolveValidatorInput<TValidator>, Date | undefined | FormData>, any>;
export type ConstrainValidator<TValidator> = unknown extends TValidator ? TValidator : Constrain<TValidator, ValidatorSerializerStringify<TValidator>>;
export interface ServerFnMiddleware<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TValidator> {
middleware: <const TNewMiddlewares = undefined>(middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>) => ServerFnAfterMiddleware<TMethod, TServerFnResponseType, TNewMiddlewares, TValidator>;
}
export interface ServerFnAfterMiddleware<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> extends ServerFnValidator<TMethod, TServerFnResponseType, TMiddlewares>, ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>, ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {
}
export type ValidatorFn<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares> = <TValidator>(validator: ConstrainValidator<TValidator>) => ServerFnAfterValidator<TMethod, TServerFnResponseType, TMiddlewares, TValidator>;
export interface ServerFnValidator<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares> {
validator: ValidatorFn<TMethod, TServerFnResponseType, TMiddlewares>;
}
export interface ServerFnAfterValidator<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> extends ServerFnMiddleware<TMethod, TServerFnResponseType, TValidator>, ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>, ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {
}
export interface ServerFnTyper<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> {
type: (typer: ServerFnTypeOrTypeFn<TMethod, TServerFnResponseType, TMiddlewares, TValidator>) => ServerFnAfterTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>;
}
export type ServerFnTypeOrTypeFn<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> = ServerFnType | ((ctx: ServerFnCtx<TMethod, TServerFnResponseType, TMiddlewares, TValidator>) => ServerFnType);
export interface ServerFnAfterTyper<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> extends ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {
}
export interface ServerFnHandler<TMethod extends Method, TServerFnResponseType extends ServerFnResponseType, TMiddlewares, TValidator> {
handler: <TNewResponse>(fn?: ServerFn<TMethod, TServerFnResponseType, TMiddlewares, TValidator, TNewResponse>) => Fetcher<TMiddlewares, TValidator, TNewResponse, TServerFnResponseType>;
}
export interface ServerFnBuilder<TMethod extends Method = 'GET', TServerFnResponseType extends ServerFnResponseType = 'data'> extends ServerFnMiddleware<TMethod, TServerFnResponseType, undefined>, ServerFnValidator<TMethod, TServerFnResponseType, undefined>, ServerFnTyper<TMethod, TServerFnResponseType, undefined, undefined>, ServerFnHandler<TMethod, TServerFnResponseType, undefined, undefined> {
options: ServerFnBaseOptions<TMethod, TServerFnResponseType, unknown, undefined, undefined>;
}
export type StaticCachedResult = {
ctx?: {
result: any;
context: any;
};
error?: any;
};
export type ServerFnStaticCache = {
getItem: (ctx: ServerFnMiddlewareResult) => StaticCachedResult | Promise<StaticCachedResult | undefined>;
setItem: (ctx: ServerFnMiddlewareResult, response: StaticCachedResult) => Promise<void>;
fetchItem: (ctx: ServerFnMiddlewareResult) => StaticCachedResult | Promise<StaticCachedResult | undefined>;
};
export declare let serverFnStaticCache: ServerFnStaticCache | undefined;
export declare function setServerFnStaticCache(cache?: ServerFnStaticCache | (() => ServerFnStaticCache | undefined)): () => void;
export declare function createServerFnStaticCache(serverFnStaticCache: ServerFnStaticCache): ServerFnStaticCache;
export declare function extractFormDataContext(formData: FormData): {
context: unknown;
data: FormData;
} | {
data: FormData;
context?: undefined;
};
export declare function flattenMiddlewares(middlewares: Array<AnyMiddleware>): Array<AnyMiddleware>;
export type ServerFnMiddlewareOptions = {
method: Method;
response?: ServerFnResponseType;
data: any;
headers?: HeadersInit;
signal?: AbortSignal;
sendContext?: any;
context?: any;
type: ServerFnTypeOrTypeFn<any, any, any, any>;
functionId: string;
};
export type ServerFnMiddlewareResult = ServerFnMiddlewareOptions & {
result?: unknown;
error?: unknown;
type: ServerFnTypeOrTypeFn<any, any, any, any>;
};
export type NextFn = (ctx: ServerFnMiddlewareResult) => Promise<ServerFnMiddlewareResult>;
export type MiddlewareFn = (ctx: ServerFnMiddlewareOptions & {
next: NextFn;
}) => Promise<ServerFnMiddlewareResult>;
export declare const applyMiddleware: (middlewareFn: MiddlewareFn, ctx: ServerFnMiddlewareOptions, nextFn: NextFn) => Promise<ServerFnMiddlewareResult>;
export declare function execValidator(validator: AnyValidator, input: unknown): unknown;
export declare function serverFnBaseToMiddleware(options: ServerFnBaseOptions<any, any, any, any, any>): AnyMiddleware;
import invariant from "tiny-invariant";
import warning from "tiny-warning";
import { startSerializer } from "./serializer.js";
import { mergeHeaders } from "./headers.js";
let serverFnStaticCache;
function setServerFnStaticCache(cache) {
const previousCache = serverFnStaticCache;
serverFnStaticCache = typeof cache === "function" ? cache() : cache;
return () => {
serverFnStaticCache = previousCache;
};
}
function createServerFnStaticCache(serverFnStaticCache2) {
return serverFnStaticCache2;
}
setServerFnStaticCache(() => {
const getStaticCacheUrl = (options, hash) => {
return `/__tsr/staticServerFnCache/${options.functionId}__${hash}.json`;
};
const jsonToFilenameSafeString = (json) => {
const sortedKeysReplacer = (key, value) => value && typeof value === "object" && !Array.isArray(value) ? Object.keys(value).sort().reduce((acc, curr) => {
acc[curr] = value[curr];
return acc;
}, {}) : value;
const jsonString = JSON.stringify(json ?? "", sortedKeysReplacer);
return jsonString.replace(/[/\\?%*:|"<>]/g, "-").replace(/\s+/g, "_");
};
const staticClientCache = typeof document !== "undefined" ? /* @__PURE__ */ new Map() : null;
return createServerFnStaticCache({
getItem: async (ctx) => {
if (typeof document === "undefined") {
const hash = jsonToFilenameSafeString(ctx.data);
const url = getStaticCacheUrl(ctx, hash);
const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR;
const { promises: fs } = await import("node:fs");
const path = await import("node:path");
const filePath = path.join(publicUrl, url);
const [cachedResult, readError] = await fs.readFile(filePath, "utf-8").then((c) => [
startSerializer.parse(c),
null
]).catch((e) => [null, e]);
if (readError && readError.code !== "ENOENT") {
throw readError;
}
return cachedResult;
}
return void 0;
},
setItem: async (ctx, response) => {
const { promises: fs } = await import("node:fs");
const path = await import("node:path");
const hash = jsonToFilenameSafeString(ctx.data);
const url = getStaticCacheUrl(ctx, hash);
const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR;
const filePath = path.join(publicUrl, url);
await fs.mkdir(path.dirname(filePath), { recursive: true });
await fs.writeFile(filePath, startSerializer.stringify(response));
},
fetchItem: async (ctx) => {
const hash = jsonToFilenameSafeString(ctx.data);
const url = getStaticCacheUrl(ctx, hash);
let result = staticClientCache == null ? void 0 : staticClientCache.get(url);
if (!result) {
result = await fetch(url, {
method: "GET"
}).then((r) => r.text()).then((d) => startSerializer.parse(d));
staticClientCache == null ? void 0 : staticClientCache.set(url, result);
}
return result;
}
});
});
function extractFormDataContext(formData) {
const serializedContext = formData.get("__TSR_CONTEXT");
formData.delete("__TSR_CONTEXT");
if (typeof serializedContext !== "string") {
return {
context: {},
data: formData
};
}
try {
const context = startSerializer.parse(serializedContext);
return {
context,
data: formData
};
} catch {
return {
data: formData
};
}
}
function flattenMiddlewares(middlewares) {
const seen = /* @__PURE__ */ new Set();
const flattened = [];
const recurse = (middleware) => {
middleware.forEach((m) => {
if (m.options.middleware) {
recurse(m.options.middleware);
}
if (!seen.has(m)) {
seen.add(m);
flattened.push(m);
}
});
};
recurse(middlewares);
return flattened;
}
const applyMiddleware = async (middlewareFn, ctx, nextFn) => {
return middlewareFn({
...ctx,
next: async (userCtx = {}) => {
return nextFn({
...ctx,
...userCtx,
context: {
...ctx.context,
...userCtx.context
},
sendContext: {
...ctx.sendContext,
...userCtx.sendContext ?? {}
},
headers: mergeHeaders(ctx.headers, userCtx.headers),
result: userCtx.result !== void 0 ? userCtx.result : ctx.response === "raw" ? userCtx : ctx.result,
error: userCtx.error ?? ctx.error
});
}
});
};
function execValidator(validator, input) {
if (validator == null) return {};
if ("~standard" in validator) {
const result = validator["~standard"].validate(input);
if (result instanceof Promise)
throw new Error("Async validation not supported");
if (result.issues)
throw new Error(JSON.stringify(result.issues, void 0, 2));
return result.value;
}
if ("parse" in validator) {
return validator.parse(input);
}
if (typeof validator === "function") {
return validator(input);
}
throw new Error("Invalid validator type!");
}
function serverFnBaseToMiddleware(options) {
return {
_types: void 0,
options: {
validator: options.validator,
validateClient: options.validateClient,
client: async ({ next, sendContext, ...ctx }) => {
var _a;
const payload = {
...ctx,
// switch the sendContext over to context
context: sendContext,
type: typeof ctx.type === "function" ? ctx.type(ctx) : ctx.type
};
if (ctx.type === "static" && process.env.NODE_ENV === "production" && typeof document !== "undefined") {
invariant(
serverFnStaticCache,
"serverFnStaticCache.fetchItem is not available!"
);
const result = await serverFnStaticCache.fetchItem(payload);
if (result) {
if (result.error) {
throw result.error;
}
return next(result.ctx);
}
warning(
result,
`No static cache item found for ${payload.functionId}__${JSON.stringify(payload.data)}, falling back to server function...`
);
}
const res = await ((_a = options.extractedFn) == null ? void 0 : _a.call(options, payload));
return next(res);
},
server: async ({ next, ...ctx }) => {
var _a;
const result = await ((_a = options.serverFn) == null ? void 0 : _a.call(options, ctx));
return next({
...ctx,
result
});
}
}
};
}
export {
applyMiddleware,
createServerFnStaticCache,
execValidator,
extractFormDataContext,
flattenMiddlewares,
serverFnBaseToMiddleware,
serverFnStaticCache,
setServerFnStaticCache
};
//# sourceMappingURL=createServerFn.js.map
{"version":3,"file":"createServerFn.js","sources":["../../src/createServerFn.ts"],"sourcesContent":["import { default as invariant } from 'tiny-invariant'\nimport { default as warning } from 'tiny-warning'\nimport { startSerializer } from './serializer'\nimport { mergeHeaders } from './headers'\nimport type { Readable } from 'node:stream'\nimport type {\n AnyValidator,\n Constrain,\n Expand,\n ResolveValidatorInput,\n SerializerParse,\n SerializerStringify,\n SerializerStringifyBy,\n Validator,\n} from '@tanstack/router-core'\nimport type {\n AnyMiddleware,\n AssignAllClientSendContext,\n AssignAllServerContext,\n IntersectAllValidatorInputs,\n IntersectAllValidatorOutputs,\n MiddlewareClientFnResult,\n MiddlewareServerFnResult,\n} from './createMiddleware'\n\nexport interface JsonResponse<TData> extends Response {\n json: () => Promise<TData>\n}\n\nexport type CompiledFetcherFnOptions = {\n method: Method\n data: unknown\n response?: ServerFnResponseType\n headers?: HeadersInit\n signal?: AbortSignal\n context?: any\n}\n\nexport type Fetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> =\n undefined extends IntersectAllValidatorInputs<TMiddlewares, TValidator>\n ? OptionalFetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType\n >\n : RequiredFetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType\n >\n\nexport interface FetcherBase {\n url: string\n __executeServer: (opts: {\n method: Method\n response?: ServerFnResponseType\n data: unknown\n headers?: HeadersInit\n context?: any\n signal: AbortSignal\n }) => Promise<unknown>\n}\n\nexport type FetchResult<\n TMiddlewares,\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> = TServerFnResponseType extends 'raw'\n ? Promise<Response>\n : TServerFnResponseType extends 'full'\n ? Promise<FullFetcherData<TMiddlewares, TResponse>>\n : Promise<FetcherData<TResponse>>\n\nexport interface OptionalFetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> extends FetcherBase {\n (\n options?: OptionalFetcherDataOptions<TMiddlewares, TValidator>,\n ): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>\n}\n\nexport interface RequiredFetcher<\n TMiddlewares,\n TValidator,\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> extends FetcherBase {\n (\n opts: RequiredFetcherDataOptions<TMiddlewares, TValidator>,\n ): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>\n}\n\nexport type FetcherBaseOptions = {\n headers?: HeadersInit\n type?: ServerFnType\n signal?: AbortSignal\n}\n\nexport type ServerFnType = 'static' | 'dynamic'\n\nexport interface OptionalFetcherDataOptions<TMiddlewares, TValidator>\n extends FetcherBaseOptions {\n data?: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>\n}\n\nexport interface RequiredFetcherDataOptions<TMiddlewares, TValidator>\n extends FetcherBaseOptions {\n data: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>\n}\n\nexport interface FullFetcherData<TMiddlewares, TResponse> {\n error: unknown\n result: FetcherData<TResponse>\n context: AssignAllClientSendContext<TMiddlewares>\n}\n\nexport type FetcherData<TResponse> =\n TResponse extends JsonResponse<any>\n ? SerializerParse<ReturnType<TResponse['json']>>\n : SerializerParse<TResponse>\n\nexport type RscStream<T> = {\n __cacheState: T\n}\n\nexport type Method = 'GET' | 'POST'\nexport type ServerFnResponseType = 'data' | 'full' | 'raw'\n\n// see https://h3.unjs.io/guide/event-handler#responses-types\nexport type RawResponse = Response | ReadableStream | Readable | null | string\n\nexport type ServerFnReturnType<\n TServerFnResponseType extends ServerFnResponseType,\n TResponse,\n> = TServerFnResponseType extends 'raw'\n ? RawResponse | Promise<RawResponse>\n : Promise<SerializerStringify<TResponse>> | SerializerStringify<TResponse>\nexport type ServerFn<\n TMethod,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n TResponse,\n> = (\n ctx: ServerFnCtx<TMethod, TServerFnResponseType, TMiddlewares, TValidator>,\n) => ServerFnReturnType<TServerFnResponseType, TResponse>\n\nexport interface ServerFnCtx<\n TMethod,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> {\n method: TMethod\n response: TServerFnResponseType\n data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TValidator>>\n context: Expand<AssignAllServerContext<TMiddlewares>>\n signal: AbortSignal\n}\n\nexport type CompiledFetcherFn<\n TResponse,\n TServerFnResponseType extends ServerFnResponseType,\n> = {\n (\n opts: CompiledFetcherFnOptions &\n ServerFnBaseOptions<Method, TServerFnResponseType>,\n ): Promise<TResponse>\n url: string\n}\n\nexport type ServerFnBaseOptions<\n TMethod extends Method = 'GET',\n TServerFnResponseType extends ServerFnResponseType = 'data',\n TResponse = unknown,\n TMiddlewares = unknown,\n TInput = unknown,\n> = {\n method: TMethod\n response?: TServerFnResponseType\n validateClient?: boolean\n middleware?: Constrain<TMiddlewares, ReadonlyArray<AnyMiddleware>>\n validator?: ConstrainValidator<TInput>\n extractedFn?: CompiledFetcherFn<TResponse, TServerFnResponseType>\n serverFn?: ServerFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TInput,\n TResponse\n >\n functionId: string\n type: ServerFnTypeOrTypeFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n AnyValidator\n >\n}\n\nexport type ValidatorSerializerStringify<TValidator> = Validator<\n SerializerStringifyBy<\n ResolveValidatorInput<TValidator>,\n Date | undefined | FormData\n >,\n any\n>\n\nexport type ConstrainValidator<TValidator> = unknown extends TValidator\n ? TValidator\n : Constrain<TValidator, ValidatorSerializerStringify<TValidator>>\n\nexport interface ServerFnMiddleware<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TValidator,\n> {\n middleware: <const TNewMiddlewares = undefined>(\n middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>,\n ) => ServerFnAfterMiddleware<\n TMethod,\n TServerFnResponseType,\n TNewMiddlewares,\n TValidator\n >\n}\n\nexport interface ServerFnAfterMiddleware<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> extends ServerFnValidator<TMethod, TServerFnResponseType, TMiddlewares>,\n ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>,\n ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {}\n\nexport type ValidatorFn<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n> = <TValidator>(\n validator: ConstrainValidator<TValidator>,\n) => ServerFnAfterValidator<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n>\n\nexport interface ServerFnValidator<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n> {\n validator: ValidatorFn<TMethod, TServerFnResponseType, TMiddlewares>\n}\n\nexport interface ServerFnAfterValidator<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> extends ServerFnMiddleware<TMethod, TServerFnResponseType, TValidator>,\n ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>,\n ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {}\n\n// Typer\nexport interface ServerFnTyper<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> {\n type: (\n typer: ServerFnTypeOrTypeFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n >,\n ) => ServerFnAfterTyper<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n >\n}\n\nexport type ServerFnTypeOrTypeFn<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> =\n | ServerFnType\n | ((\n ctx: ServerFnCtx<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n >,\n ) => ServerFnType)\n\nexport interface ServerFnAfterTyper<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> extends ServerFnHandler<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator\n > {}\n\n// Handler\nexport interface ServerFnHandler<\n TMethod extends Method,\n TServerFnResponseType extends ServerFnResponseType,\n TMiddlewares,\n TValidator,\n> {\n handler: <TNewResponse>(\n fn?: ServerFn<\n TMethod,\n TServerFnResponseType,\n TMiddlewares,\n TValidator,\n TNewResponse\n >,\n ) => Fetcher<TMiddlewares, TValidator, TNewResponse, TServerFnResponseType>\n}\n\nexport interface ServerFnBuilder<\n TMethod extends Method = 'GET',\n TServerFnResponseType extends ServerFnResponseType = 'data',\n> extends ServerFnMiddleware<TMethod, TServerFnResponseType, undefined>,\n ServerFnValidator<TMethod, TServerFnResponseType, undefined>,\n ServerFnTyper<TMethod, TServerFnResponseType, undefined, undefined>,\n ServerFnHandler<TMethod, TServerFnResponseType, undefined, undefined> {\n options: ServerFnBaseOptions<\n TMethod,\n TServerFnResponseType,\n unknown,\n undefined,\n undefined\n >\n}\n\nexport type StaticCachedResult = {\n ctx?: {\n result: any\n context: any\n }\n error?: any\n}\n\nexport type ServerFnStaticCache = {\n getItem: (\n ctx: ServerFnMiddlewareResult,\n ) => StaticCachedResult | Promise<StaticCachedResult | undefined>\n setItem: (\n ctx: ServerFnMiddlewareResult,\n response: StaticCachedResult,\n ) => Promise<void>\n fetchItem: (\n ctx: ServerFnMiddlewareResult,\n ) => StaticCachedResult | Promise<StaticCachedResult | undefined>\n}\n\nexport let serverFnStaticCache: ServerFnStaticCache | undefined\n\nexport function setServerFnStaticCache(\n cache?: ServerFnStaticCache | (() => ServerFnStaticCache | undefined),\n) {\n const previousCache = serverFnStaticCache\n serverFnStaticCache = typeof cache === 'function' ? cache() : cache\n\n return () => {\n serverFnStaticCache = previousCache\n }\n}\n\nexport function createServerFnStaticCache(\n serverFnStaticCache: ServerFnStaticCache,\n) {\n return serverFnStaticCache\n}\n\nsetServerFnStaticCache(() => {\n const getStaticCacheUrl = (\n options: ServerFnMiddlewareResult,\n hash: string,\n ) => {\n return `/__tsr/staticServerFnCache/${options.functionId}__${hash}.json`\n }\n\n const jsonToFilenameSafeString = (json: any) => {\n // Custom replacer to sort keys\n const sortedKeysReplacer = (key: string, value: any) =>\n value && typeof value === 'object' && !Array.isArray(value)\n ? Object.keys(value)\n .sort()\n .reduce((acc: any, curr: string) => {\n acc[curr] = value[curr]\n return acc\n }, {})\n : value\n\n // Convert JSON to string with sorted keys\n const jsonString = JSON.stringify(json ?? '', sortedKeysReplacer)\n\n // Replace characters invalid in filenames\n return jsonString\n .replace(/[/\\\\?%*:|\"<>]/g, '-') // Replace invalid characters with a dash\n .replace(/\\s+/g, '_') // Optionally replace whitespace with underscores\n }\n\n const staticClientCache =\n typeof document !== 'undefined' ? new Map<string, any>() : null\n\n return createServerFnStaticCache({\n getItem: async (ctx) => {\n if (typeof document === 'undefined') {\n const hash = jsonToFilenameSafeString(ctx.data)\n const url = getStaticCacheUrl(ctx, hash)\n const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR!\n\n // Use fs instead of fetch to read from filesystem\n const { promises: fs } = await import('node:fs')\n const path = await import('node:path')\n const filePath = path.join(publicUrl, url)\n\n const [cachedResult, readError] = await fs\n .readFile(filePath, 'utf-8')\n .then((c) => [\n startSerializer.parse(c) as {\n ctx: unknown\n error: any\n },\n null,\n ])\n .catch((e) => [null, e])\n\n if (readError && readError.code !== 'ENOENT') {\n throw readError\n }\n\n return cachedResult as StaticCachedResult\n }\n\n return undefined\n },\n setItem: async (ctx, response) => {\n const { promises: fs } = await import('node:fs')\n const path = await import('node:path')\n\n const hash = jsonToFilenameSafeString(ctx.data)\n const url = getStaticCacheUrl(ctx, hash)\n const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR!\n const filePath = path.join(publicUrl, url)\n\n // Ensure the directory exists\n await fs.mkdir(path.dirname(filePath), { recursive: true })\n\n // Store the result with fs\n await fs.writeFile(filePath, startSerializer.stringify(response))\n },\n fetchItem: async (ctx) => {\n const hash = jsonToFilenameSafeString(ctx.data)\n const url = getStaticCacheUrl(ctx, hash)\n\n let result: any = staticClientCache?.get(url)\n\n if (!result) {\n result = await fetch(url, {\n method: 'GET',\n })\n .then((r) => r.text())\n .then((d) => startSerializer.parse(d))\n\n staticClientCache?.set(url, result)\n }\n\n return result\n },\n })\n})\n\nexport function extractFormDataContext(formData: FormData) {\n const serializedContext = formData.get('__TSR_CONTEXT')\n formData.delete('__TSR_CONTEXT')\n\n if (typeof serializedContext !== 'string') {\n return {\n context: {},\n data: formData,\n }\n }\n\n try {\n const context = startSerializer.parse(serializedContext)\n return {\n context,\n data: formData,\n }\n } catch {\n return {\n data: formData,\n }\n }\n}\n\nexport function flattenMiddlewares(\n middlewares: Array<AnyMiddleware>,\n): Array<AnyMiddleware> {\n const seen = new Set<AnyMiddleware>()\n const flattened: Array<AnyMiddleware> = []\n\n const recurse = (middleware: Array<AnyMiddleware>) => {\n middleware.forEach((m) => {\n if (m.options.middleware) {\n recurse(m.options.middleware)\n }\n\n if (!seen.has(m)) {\n seen.add(m)\n flattened.push(m)\n }\n })\n }\n\n recurse(middlewares)\n\n return flattened\n}\n\nexport type ServerFnMiddlewareOptions = {\n method: Method\n response?: ServerFnResponseType\n data: any\n headers?: HeadersInit\n signal?: AbortSignal\n sendContext?: any\n context?: any\n type: ServerFnTypeOrTypeFn<any, any, any, any>\n functionId: string\n}\n\nexport type ServerFnMiddlewareResult = ServerFnMiddlewareOptions & {\n result?: unknown\n error?: unknown\n type: ServerFnTypeOrTypeFn<any, any, any, any>\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 const applyMiddleware = async (\n middlewareFn: MiddlewareFn,\n ctx: ServerFnMiddlewareOptions,\n nextFn: NextFn,\n) => {\n return middlewareFn({\n ...ctx,\n next: (async (\n userCtx: ServerFnMiddlewareResult | undefined = {} as any,\n ) => {\n // Return the next middleware\n return nextFn({\n ...ctx,\n ...userCtx,\n context: {\n ...ctx.context,\n ...userCtx.context,\n },\n sendContext: {\n ...ctx.sendContext,\n ...(userCtx.sendContext ?? {}),\n },\n headers: mergeHeaders(ctx.headers, userCtx.headers),\n result:\n userCtx.result !== undefined\n ? userCtx.result\n : ctx.response === 'raw'\n ? userCtx\n : (ctx as any).result,\n error: userCtx.error ?? (ctx as any).error,\n })\n }) as any,\n } as any)\n}\n\nexport function execValidator(\n validator: AnyValidator,\n input: unknown,\n): unknown {\n if (validator == null) return {}\n\n if ('~standard' in validator) {\n const result = validator['~standard'].validate(input)\n\n if (result instanceof Promise)\n throw new Error('Async validation not supported')\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\nexport function serverFnBaseToMiddleware(\n options: ServerFnBaseOptions<any, any, any, any, any>,\n): AnyMiddleware {\n return {\n _types: undefined!,\n options: {\n validator: options.validator,\n validateClient: options.validateClient,\n client: async ({ next, sendContext, ...ctx }) => {\n const payload = {\n ...ctx,\n // switch the sendContext over to context\n context: sendContext,\n type: typeof ctx.type === 'function' ? ctx.type(ctx) : ctx.type,\n } as any\n\n if (\n ctx.type === 'static' &&\n process.env.NODE_ENV === 'production' &&\n typeof document !== 'undefined'\n ) {\n invariant(\n serverFnStaticCache,\n 'serverFnStaticCache.fetchItem is not available!',\n )\n\n const result = await serverFnStaticCache.fetchItem(payload)\n\n if (result) {\n if (result.error) {\n throw result.error\n }\n\n return next(result.ctx)\n }\n\n warning(\n result,\n `No static cache item found for ${payload.functionId}__${JSON.stringify(payload.data)}, falling back to server function...`,\n )\n }\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) as unknown as MiddlewareClientFnResult<any, any, any>\n },\n server: async ({ next, ...ctx }) => {\n // Execute the server function\n const result = await options.serverFn?.(ctx)\n\n return next({\n ...ctx,\n result,\n } as any) as unknown as MiddlewareServerFnResult<any, any, any, any>\n },\n },\n }\n}\n"],"names":["serverFnStaticCache"],"mappings":"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"}
type EnvOnlyFn = <TFn extends (...args: Array<any>) => any>(fn: TFn) => TFn;
export declare const serverOnly: EnvOnlyFn;
export declare const clientOnly: EnvOnlyFn;
export {};
const serverOnly = (fn) => fn;
const clientOnly = (fn) => fn;
export {
clientOnly,
serverOnly
};
//# sourceMappingURL=envOnly.js.map
{"version":3,"file":"envOnly.js","sources":["../../src/envOnly.ts"],"sourcesContent":["type EnvOnlyFn = <TFn extends (...args: Array<any>) => any>(fn: TFn) => TFn\n\n// A function that will only be available in the server build\n// If called on the client, it will throw an error\nexport const serverOnly: EnvOnlyFn = (fn) => fn\n\n// A function that will only be available in the client build\n// If called on the server, it will throw an error\nexport const clientOnly: EnvOnlyFn = (fn) => fn\n"],"names":[],"mappings":"AAIa,MAAA,aAAwB,CAAC,OAAO;AAIhC,MAAA,aAAwB,CAAC,OAAO;"}
import { JsonResponse } from './createServerFn.js';
export declare function json<TData>(payload: TData, init?: ResponseInit): JsonResponse<TData>;
import { mergeHeaders } from "./headers.js";
function json(payload, init) {
return new Response(JSON.stringify(payload), {
...init,
headers: mergeHeaders(
{ "content-type": "application/json" },
init == null ? void 0 : init.headers
)
});
}
export {
json
};
//# sourceMappingURL=json.js.map
{"version":3,"file":"json.js","sources":["../../src/json.ts"],"sourcesContent":["import { mergeHeaders } from './headers'\nimport type { JsonResponse } from './createServerFn'\n\nexport function json<TData>(\n payload: TData,\n init?: ResponseInit,\n): JsonResponse<TData> {\n return new Response(JSON.stringify(payload), {\n ...init,\n headers: mergeHeaders(\n { 'content-type': 'application/json' },\n init?.headers,\n ),\n })\n}\n"],"names":[],"mappings":";AAGgB,SAAA,KACd,SACA,MACqB;AACrB,SAAO,IAAI,SAAS,KAAK,UAAU,OAAO,GAAG;AAAA,IAC3C,GAAG;AAAA,IACH,SAAS;AAAA,MACP,EAAE,gBAAgB,mBAAmB;AAAA,MACrC,6BAAM;AAAA,IAAA;AAAA,EACR,CACD;AACH;"}
import { AnyMiddleware } from './createMiddleware.js';
export declare const globalMiddleware: Array<AnyMiddleware>;
export declare function registerGlobalMiddleware(options: {
middleware: Array<AnyMiddleware>;
}): void;
const globalMiddleware = [];
function registerGlobalMiddleware(options) {
globalMiddleware.push(...options.middleware);
}
export {
globalMiddleware,
registerGlobalMiddleware
};
//# sourceMappingURL=registerGlobalMiddleware.js.map
{"version":3,"file":"registerGlobalMiddleware.js","sources":["../../src/registerGlobalMiddleware.ts"],"sourcesContent":["import type { AnyMiddleware } from './createMiddleware'\n\nexport const globalMiddleware: Array<AnyMiddleware> = []\n\nexport function registerGlobalMiddleware(options: {\n middleware: Array<AnyMiddleware>\n}) {\n globalMiddleware.push(...options.middleware)\n}\n"],"names":[],"mappings":"AAEO,MAAM,mBAAyC,CAAA;AAE/C,SAAS,yBAAyB,SAEtC;AACgB,mBAAA,KAAK,GAAG,QAAQ,UAAU;AAC7C;"}
// a function that can have different implementations on the client and server.
// implementations not provided will default to a no-op function.
export type IsomorphicFn<
TArgs extends Array<any> = [],
TServer = undefined,
TClient = undefined,
> = (...args: TArgs) => TServer | TClient
export interface ServerOnlyFn<TArgs extends Array<any>, TServer>
extends IsomorphicFn<TArgs, TServer> {
client: <TClient>(
clientImpl: (...args: TArgs) => TClient,
) => IsomorphicFn<TArgs, TServer, TClient>
}
export interface ClientOnlyFn<TArgs extends Array<any>, TClient>
extends IsomorphicFn<TArgs, undefined, TClient> {
server: <TServer>(
serverImpl: (...args: TArgs) => TServer,
) => IsomorphicFn<TArgs, TServer, TClient>
}
export interface IsomorphicFnBase extends IsomorphicFn {
server: <TArgs extends Array<any>, TServer>(
serverImpl: (...args: TArgs) => TServer,
) => ServerOnlyFn<TArgs, TServer>
client: <TArgs extends Array<any>, TClient>(
clientImpl: (...args: TArgs) => TClient,
) => ClientOnlyFn<TArgs, TClient>
}
// this is a dummy function, it will be replaced by the transformer
export function createIsomorphicFn(): IsomorphicFnBase {
return null!
}
import type {
ConstrainValidator,
Method,
ServerFnResponseType,
ServerFnTypeOrTypeFn,
} from './createServerFn'
import type {
Assign,
Constrain,
Expand,
IntersectAssign,
ResolveValidatorInput,
ResolveValidatorOutput,
SerializerStringify,
} from '@tanstack/router-core'
export type AssignAllMiddleware<
TMiddlewares,
TType extends keyof AnyMiddleware['_types'],
TAcc = undefined,
> = TMiddlewares extends readonly [
infer TMiddleware extends AnyMiddleware,
...infer TRest,
]
? AssignAllMiddleware<
TRest,
TType,
Assign<TAcc, TMiddleware['_types'][TType]>
>
: TAcc
/**
* Recursively resolve the client context type produced by a sequence of middleware
*/
export type AssignAllClientContextBeforeNext<
TMiddlewares,
TClientContext = undefined,
> = unknown extends TClientContext
? TClientContext
: Assign<
AssignAllMiddleware<TMiddlewares, 'allClientContextBeforeNext'>,
TClientContext
>
export type AssignAllClientSendContext<
TMiddlewares,
TSendContext = undefined,
> = unknown extends TSendContext
? TSendContext
: Assign<
AssignAllMiddleware<TMiddlewares, 'allClientSendContext'>,
TSendContext
>
export type AssignAllClientContextAfterNext<
TMiddlewares,
TClientContext = undefined,
TSendContext = undefined,
> = unknown extends TClientContext
? Assign<TClientContext, TSendContext>
: Assign<
AssignAllMiddleware<TMiddlewares, 'allClientContextAfterNext'>,
Assign<TClientContext, TSendContext>
>
/**
* Recursively resolve the server context type produced by a sequence of middleware
*/
export type AssignAllServerContext<
TMiddlewares,
TSendContext = undefined,
TServerContext = undefined,
> = unknown extends TSendContext
? Assign<TSendContext, TServerContext>
: Assign<
AssignAllMiddleware<TMiddlewares, 'allServerContext'>,
Assign<TSendContext, TServerContext>
>
export type AssignAllServerSendContext<
TMiddlewares,
TSendContext = undefined,
> = unknown extends TSendContext
? TSendContext
: Assign<
AssignAllMiddleware<TMiddlewares, 'allServerSendContext'>,
TSendContext
>
export type IntersectAllMiddleware<
TMiddlewares,
TType extends keyof AnyMiddleware['_types'],
TAcc = undefined,
> = TMiddlewares extends readonly [
infer TMiddleware extends AnyMiddleware,
...infer TRest,
]
? IntersectAllMiddleware<
TRest,
TType,
IntersectAssign<TAcc, TMiddleware['_types'][TType]>
>
: TAcc
/**
* Recursively resolve the input type produced by a sequence of middleware
*/
export type IntersectAllValidatorInputs<TMiddlewares, TValidator> =
unknown extends TValidator
? TValidator
: IntersectAssign<
IntersectAllMiddleware<TMiddlewares, 'allInput'>,
TValidator extends undefined
? undefined
: ResolveValidatorInput<TValidator>
>
/**
* Recursively merge the output type produced by a sequence of middleware
*/
export type IntersectAllValidatorOutputs<TMiddlewares, TValidator> =
unknown extends TValidator
? TValidator
: IntersectAssign<
IntersectAllMiddleware<TMiddlewares, 'allOutput'>,
TValidator extends undefined
? undefined
: ResolveValidatorOutput<TValidator>
>
export interface MiddlewareOptions<
in out TMiddlewares,
in out TValidator,
in out TServerContext,
in out TClientContext,
in out TServerFnResponseType extends ServerFnResponseType,
> {
validateClient?: boolean
middleware?: TMiddlewares
validator?: ConstrainValidator<TValidator>
client?: MiddlewareClientFn<
TMiddlewares,
TValidator,
TServerContext,
TClientContext,
TServerFnResponseType
>
server?: MiddlewareServerFn<
TMiddlewares,
TValidator,
TServerContext,
unknown,
unknown,
TServerFnResponseType
>
}
export type MiddlewareServerNextFn<TMiddlewares, TServerSendContext> = <
TNewServerContext = undefined,
TSendContext = undefined,
>(ctx?: {
context?: TNewServerContext
sendContext?: SerializerStringify<TSendContext>
}) => Promise<
ServerResultWithContext<
TMiddlewares,
TServerSendContext,
TNewServerContext,
TSendContext
>
>
export interface MiddlewareServerFnOptions<
in out TMiddlewares,
in out TValidator,
in out TServerSendContext,
in out TServerFnResponseType,
> {
data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TValidator>>
context: Expand<AssignAllServerContext<TMiddlewares, TServerSendContext>>
next: MiddlewareServerNextFn<TMiddlewares, TServerSendContext>
response: TServerFnResponseType
method: Method
filename: string
functionId: string
signal: AbortSignal
}
export type MiddlewareServerFn<
TMiddlewares,
TValidator,
TServerSendContext,
TNewServerContext,
TSendContext,
TServerFnResponseType extends ServerFnResponseType,
> = (
options: MiddlewareServerFnOptions<
TMiddlewares,
TValidator,
TServerSendContext,
TServerFnResponseType
>,
) => MiddlewareServerFnResult<
TMiddlewares,
TServerSendContext,
TNewServerContext,
TSendContext
>
export type MiddlewareServerFnResult<
TMiddlewares,
TServerSendContext,
TServerContext,
TSendContext,
> =
| Promise<
ServerResultWithContext<
TMiddlewares,
TServerSendContext,
TServerContext,
TSendContext
>
>
| ServerResultWithContext<
TMiddlewares,
TServerSendContext,
TServerContext,
TSendContext
>
export type MiddlewareClientNextFn<TMiddlewares> = <
TSendContext = undefined,
TNewClientContext = undefined,
>(ctx?: {
context?: TNewClientContext
sendContext?: SerializerStringify<TSendContext>
headers?: HeadersInit
}) => Promise<
ClientResultWithContext<TMiddlewares, TSendContext, TNewClientContext>
>
export interface MiddlewareClientFnOptions<
in out TMiddlewares,
in out TValidator,
in out TServerFnResponseType extends ServerFnResponseType,
> {
data: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>
context: Expand<AssignAllClientContextBeforeNext<TMiddlewares>>
sendContext: Expand<AssignAllServerSendContext<TMiddlewares>>
method: Method
response: TServerFnResponseType
signal: AbortSignal
next: MiddlewareClientNextFn<TMiddlewares>
filename: string
functionId: string
type: ServerFnTypeOrTypeFn<
Method,
TServerFnResponseType,
TMiddlewares,
TValidator
>
}
export type MiddlewareClientFn<
TMiddlewares,
TValidator,
TSendContext,
TClientContext,
TServerFnResponseType extends ServerFnResponseType,
> = (
options: MiddlewareClientFnOptions<
TMiddlewares,
TValidator,
TServerFnResponseType
>,
) => MiddlewareClientFnResult<TMiddlewares, TSendContext, TClientContext>
export type MiddlewareClientFnResult<
TMiddlewares,
TSendContext,
TClientContext,
> =
| Promise<ClientResultWithContext<TMiddlewares, TSendContext, TClientContext>>
| ClientResultWithContext<TMiddlewares, TSendContext, TClientContext>
export type ServerResultWithContext<
in out TMiddlewares,
in out TServerSendContext,
in out TServerContext,
in out TSendContext,
> = {
'use functions must return the result of next()': true
_types: {
context: TServerContext
sendContext: TSendContext
}
context: Expand<
AssignAllServerContext<TMiddlewares, TServerSendContext, TServerContext>
>
sendContext: Expand<AssignAllClientSendContext<TMiddlewares, TSendContext>>
}
export type ClientResultWithContext<
in out TMiddlewares,
in out TSendContext,
in out TClientContext,
> = {
'use functions must return the result of next()': true
context: Expand<AssignAllClientContextAfterNext<TMiddlewares, TClientContext>>
sendContext: Expand<AssignAllServerSendContext<TMiddlewares, TSendContext>>
headers: HeadersInit
}
export type AnyMiddleware = MiddlewareWithTypes<
any,
any,
any,
any,
any,
any,
any
>
export interface MiddlewareTypes<
in out TMiddlewares,
in out TValidator,
in out TServerContext,
in out TServerSendContext,
in out TClientContext,
in out TClientSendContext,
> {
middlewares: TMiddlewares
input: ResolveValidatorInput<TValidator>
allInput: IntersectAllValidatorInputs<TMiddlewares, TValidator>
output: ResolveValidatorOutput<TValidator>
allOutput: IntersectAllValidatorOutputs<TMiddlewares, TValidator>
clientContext: TClientContext
allClientContextBeforeNext: AssignAllClientContextBeforeNext<
TMiddlewares,
TClientContext
>
allClientContextAfterNext: AssignAllClientContextAfterNext<
TMiddlewares,
TClientContext,
TClientSendContext
>
serverContext: TServerContext
serverSendContext: TServerSendContext
allServerSendContext: AssignAllServerSendContext<
TMiddlewares,
TServerSendContext
>
allServerContext: AssignAllServerContext<
TMiddlewares,
TServerSendContext,
TServerContext
>
clientSendContext: TClientSendContext
allClientSendContext: AssignAllClientSendContext<
TMiddlewares,
TClientSendContext
>
validator: TValidator
}
export interface MiddlewareWithTypes<
TMiddlewares,
TValidator,
TServerContext,
TServerSendContext,
TClientContext,
TClientSendContext,
TServerFnResponseType extends ServerFnResponseType,
> {
_types: MiddlewareTypes<
TMiddlewares,
TValidator,
TServerContext,
TServerSendContext,
TClientContext,
TClientSendContext
>
options: MiddlewareOptions<
TMiddlewares,
TValidator,
TServerContext,
TClientContext,
TServerFnResponseType
>
}
export interface MiddlewareAfterValidator<
TMiddlewares,
TValidator,
TServerFnResponseType extends ServerFnResponseType,
> extends MiddlewareWithTypes<
TMiddlewares,
TValidator,
undefined,
undefined,
undefined,
undefined,
ServerFnResponseType
>,
MiddlewareServer<
TMiddlewares,
TValidator,
undefined,
undefined,
TServerFnResponseType
>,
MiddlewareClient<TMiddlewares, TValidator, ServerFnResponseType> {}
export interface MiddlewareValidator<
TMiddlewares,
TServerFnResponseType extends ServerFnResponseType,
> {
validator: <TNewValidator>(
input: ConstrainValidator<TNewValidator>,
) => MiddlewareAfterValidator<
TMiddlewares,
TNewValidator,
TServerFnResponseType
>
}
export interface MiddlewareAfterServer<
TMiddlewares,
TValidator,
TServerContext,
TServerSendContext,
TClientContext,
TClientSendContext,
TServerFnResponseType extends ServerFnResponseType,
> extends MiddlewareWithTypes<
TMiddlewares,
TValidator,
TServerContext,
TServerSendContext,
TClientContext,
TClientSendContext,
TServerFnResponseType
> {}
export interface MiddlewareServer<
TMiddlewares,
TValidator,
TServerSendContext,
TClientContext,
TServerFnResponseType extends ServerFnResponseType,
> {
server: <TNewServerContext = undefined, TSendContext = undefined>(
server: MiddlewareServerFn<
TMiddlewares,
TValidator,
TServerSendContext,
TNewServerContext,
TSendContext,
TServerFnResponseType
>,
) => MiddlewareAfterServer<
TMiddlewares,
TValidator,
TNewServerContext,
TServerSendContext,
TClientContext,
TSendContext,
ServerFnResponseType
>
}
export interface MiddlewareAfterClient<
TMiddlewares,
TValidator,
TServerSendContext,
TClientContext,
TServerFnResponseType extends ServerFnResponseType,
> extends MiddlewareWithTypes<
TMiddlewares,
TValidator,
undefined,
TServerSendContext,
TClientContext,
undefined,
TServerFnResponseType
>,
MiddlewareServer<
TMiddlewares,
TValidator,
TServerSendContext,
TClientContext,
TServerFnResponseType
> {}
export interface MiddlewareClient<
TMiddlewares,
TValidator,
TServerFnResponseType extends ServerFnResponseType,
> {
client: <TSendServerContext = undefined, TNewClientContext = undefined>(
client: MiddlewareClientFn<
TMiddlewares,
TValidator,
TSendServerContext,
TNewClientContext,
TServerFnResponseType
>,
) => MiddlewareAfterClient<
TMiddlewares,
TValidator,
TSendServerContext,
TNewClientContext,
ServerFnResponseType
>
}
export interface MiddlewareAfterMiddleware<
TMiddlewares,
TServerFnResponseType extends ServerFnResponseType,
> extends MiddlewareWithTypes<
TMiddlewares,
undefined,
undefined,
undefined,
undefined,
undefined,
TServerFnResponseType
>,
MiddlewareServer<
TMiddlewares,
undefined,
undefined,
undefined,
TServerFnResponseType
>,
MiddlewareClient<TMiddlewares, undefined, TServerFnResponseType>,
MiddlewareValidator<TMiddlewares, TServerFnResponseType> {}
export interface Middleware<TServerFnResponseType extends ServerFnResponseType>
extends MiddlewareAfterMiddleware<unknown, TServerFnResponseType> {
middleware: <const TNewMiddlewares = undefined>(
middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>,
) => MiddlewareAfterMiddleware<TNewMiddlewares, TServerFnResponseType>
}
export function createMiddleware(
options?: {
validateClient?: boolean
},
__opts?: MiddlewareOptions<
unknown,
undefined,
undefined,
undefined,
ServerFnResponseType
>,
): Middleware<ServerFnResponseType> {
// const resolvedOptions = (__opts || options) as MiddlewareOptions<
const resolvedOptions =
__opts ||
((options || {}) as MiddlewareOptions<
unknown,
undefined,
undefined,
undefined,
ServerFnResponseType
>)
return {
options: resolvedOptions as any,
middleware: (middleware: any) => {
return createMiddleware(
undefined,
Object.assign(resolvedOptions, { middleware }),
) as any
},
validator: (validator: any) => {
return createMiddleware(
undefined,
Object.assign(resolvedOptions, { validator }),
) as any
},
client: (client: any) => {
return createMiddleware(
undefined,
Object.assign(resolvedOptions, { client }),
) as any
},
server: (server: any) => {
return createMiddleware(
undefined,
Object.assign(resolvedOptions, { server }),
) as any
},
} as unknown as Middleware<ServerFnResponseType>
}
import { default as invariant } from 'tiny-invariant'
import { default as warning } from 'tiny-warning'
import { startSerializer } from './serializer'
import { mergeHeaders } from './headers'
import type { Readable } from 'node:stream'
import type {
AnyValidator,
Constrain,
Expand,
ResolveValidatorInput,
SerializerParse,
SerializerStringify,
SerializerStringifyBy,
Validator,
} from '@tanstack/router-core'
import type {
AnyMiddleware,
AssignAllClientSendContext,
AssignAllServerContext,
IntersectAllValidatorInputs,
IntersectAllValidatorOutputs,
MiddlewareClientFnResult,
MiddlewareServerFnResult,
} from './createMiddleware'
export interface JsonResponse<TData> extends Response {
json: () => Promise<TData>
}
export type CompiledFetcherFnOptions = {
method: Method
data: unknown
response?: ServerFnResponseType
headers?: HeadersInit
signal?: AbortSignal
context?: any
}
export type Fetcher<
TMiddlewares,
TValidator,
TResponse,
TServerFnResponseType extends ServerFnResponseType,
> =
undefined extends IntersectAllValidatorInputs<TMiddlewares, TValidator>
? OptionalFetcher<
TMiddlewares,
TValidator,
TResponse,
TServerFnResponseType
>
: RequiredFetcher<
TMiddlewares,
TValidator,
TResponse,
TServerFnResponseType
>
export interface FetcherBase {
url: string
__executeServer: (opts: {
method: Method
response?: ServerFnResponseType
data: unknown
headers?: HeadersInit
context?: any
signal: AbortSignal
}) => Promise<unknown>
}
export type FetchResult<
TMiddlewares,
TResponse,
TServerFnResponseType extends ServerFnResponseType,
> = TServerFnResponseType extends 'raw'
? Promise<Response>
: TServerFnResponseType extends 'full'
? Promise<FullFetcherData<TMiddlewares, TResponse>>
: Promise<FetcherData<TResponse>>
export interface OptionalFetcher<
TMiddlewares,
TValidator,
TResponse,
TServerFnResponseType extends ServerFnResponseType,
> extends FetcherBase {
(
options?: OptionalFetcherDataOptions<TMiddlewares, TValidator>,
): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>
}
export interface RequiredFetcher<
TMiddlewares,
TValidator,
TResponse,
TServerFnResponseType extends ServerFnResponseType,
> extends FetcherBase {
(
opts: RequiredFetcherDataOptions<TMiddlewares, TValidator>,
): FetchResult<TMiddlewares, TResponse, TServerFnResponseType>
}
export type FetcherBaseOptions = {
headers?: HeadersInit
type?: ServerFnType
signal?: AbortSignal
}
export type ServerFnType = 'static' | 'dynamic'
export interface OptionalFetcherDataOptions<TMiddlewares, TValidator>
extends FetcherBaseOptions {
data?: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>
}
export interface RequiredFetcherDataOptions<TMiddlewares, TValidator>
extends FetcherBaseOptions {
data: Expand<IntersectAllValidatorInputs<TMiddlewares, TValidator>>
}
export interface FullFetcherData<TMiddlewares, TResponse> {
error: unknown
result: FetcherData<TResponse>
context: AssignAllClientSendContext<TMiddlewares>
}
export type FetcherData<TResponse> =
TResponse extends JsonResponse<any>
? SerializerParse<ReturnType<TResponse['json']>>
: SerializerParse<TResponse>
export type RscStream<T> = {
__cacheState: T
}
export type Method = 'GET' | 'POST'
export type ServerFnResponseType = 'data' | 'full' | 'raw'
// see https://h3.unjs.io/guide/event-handler#responses-types
export type RawResponse = Response | ReadableStream | Readable | null | string
export type ServerFnReturnType<
TServerFnResponseType extends ServerFnResponseType,
TResponse,
> = TServerFnResponseType extends 'raw'
? RawResponse | Promise<RawResponse>
: Promise<SerializerStringify<TResponse>> | SerializerStringify<TResponse>
export type ServerFn<
TMethod,
TServerFnResponseType extends ServerFnResponseType,
TMiddlewares,
TValidator,
TResponse,
> = (
ctx: ServerFnCtx<TMethod, TServerFnResponseType, TMiddlewares, TValidator>,
) => ServerFnReturnType<TServerFnResponseType, TResponse>
export interface ServerFnCtx<
TMethod,
TServerFnResponseType extends ServerFnResponseType,
TMiddlewares,
TValidator,
> {
method: TMethod
response: TServerFnResponseType
data: Expand<IntersectAllValidatorOutputs<TMiddlewares, TValidator>>
context: Expand<AssignAllServerContext<TMiddlewares>>
signal: AbortSignal
}
export type CompiledFetcherFn<
TResponse,
TServerFnResponseType extends ServerFnResponseType,
> = {
(
opts: CompiledFetcherFnOptions &
ServerFnBaseOptions<Method, TServerFnResponseType>,
): Promise<TResponse>
url: string
}
export type ServerFnBaseOptions<
TMethod extends Method = 'GET',
TServerFnResponseType extends ServerFnResponseType = 'data',
TResponse = unknown,
TMiddlewares = unknown,
TInput = unknown,
> = {
method: TMethod
response?: TServerFnResponseType
validateClient?: boolean
middleware?: Constrain<TMiddlewares, ReadonlyArray<AnyMiddleware>>
validator?: ConstrainValidator<TInput>
extractedFn?: CompiledFetcherFn<TResponse, TServerFnResponseType>
serverFn?: ServerFn<
TMethod,
TServerFnResponseType,
TMiddlewares,
TInput,
TResponse
>
functionId: string
type: ServerFnTypeOrTypeFn<
TMethod,
TServerFnResponseType,
TMiddlewares,
AnyValidator
>
}
export type ValidatorSerializerStringify<TValidator> = Validator<
SerializerStringifyBy<
ResolveValidatorInput<TValidator>,
Date | undefined | FormData
>,
any
>
export type ConstrainValidator<TValidator> = unknown extends TValidator
? TValidator
: Constrain<TValidator, ValidatorSerializerStringify<TValidator>>
export interface ServerFnMiddleware<
TMethod extends Method,
TServerFnResponseType extends ServerFnResponseType,
TValidator,
> {
middleware: <const TNewMiddlewares = undefined>(
middlewares: Constrain<TNewMiddlewares, ReadonlyArray<AnyMiddleware>>,
) => ServerFnAfterMiddleware<
TMethod,
TServerFnResponseType,
TNewMiddlewares,
TValidator
>
}
export interface ServerFnAfterMiddleware<
TMethod extends Method,
TServerFnResponseType extends ServerFnResponseType,
TMiddlewares,
TValidator,
> extends ServerFnValidator<TMethod, TServerFnResponseType, TMiddlewares>,
ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>,
ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {}
export type ValidatorFn<
TMethod extends Method,
TServerFnResponseType extends ServerFnResponseType,
TMiddlewares,
> = <TValidator>(
validator: ConstrainValidator<TValidator>,
) => ServerFnAfterValidator<
TMethod,
TServerFnResponseType,
TMiddlewares,
TValidator
>
export interface ServerFnValidator<
TMethod extends Method,
TServerFnResponseType extends ServerFnResponseType,
TMiddlewares,
> {
validator: ValidatorFn<TMethod, TServerFnResponseType, TMiddlewares>
}
export interface ServerFnAfterValidator<
TMethod extends Method,
TServerFnResponseType extends ServerFnResponseType,
TMiddlewares,
TValidator,
> extends ServerFnMiddleware<TMethod, TServerFnResponseType, TValidator>,
ServerFnTyper<TMethod, TServerFnResponseType, TMiddlewares, TValidator>,
ServerFnHandler<TMethod, TServerFnResponseType, TMiddlewares, TValidator> {}
// Typer
export interface ServerFnTyper<
TMethod extends Method,
TServerFnResponseType extends ServerFnResponseType,
TMiddlewares,
TValidator,
> {
type: (
typer: ServerFnTypeOrTypeFn<
TMethod,
TServerFnResponseType,
TMiddlewares,
TValidator
>,
) => ServerFnAfterTyper<
TMethod,
TServerFnResponseType,
TMiddlewares,
TValidator
>
}
export type ServerFnTypeOrTypeFn<
TMethod extends Method,
TServerFnResponseType extends ServerFnResponseType,
TMiddlewares,
TValidator,
> =
| ServerFnType
| ((
ctx: ServerFnCtx<
TMethod,
TServerFnResponseType,
TMiddlewares,
TValidator
>,
) => ServerFnType)
export interface ServerFnAfterTyper<
TMethod extends Method,
TServerFnResponseType extends ServerFnResponseType,
TMiddlewares,
TValidator,
> extends ServerFnHandler<
TMethod,
TServerFnResponseType,
TMiddlewares,
TValidator
> {}
// Handler
export interface ServerFnHandler<
TMethod extends Method,
TServerFnResponseType extends ServerFnResponseType,
TMiddlewares,
TValidator,
> {
handler: <TNewResponse>(
fn?: ServerFn<
TMethod,
TServerFnResponseType,
TMiddlewares,
TValidator,
TNewResponse
>,
) => Fetcher<TMiddlewares, TValidator, TNewResponse, TServerFnResponseType>
}
export interface ServerFnBuilder<
TMethod extends Method = 'GET',
TServerFnResponseType extends ServerFnResponseType = 'data',
> extends ServerFnMiddleware<TMethod, TServerFnResponseType, undefined>,
ServerFnValidator<TMethod, TServerFnResponseType, undefined>,
ServerFnTyper<TMethod, TServerFnResponseType, undefined, undefined>,
ServerFnHandler<TMethod, TServerFnResponseType, undefined, undefined> {
options: ServerFnBaseOptions<
TMethod,
TServerFnResponseType,
unknown,
undefined,
undefined
>
}
export type StaticCachedResult = {
ctx?: {
result: any
context: any
}
error?: any
}
export type ServerFnStaticCache = {
getItem: (
ctx: ServerFnMiddlewareResult,
) => StaticCachedResult | Promise<StaticCachedResult | undefined>
setItem: (
ctx: ServerFnMiddlewareResult,
response: StaticCachedResult,
) => Promise<void>
fetchItem: (
ctx: ServerFnMiddlewareResult,
) => StaticCachedResult | Promise<StaticCachedResult | undefined>
}
export let serverFnStaticCache: ServerFnStaticCache | undefined
export function setServerFnStaticCache(
cache?: ServerFnStaticCache | (() => ServerFnStaticCache | undefined),
) {
const previousCache = serverFnStaticCache
serverFnStaticCache = typeof cache === 'function' ? cache() : cache
return () => {
serverFnStaticCache = previousCache
}
}
export function createServerFnStaticCache(
serverFnStaticCache: ServerFnStaticCache,
) {
return serverFnStaticCache
}
setServerFnStaticCache(() => {
const getStaticCacheUrl = (
options: ServerFnMiddlewareResult,
hash: string,
) => {
return `/__tsr/staticServerFnCache/${options.functionId}__${hash}.json`
}
const jsonToFilenameSafeString = (json: any) => {
// Custom replacer to sort keys
const sortedKeysReplacer = (key: string, value: any) =>
value && typeof value === 'object' && !Array.isArray(value)
? Object.keys(value)
.sort()
.reduce((acc: any, curr: string) => {
acc[curr] = value[curr]
return acc
}, {})
: value
// Convert JSON to string with sorted keys
const jsonString = JSON.stringify(json ?? '', sortedKeysReplacer)
// Replace characters invalid in filenames
return jsonString
.replace(/[/\\?%*:|"<>]/g, '-') // Replace invalid characters with a dash
.replace(/\s+/g, '_') // Optionally replace whitespace with underscores
}
const staticClientCache =
typeof document !== 'undefined' ? new Map<string, any>() : null
return createServerFnStaticCache({
getItem: async (ctx) => {
if (typeof document === 'undefined') {
const hash = jsonToFilenameSafeString(ctx.data)
const url = getStaticCacheUrl(ctx, hash)
const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR!
// Use fs instead of fetch to read from filesystem
const { promises: fs } = await import('node:fs')
const path = await import('node:path')
const filePath = path.join(publicUrl, url)
const [cachedResult, readError] = await fs
.readFile(filePath, 'utf-8')
.then((c) => [
startSerializer.parse(c) as {
ctx: unknown
error: any
},
null,
])
.catch((e) => [null, e])
if (readError && readError.code !== 'ENOENT') {
throw readError
}
return cachedResult as StaticCachedResult
}
return undefined
},
setItem: async (ctx, response) => {
const { promises: fs } = await import('node:fs')
const path = await import('node:path')
const hash = jsonToFilenameSafeString(ctx.data)
const url = getStaticCacheUrl(ctx, hash)
const publicUrl = process.env.TSS_OUTPUT_PUBLIC_DIR!
const filePath = path.join(publicUrl, url)
// Ensure the directory exists
await fs.mkdir(path.dirname(filePath), { recursive: true })
// Store the result with fs
await fs.writeFile(filePath, startSerializer.stringify(response))
},
fetchItem: async (ctx) => {
const hash = jsonToFilenameSafeString(ctx.data)
const url = getStaticCacheUrl(ctx, hash)
let result: any = staticClientCache?.get(url)
if (!result) {
result = await fetch(url, {
method: 'GET',
})
.then((r) => r.text())
.then((d) => startSerializer.parse(d))
staticClientCache?.set(url, result)
}
return result
},
})
})
export function extractFormDataContext(formData: FormData) {
const serializedContext = formData.get('__TSR_CONTEXT')
formData.delete('__TSR_CONTEXT')
if (typeof serializedContext !== 'string') {
return {
context: {},
data: formData,
}
}
try {
const context = startSerializer.parse(serializedContext)
return {
context,
data: formData,
}
} catch {
return {
data: formData,
}
}
}
export function flattenMiddlewares(
middlewares: Array<AnyMiddleware>,
): Array<AnyMiddleware> {
const seen = new Set<AnyMiddleware>()
const flattened: Array<AnyMiddleware> = []
const recurse = (middleware: Array<AnyMiddleware>) => {
middleware.forEach((m) => {
if (m.options.middleware) {
recurse(m.options.middleware)
}
if (!seen.has(m)) {
seen.add(m)
flattened.push(m)
}
})
}
recurse(middlewares)
return flattened
}
export type ServerFnMiddlewareOptions = {
method: Method
response?: ServerFnResponseType
data: any
headers?: HeadersInit
signal?: AbortSignal
sendContext?: any
context?: any
type: ServerFnTypeOrTypeFn<any, any, any, any>
functionId: string
}
export type ServerFnMiddlewareResult = ServerFnMiddlewareOptions & {
result?: unknown
error?: unknown
type: ServerFnTypeOrTypeFn<any, any, any, any>
}
export type NextFn = (
ctx: ServerFnMiddlewareResult,
) => Promise<ServerFnMiddlewareResult>
export type MiddlewareFn = (
ctx: ServerFnMiddlewareOptions & {
next: NextFn
},
) => Promise<ServerFnMiddlewareResult>
export const applyMiddleware = async (
middlewareFn: MiddlewareFn,
ctx: ServerFnMiddlewareOptions,
nextFn: NextFn,
) => {
return middlewareFn({
...ctx,
next: (async (
userCtx: ServerFnMiddlewareResult | undefined = {} as any,
) => {
// Return the next middleware
return nextFn({
...ctx,
...userCtx,
context: {
...ctx.context,
...userCtx.context,
},
sendContext: {
...ctx.sendContext,
...(userCtx.sendContext ?? {}),
},
headers: mergeHeaders(ctx.headers, userCtx.headers),
result:
userCtx.result !== undefined
? userCtx.result
: ctx.response === 'raw'
? userCtx
: (ctx as any).result,
error: userCtx.error ?? (ctx as any).error,
})
}) as any,
} as any)
}
export function execValidator(
validator: AnyValidator,
input: unknown,
): unknown {
if (validator == null) return {}
if ('~standard' in validator) {
const result = validator['~standard'].validate(input)
if (result instanceof Promise)
throw new Error('Async validation not supported')
if (result.issues)
throw new Error(JSON.stringify(result.issues, undefined, 2))
return result.value
}
if ('parse' in validator) {
return validator.parse(input)
}
if (typeof validator === 'function') {
return validator(input)
}
throw new Error('Invalid validator type!')
}
export function serverFnBaseToMiddleware(
options: ServerFnBaseOptions<any, any, any, any, any>,
): AnyMiddleware {
return {
_types: undefined!,
options: {
validator: options.validator,
validateClient: options.validateClient,
client: async ({ next, sendContext, ...ctx }) => {
const payload = {
...ctx,
// switch the sendContext over to context
context: sendContext,
type: typeof ctx.type === 'function' ? ctx.type(ctx) : ctx.type,
} as any
if (
ctx.type === 'static' &&
process.env.NODE_ENV === 'production' &&
typeof document !== 'undefined'
) {
invariant(
serverFnStaticCache,
'serverFnStaticCache.fetchItem is not available!',
)
const result = await serverFnStaticCache.fetchItem(payload)
if (result) {
if (result.error) {
throw result.error
}
return next(result.ctx)
}
warning(
result,
`No static cache item found for ${payload.functionId}__${JSON.stringify(payload.data)}, falling back to server function...`,
)
}
// Execute the extracted function
// but not before serializing the context
const res = await options.extractedFn?.(payload)
return next(res) as unknown as MiddlewareClientFnResult<any, any, any>
},
server: async ({ next, ...ctx }) => {
// Execute the server function
const result = await options.serverFn?.(ctx)
return next({
...ctx,
result,
} as any) as unknown as MiddlewareServerFnResult<any, any, any, any>
},
},
}
}
type EnvOnlyFn = <TFn extends (...args: Array<any>) => any>(fn: TFn) => TFn
// A function that will only be available in the server build
// If called on the client, it will throw an error
export const serverOnly: EnvOnlyFn = (fn) => fn
// A function that will only be available in the client build
// If called on the server, it will throw an error
export const clientOnly: EnvOnlyFn = (fn) => fn
import { mergeHeaders } from './headers'
import type { JsonResponse } from './createServerFn'
export function json<TData>(
payload: TData,
init?: ResponseInit,
): JsonResponse<TData> {
return new Response(JSON.stringify(payload), {
...init,
headers: mergeHeaders(
{ 'content-type': 'application/json' },
init?.headers,
),
})
}
import type { AnyMiddleware } from './createMiddleware'
export const globalMiddleware: Array<AnyMiddleware> = []
export function registerGlobalMiddleware(options: {
middleware: Array<AnyMiddleware>
}) {
globalMiddleware.push(...options.middleware)
}
import { expectTypeOf, test } from 'vitest'
import { createIsomorphicFn } from '../createIsomorphicFn'
test('createIsomorphicFn with no implementations', () => {
const fn = createIsomorphicFn()
expectTypeOf(fn).toBeCallableWith()
expectTypeOf(fn).returns.toBeUndefined()
expectTypeOf(fn).toHaveProperty('server')
expectTypeOf(fn).toHaveProperty('client')
})
test('createIsomorphicFn with server implementation', () => {
const fn = createIsomorphicFn().server(() => 'data')
expectTypeOf(fn).toBeCallableWith()
expectTypeOf(fn).returns.toEqualTypeOf<string | undefined>()
expectTypeOf(fn).toHaveProperty('client')
expectTypeOf(fn).not.toHaveProperty('server')
})
test('createIsomorphicFn with client implementation', () => {
const fn = createIsomorphicFn().client(() => 'data')
expectTypeOf(fn).toBeCallableWith()
expectTypeOf(fn).returns.toEqualTypeOf<string | undefined>()
expectTypeOf(fn).toHaveProperty('server')
expectTypeOf(fn).not.toHaveProperty('client')
})
test('createIsomorphicFn with server and client implementation', () => {
const fn = createIsomorphicFn()
.server(() => 'data')
.client(() => 'data')
expectTypeOf(fn).toBeCallableWith()
expectTypeOf(fn).returns.toEqualTypeOf<string>()
expectTypeOf(fn).not.toHaveProperty('server')
expectTypeOf(fn).not.toHaveProperty('client')
})
test('createIsomorphicFn with varying returns', () => {
const fn = createIsomorphicFn()
.server(() => 'data')
.client(() => 1)
expectTypeOf(fn).toBeCallableWith()
expectTypeOf(fn).returns.toEqualTypeOf<string | number>()
})
test('createIsomorphicFn with arguments', () => {
const fn = createIsomorphicFn()
.server((a: number, b: string) => 'data')
.client((...args) => {
expectTypeOf(args).toEqualTypeOf<[number, string]>()
return 1
})
expectTypeOf(fn).toBeCallableWith(1, 'a')
expectTypeOf(fn).returns.toEqualTypeOf<string | number>()
const fn2 = createIsomorphicFn()
.client((a: number, b: string) => 'data')
.server((...args) => {
expectTypeOf(args).toEqualTypeOf<[number, string]>()
return 1
})
expectTypeOf(fn2).toBeCallableWith(1, 'a')
expectTypeOf(fn2).returns.toEqualTypeOf<string | number>()
})
import { expectTypeOf, test } from 'vitest'
import { createMiddleware } from '../createMiddleware'
import type { Constrain, Validator } from '@tanstack/router-core'
test('createServeMiddleware removes middleware after middleware,', () => {
const middleware = createMiddleware()
expectTypeOf(middleware).toHaveProperty('middleware')
expectTypeOf(middleware).toHaveProperty('server')
expectTypeOf(middleware).toHaveProperty('validator')
const middlewareAfterMiddleware = middleware.middleware([])
expectTypeOf(middlewareAfterMiddleware).toHaveProperty('validator')
expectTypeOf(middlewareAfterMiddleware).toHaveProperty('server')
expectTypeOf(middlewareAfterMiddleware).not.toHaveProperty('middleware')
const middlewareAfterInput = middleware.validator(() => {})
expectTypeOf(middlewareAfterInput).toHaveProperty('server')
expectTypeOf(middlewareAfterInput).not.toHaveProperty('middleware')
const middlewareAfterServer = middleware.server(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<undefined>()
expectTypeOf(options.data).toEqualTypeOf<undefined>()
expectTypeOf(options.method).toEqualTypeOf<'GET' | 'POST'>()
const result = await options.next({
context: {
a: 'a',
},
})
expectTypeOf(result.context).toEqualTypeOf<{ a: string }>()
expectTypeOf(result.sendContext).toEqualTypeOf<undefined>()
return result
})
expectTypeOf(middlewareAfterServer).not.toHaveProperty('server')
expectTypeOf(middlewareAfterServer).not.toHaveProperty('input')
expectTypeOf(middlewareAfterServer).not.toHaveProperty('middleware')
})
test('createMiddleware merges server context', () => {
const middleware1 = createMiddleware().server(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<undefined>()
expectTypeOf(options.data).toEqualTypeOf<undefined>()
expectTypeOf(options.method).toEqualTypeOf<'GET' | 'POST'>()
const result = await options.next({ context: { a: true } })
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
_types: {
context: {
a: boolean
}
sendContext: undefined
}
context: { a: boolean }
sendContext: undefined
}>()
return result
})
const middleware2 = createMiddleware().server(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<undefined>()
expectTypeOf(options.data).toEqualTypeOf<undefined>()
expectTypeOf(options.method).toEqualTypeOf<'GET' | 'POST'>()
const result = await options.next({ context: { b: 'test' } })
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
_types: {
context: {
b: string
}
sendContext: undefined
}
context: { b: string }
sendContext: undefined
}>()
return result
})
const middleware3 = createMiddleware()
.middleware([middleware1, middleware2])
.server(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<{ a: boolean; b: string }>()
const result = await options.next({ context: { c: 0 } })
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
_types: {
context: {
c: number
}
sendContext: undefined
}
context: { a: boolean; b: string; c: number }
sendContext: undefined
}>()
return result
})
createMiddleware()
.middleware([middleware3])
.server(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<{
a: boolean
b: string
c: number
}>()
const result = await options.next({ context: { d: 5 } })
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
_types: {
context: {
d: number
}
sendContext: undefined
}
context: { a: boolean; b: string; c: number; d: number }
sendContext: undefined
}>()
return result
})
})
test('createMiddleware merges client context and sends to the server', () => {
const middleware1 = createMiddleware().client(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<undefined>()
const result = await options.next({ context: { a: true } })
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
context: { a: boolean }
sendContext: undefined
headers: HeadersInit
}>()
return result
})
const middleware2 = createMiddleware().client(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<undefined>()
const result = await options.next({ context: { b: 'test' } })
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
context: { b: string }
sendContext: undefined
headers: HeadersInit
}>()
return result
})
const middleware3 = createMiddleware()
.middleware([middleware1, middleware2])
.client(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<{ a: boolean; b: string }>()
const result = await options.next({ context: { c: 0 } })
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
context: { a: boolean; b: string; c: number }
sendContext: undefined
headers: HeadersInit
}>()
return result
})
const middleware4 = createMiddleware()
.middleware([middleware3])
.client(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<{
a: boolean
b: string
c: number
}>()
const result = await options.next({
sendContext: { ...options.context, d: 5 },
})
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
context: { a: boolean; b: string; c: number }
sendContext: { a: boolean; b: string; c: number; d: number }
headers: HeadersInit
}>()
return result
})
createMiddleware()
.middleware([middleware4])
.server(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<{
a: boolean
b: string
c: number
d: number
}>()
const result = await options.next({
context: {
e: 'e',
},
})
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
_types: {
context: {
e: string
}
sendContext: undefined
}
context: { a: boolean; b: string; c: number; d: number; e: string }
sendContext: undefined
}>()
return result
})
})
test('createMiddleware merges input', () => {
const middleware1 = createMiddleware()
.validator(() => {
return {
a: 'a',
} as const
})
.server(({ data, next }) => {
expectTypeOf(data).toEqualTypeOf<{ readonly a: 'a' }>()
return next()
})
const middleware2 = createMiddleware()
.middleware([middleware1])
.validator(() => {
return {
b: 'b',
} as const
})
.server(({ data, next }) => {
expectTypeOf(data).toEqualTypeOf<{ readonly a: 'a'; readonly b: 'b' }>
return next()
})
createMiddleware()
.middleware([middleware2])
.validator(() => ({ c: 'c' }) as const)
.server(({ next, data }) => {
expectTypeOf(data).toEqualTypeOf<{
readonly a: 'a'
readonly b: 'b'
readonly c: 'c'
}>
return next()
})
})
test('createMiddleware merges server context and client context, sends server context to the client and merges ', () => {
const middleware1 = createMiddleware()
.client(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<undefined>()
const result = await options.next({
context: { fromClient1: 'fromClient1' },
})
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
context: { fromClient1: string }
sendContext: undefined
headers: HeadersInit
}>()
return result
})
.server(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<undefined>()
const result = await options.next({
context: { fromServer1: 'fromServer1' },
})
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
_types: {
context: {
fromServer1: string
}
sendContext: undefined
}
context: { fromServer1: string }
sendContext: undefined
}>()
return result
})
const middleware2 = createMiddleware()
.client(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<undefined>()
const result = await options.next({
context: { fromClient2: 'fromClient2' },
})
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
context: { fromClient2: string }
sendContext: undefined
headers: HeadersInit
}>()
return result
})
.server(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<undefined>()
const result = await options.next({
context: { fromServer2: 'fromServer2' },
})
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
_types: {
context: {
fromServer2: string
}
sendContext: undefined
}
context: { fromServer2: string }
sendContext: undefined
}>()
return result
})
const middleware3 = createMiddleware()
.middleware([middleware1, middleware2])
.client(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<{
fromClient1: string
fromClient2: string
}>()
const result = await options.next({
context: { fromClient3: 'fromClient3' },
})
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
context: {
fromClient1: string
fromClient2: string
fromClient3: string
}
sendContext: undefined
headers: HeadersInit
}>()
return result
})
.server(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<{
fromServer1: string
fromServer2: string
}>()
const result = await options.next({
context: { fromServer3: 'fromServer3' },
})
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
_types: {
context: {
fromServer3: string
}
sendContext: undefined
}
context: {
fromServer1: string
fromServer2: string
fromServer3: string
}
sendContext: undefined
}>()
return result
})
const middleware4 = createMiddleware()
.middleware([middleware3])
.client(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<{
fromClient1: string
fromClient2: string
fromClient3: string
}>()
const result = await options.next({
context: { fromClient4: 'fromClient4' },
sendContext: { toServer1: 'toServer1' },
})
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
context: {
fromClient1: string
fromClient2: string
fromClient3: string
fromClient4: string
}
sendContext: { toServer1: 'toServer1' }
headers: HeadersInit
}>()
return result
})
.server(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<{
fromServer1: string
fromServer2: string
fromServer3: string
toServer1: 'toServer1'
}>()
const result = await options.next({
context: { fromServer4: 'fromServer4' },
sendContext: { toClient1: 'toClient1' },
})
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
_types: {
context: {
fromServer4: string
}
sendContext: {
toClient1: 'toClient1'
}
}
context: {
fromServer1: string
fromServer2: string
fromServer3: string
fromServer4: string
toServer1: 'toServer1'
}
sendContext: { toClient1: 'toClient1' }
}>()
return result
})
createMiddleware()
.middleware([middleware4])
.client(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<{
fromClient1: string
fromClient2: string
fromClient3: string
fromClient4: string
}>()
const result = await options.next({
context: { fromClient5: 'fromClient5' },
sendContext: { toServer2: 'toServer2' },
})
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
context: {
fromClient1: string
fromClient2: string
fromClient3: string
fromClient4: string
fromClient5: string
toClient1: 'toClient1'
}
sendContext: { toServer1: 'toServer1'; toServer2: 'toServer2' }
headers: HeadersInit
}>()
return result
})
.server(async (options) => {
expectTypeOf(options.context).toEqualTypeOf<{
fromServer1: string
fromServer2: string
fromServer3: string
fromServer4: string
toServer1: 'toServer1'
toServer2: 'toServer2'
}>()
const result = await options.next({
context: { fromServer5: 'fromServer5' },
sendContext: { toClient2: 'toClient2' },
})
expectTypeOf(result).toEqualTypeOf<{
'use functions must return the result of next()': true
_types: {
context: {
fromServer5: string
}
sendContext: {
toClient2: 'toClient2'
}
}
context: {
fromServer1: string
fromServer2: string
fromServer3: string
fromServer4: string
fromServer5: string
toServer1: 'toServer1'
toServer2: 'toServer2'
}
sendContext: { toClient1: 'toClient1'; toClient2: 'toClient2' }
}>()
return result
})
})
test('createMiddleware sendContext cannot send a function', () => {
createMiddleware()
.client(({ next }) => {
expectTypeOf(next<{ func: () => 'func' }>)
.parameter(0)
.exclude<undefined>()
.toHaveProperty('sendContext')
.toEqualTypeOf<{ func: 'Function is not serializable' } | undefined>()
return next()
})
.server(({ next }) => {
expectTypeOf(next<undefined, { func: () => 'func' }>)
.parameter(0)
.exclude<undefined>()
.toHaveProperty('sendContext')
.toEqualTypeOf<{ func: 'Function is not serializable' } | undefined>()
return next()
})
})
test('createMiddleware cannot validate function', () => {
const validator = createMiddleware().validator<
(input: { func: () => 'string' }) => { output: 'string' }
>
expectTypeOf(validator)
.parameter(0)
.toEqualTypeOf<
Constrain<
(input: { func: () => 'string' }) => { output: 'string' },
Validator<{ func: 'Function is not serializable' }, any>
>
>()
})
test('createMiddleware can validate Date', () => {
const validator = createMiddleware().validator<
(input: Date) => { output: 'string' }
>
expectTypeOf(validator)
.parameter(0)
.toEqualTypeOf<
Constrain<(input: Date) => { output: 'string' }, Validator<Date, any>>
>()
})
test('createMiddleware can validate FormData', () => {
const validator = createMiddleware().validator<
(input: FormData) => { output: 'string' }
>
expectTypeOf(validator)
.parameter(0)
.toEqualTypeOf<
Constrain<
(input: FormData) => { output: 'string' },
Validator<FormData, any>
>
>()
})
import { expectTypeOf, test } from 'vitest'
import { clientOnly, serverOnly } from '../envOnly'
const inputFn = () => 'output'
const genericInputFn = <T>(input: T) => input
function overloadedFn(input: string): string
function overloadedFn(input: number): number
function overloadedFn(input: any) {
return input
}
test("clientOnly returns the function it's given", () => {
const outputFn = clientOnly(inputFn)
expectTypeOf(outputFn).toEqualTypeOf<typeof inputFn>()
const genericOutputFn = clientOnly(genericInputFn)
expectTypeOf(genericOutputFn).toEqualTypeOf<typeof genericInputFn>()
const overloadedOutputFn = clientOnly(overloadedFn)
expectTypeOf(overloadedOutputFn).toEqualTypeOf<typeof overloadedFn>()
})
test("serverOnly returns the function it's given", () => {
const outputFn = serverOnly(inputFn)
expectTypeOf(outputFn).toEqualTypeOf<typeof inputFn>()
const genericOutputFn = serverOnly(genericInputFn)
expectTypeOf(genericOutputFn).toEqualTypeOf<typeof genericInputFn>()
const overloadedOutputFn = serverOnly(overloadedFn)
expectTypeOf(overloadedOutputFn).toEqualTypeOf<typeof overloadedFn>()
})
import { describe, expect, it } from 'vitest'
import { json } from '../json'
describe('json', () => {
it('sets the content type to application/json and stringifies the data', async () => {
const data = { foo: 'bar' }
const response = json(data)
expect(response.headers.get('Content-Type')).toBe('application/json')
const responseClone = response.clone()
await expect(responseClone.text()).resolves.toEqual(JSON.stringify(data))
await expect(response.json()).resolves.toEqual(data)
})
it("doesn't override the content type if it's already set", () => {
const response = json(null, { headers: { 'Content-Type': 'text/plain' } })
expect(response.headers.get('Content-Type')).toBe('text/plain')
})
it('reflects passed status and statusText', () => {
const response = json(null, { status: 404, statusText: 'Not Found' })
expect(response.status).toBe(404)
expect(response.statusText).toBe('Not Found')
})
it.each<[string, HeadersInit]>([
['plain object', { 'X-TYPE': 'example' }],
['array', [['X-TYPE', 'example']]],
['Headers', new Headers({ 'X-TYPE': 'example' })],
])('merges headers from %s', (_, headers) => {
const response = json(null, { headers })
expect(response.headers.get('X-TYPE')).toBe('example')
expect(response.headers.get('Content-Type')).toBe('application/json')
})
})
+22
-0

@@ -6,5 +6,27 @@ "use strict";

const ssrClient = require("./ssr-client.cjs");
const createIsomorphicFn = require("./createIsomorphicFn.cjs");
const envOnly = require("./envOnly.cjs");
const json = require("./json.cjs");
const createMiddleware = require("./createMiddleware.cjs");
const registerGlobalMiddleware = require("./registerGlobalMiddleware.cjs");
const createServerFn = require("./createServerFn.cjs");
exports.mergeHeaders = headers.mergeHeaders;
exports.startSerializer = serializer.startSerializer;
exports.hydrate = ssrClient.hydrate;
exports.createIsomorphicFn = createIsomorphicFn.createIsomorphicFn;
exports.clientOnly = envOnly.clientOnly;
exports.serverOnly = envOnly.serverOnly;
exports.json = json.json;
exports.createMiddleware = createMiddleware.createMiddleware;
exports.globalMiddleware = registerGlobalMiddleware.globalMiddleware;
exports.registerGlobalMiddleware = registerGlobalMiddleware.registerGlobalMiddleware;
exports.applyMiddleware = createServerFn.applyMiddleware;
exports.execValidator = createServerFn.execValidator;
exports.extractFormDataContext = createServerFn.extractFormDataContext;
exports.flattenMiddlewares = createServerFn.flattenMiddlewares;
exports.serverFnBaseToMiddleware = createServerFn.serverFnBaseToMiddleware;
Object.defineProperty(exports, "serverFnStaticCache", {
enumerable: true,
get: () => createServerFn.serverFnStaticCache
});
//# sourceMappingURL=index.cjs.map
export { mergeHeaders } from './headers.cjs';
export { startSerializer } from './serializer.cjs';
export { type DehydratedRouter, type ClientExtractedBaseEntry, type StartSsrGlobal, type ClientExtractedEntry, type SsrMatch, type ClientExtractedPromise, type ClientExtractedStream, type ResolvePromiseState, hydrate, } from './ssr-client.cjs';
export { createIsomorphicFn, type IsomorphicFn, type ServerOnlyFn, type ClientOnlyFn, type IsomorphicFnBase, } from './createIsomorphicFn.cjs';
export { serverOnly, clientOnly } from './envOnly.cjs';
export { type JsonResponse } from './createServerFn.cjs';
export { json } from './json.cjs';
export { createMiddleware, type IntersectAllValidatorInputs, type IntersectAllValidatorOutputs, type MiddlewareServerFn, type AnyMiddleware, type MiddlewareOptions, type MiddlewareWithTypes, type MiddlewareValidator, type MiddlewareServer, type MiddlewareAfterClient, type MiddlewareAfterMiddleware, type MiddlewareAfterServer, type Middleware, type MiddlewareClientFnOptions, type MiddlewareClientFnResult, type MiddlewareClientNextFn, type ClientResultWithContext, type AssignAllClientContextBeforeNext, type AssignAllMiddleware, type AssignAllServerContext, type MiddlewareAfterValidator, type MiddlewareClientFn, type MiddlewareServerFnResult, type MiddlewareClient, type MiddlewareServerFnOptions, type MiddlewareServerNextFn, type ServerResultWithContext, } from './createMiddleware.cjs';
export { registerGlobalMiddleware, globalMiddleware, } from './registerGlobalMiddleware.cjs';
export type { ServerFn as FetchFn, ServerFnCtx as FetchFnCtx, CompiledFetcherFnOptions, CompiledFetcherFn, Fetcher, RscStream, FetcherData, FetcherBaseOptions, ServerFn, ServerFnCtx, ServerFnResponseType, MiddlewareFn, ServerFnMiddlewareOptions, ServerFnMiddlewareResult, ServerFnBuilder, ServerFnType, ServerFnBaseOptions, NextFn, Method, StaticCachedResult, } from './createServerFn.cjs';
export { applyMiddleware, execValidator, serverFnBaseToMiddleware, extractFormDataContext, flattenMiddlewares, serverFnStaticCache, } from './createServerFn.cjs';
export { mergeHeaders } from './headers.js';
export { startSerializer } from './serializer.js';
export { type DehydratedRouter, type ClientExtractedBaseEntry, type StartSsrGlobal, type ClientExtractedEntry, type SsrMatch, type ClientExtractedPromise, type ClientExtractedStream, type ResolvePromiseState, hydrate, } from './ssr-client.js';
export { createIsomorphicFn, type IsomorphicFn, type ServerOnlyFn, type ClientOnlyFn, type IsomorphicFnBase, } from './createIsomorphicFn.js';
export { serverOnly, clientOnly } from './envOnly.js';
export { type JsonResponse } from './createServerFn.js';
export { json } from './json.js';
export { createMiddleware, type IntersectAllValidatorInputs, type IntersectAllValidatorOutputs, type MiddlewareServerFn, type AnyMiddleware, type MiddlewareOptions, type MiddlewareWithTypes, type MiddlewareValidator, type MiddlewareServer, type MiddlewareAfterClient, type MiddlewareAfterMiddleware, type MiddlewareAfterServer, type Middleware, type MiddlewareClientFnOptions, type MiddlewareClientFnResult, type MiddlewareClientNextFn, type ClientResultWithContext, type AssignAllClientContextBeforeNext, type AssignAllMiddleware, type AssignAllServerContext, type MiddlewareAfterValidator, type MiddlewareClientFn, type MiddlewareServerFnResult, type MiddlewareClient, type MiddlewareServerFnOptions, type MiddlewareServerNextFn, type ServerResultWithContext, } from './createMiddleware.js';
export { registerGlobalMiddleware, globalMiddleware, } from './registerGlobalMiddleware.js';
export type { ServerFn as FetchFn, ServerFnCtx as FetchFnCtx, CompiledFetcherFnOptions, CompiledFetcherFn, Fetcher, RscStream, FetcherData, FetcherBaseOptions, ServerFn, ServerFnCtx, ServerFnResponseType, MiddlewareFn, ServerFnMiddlewareOptions, ServerFnMiddlewareResult, ServerFnBuilder, ServerFnType, ServerFnBaseOptions, NextFn, Method, StaticCachedResult, } from './createServerFn.js';
export { applyMiddleware, execValidator, serverFnBaseToMiddleware, extractFormDataContext, flattenMiddlewares, serverFnStaticCache, } from './createServerFn.js';
import { mergeHeaders } from "./headers.js";
import { startSerializer } from "./serializer.js";
import { hydrate } from "./ssr-client.js";
import { createIsomorphicFn } from "./createIsomorphicFn.js";
import { clientOnly, serverOnly } from "./envOnly.js";
import { json } from "./json.js";
import { createMiddleware } from "./createMiddleware.js";
import { globalMiddleware, registerGlobalMiddleware } from "./registerGlobalMiddleware.js";
import { applyMiddleware, execValidator, extractFormDataContext, flattenMiddlewares, serverFnBaseToMiddleware, serverFnStaticCache } from "./createServerFn.js";
export {
applyMiddleware,
clientOnly,
createIsomorphicFn,
createMiddleware,
execValidator,
extractFormDataContext,
flattenMiddlewares,
globalMiddleware,
hydrate,
json,
mergeHeaders,
registerGlobalMiddleware,
serverFnBaseToMiddleware,
serverFnStaticCache,
serverOnly,
startSerializer
};
//# sourceMappingURL=index.js.map
+2
-1
{
"name": "@tanstack/start-client-core",
"version": "1.114.4",
"version": "1.114.5",
"description": "Modern and scalable routing for React applications",

@@ -52,2 +52,3 @@ "author": "Tanner Linsley",

"tiny-invariant": "^1.3.3",
"tiny-warning": "^1.0.3",
"@tanstack/router-core": "^1.114.3"

@@ -54,0 +55,0 @@ },

@@ -14,1 +14,74 @@ export { mergeHeaders } from './headers'

} from './ssr-client'
export {
createIsomorphicFn,
type IsomorphicFn,
type ServerOnlyFn,
type ClientOnlyFn,
type IsomorphicFnBase,
} from './createIsomorphicFn'
export { serverOnly, clientOnly } from './envOnly'
export { type JsonResponse } from './createServerFn'
export { json } from './json'
export {
createMiddleware,
type IntersectAllValidatorInputs,
type IntersectAllValidatorOutputs,
type MiddlewareServerFn,
type AnyMiddleware,
type MiddlewareOptions,
type MiddlewareWithTypes,
type MiddlewareValidator,
type MiddlewareServer,
type MiddlewareAfterClient,
type MiddlewareAfterMiddleware,
type MiddlewareAfterServer,
type Middleware,
type MiddlewareClientFnOptions,
type MiddlewareClientFnResult,
type MiddlewareClientNextFn,
type ClientResultWithContext,
type AssignAllClientContextBeforeNext,
type AssignAllMiddleware,
type AssignAllServerContext,
type MiddlewareAfterValidator,
type MiddlewareClientFn,
type MiddlewareServerFnResult,
type MiddlewareClient,
type MiddlewareServerFnOptions,
type MiddlewareServerNextFn,
type ServerResultWithContext,
} from './createMiddleware'
export {
registerGlobalMiddleware,
globalMiddleware,
} from './registerGlobalMiddleware'
export type {
ServerFn as FetchFn,
ServerFnCtx as FetchFnCtx,
CompiledFetcherFnOptions,
CompiledFetcherFn,
Fetcher,
RscStream,
FetcherData,
FetcherBaseOptions,
ServerFn,
ServerFnCtx,
ServerFnResponseType,
MiddlewareFn,
ServerFnMiddlewareOptions,
ServerFnMiddlewareResult,
ServerFnBuilder,
ServerFnType,
ServerFnBaseOptions,
NextFn,
Method,
StaticCachedResult,
} from './createServerFn'
export {
applyMiddleware,
execValidator,
serverFnBaseToMiddleware,
extractFormDataContext,
flattenMiddlewares,
serverFnStaticCache,
} from './createServerFn'

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet