import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'; import { useRequestsStore } from '@/stores/'; import { LogoutReason, logout, refresh } from '@/auth'; import getRootPath from '@/utils/get-root-path'; const api = axios.create({ baseURL: getRootPath(), withCredentials: true, headers: { 'Cache-Control': 'no-cache', }, }); interface RequestConfig extends AxiosRequestConfig { id: string; } interface Response extends AxiosResponse { config: RequestConfig; } export interface RequestError extends AxiosError { response: Response; } export const onRequest = (config: AxiosRequestConfig) => { const requestsStore = useRequestsStore(); const id = requestsStore.startRequest(); const requestConfig: RequestConfig = { id: id, ...config, }; return requestConfig; }; export const onResponse = (response: AxiosResponse | Response) => { const requestsStore = useRequestsStore(); const id = (response.config as RequestConfig).id; requestsStore.endRequest(id); return response; }; export const onError = async (error: RequestError) => { const requestsStore = useRequestsStore(); const id = (error.response.config as RequestConfig).id; requestsStore.endRequest(id); // If a request fails with the unauthorized error, it either means that your user doesn't have // access, or that your session doesn't exist / has expired. // In case of the second, we should force the app to logout completely and redirect to the login // view. /* istanbul ignore next */ const status = error.response?.status; /* istanbul ignore next */ const code = error.response?.data?.errors?.[0]?.extensions?.code; if ( status === 401 && code === 'INVALID_CREDENTIALS' && error.request.responseURL.includes('refresh') === false && error.request.responseURL.includes('login') === false && error.request.responseURL.includes('tfa') === false ) { let newToken: string; try { newToken = await refresh(); } catch { logout({ reason: LogoutReason.SESSION_EXPIRED }); return Promise.reject(); } if (newToken) { return api.request({ ...error.config, headers: { Authorization: `Bearer ${newToken}`, }, }); } } return Promise.reject(error); }; api.interceptors.request.use(onRequest); api.interceptors.response.use(onResponse, onError); export default api; function getToken() { return api.defaults.headers?.['Authorization']?.split(' ')[1] || null; } export function addTokenToURL(url: string) { const token = getToken(); if (url.includes('?')) { return (url += '&access_token=' + token); } else { return (url += '?access_token=' + token); } }