/** * Standardized API error classes for consistent error handling */ export class ApiError extends Error { constructor( public code: string, message: string, public status: number, public details?: Record, ) { super(message); this.name = "ApiError"; } toJSON() { return { error: this.code, message: this.message, ...(this.details && { details: this.details }), }; } } export class DatabaseNotInitializedError extends ApiError { constructor(message = "Database not initialized") { super("DATABASE_NOT_INITIALIZED", message, 503); this.name = "DatabaseNotInitializedError"; } } export class TableNotFoundError extends ApiError { constructor(tableName: string) { super("TABLE_NOT_FOUND", `Table "${tableName}" not found`, 503, { tableName, }); this.name = "TableNotFoundError"; } } export class ValidationError extends ApiError { constructor(message: string, details?: Record) { super("VALIDATION_ERROR", message, 400, details); this.name = "ValidationError"; } } export class NotFoundError extends ApiError { constructor(resource: string, id?: string) { const message = id ? `${resource} with id "${id}" not found` : `${resource} not found`; super("NOT_FOUND", message, 404, { resource, id }); this.name = "NotFoundError"; } } export class UnauthorizedError extends ApiError { constructor(message = "Unauthorized") { super("UNAUTHORIZED", message, 401); this.name = "UnauthorizedError"; } } export class ForbiddenError extends ApiError { constructor(message = "Forbidden") { super("FORBIDDEN", message, 403); this.name = "ForbiddenError"; } } export class SubscriptionRequiredError extends ApiError { constructor( message = "An active subscription is required for this feature.", upgradeUrl?: string, ) { super("SUBSCRIPTION_REQUIRED", message, 402, { ...(upgradeUrl && { upgradeUrl }), }); this.name = "SubscriptionRequiredError"; } } export class DatabaseQuotaExceededError extends ApiError { constructor( message = "Database quota exceeded. Operations are temporarily blocked.", ) { super("DATABASE_QUOTA_EXCEEDED", message, 503, { retryable: true, hint: "The database has exceeded its free tier quota. Please try again later or upgrade the plan.", }); this.name = "DatabaseQuotaExceededError"; } }