Files
papercrate/frontend/src/hooks/useApiError.ts
T
2025-11-13 01:07:55 +01:00

51 lines
1.5 KiB
TypeScript

import { useCallback } from 'react';
type ApiLogger = Pick<typeof console, 'error'>;
type ApiErrorVariant = 'error' | 'info' | 'success' | 'warning' | string;
interface ReportPayload {
message: string;
variant: ApiErrorVariant;
retry?: (() => void) | null;
error: unknown;
}
interface UseApiErrorOptions {
logger?: ApiLogger;
onReport?: (payload: ReportPayload) => void;
}
const noop = () => {};
const normalizeMessage = (error: unknown): string => {
if (!error) return 'Something went wrong.';
if (typeof (error as { trim?: () => string })?.trim === 'function') {
return (error as { trim: () => string }).trim();
}
const typed = error as { response?: { data?: { error?: string; message?: string } }; message?: string };
if (typed.response?.data?.error) return typed.response.data.error;
if (typed.response?.data?.message) return typed.response.data.message;
return typed.message || 'Something went wrong.';
};
const useApiError = ({
logger = console,
onReport = noop,
}: UseApiErrorOptions = {}) => {
return useCallback(
(
error: unknown,
{ message, variant = 'error', retry = null }: { message?: string; variant?: ApiErrorVariant; retry?: (() => void) | null } = {},
) => {
const normalizedMessage = message || normalizeMessage(error);
logger.error('[API]', normalizedMessage, error);
onReport({ message: normalizedMessage, variant, retry, error });
return normalizedMessage;
},
[logger, onReport],
);
};
export default useApiError;