UNPKG

@trpc/server

Version:

The tRPC server library

135 lines (121 loc) • 2.99 kB
import { getHTTPStatusCodeFromError } from '../http/getHTTPStatusCode'; import type { ProcedureType } from '../procedure'; import type { TRPC_ERROR_CODE_KEY, TRPC_ERROR_CODE_NUMBER, TRPCErrorShape, } from '../rpc'; import { TRPC_ERROR_CODES_BY_KEY } from '../rpc'; import type { Overwrite, Simplify } from '../types'; import type { TRPCError } from './TRPCError'; /** * @internal */ export interface ErrorFormatterOptions<TContext> { error: TRPCError; type: ProcedureType | 'unknown'; path: string | undefined; input: unknown; ctx: TContext; shape: DefaultErrorShape; } /** * @internal */ export type ErrorFormatter<TContext, TShape extends TRPCErrorShape> = ( opts: ErrorFormatterOptions<TContext | undefined>, ) => TShape; /** * @internal */ export type ProcedureErrorFormatter< TContext, TContextOverrides, TShape extends TRPCErrorShape | undefined | void, > = ( opts: ErrorFormatterOptions<Simplify<Overwrite<TContext, TContextOverrides>>>, ) => TShape; /** * @internal */ export type AnyProcedureErrorFormatter = ProcedureErrorFormatter<any, any, any>; /** * @internal */ export type DefaultErrorData = { code: TRPC_ERROR_CODE_KEY; httpStatus: number; /** * Path to the procedure that threw the error */ path?: string; /** * Stack trace of the error (only in development) */ stack?: string; }; /** * @internal */ export interface DefaultErrorShape extends TRPCErrorShape<DefaultErrorData> { message: string; code: TRPC_ERROR_CODE_NUMBER; } export const defaultFormatter: ErrorFormatter<any, any> = ({ shape }) => { return shape; }; /** * @internal */ export function getDefaultErrorShape(opts: { error: TRPCError; path: string | undefined; isDev: boolean; }): DefaultErrorShape { const shape: DefaultErrorShape = { message: opts.error.message, code: TRPC_ERROR_CODES_BY_KEY[opts.error.code], data: { code: opts.error.code, httpStatus: getHTTPStatusCodeFromError(opts.error), }, }; if (opts.isDev && typeof opts.error.stack === 'string') { shape.data.stack = opts.error.stack; } if (typeof opts.path === 'string') { shape.data.path = opts.path; } return shape; } const formattedShapeSymbol = Symbol('trpc_formattedErrorShape'); /** * @internal */ export function setFormattedErrorShape( error: TRPCError, shape: TRPCErrorShape, ): asserts error is TRPCError & { [formattedShapeSymbol]: TRPCErrorShape } { Object.defineProperty(error, formattedShapeSymbol, { value: shape, enumerable: false, configurable: true, writable: true, }); } /** * @internal */ export function getFormattedErrorShape( error: TRPCError, ): TRPCErrorShape | undefined { if (isFormattedErrorShape(error)) { return error[formattedShapeSymbol]; } return undefined; } export function isFormattedErrorShape( error: TRPCError, ): error is TRPCError & { [formattedShapeSymbol]: TRPCErrorShape } { return formattedShapeSymbol in error; }