import axios, { type AxiosRequestConfig } from "axios"; import { AUTH_FLAG } from "@/context/AuthContext"; export const privateApi = axios.create({ withCredentials: true, baseURL: '', }); let isRefreshing = false; let failedQueue: Array<{ resolve: (value?: unknown) => void; reject: (reason?: any) => void; }> = []; const processQueue = (error: any = null) => { failedQueue.forEach((promise) => { if (error) { promise.reject(error); } else { promise.resolve(); } }); failedQueue = []; }; privateApi.interceptors.response.use( (res) => res, async (error) => { const original = error.config; if (error.response?.status === 400 && error.response?.data) { const data = error.response.data; if (typeof data === 'object' && !Array.isArray(data)) { const firstKey = Object.keys(data)[0]; if (firstKey && Array.isArray(data[firstKey]) && data[firstKey].length > 0) { error.message = data[firstKey][0]; } } } if (error.response?.status === 401 && !original._retry) { if (original.url?.includes("/api/account/logout/")) { return Promise.reject(error); } if (error.response?.data?.code === "user_not_found") { processQueue(error); isRefreshing = false; localStorage.removeItem(AUTH_FLAG); window.location.href = "/social/login"; return Promise.reject(error); } if (original.url?.includes("/api/account/token/refresh/")) { processQueue(error); isRefreshing = false; localStorage.removeItem(AUTH_FLAG); try { await privateApi.post("/api/account/logout/"); } catch { // cookies may already be expired } window.location.href = "/social/login"; return Promise.reject(error); } if (isRefreshing) { return new Promise((resolve, reject) => { failedQueue.push({ resolve, reject }); }) .then(() => privateApi(original)) .catch((err) => Promise.reject(err)); } original._retry = true; isRefreshing = true; try { await privateApi.post("/api/account/token/refresh/"); processQueue(); return privateApi(original); } catch (refreshError) { processQueue(refreshError); return Promise.reject(refreshError); } finally { isRefreshing = false; } } return Promise.reject(error); } ); export const privateMutator = async (config: AxiosRequestConfig): Promise => { if (config.data instanceof FormData) { delete config.headers?.['Content-Type']; } const response = await privateApi.request(config); return response.data; };