UNPKG

@revrag-ai/embed-react-native

Version:

A powerful React Native library for integrating AI-powered voice agents into mobile applications. Features real-time voice communication, intelligent speech processing, customizable UI components, and comprehensive event handling for building conversation

226 lines (210 loc) 6.52 kB
"use strict"; /** * API Error handling system * Centralizes all error handling logic with status codes and definitions */ /** * HTTP Status Code definitions */ export const HTTP_STATUS_CODES = { // 2xx Success 200: 'OK', 201: 'Created', 204: 'No Content', // 4xx Client Errors 400: 'Bad Request', 401: 'Unauthorized', 403: 'Forbidden', 404: 'Not Found', 408: 'Request Timeout', 422: 'Unprocessable Entity', 429: 'Too Many Requests', // 5xx Server Errors 500: 'Internal Server Error', 502: 'Bad Gateway', 503: 'Service Unavailable', 504: 'Gateway Timeout' }; /** * Predefined error types and their definitions */ export const ERROR_TYPES = { NETWORK: { code: 'NETWORK_ERROR', message: 'Network request failed. Please check your internet connection and try again.', type: 'NETWORK' }, ATS: { code: 'ATS_ERROR', message: 'Network request blocked by iOS App Transport Security. Please configure ATS exceptions in Info.plist for HTTP endpoints, or use HTTPS instead.', type: 'ATS' }, TIMEOUT: { code: 'TIMEOUT_ERROR', message: 'Request timeout. The API server may be slow to respond or unreachable.', type: 'TIMEOUT' }, AUTH: { code: 'AUTH_ERROR', message: 'Authentication failed. Please check your API credentials.', type: 'AUTH' }, SERVER: { code: 'SERVER_ERROR', message: 'Server error occurred. Please try again later.', type: 'SERVER' }, VALIDATION: { code: 'VALIDATION_ERROR', message: 'Invalid request data. Please check your input.', type: 'VALIDATION' }, UNKNOWN: { code: 'UNKNOWN_ERROR', message: 'An unknown error occurred. Please try again.', type: 'UNKNOWN' } }; /** * Enhanced error handler that categorizes and formats errors */ export class ApiErrorHandler { /** * Handle HTTP response errors */ static handleHttpError(response, responseData) { const statusCode = response.status; const statusText = HTTP_STATUS_CODES[statusCode] || 'Unknown Status'; // Extract error message from response data if available const serverMessage = responseData?.error || responseData?.message || ''; // Determine error type based on status code let errorType = 'SERVER'; let code; let baseMessage; if (statusCode >= 400 && statusCode < 500) { if (statusCode === 401 || statusCode === 403) { errorType = 'AUTH'; code = ERROR_TYPES.AUTH.code; baseMessage = ERROR_TYPES.AUTH.message; } else if (statusCode === 408) { errorType = 'TIMEOUT'; code = ERROR_TYPES.TIMEOUT.code; baseMessage = ERROR_TYPES.TIMEOUT.message; } else if (statusCode === 422) { errorType = 'VALIDATION'; code = ERROR_TYPES.VALIDATION.code; baseMessage = ERROR_TYPES.VALIDATION.message; } else { errorType = 'VALIDATION'; code = ERROR_TYPES.VALIDATION.code; baseMessage = ERROR_TYPES.VALIDATION.message; } } else { code = ERROR_TYPES.SERVER.code; baseMessage = ERROR_TYPES.SERVER.message; } return { code, message: serverMessage || `${baseMessage} (${statusCode}: ${statusText})`, statusCode, details: serverMessage ? `HTTP ${statusCode}: ${statusText}` : undefined, type: errorType }; } /** * Handle network and other runtime errors */ static handleRuntimeError(error, apiBaseUrl) { const errorMessage = error.message.toLowerCase(); // iOS ATS related errors if (errorMessage.includes('the resource could not be loaded') || errorMessage.includes('app transport security')) { return { ...ERROR_TYPES.ATS, message: `${ERROR_TYPES.ATS.message} Error: ${error.message}`, details: `API endpoint: ${apiBaseUrl}` }; } // Network connectivity errors if (errorMessage.includes('network request failed') || errorMessage.includes('failed to fetch') || errorMessage.includes('fetch')) { return { ...ERROR_TYPES.NETWORK, message: `${ERROR_TYPES.NETWORK.message} API endpoint: ${apiBaseUrl}. Error: ${error.message}`, details: `Endpoint: ${apiBaseUrl}` }; } // Timeout errors if (errorMessage.includes('timeout') || errorMessage.includes('aborted')) { return { ...ERROR_TYPES.TIMEOUT, message: `${ERROR_TYPES.TIMEOUT.message} Error: ${error.message}`, details: `Endpoint: ${apiBaseUrl}` }; } // Authentication errors if (errorMessage.includes('unauthorized') || errorMessage.includes('authentication') || errorMessage.includes('api key')) { return { ...ERROR_TYPES.AUTH, message: `${ERROR_TYPES.AUTH.message} Error: ${error.message}` }; } // Default to unknown error return { ...ERROR_TYPES.UNKNOWN, message: `${ERROR_TYPES.UNKNOWN.message} Error: ${error.message}` }; } /** * Format error for API response */ static formatErrorResponse(apiError) { return { success: false, error: apiError.message, errorCode: apiError.code, statusCode: apiError.statusCode, type: apiError.type }; } /** * Main error processing method */ static async processApiError(error, response, apiBaseUrl) { let apiError; if (response && !response.ok) { // HTTP error - try to get response data let responseData; try { responseData = await response.json(); } catch (e) { // If JSON parsing fails, use response text or status responseData = { error: response.statusText }; } apiError = this.handleHttpError(response, responseData); } else if (error instanceof Error) { // Runtime error apiError = this.handleRuntimeError(error, apiBaseUrl); } else { // Unknown error type apiError = { ...ERROR_TYPES.UNKNOWN, message: `${ERROR_TYPES.UNKNOWN.message} Details: ${String(error)}` }; } return this.formatErrorResponse(apiError); } } /** * Convenience function for processing API errors */ export const processApiError = async (error, response, apiBaseUrl) => { return ApiErrorHandler.processApiError(error, response, apiBaseUrl); }; /** * Type guard to check if a response is an error response */ export const isApiErrorResponse = response => { return response && typeof response === 'object' && response.success === false; }; //# sourceMappingURL=api.error.js.map