import type { StartInstanceOptions } from './createStart' import type { AnyServerFn, ConstrainValidator, Method } from './createServerFn' import type { AnyContext, Assign, Constrain, Expand, IntersectAssign, Register, ResolveValidatorInput, ResolveValidatorOutput, ValidateSerializableInput, } from '@tanstack/router-core' export type CreateMiddlewareFn = ( options?: { type?: TType }, __opts?: FunctionMiddlewareOptions< TRegister, unknown, undefined, undefined, undefined >, ) => CreateMiddlewareResult export const createMiddleware: CreateMiddlewareFn<{}> = (options, __opts) => { const resolvedOptions = { type: 'request', ...(__opts || options), } return { options: resolvedOptions, middleware: (middleware: any) => { return createMiddleware( {} as any, Object.assign(resolvedOptions, { middleware }), ) as any }, inputValidator: (inputValidator: any) => { return createMiddleware( {} as any, Object.assign(resolvedOptions, { inputValidator }), ) as any }, client: (client: any) => { return createMiddleware( {} as any, Object.assign(resolvedOptions, { client }), ) as any }, server: (server: any) => { return createMiddleware( {} as any, Object.assign(resolvedOptions, { server }), ) as any }, } as any } export type MiddlewareType = 'request' | 'function' export type CreateMiddlewareResult< TRegister, TType extends MiddlewareType, > = 'request' extends TType ? RequestMiddleware : FunctionMiddleware export interface FunctionMiddleware extends FunctionMiddlewareAfterMiddleware { middleware: ( middlewares: Constrain< TNewMiddlewares, ReadonlyArray >, ) => FunctionMiddlewareAfterMiddleware } export interface FunctionMiddlewareAfterMiddleware extends FunctionMiddlewareWithTypes< TRegister, TMiddlewares, undefined, undefined, undefined, undefined, undefined >, FunctionMiddlewareServer< TRegister, TMiddlewares, undefined, undefined, undefined >, FunctionMiddlewareClient, FunctionMiddlewareValidator {} export interface FunctionMiddlewareWithTypes< TRegister, TMiddlewares, TInputValidator, TServerContext, TServerSendContext, TClientContext, TClientSendContext, > { _types: FunctionMiddlewareTypes< TRegister, TMiddlewares, TInputValidator, TServerContext, TServerSendContext, TClientContext, TClientSendContext > options: FunctionMiddlewareOptions< TRegister, TMiddlewares, TInputValidator, TServerContext, TClientContext > } export interface FunctionMiddlewareTypes< in out TRegister, in out TMiddlewares, in out TInputValidator, in out TServerContext, in out TServerSendContext, in out TClientContext, in out TClientSendContext, > { type: 'function' middlewares: TMiddlewares input: ResolveValidatorInput allInput: IntersectAllValidatorInputs output: ResolveValidatorOutput allOutput: IntersectAllValidatorOutputs clientContext: TClientContext allClientContextBeforeNext: AssignAllClientContextBeforeNext< TMiddlewares, TClientContext > allClientContextAfterNext: AssignAllClientContextAfterNext< TMiddlewares, TClientContext, TClientSendContext > serverContext: TServerContext serverSendContext: TServerSendContext allServerSendContext: AssignAllServerSendContext< TMiddlewares, TServerSendContext > allServerContext: AssignAllServerFnContext< TRegister, TMiddlewares, TServerSendContext, TServerContext > clientSendContext: TClientSendContext allClientSendContext: AssignAllClientSendContext< TMiddlewares, TClientSendContext > inputValidator: TInputValidator } /** * Recursively resolve the input type produced by a sequence of middleware */ export type IntersectAllValidatorInputs = unknown extends TInputValidator ? TInputValidator : TInputValidator extends undefined ? IntersectAllMiddleware : IntersectAssign< IntersectAllMiddleware, ResolveValidatorInput > export type IntersectAllMiddleware< TMiddlewares, TType extends | keyof AnyFunctionMiddleware['_types'] | keyof AnyRequestMiddleware['_types'] | keyof AnyServerFn['_types'], TAcc = undefined, > = TMiddlewares extends readonly [infer TMiddleware, ...infer TRest] ? TMiddleware extends | AnyFunctionMiddleware | AnyRequestMiddleware | AnyServerFn ? IntersectAllMiddleware< TRest, TType, IntersectAssign< TAcc, TMiddleware['_types'][TType & keyof TMiddleware['_types']] > > : TAcc : TAcc export type AnyFunctionMiddleware = FunctionMiddlewareWithTypes< any, any, any, any, any, any, any > /** * Recursively merge the output type produced by a sequence of middleware */ export type IntersectAllValidatorOutputs = unknown extends TInputValidator ? TInputValidator : TInputValidator extends undefined ? IntersectAllMiddleware : IntersectAssign< IntersectAllMiddleware, ResolveValidatorOutput > /** * Recursively resolve the client context type produced by a sequence of middleware */ export type AssignAllClientContextBeforeNext< TMiddlewares, TClientContext = undefined, > = unknown extends TClientContext ? TClientContext : Assign< AssignAllMiddleware, TClientContext > export type AssignAllMiddleware< TMiddlewares, TType extends | keyof AnyFunctionMiddleware['_types'] | keyof AnyRequestMiddleware['_types'] | keyof AnyServerFn['_types'], TAcc = undefined, > = TMiddlewares extends readonly [infer TMiddleware, ...infer TRest] ? TMiddleware extends | AnyFunctionMiddleware | AnyRequestMiddleware | AnyServerFn ? AssignAllMiddleware< TRest, TType, Assign > : TAcc : TAcc export type AssignAllClientContextAfterNext< TMiddlewares, TClientContext = undefined, TSendContext = undefined, > = unknown extends TClientContext ? Assign : Assign< AssignAllMiddleware, Assign > export type AssignAllServerSendContext< TMiddlewares, TSendContext = undefined, > = unknown extends TSendContext ? TSendContext : Assign< AssignAllMiddleware, TSendContext > export type AssignAllServerRequestContext< TRegister, TMiddlewares, TSendContext = undefined, TServerContext = undefined, > = Assign< // Fetch Request Context GlobalFetchRequestContext, Assign< GlobalServerRequestContext, __AssignAllServerRequestContext > > // export type GlobalFetchRequestContext = AnyContext export type GlobalFetchRequestContext = Register extends { server: { requestContext: infer TRequestContext } } ? TRequestContext : AnyContext export type GlobalServerRequestContext = TRegister extends { config: StartInstanceOptions } ? AssignAllMiddleware : AnyContext type __AssignAllServerRequestContext< TMiddlewares, TSendContext = undefined, TServerContext = undefined, > = unknown extends TSendContext ? Assign : Assign< AssignAllMiddleware, Assign > export type AssignAllServerFnContext< TRegister, TMiddlewares, TSendContext = undefined, TServerContext = undefined, > = Assign< GlobalFetchRequestContext, Assign< GlobalServerRequestContext, // TODO: This enabled global middleware // type inference, but creates a circular types issue. No idea how to fix this. // AnyContext, Assign< GlobalServerFnContext, // TODO: This enabled global middleware // type inference, but creates a circular types issue. No idea how to fix this. // AnyContext,/ __AssignAllServerFnContext > > > type GlobalServerFnContext = TRegister extends { config: StartInstanceOptions } ? AssignAllMiddleware : AnyContext type __AssignAllServerFnContext< TMiddlewares, TSendContext = undefined, TServerContext = undefined, > = unknown extends TSendContext ? Assign : Assign< AssignAllMiddleware, Assign > export type AssignAllClientSendContext< TMiddlewares, TSendContext = undefined, > = unknown extends TSendContext ? TSendContext : Assign< AssignAllMiddleware, TSendContext > export interface FunctionMiddlewareOptions< in out TRegister, in out TMiddlewares, in out TInputValidator, in out TServerContext, in out TClientContext, > { middleware?: TMiddlewares inputValidator?: ConstrainValidator client?: FunctionMiddlewareClientFn< TRegister, TMiddlewares, TInputValidator, TServerContext, TClientContext > server?: FunctionMiddlewareServerFn< TRegister, TMiddlewares, TInputValidator, TServerContext, unknown, unknown > } export type FunctionMiddlewareClientNextFn = < TSendContext = undefined, TNewClientContext = undefined, >(ctx?: { context?: TNewClientContext sendContext?: ValidateSerializableInput headers?: HeadersInit }) => Promise< FunctionClientResultWithContext > export interface FunctionMiddlewareServer< TRegister, TMiddlewares, TInputValidator, TServerSendContext, TClientContext, > { server: ( server: FunctionMiddlewareServerFn< TRegister, TMiddlewares, TInputValidator, TServerSendContext, TNewServerContext, TSendContext >, ) => FunctionMiddlewareAfterServer< TRegister, TMiddlewares, TInputValidator, TNewServerContext, TServerSendContext, TClientContext, TSendContext > } export type FunctionMiddlewareServerFn< TRegister, TMiddlewares, TInputValidator, TServerSendContext, TNewServerContext, TSendContext, > = ( options: FunctionMiddlewareServerFnOptions< TRegister, TMiddlewares, TInputValidator, TServerSendContext >, ) => FunctionMiddlewareServerFnResult< TRegister, TMiddlewares, TServerSendContext, TNewServerContext, TSendContext > export type FunctionMiddlewareServerNextFn< TRegister, TMiddlewares, TServerSendContext, > = (ctx?: { context?: TNewServerContext sendContext?: ValidateSerializableInput }) => Promise< FunctionServerResultWithContext< TRegister, TMiddlewares, TServerSendContext, TNewServerContext, TSendContext > > export type FunctionServerResultWithContext< in out TRegister, 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< AssignAllServerFnContext< TRegister, TMiddlewares, TServerSendContext, TServerContext > > sendContext: Expand> } export interface FunctionMiddlewareServerFnOptions< in out TRegister, in out TMiddlewares, in out TInputValidator, in out TServerSendContext, > { data: Expand> context: Expand< AssignAllServerFnContext > next: FunctionMiddlewareServerNextFn< TRegister, TMiddlewares, TServerSendContext > method: Method filename: string functionId: string signal: AbortSignal } export type FunctionMiddlewareServerFnResult< TRegister, TMiddlewares, TServerSendContext, TServerContext, TSendContext, > = | Promise< FunctionServerResultWithContext< TRegister, TMiddlewares, TServerSendContext, TServerContext, TSendContext > > | FunctionServerResultWithContext< TRegister, TMiddlewares, TServerSendContext, TServerContext, TSendContext > export interface FunctionMiddlewareAfterServer< TRegister, TMiddlewares, TInputValidator, TServerContext, TServerSendContext, TClientContext, TClientSendContext, > extends FunctionMiddlewareWithTypes< TRegister, TMiddlewares, TInputValidator, TServerContext, TServerSendContext, TClientContext, TClientSendContext > {} export interface FunctionMiddlewareClient< TRegister, TMiddlewares, TInputValidator, > { client: ( client: FunctionMiddlewareClientFn< TRegister, TMiddlewares, TInputValidator, TSendServerContext, TNewClientContext >, ) => FunctionMiddlewareAfterClient< TRegister, TMiddlewares, TInputValidator, TSendServerContext, TNewClientContext > } export type FunctionMiddlewareClientFn< TRegister, TMiddlewares, TInputValidator, TSendContext, TClientContext, > = ( options: FunctionMiddlewareClientFnOptions< TRegister, TMiddlewares, TInputValidator >, ) => FunctionMiddlewareClientFnResult< TMiddlewares, TSendContext, TClientContext > export interface FunctionMiddlewareClientFnOptions< in out TRegister, in out TMiddlewares, in out TInputValidator, > { data: Expand> context: Expand> sendContext: Expand> method: Method signal: AbortSignal next: FunctionMiddlewareClientNextFn filename: string functionId: string } export type FunctionMiddlewareClientFnResult< TMiddlewares, TSendContext, TClientContext, > = | Promise< FunctionClientResultWithContext< TMiddlewares, TSendContext, TClientContext > > | FunctionClientResultWithContext export type FunctionClientResultWithContext< in out TMiddlewares, in out TSendContext, in out TClientContext, > = { 'use functions must return the result of next()': true context: Expand> sendContext: Expand> headers: HeadersInit } export interface FunctionMiddlewareAfterClient< TRegister, TMiddlewares, TInputValidator, TServerSendContext, TClientContext, > extends FunctionMiddlewareWithTypes< TRegister, TMiddlewares, TInputValidator, undefined, TServerSendContext, TClientContext, undefined >, FunctionMiddlewareServer< TRegister, TMiddlewares, TInputValidator, TServerSendContext, TClientContext > {} export interface FunctionMiddlewareValidator { inputValidator: ( inputValidator: ConstrainValidator, ) => FunctionMiddlewareAfterValidator } export interface FunctionMiddlewareAfterValidator< TRegister, TMiddlewares, TInputValidator, > extends FunctionMiddlewareWithTypes< TRegister, TMiddlewares, TInputValidator, undefined, undefined, undefined, undefined >, FunctionMiddlewareServer< TRegister, TMiddlewares, TInputValidator, undefined, undefined >, FunctionMiddlewareClient {} export interface RequestMiddleware extends RequestMiddlewareAfterMiddleware { middleware: ( middlewares: Constrain>, ) => RequestMiddlewareAfterMiddleware } export type AnyRequestMiddleware = RequestMiddlewareWithTypes export interface RequestMiddlewareWithTypes< TRegister, TMiddlewares, TServerContext, > { _types: RequestMiddlewareTypes options: RequestMiddlewareOptions } export interface RequestMiddlewareOptions< in out TRegister, in out TMiddlewares, in out TServerContext, > { middleware?: TMiddlewares server?: RequestServerFn } export interface RequestMiddlewareTypes< TRegister, TMiddlewares, TServerContext, > { type: 'request' // this only exists so we can use request middlewares in server functions allInput: undefined // this only exists so we can use request middlewares in server functions allOutput: undefined middlewares: TMiddlewares serverContext: TServerContext allServerContext: AssignAllServerRequestContext< TRegister, TMiddlewares, undefined, TServerContext > } export interface RequestMiddlewareAfterMiddleware extends RequestMiddlewareWithTypes, RequestMiddlewareServer {} export interface RequestMiddlewareServer { server: ( fn: RequestServerFn, ) => RequestMiddlewareAfterServer } export type RequestServerFn = ( options: RequestServerOptions, ) => RequestMiddlewareServerFnResult export interface RequestServerOptions { request: Request pathname: string context: Expand> next: RequestServerNextFn } export type RequestServerNextFn = < TServerContext = undefined, >( options?: RequestServerNextFnOptions, ) => RequestServerNextFnResult export interface RequestServerNextFnOptions { context?: TServerContext } export type RequestServerNextFnResult = | Promise> | RequestServerResult export type RequestMiddlewareServerFnResult< TRegister, TMiddlewares, TServerContext, > = | Promise< RequestServerResult | Response > | RequestServerResult | Response export interface RequestServerResult { request: Request pathname: string context: Expand< AssignAllServerRequestContext< TRegister, TMiddlewares, undefined, TServerContext > > response: Response } export interface RequestMiddlewareAfterServer< TRegister, TMiddlewares, TServerContext, > extends RequestMiddlewareWithTypes {}