import { assertNotBrowser } from './assertNotBrowser' ; import { getHTTPStatusCodeFromError } from './http/internals/getHTTPStatusCode' ; import { MiddlewareFunction } from './internals/middlewares' ; import { createProcedure , CreateProcedureOptions , CreateProcedureWithInput , CreateProcedureWithInputOutputParser , CreateProcedureWithoutInput , inferProcedureFromOptions , Procedure , ProcedureCallOptions , } from './internals/procedure' ; import { TRPCErrorShape , TRPC_ERROR_CODES_BY_KEY , TRPC_ERROR_CODE_KEY , TRPC_ERROR_CODE_NUMBER , } from './rpc' ; import { Subscription } from './subscription' ; import { CombinedDataTransformer , DataTransformerOptions } from './transformer' ; import { TRPCError } from './TRPCError' ; import { flatten , Prefixer , ThenArg } from './types' ; assertNotBrowser ( ) ; public export type ProcedureType = 'query' | 'mutation' | 'subscription' ; internal export type ProcedureRecord < TInputContext = any , TContext = any , TInput = any , TParsedInput = any , TOutput = any > = Record < string , Procedure < TInputContext , TContext , TInput , TParsedInput , TOutput > > ; public export type inferProcedureInput < TProcedure extends Procedure < any , any , any , any , any > > = TProcedure extends Procedure < any , any , infer Input , any , any > ? undefined extends Input ? Input | null | void : Input : undefined ; public export type inferAsyncReturnType < TFunction extends ( ... args : any ) => any > = ThenArg < ReturnType < TFunction > > ; public export type inferProcedureOutput < TProcedure extends Procedure < any , any , any , any , any > > = inferAsyncReturnType < TProcedure [ 'call' ] > ; public beta export type inferSubscriptionOutput < TRouter extends AnyRouter , TPath extends keyof TRouter [ '_def' ] [ 'subscriptions' ] > = ReturnType < inferAsyncReturnType < TRouter [ '_def' ] [ 'subscriptions' ] [ TPath ] [ 'call' ] > [ 'output' ] > ; function getDataTransformer ( transformer ) { if ( 'input' in transformer ) { return transformer ; } return { input : transformer , output : transformer } ; } internal export type inferHandlerInput < TProcedure extends Procedure < any , any , any , any , any > > = TProcedure extends Procedure < any , any , infer TInput , any , any > ? undefined extends TInput ? unknown extends TInput ? [ ( null | undefined ) ? ] : [ ( TInput | null | undefined ) ? ] : [ TInput ] : [ ( undefined | null ) ? ] ; type inferHandlerFn < TProcedures extends ProcedureRecord > = < TProcedure extends TProcedures [ TPath ] , TPath extends keyof TProcedures & string > ( path : TPath , ... args : inferHandlerInput < TProcedure > ) => Promise < inferProcedureOutput < TProcedures [ TPath ] > > ; internal export type inferRouterContext < TRouter extends AnyRouter > = Parameters < TRouter [ 'createCaller' ] > [ 0 ] ; public export type AnyRouter < TContext = any > = Router < any , TContext , any , any , any , any > ; internal export type inferRouterError < TRouter extends AnyRouter > = ReturnType < TRouter [ 'getErrorShape' ] > ; const PROCEDURE_DEFINITION_MAP = { query : 'queries' , mutation : 'mutations' , subscription : 'subscriptions' } ; internal export type ErrorFormatter < TContext , TShape extends TRPCErrorShape < number > > = ( { error , } : { error : TRPCError ; type : ProcedureType | 'unknown' ; path : string | undefined ; input : unknown ; ctx : undefined | TContext ; shape : DefaultErrorShape ; } ) => TShape ; type DefaultErrorData = { code : TRPC_ERROR_CODE_KEY ; httpStatus : number ; path ? : string ; stack ? : string ; } ; internal export interface DefaultErrorShape extends TRPCErrorShape < TRPC_ERROR_CODE_NUMBER , DefaultErrorData > { message : string ; code : TRPC_ERROR_CODE_NUMBER ; } /**
 * Create an empty object with `Object.create(null)`.
 * Objects made from `Object.create(null)` are totally empty -- they do not inherit anything from Object.prototype.
 */ function safeObject ( ) ; /**
 * Create an object without inheriting anything from `Object.prototype`
 */ function safeObject < TObj1 > ( obj ) ; /**
 * Merge two objects without inheritance from `Object.prototype`
 */ function safeObject < TObj1 , TObj2 > ( obj1 , obj2 ) ; function safeObject ( ... args ) { return Object . assign ( Object . create ( null ) , ... args ) ; } const defaultFormatter = ( { shape , } ) => { return shape ; } ; const defaultTransformer = { input : { serialize : ( obj ) => obj , deserialize : ( obj ) => obj } , output : { serialize : ( obj ) => obj , deserialize : ( obj ) => obj } } ; type SwapProcedureContext < TProcedure extends Procedure < any , any , any , any , any > , TNewContext > = TProcedure extends Procedure < infer TInputContext , infer _TOldContext , infer TInput , infer TParsedInput , infer TOutput > ? Procedure < TInputContext , TNewContext , TInput , TParsedInput , TOutput > : never ; type SwapContext < TObj extends ProcedureRecord < any , any , any , any > , TNewContext > = { [ P in keyof TObj ] : SwapProcedureContext < TObj [ P ] , TNewContext > ; } ; internal export class Router < TInputContext , TContext , TQueries extends ProcedureRecord < TInputContext , TContext > , TMutations extends ProcedureRecord < TInputContext , TContext > , TSubscriptions extends ProcedureRecord < TInputContext , TContext , unknown , Subscription < unknown > > , TErrorShape extends TRPCErrorShape < number > > { readonly _def : { queries : TQueries ; mutations : TMutations ; subscriptions : TSubscriptions ; middlewares : MiddlewareFunction < TInputContext , TContext > [ ] ; errorFormatter : ErrorFormatter < TContext , TErrorShape > ; transformer : CombinedDataTransformer ; } ; constructor ( def ? ) { this . _def = { queries : ( def ?. queries ?? safeObject ( ) ) as TQueries , mutations : ( def ?. mutations ?? safeObject ( ) ) as TMutations , subscriptions : ( def ?. subscriptions ?? safeObject ( ) ) as TSubscriptions , middlewares : def ?. middlewares ?? [ ] , errorFormatter : def ?. errorFormatter ?? defaultFormatter , transformer : def ?. transformer ?? defaultTransformer } ; } private static prefixProcedures < TProcedures extends ProcedureRecord , TPrefix extends string > ( procedures , prefix ) { const eps = safeObject ( ) ; for ( const key in procedures ) { eps [ prefix + key ] = procedures [ key ] ; } return eps as any ; } public query < TPath extends string , TInput , TParsedInput , TOutput > ( path , procedure ) ; public query < TPath extends string , TInput , TOutput > ( path , procedure ) ; public query < TPath extends string , TOutput > ( path , procedure ) ; query ( path , procedure ) { const router = new Router < TContext , TContext , any , { } , { } , any > ( { queries : safeObject ( { [ path ] : createProcedure ( procedure ) } ) } ) ; return this . merge ( router ) ; } public mutation < TPath extends string , TInput , TParsedInput , TOutput > ( path , procedure ) ; public mutation < TPath extends string , TInput , TOutput > ( path , procedure ) ; public mutation < TPath extends string , TOutput > ( path , procedure ) ; public mutation ( path , procedure ) { const router = new Router < TContext , TContext , { } , any , { } , any > ( { mutations : safeObject ( { [ path ] : createProcedure ( procedure ) } ) } ) ; return this . merge ( router ) ; } beta public subscription < TPath extends string , TInput , TParsedInput , TOutput extends Subscription < unknown > > ( path , procedure ) ; beta public subscription < TPath extends string , TInput , TOutput extends Subscription < unknown > > ( path , procedure ) ; beta public subscription < TPath extends string , TOutput extends Subscription < unknown > > ( path , procedure ) ; public subscription ( path , procedure ) { const router = new Router < TContext , TContext , { } , { } , any , any > ( { subscriptions : safeObject ( { [ path ] : createProcedure ( procedure ) } ) } ) ; return this . merge ( router ) as any ; } param router public merge < TChildRouter extends Router < TContext , any , any , any , any , any > > ( router ) ; param prefix param router public merge < TPath extends string , TChildRouter extends Router < TContext , any , any , any , any , any > > ( prefix , router ) ; public merge ( prefixOrRouter , maybeRouter ? ) { let prefix = '' ; let childRouter ; if ( typeof prefixOrRouter === 'string' && maybeRouter instanceof Router ) { prefix = prefixOrRouter ; childRouter = maybeRouter ; } else if ( prefixOrRouter instanceof Router ) { childRouter = prefixOrRouter ; } else { throw new Error ( 'Invalid args' ) ; } const duplicateQueries = Object . keys ( childRouter . _def . queries ) . filter ( ( key ) => ! ! this . _def [ 'queries' ] [ prefix + key ] ) ; const duplicateMutations = Object . keys ( childRouter . _def . mutations ) . filter ( ( key ) => ! ! this . _def [ 'mutations' ] [ prefix + key ] ) ; const duplicateSubscriptions = Object . keys ( childRouter . _def . subscriptions ) . filter ( ( key ) => ! ! this . _def [ 'subscriptions' ] [ prefix + key ] ) ; const duplicates = [ ... duplicateQueries , ... duplicateMutations , ... duplicateSubscriptions , ] ; if ( duplicates . length ) { throw new Error ( `Duplicate endpoint(s): ${ duplicates . join ( ', ' ) }` ) ; } const mergeProcedures = ( defs ) => { const newDefs = safeObject ( ) as typeof defs ; for ( const key in defs ) { const procedure = defs [ key ] ; const newProcedure = procedure . inheritMiddlewares ( this . _def . middlewares ) ; newDefs [ key ] = newProcedure ; } return Router . prefixProcedures ( newDefs , prefix ) ; } ; return new Router < TInputContext , any , any , any , any , TErrorShape > ( { ... this . _def , queries : safeObject ( this . _def . queries , mergeProcedures ( childRouter . _def . queries ) ) , mutations : safeObject ( this . _def . mutations , mergeProcedures ( childRouter . _def . mutations ) ) , subscriptions : safeObject ( this . _def . subscriptions , mergeProcedures ( childRouter . _def . subscriptions ) ) } ) ; } /**
     * Invoke procedure. Only for internal use within library.
     */ private async call ( opts ) { const { type , path } = opts ; const defTarget = PROCEDURE_DEFINITION_MAP [ type ] ; const defs = this . _def [ defTarget ] ; const procedure = defs [ path ] as Procedure < TInputContext , TContext , any , any , any > | undefined ; if ( ! procedure ) { throw new TRPCError ( { code : 'NOT_FOUND' , message : `No "${ type }"-procedure on path "${ path }"` } ) ; } return procedure . call ( opts ) ; } public createCaller ( ctx ) { return { query : ( path , ... args ) => { return this . call ( { type : 'query' , ctx , path , rawInput : args [ 0 ] } ) as any ; } , mutation : ( path , ... args ) => { return this . call ( { type : 'mutation' , ctx , path , rawInput : args [ 0 ] } ) as any ; } , subscription : ( path , ... args ) => { return this . call ( { type : 'subscription' , ctx , path , rawInput : args [ 0 ] } ) as any ; } } ; } link public middleware < TNewContext > ( middleware ) { return new Router ( { ... this . _def , middlewares : [ ... this . _def . middlewares , middleware as any ] } as any ) ; } link public formatError < TErrorFormatter extends ErrorFormatter < TContext , TRPCErrorShape < number > > > ( errorFormatter ) { if ( this . _def . errorFormatter !== ( defaultFormatter as any ) ) { throw new Error ( 'You seem to have double `formatError()`-calls in your router tree' ) ; } return new Router < TInputContext , TContext , TQueries , TMutations , TSubscriptions , ReturnType < TErrorFormatter > > ( { ... this . _def , errorFormatter : errorFormatter as any } ) ; } public getErrorShape ( opts ) { const { path , error } = opts ; const { code } = opts . error ; const shape = { message : error . message , code : TRPC_ERROR_CODES_BY_KEY [ code ] , data : { code , httpStatus : getHTTPStatusCodeFromError ( error ) } } ; if ( process . env . NODE_ENV !== 'production' && typeof opts . error . stack === 'string' ) { shape . data . stack = opts . error . stack ; } if ( typeof path === 'string' ) { shape . data . path = path ; } return this . _def . errorFormatter ( { ... opts , shape } ) ; } link transformer ( _transformer ) { const transformer = getDataTransformer ( _transformer ) ; if ( this . _def . transformer !== defaultTransformer ) { throw new Error ( 'You seem to have double `transformer()`-calls in your router tree' ) ; } return new Router < TInputContext , TContext , TQueries , TMutations , TSubscriptions , TErrorShape > ( { ... this . _def , transformer } ) ; } alpha public flat ( ) { return this as any ; } } deprecated export class LegacyRouter < TContext , TQueries extends ProcedureRecord < TContext , TContext > , TMutations extends ProcedureRecord < TContext , TContext > , TSubscriptions extends ProcedureRecord < TContext , TContext , unknown , Subscription < unknown > > , TErrorShape extends TRPCErrorShape < number > > extends Router < TContext , TContext , TQueries , TMutations , TSubscriptions , TErrorShape > { } export function router < TContext > ( ) { return new Router < TContext , TContext , { } , { } , { } , DefaultErrorShape > ( ) ; }