import axios, { AxiosInstance } from 'axios'; import { useContext } from 'react'; import { refreshToken as updateToken } from '../Services/authService'; import axiosInstance from '../Services/axiosInstance'; import { AuthContext } from '../Context/AuthContext'; import addAccessTokenToHeaders from '../Services/addAccessTokenToHeaders'; const useFetch = (): AxiosInstance => { const { setAuth, refreshTokenReminder } = useContext(AuthContext); const authFetch = axiosInstance(); // Request interceptor for API calls authFetch.interceptors.request.use( addAccessTokenToHeaders, error => Promise.reject(error) ); // Response interceptor for API calls authFetch.interceptors.response.use( (response) => response, async (error) => { const originalRequest = error.config; if (error.response?.status === 401 && originalRequest && !originalRequest._retry && refreshTokenReminder) { originalRequest._retry = true; const deviceCode = localStorage.getItem('device_code'); const refreshToken = localStorage.getItem('refresh_token'); if (!refreshToken || !deviceCode) { setAuth(); return Promise.reject(error); } try { if (refreshTokenReminder.current.refreshToken !== refreshToken) { refreshTokenReminder.current = { refreshToken, promise: updateToken(refreshToken), }; } const response = await refreshTokenReminder.current.promise; if (!response) { throw new Error('Received empty refresh token response.'); } const { access_token, refresh_token } = response; axios.defaults.headers.common['Authorization'] = `Bearer ${access_token}`; setAuth({ deviceCode, accessToken: access_token, refreshToken: refresh_token }); return authFetch(originalRequest); } catch { setAuth(); } } return Promise.reject(error); } ); return authFetch; }; export default useFetch;