pagamio-frontend-commons-lib
Version:
Pagamio library for Frontend reusable components like the form engine and table container
191 lines (190 loc) • 6.46 kB
JavaScript
/**
* Different types of errors that can occur during authentication
*/
export var AuthErrorType;
(function (AuthErrorType) {
AuthErrorType["NETWORK"] = "NETWORK";
AuthErrorType["AUTHENTICATION"] = "AUTHENTICATION";
AuthErrorType["SERVER"] = "SERVER";
AuthErrorType["VALIDATION"] = "VALIDATION";
AuthErrorType["UNKNOWN"] = "UNKNOWN";
})(AuthErrorType || (AuthErrorType = {}));
/**
* Network error indicators
*/
const NETWORK_ERROR_INDICATORS = {
ERROR_MESSAGES: ['NetworkError', 'Failed to fetch', 'ERR_NETWORK', 'ERR_INTERNET_DISCONNECTED'],
STRING_INDICATORS: [
'network error',
'connection failed',
'timeout',
'unreachable',
'no internet',
'connection refused',
],
};
/**
* Authentication error indicators
*/
const AUTH_ERROR_INDICATORS = ['invalid credentials', 'invalid username', 'invalid password', 'unauthorized'];
/**
* Common network error message
*/
const NETWORK_ERROR_MESSAGE = 'Unable to connect. Please check your internet connection and try again.';
/**
* Checks if the error is a network-related error
*/
function isNetworkError(error) {
// Handle fetch/network errors
if (error instanceof TypeError && error.message.includes('fetch')) {
return {
type: AuthErrorType.NETWORK,
message: NETWORK_ERROR_MESSAGE,
originalError: error,
};
}
// Handle network timeout
if (error instanceof Error && error.name === 'AbortError') {
return {
type: AuthErrorType.NETWORK,
message: 'Connection timed out. Please check your internet connection and try again.',
originalError: error,
};
}
// Handle offline detection
if (!navigator.onLine) {
return {
type: AuthErrorType.NETWORK,
message: 'You appear to be offline. Please check your internet connection and try again.',
originalError: error instanceof Error ? error : undefined,
};
}
// Handle Error objects with network indicators
if (error instanceof Error) {
const hasNetworkIndicator = NETWORK_ERROR_INDICATORS.ERROR_MESSAGES.some((indicator) => error.message.includes(indicator));
if (hasNetworkIndicator) {
return {
type: AuthErrorType.NETWORK,
message: NETWORK_ERROR_MESSAGE,
originalError: error,
};
}
}
// Handle string errors with network indicators
if (typeof error === 'string') {
const lowercaseError = error.toLowerCase();
const hasNetworkIndicator = NETWORK_ERROR_INDICATORS.STRING_INDICATORS.some((indicator) => lowercaseError.includes(indicator));
if (hasNetworkIndicator) {
return {
type: AuthErrorType.NETWORK,
message: NETWORK_ERROR_MESSAGE,
};
}
}
return null;
}
/**
* Checks if the error is an authentication-related custom error
*/
function isCustomAuthError(customError) {
if (customError.code !== 'UNKNOWN_ERROR') {
return false;
}
const message = customError.message.toLowerCase();
return AUTH_ERROR_INDICATORS.some((indicator) => message.includes(indicator));
}
/**
* Creates error info object
*/
function createErrorInfo(type, message, originalError) {
return {
type,
message,
originalError: originalError instanceof Error ? originalError : undefined,
};
}
/**
* Handles custom server error format
*/
function handleCustomError(error) {
// Handle authentication errors
if (isCustomAuthError(error)) {
return createErrorInfo(AuthErrorType.AUTHENTICATION, 'Invalid credentials. Please check your username and password.', error);
}
// Handle validation errors
if (error.code === 'VALIDATION_ERROR') {
return createErrorInfo(AuthErrorType.VALIDATION, error.message || 'Please check your input and try again.', error);
}
// For other custom errors, use the server message
return createErrorInfo(AuthErrorType.UNKNOWN, error.message || 'An error occurred. Please try again.', error);
}
/**
* Maps HTTP status to error type and message
*/
function getHttpErrorMapping(status) {
if (status === 401 || status === 403) {
return {
type: AuthErrorType.AUTHENTICATION,
message: 'Invalid credentials. Please check your username and password.',
};
}
if (status === 422) {
return {
type: AuthErrorType.VALIDATION,
message: 'Please check your input and try again.',
};
}
if (status === 500 || status === 502 || status === 503) {
return {
type: AuthErrorType.SERVER,
message: 'Server is temporarily unavailable. Please try again later.',
};
}
if (status >= 500) {
return {
type: AuthErrorType.SERVER,
message: 'Server error occurred. Please try again later.',
};
}
return null;
}
/**
* Handles HTTP status code errors
*/
function handleHttpError(httpError) {
const mapping = getHttpErrorMapping(httpError.status);
if (!mapping) {
return null;
}
const message = httpError.status === 422 && httpError.message ? httpError.message : mapping.message;
return createErrorInfo(mapping.type, message, httpError);
}
/**
* Detects the type of error and returns appropriate user-friendly message
*/
export function detectErrorType(error) {
// Check for network errors first
const networkError = isNetworkError(error);
if (networkError) {
return networkError;
}
// Handle custom error format
if (error && typeof error === 'object' && 'code' in error && 'message' in error) {
const customError = error;
return handleCustomError(customError);
}
// Handle HTTP errors
if (error && typeof error === 'object' && 'status' in error) {
const httpError = error;
const httpResult = handleHttpError(httpError);
if (httpResult) {
return httpResult;
}
}
// Handle generic Error objects
if (error instanceof Error) {
return createErrorInfo(AuthErrorType.UNKNOWN, error.message || 'An unexpected error occurred. Please try again.', error);
}
// Fallback
return createErrorInfo(AuthErrorType.UNKNOWN, 'An unexpected error occurred. Please try again.');
}