/** * Error handling utilities */ import { HostexApiResponse } from '../types/index.js'; /** * Hostex API error */ export class HostexApiError extends Error { constructor( message: string, public readonly errorCode: number, public readonly requestId?: string, public readonly statusCode?: number, public readonly response?: unknown ) { super(message); this.name = 'HostexApiError'; Object.setPrototypeOf(this, HostexApiError.prototype); } /** * Check if this is a specific Hostex error code */ isErrorCode(code: number): boolean { return this.errorCode === code; } /** * Check if this is a network/timeout error */ isNetworkError(): boolean { return !this.statusCode || this.statusCode >= 500; } /** * Check if this is an authentication error */ isAuthError(): boolean { return this.statusCode === 401 || this.statusCode === 403; } /** * Check if this is a rate limit error */ isRateLimitError(): boolean { return this.statusCode === 429; } /** * Convert to JSON */ toJSON(): object { return { name: this.name, message: this.message, errorCode: this.errorCode, requestId: this.requestId, statusCode: this.statusCode, }; } } /** * Thrown when a request times out waiting for rate limit capacity */ export class RateLimitTimeoutError extends HostexApiError { constructor( public readonly endpointCategory: string, public readonly timeoutMs: number ) { super( `Rate limit timeout: ${endpointCategory} capacity not available within ${timeoutMs}ms`, 429, undefined, 429 ); this.name = 'RateLimitTimeoutError'; Object.setPrototypeOf(this, RateLimitTimeoutError.prototype); } } /** * Create error from Hostex API response */ export function createErrorFromResponse( response: HostexApiResponse, statusCode?: number ): HostexApiError { return new HostexApiError( response.error_msg || 'Unknown error', response.error_code, response.request_id, statusCode, response ); } /** * Check if error is retryable by the withRetry loop. * Note: 429 rate limit errors are NOT retried here because * the axios interceptor already handles a one-time retry with delay. * Retrying 429s in withRetry causes request multiplication that * worsens rate limiting. */ export function isRetryableError(error: unknown): boolean { if (error instanceof HostexApiError) { return error.isNetworkError(); } return false; }