import type { AxiosError, AxiosInstance, AxiosPromise, AxiosRequestConfig, AxiosResponse, } from 'axios'; import axios from 'axios'; import type { Subscriber } from 'rxjs'; import { Observable } from 'rxjs'; import type { AxiosObservable } from './AxiosObservable'; type Any = any; export namespace Axios { export type RequestInterceptor = ( config: AxiosRequestConfig, ) => AxiosRequestConfig | Promise; export type ResponseInterceptor = ( response: AxiosResponse, ) => AxiosResponse | Promise>; export type ErrorInterceptor = ( error: AxiosError, ) => void | Promise; } /** * @package [react3l-axios-observable](https://www.npmjs.com/package/react3l-axios-observable) * @namespace Axios * @author thanhtunguet * @description Axios class, like axios, but with observable methods */ export class Axios implements Pick { /** * Axios default config * * @type {AxiosRequestConfig} */ public static defaults: AxiosInstance['defaults'] = axios.defaults; /** * Axios interceptor manager * * @type {AxiosInstance["interceptor"]} */ public static interceptors: AxiosInstance['interceptors'] = axios.interceptors; private axiosInstance: AxiosInstance; /** * Class constructor * * @param axiosInstance - Axios instance */ constructor(axiosInstance: AxiosInstance) { this.axiosInstance = axiosInstance; } public get interceptors(): AxiosInstance['interceptors'] { return this.axiosInstance.interceptors; } public get defaults(): AxiosInstance['defaults'] { return this.axiosInstance.defaults; } /** * Create a new Axios instance * @param config {AxiosRequestConfig} */ public static create(config?: AxiosRequestConfig): Axios { const axiosInstance: AxiosInstance = axios.create(config); return new Axios(axiosInstance); } public static request( config: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable(axios.request, config); } public static get( url: string, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable(axios.get, url, config); } public static delete( url: string, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable(axios.delete, url, config); } public static head( url: string, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable(axios.head, url, config); } public static options( url: string, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable(axios.options, url, config); } public static post( url: string, data?: Any, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable(axios.post, url, data, config); } public static put( url: string, data?: Any, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable(axios.put, url, data, config); } public static patch( url: string, data?: Any, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable(axios.patch, url, data, config); } /** * Create an observable function from a promise function * * @param promiseFunction * @param args * @private */ private static createObservable( promiseFunction: (...args: Any[]) => AxiosPromise, ...args: Any[] ): AxiosObservable { let config: AxiosRequestConfig = args[args.length - 1]; config = typeof config === 'object' ? { ...config } : {}; args[args.length - 1] = config; let abortController: AbortController; const hasSignal = !!config.signal; if (hasSignal) { console.warn( `No need to use abort signal, just unsubscribe the subscription would cancel the http request automatically`, ); } return new Observable>( (subscriber: Subscriber>) => { if (!hasSignal) { abortController = new AbortController(); config.signal = abortController.signal; } promiseFunction(...args) .then((response: any) => { subscriber.next(response); subscriber.complete(); }) .catch((error: AxiosError) => subscriber.error(error)); // Return unsubscribe function return () => { if (abortController && !hasSignal) { abortController.abort(); } }; }, ); } public request(config: AxiosRequestConfig): AxiosObservable { return Axios.createObservable(this.axiosInstance.request, config); } public get( url: string, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable(this.axiosInstance.get, url, config); } public delete( url: string, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable(this.axiosInstance.delete, url, config); } public head( url: string, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable(this.axiosInstance.head, url, config); } public options( url: string, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable(this.axiosInstance.options, url, config); } public post( url: string, data?: Any, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable( this.axiosInstance.post, url, data, config, ); } public put( url: string, data?: Any, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable(this.axiosInstance.put, url, data, config); } public patch( url: string, data?: Any, config?: AxiosRequestConfig, ): AxiosObservable { return Axios.createObservable( this.axiosInstance.patch, url, data, config, ); } }