/** * API client — Axios instance with JWT auth and automatic refresh. */ import axios from 'axios'; import { useAuthStore } from '@/stores/auth'; const API_BASE = import.meta.env.VITE_API_URL || '/api'; const api = axios.create({ baseURL: `${API_BASE}/v1`, headers: { 'Content-Type': 'application/json' }, withCredentials: true, // Send refresh token cookie }); // Request interceptor: attach access token api.interceptors.request.use((config) => { const token = useAuthStore.getState().accessToken; if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }); // Response interceptor: auto-refresh on 401 api.interceptors.response.use( (response) => response, async (error) => { const original = error.config; if (error.response?.status === 401 && !original._retry) { original._retry = true; try { const { data } = await axios.post( `${API_BASE}/v1/auth/refresh`, {}, { withCredentials: true }, ); useAuthStore.getState().setAccessToken(data.access_token); original.headers.Authorization = `Bearer ${data.access_token}`; return api(original); } catch { useAuthStore.getState().logout(); window.location.href = '/login'; return Promise.reject(error); } } return Promise.reject(error); }, ); export default api;