import { AnyProcedure, AnyRouter, DefaultErrorShape, Maybe, inferRouterError, } from '@trpc/server'; import { TRPCErrorResponse } from '@trpc/server/rpc'; type RouterOrProcedure = AnyRouter | AnyProcedure; type inferErrorShape = TRouterOrProcedure extends AnyRouter ? inferRouterError : TRouterOrProcedure['_def']['_config']['$types']['errorShape']; export interface TRPCClientErrorBase { readonly message: string; readonly shape: Maybe; readonly data: Maybe; } export type TRPCClientErrorLike = TRPCClientErrorBase>; export class TRPCClientError extends Error implements TRPCClientErrorBase> { public readonly cause; public readonly shape: Maybe>; public readonly data: Maybe['data']>; public readonly meta; constructor( message: string, opts?: { result?: Maybe>; cause?: Error; meta?: Record; }, ) { const cause = opts?.cause; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore https://github.com/tc39/proposal-error-cause super(message, { cause }); this.meta = opts?.meta; this.cause = cause; this.shape = opts?.result?.error; this.data = opts?.result?.error.data; this.name = 'TRPCClientError'; Object.setPrototypeOf(this, TRPCClientError.prototype); } public static from( cause: Error | TRPCErrorResponse, opts: { meta?: Record } = {}, ): TRPCClientError { if (!(cause instanceof Error)) { return new TRPCClientError( cause.error.message ?? '', { ...opts, cause: undefined, result: cause as any, }, ); } if (cause.name === 'TRPCClientError') { return cause as TRPCClientError; } return new TRPCClientError(cause.message, { ...opts, cause, result: null, }); } }