/** * 🔌 API Client Configuration * Cliente HTTP para comunicação com backend */ import axios, { AxiosInstance, AxiosError } from 'axios'; import { ApiError, TaskApiError } from './types'; const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000/api'; const API_TIMEOUT = parseInt(process.env.NEXT_PUBLIC_API_TIMEOUT || '10000'); /** * Instância Axios configurada */ const apiClient: AxiosInstance = axios.create({ baseURL: API_URL, timeout: API_TIMEOUT, headers: { 'Content-Type': 'application/json', }, }); /** * Interceptor: Adicionar token JWT às requisições */ apiClient.interceptors.request.use( (config) => { // Obter token do localStorage const token = typeof window !== 'undefined' ? localStorage.getItem('auth_token') : null; if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => { return Promise.reject(error); }, ); /** * Interceptor: Tratar respostas e erros */ apiClient.interceptors.response.use( (response) => response, (error: AxiosError) => { const status = error.response?.status; const data = error.response?.data as any; // Logout em caso de token inválido if (status === 401) { localStorage.removeItem('auth_token'); localStorage.removeItem('auth_user'); window.dispatchEvent(new Event('auth:logout')); } // Lançar erro customizado throw new TaskApiError( status || 500, data?.message || error.message || 'Erro na API', error, ); }, ); /** * Helper: tratamento de erros */ export const handleApiError = (error: any): string => { if (error instanceof TaskApiError) { return error.message; } if (error instanceof axios.AxiosError) { return ( (error.response?.data as any)?.message || error.message || 'Erro na requisição' ); } return 'Erro desconhecido'; }; export default apiClient;