UNPKG

@oxyhq/services

Version:

Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀

157 lines (143 loc) • 4.64 kB
"use strict"; import { logger } from './loggerUtils'; /** * Error handling utilities for consistent error processing */ /** * Common error codes */ export const ErrorCodes = { // Authentication errors UNAUTHORIZED: 'UNAUTHORIZED', FORBIDDEN: 'FORBIDDEN', INVALID_TOKEN: 'INVALID_TOKEN', MISSING_TOKEN: 'MISSING_TOKEN', // Validation errors VALIDATION_ERROR: 'VALIDATION_ERROR', BAD_REQUEST: 'BAD_REQUEST', MISSING_PARAMETER: 'MISSING_PARAMETER', INVALID_FORMAT: 'INVALID_FORMAT', // Resource errors NOT_FOUND: 'NOT_FOUND', ALREADY_EXISTS: 'ALREADY_EXISTS', CONFLICT: 'CONFLICT', // Server errors INTERNAL_ERROR: 'INTERNAL_ERROR', SERVICE_UNAVAILABLE: 'SERVICE_UNAVAILABLE', TIMEOUT: 'TIMEOUT', // Network errors NETWORK_ERROR: 'NETWORK_ERROR', CONNECTION_FAILED: 'CONNECTION_FAILED' }; /** * Create a standardized API error */ export function createApiError(message, code = ErrorCodes.INTERNAL_ERROR, status = 500, details) { return { message, code, status, details }; } /** * Handle common HTTP errors and convert to ApiError */ export function handleHttpError(error) { // If it's already an ApiError, return it if (error && typeof error === 'object' && 'code' in error && 'status' in error) { return error; } // Handle AbortError (timeout or cancelled requests) if (error instanceof Error && error.name === 'AbortError') { return createApiError('Request timeout or cancelled', ErrorCodes.TIMEOUT, 0); } // Handle TypeError (network failures, CORS, etc.) if (error instanceof TypeError) { // Check if it's a network-related TypeError if (error.message.includes('fetch') || error.message.includes('network') || error.message.includes('Failed to fetch')) { return createApiError('Network error - failed to connect to server', ErrorCodes.NETWORK_ERROR, 0); } return createApiError(error.message || 'Network error occurred', ErrorCodes.NETWORK_ERROR, 0); } // Handle fetch Response errors - check if it has response property with status if (error && typeof error === 'object' && 'response' in error) { const fetchError = error; const status = fetchError.response?.status || fetchError.status; if (status) { return createApiError(fetchError.message || `HTTP ${status} error`, getErrorCodeFromStatus(status), status); } } // Handle standard errors if (error instanceof Error) { // Check for common error patterns if (error.message.includes('timeout') || error.message.includes('aborted')) { return createApiError('Request timeout', ErrorCodes.TIMEOUT, 0); } if (error.message.includes('network') || error.message.includes('fetch')) { return createApiError(error.message || 'Network error occurred', ErrorCodes.NETWORK_ERROR, 0); } return createApiError(error.message || 'Unknown error occurred', ErrorCodes.INTERNAL_ERROR, 500); } // Handle other errors return createApiError(String(error) || 'Unknown error occurred', ErrorCodes.INTERNAL_ERROR, 500); } /** * Get error code from HTTP status * Exported for use in other modules */ export function getErrorCodeFromStatus(status) { switch (status) { case 400: return ErrorCodes.BAD_REQUEST; case 401: return ErrorCodes.UNAUTHORIZED; case 403: return ErrorCodes.FORBIDDEN; case 404: return ErrorCodes.NOT_FOUND; case 409: return ErrorCodes.CONFLICT; case 422: return ErrorCodes.VALIDATION_ERROR; case 500: return ErrorCodes.INTERNAL_ERROR; case 503: return ErrorCodes.SERVICE_UNAVAILABLE; default: return ErrorCodes.INTERNAL_ERROR; } } /** * Validate required fields and throw error if missing */ export function validateRequiredFields(data, fields) { const missing = fields.filter(field => !data[field]); if (missing.length > 0) { throw createApiError(`Missing required fields: ${missing.join(', ')}`, ErrorCodes.MISSING_PARAMETER, 400); } } /** * Safe error logging with context */ export function logError(error, context) { if (error instanceof Error) { logger.error(error.message, { component: context || 'errorUtils', method: 'logError', stack: error.stack }); } else { logger.error(String(error), { component: context || 'errorUtils', method: 'logError' }); } } /** * Retry function with exponential backoff * Re-exports retryAsync for backward compatibility * @deprecated Use retryAsync from asyncUtils instead */ export { retryAsync as retryWithBackoff } from './asyncUtils'; //# sourceMappingURL=errorUtils.js.map