* refactor: consolidate error handlers to use getServerErrorFromUnknown - Migrate server-only code to use getServerErrorFromUnknown for better error handling - Add JSDoc documentation to both getErrorFromUnknown and getServerErrorFromUnknown - Update webhook handlers, payment services, email service, and booking service - Keep getErrorFromUnknown for client-side and isomorphic code - Improve error message extraction by using err.cause?.stack instead of err.stack - Fix ESLint warnings: replace 'any' with 'unknown' types, fix hasOwnProperty usage Co-Authored-By: benny@cal.com <sldisek783@gmail.com> * Update packages/app-store/paypal/api/webhook.ts Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> * refactor --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
87 lines
3.1 KiB
TypeScript
87 lines
3.1 KiB
TypeScript
import { ErrorCode } from "@calcom/lib/errorCodes";
|
|
|
|
export class ErrorWithCode extends Error {
|
|
code: ErrorCode;
|
|
data?: Record<string, unknown>;
|
|
constructor(code: ErrorCode, message?: string, data?: Record<string, unknown>) {
|
|
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<string, unknown>) => new ErrorWithCode(code, message, data);
|
|
}
|
|
throw new Error(`Unknown error code: ${prop}`);
|
|
},
|
|
}) as unknown as Record<
|
|
keyof typeof ErrorCode,
|
|
(message?: string, data?: Record<string, unknown>) => ErrorWithCode
|
|
>;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Converts unknown error types to Error objects.
|
|
*
|
|
* @deprecated For server-side code, use `getServerErrorFromUnknown` from `@calcom/lib/server/getServerErrorFromUnknown` instead.
|
|
* This function should only be used in client-side or isomorphic code (React components, shared utilities).
|
|
*
|
|
* Use this function when:
|
|
* - You're in a React component that runs on the client
|
|
* - You're in shared/isomorphic code that cannot import server-only dependencies
|
|
* - You only need a basic Error object without HTTP status code mapping
|
|
*
|
|
* For server-side error handling (API routes, tRPC handlers, webhooks), use `getServerErrorFromUnknown`
|
|
* which provides proper HTTP status code mapping, error redaction, and handles Zod/Prisma/Stripe errors.
|
|
*
|
|
* @param cause - The unknown error to convert
|
|
* @returns An Error object with optional statusCode and code properties
|
|
*/
|
|
export function getErrorFromUnknown(cause: unknown): Error & { statusCode?: number; code?: string } {
|
|
if (cause instanceof Error) {
|
|
return cause;
|
|
}
|
|
if (typeof cause === "string") {
|
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
// @ts-ignore https://github.com/tc39/proposal-error-cause
|
|
return new Error(cause, { cause });
|
|
}
|
|
|
|
return new Error(`Unhandled error of type '${typeof cause}''`);
|
|
}
|
|
|
|
export async function handleErrorsJson<Type>(response: Response): Promise<Type> {
|
|
// FIXME: I don't know why we are handling gzipped case separately. This should be handled by fetch itself.
|
|
if (response.headers.get("content-encoding") === "gzip") {
|
|
const responseText = await response.text();
|
|
return new Promise((resolve) => resolve(JSON.parse(responseText)));
|
|
}
|
|
|
|
if (response.status === 204) {
|
|
return new Promise((resolve) => resolve({} as Type));
|
|
}
|
|
|
|
if (!response.ok && (response.status < 200 || response.status >= 300)) {
|
|
response.json().then(console.log);
|
|
throw Error(response.statusText);
|
|
}
|
|
|
|
return response.json();
|
|
}
|
|
|
|
export function handleErrorsRaw(response: Response) {
|
|
if (response.status === 204) {
|
|
console.error({ response });
|
|
return "{}";
|
|
}
|
|
if (!response.ok || response.status < 200 || response.status >= 300) {
|
|
response.text().then(console.log);
|
|
throw Error(response.statusText);
|
|
}
|
|
return response.text();
|
|
}
|