import axios from 'axios'; import { tokenStorage } from '@/lib/utils/tokenStorage'; const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000'; export const apiClient = axios.create({ baseURL: API_BASE_URL, headers: { 'Content-Type': 'application/json', }, withCredentials: true, }); // Request interceptor to add auth token apiClient.interceptors.request.use( (config) => { const token = tokenStorage.getAccessToken(); if (token) { config.headers.Authorization = `Bearer ${token}`; } return config; }, (error) => { return Promise.reject(error); } ); // Response interceptor to handle token refresh apiClient.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; // Only handle token refresh on client side if (typeof window === 'undefined') { return Promise.reject(error); } // If error is 401 and we haven't tried to refresh yet if (error.response?.status === 401 && !originalRequest._retry) { originalRequest._retry = true; try { const refreshToken = tokenStorage.getRefreshToken(); if (!refreshToken) { throw new Error('No refresh token'); } const response = await axios.post( `${API_BASE_URL}/api/v1/auth/refresh`, { refreshToken }, { headers: { 'Content-Type': 'application/json' }, withCredentials: true } ); // Handle different response structures let newAccessToken; let newRefreshToken; if (response.data?.data?.tokens?.accessToken) { newAccessToken = response.data.data.tokens.accessToken; newRefreshToken = response.data.data.tokens.refreshToken; } else if (response.data?.tokens?.accessToken) { newAccessToken = response.data.tokens.accessToken; newRefreshToken = response.data.tokens.refreshToken; } else if (response.data?.accessToken) { newAccessToken = response.data.accessToken; newRefreshToken = response.data.refreshToken; } else { throw new Error('Invalid token refresh response'); } // Update tokens in storage tokenStorage.setAccessToken(newAccessToken); if (newRefreshToken) { tokenStorage.setRefreshToken(newRefreshToken); } // Retry original request with new token originalRequest.headers.Authorization = `Bearer ${newAccessToken}`; return apiClient(originalRequest); } catch (refreshError) { console.error('Token refresh failed:', refreshError); // Refresh failed, clear tokens and redirect to login tokenStorage.clearTokens(); // Avoid redirect loop - only redirect if not already on login page if (!window.location.pathname.includes('/login')) { window.location.href = '/login'; } return Promise.reject(refreshError); } } return Promise.reject(error); } ); export default apiClient;