Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | 16x 25x 8x 17x 25x 15x 1x 14x 14x 7x 7x 5x 9x 9x 1x 8x 16x 16x 16x 12x 12x 3x 3x 9x 9x 9x 12x 12x 4x 16x | import { AxiosError } from 'axios';
export interface FormattedError {
message: string;
statusCode?: number;
correlationId?: string;
isNetworkError?: boolean;
isTimeoutError?: boolean;
originalError?: Error | AxiosError | unknown;
}
/**
* Error message mapping for common HTTP status codes
*/
const ERROR_MESSAGES: Record<number, string> = {
0: 'Unable to connect to the server. Please check your network connection.',
400: 'Invalid request. Please check your input and try again.',
401: 'Your session has expired. Please log in again.',
403: 'You do not have permission to access this resource.',
404: 'The requested resource was not found. It may have been deleted or does not exist.',
409: 'Conflict: This item already exists. Please check and try again.',
429: 'Too many requests. Rate limit exceeded. Please try again later.',
500: 'Server error: Something went wrong. Please try again later.',
503: 'Service temporarily unavailable due to maintenance. Please try again later.',
};
/**
* Get user-friendly error message based on HTTP status code
*
* @param statusCode - HTTP status code
* @param customMessage - Optional custom message from API
* @returns User-friendly error message
*/
export function getErrorMessage(statusCode: number, customMessage?: string): string {
// If custom message provided and not empty, use it
if (customMessage && customMessage.trim()) {
return customMessage;
}
// Get message for status code or use generic message
const message = ERROR_MESSAGES[statusCode] || 'An unexpected error occurred. Please try again.';
// TODO: Implement i18n translation when error message translations are available
// For now, return English messages
// const translationKey = `errors.http.${statusCode}`;
// return i18n.t(translationKey, { defaultValue: message });
return message;
}
/**
* Extract correlation ID from error response
*
* Checks both response headers and response data for correlation ID
*
* @param error - Axios error object
* @returns Correlation ID if found, undefined otherwise
*/
export function extractCorrelationId(error: AxiosError): string | undefined {
if (!error.response) {
return undefined;
}
// Check headers first (case-insensitive)
const headers = error.response.headers;
if (headers) {
const correlationId =
headers['x-correlation-id'] || headers['X-Correlation-ID'] || headers['X-CORRELATION-ID'];
if (correlationId) {
return correlationId as string;
}
}
// Check response data
const data = error.response.data as Record<string, unknown>;
if (data && typeof data.correlationId === 'string') {
return data.correlationId;
}
return undefined;
}
/**
* Format error for display in UI
*
* Extracts relevant information from Error or AxiosError and formats it
* for consistent display in the UI
*
* @param error - Error or AxiosError object
* @returns Formatted error object
*/
export function formatErrorForDisplay(error: unknown): FormattedError {
// Handle AxiosError (API errors)
// Check for isAxiosError flag, response object, or axios-specific error codes
const errorObj = error as Partial<AxiosError>;
const isAxiosLike =
errorObj.isAxiosError ||
errorObj.response ||
errorObj.code === 'ERR_NETWORK' ||
errorObj.code === 'ECONNABORTED';
if (isAxiosLike) {
const axiosError = error as AxiosError;
// Network error (no response)
if (!axiosError.response) {
const isTimeout =
axiosError.code === 'ECONNABORTED' ||
(axiosError.message && axiosError.message.includes('timeout'));
return {
message: isTimeout
? 'Timeout: The request is taking longer than expected. Please try again.'
: getErrorMessage(0),
isNetworkError: isTimeout ? false : true,
isTimeoutError: isTimeout ? true : false,
originalError: error,
};
}
// HTTP error with response
const statusCode = axiosError.response.status;
const responseData = axiosError.response.data as Record<string, unknown>;
const customMessage =
typeof responseData?.message === 'string' ? responseData.message : undefined;
const correlationId = extractCorrelationId(axiosError);
return {
message: getErrorMessage(statusCode, customMessage),
statusCode,
correlationId,
originalError: error,
};
}
// Handle generic Error
const errorMessage =
error instanceof Error ? error.message : 'An unexpected error occurred. Please try again.';
return {
message: errorMessage,
originalError: error,
};
}
|