/* eslint-disable @typescript-eslint/no-explicit-any */ import axios, { AxiosRequestConfig, AxiosError } from 'axios'; /* TODO: fix dependency cycle */ // eslint-disable-next-line import/no-cycle import { refreshToken } from './data-service'; import { setTokenHeader } from './headers-helpers'; let isRefreshing = false; let failedQueue: { resolve: (value?: any) => void; reject: (reason?: any) => void }[] = []; const processQueue = (error: AxiosError | null, token: string | null = null) => { failedQueue.forEach((prom) => { if (error) { prom.reject(error); } else { prom.resolve(token); } }); failedQueue = []; }; axios.interceptors.response.use( (response) => response, (error) => { const originalRequest = error.config; if (error.response.status === 401 && !originalRequest._retry) { if (isRefreshing) { return new Promise(function (resolve, reject) { failedQueue.push({ resolve, reject }); }) .then((token) => { originalRequest.headers['Authorization'] = 'Bearer ' + token; return axios(originalRequest); }) .catch((err) => { return Promise.reject(err); }); } originalRequest._retry = true; isRefreshing = true; return new Promise(function (resolve, reject) { refreshToken() .then(({ token }) => { if (token) { originalRequest.headers['Authorization'] = 'Bearer ' + token; setTokenHeader(token); window.dispatchEvent(new CustomEvent('tokenUpdated', { detail: token })); processQueue(null, token); resolve(axios(originalRequest)); } else { window.location.href = '/login'; } }) .catch((err) => { processQueue(err, null); reject(err); }) .then(() => { isRefreshing = false; }); }); } return Promise.reject(error); }, ); async function _get(url: string, options?: AxiosRequestConfig): Promise { const response = await axios.get(url, { ...options }); return response.data; } async function _post(url: string, data?: any) { const response = await axios.post(url, JSON.stringify(data), { headers: { 'Content-Type': 'application/json' }, }); return response.data; } async function _postMultiPart(url: string, formData: FormData, options?: AxiosRequestConfig) { const response = await axios.post(url, formData, { ...options, headers: { 'Content-Type': 'multipart/form-data' }, }); return response.data; } async function _put(url: string, data?: any) { const response = await axios.put(url, JSON.stringify(data), { headers: { 'Content-Type': 'application/json' }, }); return response.data; } async function _delete(url: string): Promise { const response = await axios.delete(url); return response.data; } async function _deleteWithOptions(url: string, options?: AxiosRequestConfig): Promise { const response = await axios.delete(url, { ...options }); return response.data; } async function _patch(url: string, data?: any) { const response = await axios.patch(url, JSON.stringify(data), { headers: { 'Content-Type': 'application/json' }, }); return response.data; } export default { get: _get, post: _post, postMultiPart: _postMultiPart, put: _put, delete: _delete, deleteWithOptions: _deleteWithOptions, patch: _patch, };