diff --git a/packages/lib/errors.ts b/packages/lib/errors.ts index b9f292adb3..a97dcbf618 100644 --- a/packages/lib/errors.ts +++ b/packages/lib/errors.ts @@ -1,3 +1,29 @@ +import { ErrorCode } from "@calcom/lib/errorCodes"; + +export class ErrorWithCode extends Error { + code: ErrorCode; + data?: Record; + constructor(code: ErrorCode, message?: string, data?: Record) { + super(message); + this.code = code; + this.data = data; + } + static get Factory() { + return new Proxy(ErrorWithCode, { + get(_, prop: string) { + if (prop in ErrorCode) { + const code = ErrorCode[prop as keyof typeof ErrorCode]; + return (message?: string, data?: Record) => new ErrorWithCode(code, message, data); + } + throw new Error(`Unknown error code: ${prop}`); + }, + }) as unknown as Record< + keyof typeof ErrorCode, + (message?: string, data?: Record) => ErrorWithCode + >; + } +} + export function getErrorFromUnknown(cause: unknown): Error & { statusCode?: number; code?: string } { if (cause instanceof Error) { return cause; diff --git a/packages/lib/server/getServerErrorFromUnknown.ts b/packages/lib/server/getServerErrorFromUnknown.ts index c4d7819660..f0eb8f421c 100644 --- a/packages/lib/server/getServerErrorFromUnknown.ts +++ b/packages/lib/server/getServerErrorFromUnknown.ts @@ -1,4 +1,4 @@ -import { PrismaClientKnownRequestError, NotFoundError } from "@prisma/client/runtime/library"; +import { Prisma } from "@prisma/client"; import Stripe from "stripe"; import type { ZodIssue } from "zod"; import { ZodError } from "zod"; @@ -14,6 +14,10 @@ function isZodError(cause: unknown): cause is ZodError { return cause instanceof ZodError || (hasName(cause) && cause.name === "ZodError"); } +function isPrismaError(cause: unknown): cause is Prisma.PrismaClientKnownRequestError { + return cause instanceof Prisma.PrismaClientKnownRequestError; +} + function parseZodErrorIssues(issues: ZodIssue[]): string { return issues .map((i) => @@ -40,12 +44,8 @@ export function getServerErrorFromUnknown(cause: unknown): HttpError { message: "Unexpected error, please reach out for our customer support.", }); } - - if (cause instanceof PrismaClientKnownRequestError) { - return getHttpError({ statusCode: 400, cause }); - } - if (cause instanceof NotFoundError) { - return getHttpError({ statusCode: 404, cause }); + if (isPrismaError(cause)) { + return getServerErrorFromPrismaError(cause); } if (cause instanceof Stripe.errors.StripeInvalidRequestError) { return getHttpError({ statusCode: 400, cause }); @@ -80,3 +80,10 @@ function getHttpError({ statusCode, cause }: { statusCode: numb const redacted = redactError(cause); return new HttpError({ statusCode, message: redacted.message, cause: redacted }); } + +function getServerErrorFromPrismaError(cause: Prisma.PrismaClientKnownRequestError) { + if (cause.code === "P2025") { + return getHttpError({ statusCode: 404, cause }); + } + return getHttpError({ statusCode: 400, cause }); +}