/* eslint-disable @typescript-eslint/no-non-null-assertion */ import type { AnyMutationProcedure, AnyProcedure, AnyQueryProcedure, AnyRouter, AnySubscriptionProcedure, IntersectionError, ProcedureArgs, ProcedureRouterRecord, ProcedureType, } from '@trpc/server'; import type { Unsubscribable } from '@trpc/server/observable'; import { createFlatProxy, createRecursiveProxy, inferTransformedProcedureOutput, inferTransformedSubscriptionOutput, } from '@trpc/server/shared'; import { TRPCClientError } from './TRPCClientError'; import { TRPCClient } from './createTRPCClient'; import { CreateTRPCClientOptions } from './createTRPCUntypedClient'; import { TRPCSubscriptionObserver, TRPCUntypedClient, UntypedClientProperties, } from './internals/TRPCUntypedClient'; /** @public */ export type inferRouterProxyClient = DecoratedProcedureRecord; type Resolver = ( ...args: ProcedureArgs ) => Promise>; type SubscriptionResolver = ( ...args: [ input: ProcedureArgs[0], opts: ProcedureArgs[1] & Partial< TRPCSubscriptionObserver< inferTransformedSubscriptionOutput, TRPCClientError > >, ] ) => Unsubscribable; type DecorateProcedure = TProcedure extends AnyQueryProcedure ? { query: Resolver; } : TProcedure extends AnyMutationProcedure ? { mutate: Resolver; } : TProcedure extends AnySubscriptionProcedure ? { subscribe: SubscriptionResolver; } : never; /** * @internal */ type DecoratedProcedureRecord = { [TKey in keyof TProcedures]: TProcedures[TKey] extends AnyRouter ? DecoratedProcedureRecord : TProcedures[TKey] extends AnyProcedure ? DecorateProcedure : never; }; const clientCallTypeMap: Record, ProcedureType> = { query: 'query', mutate: 'mutation', subscribe: 'subscription', }; export type CreateTRPCProxyClient = DecoratedProcedureRecord< TRouter['_def']['record'] > extends infer TProcedureRecord ? UntypedClientProperties & keyof TProcedureRecord extends never ? TProcedureRecord : IntersectionError : never; /** * @deprecated use `createTRPCProxyClient` instead * @internal */ export function createTRPCClientProxy( client: TRPCClient, ) { return createFlatProxy>((key) => { if (client.hasOwnProperty(key)) { return (client as any)[key as any]; } return createRecursiveProxy(({ path, args }) => { const pathCopy = [key, ...path]; const clientCallType = pathCopy.pop()! as keyof DecorateProcedure; const procedureType = clientCallTypeMap[clientCallType]; const fullPath = pathCopy.join('.'); return (client as any)[procedureType](fullPath, ...args); }); }); } export function createTRPCProxyClient( opts: CreateTRPCClientOptions, ) { const client = new TRPCUntypedClient(opts); const proxy = createTRPCClientProxy(client as TRPCClient); return proxy; }