/* eslint-disable consistent-return */ /* eslint-disable no-param-reassign */ import axios, { AxiosInstance } from 'axios'; import { staticMessages } from '~/driven/utils/constants/staticMessages'; import { ApiGlobalResponseObject } from '~/driven/utils/protocols/serviceProtocols'; import { apiUrls } from '~/driven/utils/configs/appConfig'; import { HttpOptionsType } from './protocols'; interface IUserTokens { accessToken: string | null; refreshToken: string | null; } export class HTTPPovider { private userTokens: IUserTokens; private updateAccessToken: (newAccessToken: string) => void; private navigateToAuth: () => void; constructor( userTokens: IUserTokens, updateAccessToken: (newAccessToken: string) => void, navigateToAuth: () => void, ) { this.userTokens = userTokens; this.updateAccessToken = updateAccessToken; this.navigateToAuth = navigateToAuth; } private initalizeAxiosInstance() { const instance = axios.create(); return instance; } private handleRequestInterceptor() { const axiosInstance = this.initalizeAxiosInstance(); axiosInstance.interceptors.request.use((config) => { config.headers.Authorization = `Bearer ${this.userTokens.accessToken}`; return config; }); return axiosInstance; } async request(customOptions: HttpOptionsType) { const axiosInstance = this.handleRequestInterceptor(); this.responseIncepter(axiosInstance); const response = await axiosInstance>(customOptions); if (!response) throw new Error(staticMessages.service.errors[500]); return response.data.data; } /** * @todo should be handled in business logic */ private async refreshAccessToken() { try { const response = await axios.post(apiUrls.generic.authRefresh, { refresh_token: this.userTokens.refreshToken, }); this.updateAccessToken(response.data.access_token as string); return response.data.access_token; } catch (err) { this.navigateToAuth(); } } private responseIncepter(axiosInstance: AxiosInstance) { axiosInstance.interceptors.response.use( (response) => response, (error) => { const originalRequest = error.config; if (error.response.status === 401 && error.response.message === 'Unauthorized') { const newAccessToken = this.refreshAccessToken().then(() => { originalRequest.headers.Authorization = `Bearer ${newAccessToken}`; return axios(originalRequest); }); } return Promise.reject(error); }, ); } }