1import { prettifyError, ZodError } from "zod/v4"; 2 3export const StatusCodes: Record<number, string> = { 4 400: "Bad Request", 5 403: "Forbidden", 6 404: "Not Found", 7 408: "Request Timeout", 8 409: "Conflict", 9 429: "Too Many Requests", 10 499: "Client Closed Request", 11 500: "Internal Server Error", 12}; 13 14export class BaseError extends Error { 15 status: number; 16 17 constructor(message: string, status: number, cause?: Error) { 18 const statusText = StatusCodes[status] || "Unknown"; 19 super(`${status} ${statusText}: ${message}`); 20 21 this.name = this.constructor.name; 22 this.status = status; 23 this.cause = cause; 24 } 25} 26 27export class CancellationError extends BaseError { 28 constructor(reason: string, cause?: Error) { 29 super(`${reason} was cancelled`, 499, cause); 30 } 31} 32 33export class AuthError extends BaseError { 34 constructor(reason: string, cause?: Error) { 35 super(`authentication failed: ${reason}`, 403, cause); 36 } 37} 38 39export class ValidationError extends BaseError { 40 constructor(zodError: ZodError, cause?: Error) { 41 super(`validation failed: ${prettifyError(zodError)}`, 400, cause); 42 } 43} 44 45export class NotFoundError extends BaseError { 46 constructor(resource: string, cause?: Error) { 47 super(`${resource} not found`, 404, cause); 48 } 49} 50 51export class ConflictError extends BaseError { 52 constructor(reason: string, cause?: Error) { 53 super(`conflict: ${reason}`, 409, cause); 54 } 55} 56 57export class RateLimitError extends BaseError { 58 constructor(reason: string, cause?: Error) { 59 super(`rate limit exceeded: ${reason}`, 429, cause); 60 } 61} 62 63export class NormalizedError extends Error { 64 value: unknown; 65 constructor(value: unknown, cause?: Error) { 66 super(cause?.message || String(value)); 67 this.value = value; 68 } 69} 70 71export function normalizeError(value: unknown) { 72 if (value instanceof Error) { 73 return value; 74 } else { 75 return new NormalizedError(value); 76 } 77}