89 lines
2.6 KiB
TypeScript
89 lines
2.6 KiB
TypeScript
/* 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<R>(customOptions: HttpOptionsType) {
|
|
const axiosInstance = this.handleRequestInterceptor();
|
|
this.responseIncepter(axiosInstance);
|
|
|
|
const response = await axiosInstance<ApiGlobalResponseObject<R>>(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);
|
|
},
|
|
);
|
|
}
|
|
}
|