import axios, { AxiosInstance } from "axios"; import { BaseClient } from "./clients/clientBase"; import { EventEmitterReadonly, TypedEventEmitter } from "./utils/typedEmitter"; type HttpEvents = { info: [arg1: string]; error: [arg1: { code: string; message: string }]; }; export default class HTTP { public readonly http: AxiosInstance; protected readonly httpEmitter: TypedEventEmitter; protected client: BaseClient; constructor(client: BaseClient) { this.client = client; this.http = axios.create({ baseURL: this.client.serverAdress + "/api", headers: { "Cache-Control": "no-cache", Pragma: "no-cache", Expires: "0", }, }); this.httpEmitter = new TypedEventEmitter(); this.setRequestInterceptor(); this.setResponseInterceptor(); } get httpEvents(): EventEmitterReadonly { return this.httpEmitter; } private setRequestInterceptor() { this.http.interceptors.request.use( (config) => { if (config.headers && !config.headers.Authorization) { config.headers.Authorization = `Bearer ${this.client.accessToken}`; } return config; }, (error) => { return Promise.reject(error); } ); } private setResponseInterceptor() { this.http.interceptors.response.use( (response) => { return response; }, async (error) => { if (!error.config.url.includes("/admin")) { return Promise.reject(error); } const originalRequest = error.config; // Handle token expiration and retry the request with a refreshed token if (error.response && error.response.status === 401 && !originalRequest._retry) { originalRequest._retry = true; return await this.client .refreshToken() .then(() => { this.httpEmitter.emit("info", "successfully refreshed token"); return this.http(originalRequest); }) .catch(() => {}); } this.httpEmitter.emit("error", { code: error.code, message: error.message, }); return Promise.reject(error); } ); } }