Files
playzer/apps/frontend/src/lib/api/http.ts
2026-06-10 09:39:20 -03:00

87 lines
2.5 KiB
TypeScript

import axios, { AxiosError, type AxiosInstance } from 'axios';
import { ApiClientError, apiBaseUrl, handlers } from './base';
export const http: AxiosInstance = axios.create({
baseURL: apiBaseUrl,
withCredentials: true,
headers: {
'Content-Type': 'application/json',
},
});
function extractMessage(details: unknown, fallback: string): string {
if (typeof details === 'object' && details) {
if ('message' in details && typeof details.message === 'string') {
return details.message;
}
if ('detail' in details && typeof details.detail === 'string') {
return details.detail;
}
if ('error' in details && typeof details.error === 'object' && details.error) {
const zodError = details.error as Record<string, unknown>;
if (Array.isArray(zodError.issues) && zodError.issues.length > 0) {
const firstIssue = zodError.issues[0] as { message?: string };
if (typeof firstIssue.message === 'string') return firstIssue.message;
}
if (typeof zodError.message === 'string') {
try {
const parsed = JSON.parse(zodError.message);
if (
Array.isArray(parsed) &&
parsed.length > 0 &&
typeof parsed[0]?.message === 'string'
) {
return parsed[0].message;
}
} catch {
/* not JSON, use raw string */
}
return zodError.message;
}
}
}
return fallback;
}
function normalizeError(error: unknown): ApiClientError {
if (error instanceof ApiClientError) return error;
if (axios.isAxiosError(error)) {
const status = error.response?.status;
const details = error.response?.data;
return new ApiClientError(extractMessage(details, error.message || 'Request failed'), {
status,
details,
causeError: error,
});
}
if (error instanceof Error) {
return new ApiClientError(error.message, { causeError: error });
}
return new ApiClientError('Error inesperado.', { causeError: error });
}
http.interceptors.response.use(
(response) => response,
async (error: AxiosError) => {
const normalized = normalizeError(error);
if (normalized.status === 401 && handlers.onUnauthorized) {
await handlers.onUnauthorized(normalized);
}
if (normalized.status === 403 && handlers.onForbidden) {
await handlers.onForbidden(normalized);
}
if (handlers.onError) {
await handlers.onError(normalized);
}
return Promise.reject(normalized);
}
);