// Axios API client with base URL and auth interceptor. import axios from 'axios'; const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000/api/v1'; const api = axios.create({ baseURL: API_BASE_URL, headers: { 'Content-Type': 'application/json', }, }); // Request interceptor: attach access token api.interceptors.request.use( (config) => { const token = localStorage.getItem('access_token'); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => Promise.reject(error), ); // Response interceptor: handle 401 & auto-refresh api.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; // If 401 and not already retried and a refresh token exists if ( error.response?.status === 401 && !originalRequest._retry && localStorage.getItem('refresh_token') ) { originalRequest._retry = true; try { const refreshToken = localStorage.getItem('refresh_token'); const response = await axios.post(`${API_BASE_URL}/auth/refresh`, { refresh_token: refreshToken, }); const { access_token, refresh_token: newRefreshToken, user } = response.data; localStorage.setItem('access_token', access_token); localStorage.setItem('refresh_token', newRefreshToken); // Optionally update store const { useAuthStore } = await import('../stores/authStore'); useAuthStore.getState().setUser(user); // Retry original request with new token originalRequest.headers.Authorization = `Bearer ${access_token}`; return api(originalRequest); } catch (refreshError) { // Refresh failed – logout localStorage.removeItem('access_token'); localStorage.removeItem('refresh_token'); localStorage.removeItem('user'); window.location.href = '/login'; return Promise.reject(refreshError); } } return Promise.reject(error); }, ); export default api;