--- /dev/null
+export const ERROR_MESSAGES = {
+ NETWORK: {
+ GENERIC: 'Failed to connect to server',
+ NXDOMAIN: 'Server not found - check server address',
+ REFUSED: 'Connection refused - server may be offline',
+ TIMEOUT: 'Request timed out',
+ UNREACHABLE: 'Server is not running or unreachable'
+ },
+ HTTP: {
+ GENERIC: 'Request failed',
+ ACCESS_DENIED: 'Access denied',
+ INTERNAL_ERROR: 'Server error - check server logs',
+ NOT_FOUND: 'Not found',
+ TEMPORARILY_UNAVAILABLE: 'Server temporarily unavailable'
+ }
+};
+
+export const HTTP_CODE_TO_STRING: Record<string, string> = {
+ 401: ERROR_MESSAGES.HTTP.ACCESS_DENIED,
+ 403: ERROR_MESSAGES.HTTP.ACCESS_DENIED,
+ 500: ERROR_MESSAGES.HTTP.INTERNAL_ERROR,
+ 503: ERROR_MESSAGES.HTTP.TEMPORARILY_UNAVAILABLE
+};
this.props = props;
this.error = null;
this.detectRole(props);
- } catch (error) {
- this.error = this.getErrorMessage(error);
+ } catch (error: unknown) {
+ this.error = error instanceof Error ? error.message : String(error);
console.error('Error fetching server properties:', error);
} finally {
this.loading = false;
await fetchPromise;
}
- private getErrorMessage(error: unknown): string {
- if (error instanceof Error) {
- const message = error.message || '';
-
- if (error.name === 'TypeError' && message.includes('fetch')) {
- return 'Server is not running or unreachable';
- } else if (message.includes('ECONNREFUSED')) {
- return 'Connection refused - server may be offline';
- } else if (message.includes('ENOTFOUND')) {
- return 'Server not found - check server address';
- } else if (message.includes('ETIMEDOUT')) {
- return 'Request timed out';
- } else if (message.includes('503')) {
- return 'Server temporarily unavailable';
- } else if (message.includes('500')) {
- return 'Server error - check server logs';
- } else if (message.includes('404')) {
- return 'Server endpoint not found';
- } else if (message.includes('403') || message.includes('401')) {
- return 'Access denied';
- }
- }
-
- return 'Failed to connect to server';
- }
-
clear(): void {
this.props = null;
this.error = null;
import { base } from '$app/paths';
import { getJsonHeaders, getAuthHeaders } from './api-headers';
import { UrlProtocol } from '$lib/enums';
+import { ERROR_MESSAGES, HTTP_CODE_TO_STRING } from '$lib/constants/error';
/**
* API Fetch Utilities
? path
: `${base}${path}`;
- const response = await fetch(url, {
- ...fetchOptions,
- headers
- });
+ let response;
+ try {
+ response = await fetch(url, {
+ ...fetchOptions,
+ headers
+ });
+ } catch (e) {
+ throw new Error(beautifyNetworkError(e));
+ }
if (!response.ok) {
const errorMessage = await parseErrorMessage(response);
const baseHeaders = authOnly ? getAuthHeaders() : getJsonHeaders();
const headers = { ...baseHeaders, ...customHeaders };
- const response = await fetch(url.toString(), {
- ...fetchOptions,
- headers
- });
+ let response;
+ try {
+ response = await fetch(url.toString(), {
+ ...fetchOptions,
+ headers
+ });
+ } catch (e) {
+ throw new Error(beautifyNetworkError(e));
+ }
if (!response.ok) {
const errorMessage = await parseErrorMessage(response);
// JSON parsing failed, use status text
}
- return `Request failed: ${response.status} ${response.statusText}`;
+ const httpErrorStr = HTTP_CODE_TO_STRING[response.status];
+ if (httpErrorStr) {
+ return httpErrorStr;
+ }
+
+ return `${ERROR_MESSAGES.HTTP.GENERIC}: ${response.status} ${response.statusText}`;
+}
+
+/**
+ * Converts a network issue into a human-readable message.
+ * @param throwable - The throwable raised during fetch operation
+ * @returns Error in an human-readable format
+ */
+function beautifyNetworkError(throwable: unknown): string {
+ let message;
+ if (throwable instanceof Error) {
+ message = throwable.message;
+ if (throwable.name === 'TypeError' && message.includes('fetch')) {
+ return ERROR_MESSAGES.NETWORK.UNREACHABLE;
+ }
+ } else {
+ message = String(throwable);
+ }
+
+ if (message.includes('ECONNREFUSED')) {
+ return ERROR_MESSAGES.NETWORK.REFUSED;
+ } else if (message.includes('ENOTFOUND')) {
+ return ERROR_MESSAGES.NETWORK.NXDOMAIN;
+ } else if (message.includes('ETIMEDOUT')) {
+ return ERROR_MESSAGES.NETWORK.TIMEOUT;
+ }
+
+ return `${ERROR_MESSAGES.NETWORK.GENERIC} (${message})`;
}