import Axios , { AxiosError , AxiosRequestConfig , AxiosResponse } from 'axios' ; import { APIClient } from './api_client' ; import { APIErrorResponse , APIResponse , HashMap } from './api_types' ; import { APIError } from './errors' ; const API_RECONNECT_MAX_RETRY_COUNT = 3 ; const REQUEST_RETRY_TIMEOUT = 1000 ; export class APIResource { public apiClient : APIClient ; public path : string ; public constructor ( apiClient ) { this . apiClient = apiClient ; this . path = '' ; } public get headers ( ) : HashMap { return this . apiClient . headers ; } public get resourcePath ( ) : string { return `${ this . apiClient . currentNode }/api${ this . path }` ; } public async handleRetry ( error , req , retryCount ) { if ( this . apiClient . hasAvailableNodes ( ) ) { return new Promise < APIResponse > ( resolve => setTimeout ( resolve , REQUEST_RETRY_TIMEOUT ) ) . then ( async ( ) : Promise < APIResponse > => { if ( retryCount > API_RECONNECT_MAX_RETRY_COUNT ) { throw error ; } if ( this . apiClient . randomizeNodes ) { this . apiClient . banActiveNodeAndSelect ( ) ; } return this . request ( req , true , retryCount + 1 ) ; } ) ; } return Promise . reject ( error ) ; } public async request ( req , retry , retryCount = 1 ) { const request = Axios . request ( req ) . then ( ( res ) => res . data ) . catch ( ( error ) : void => { if ( error . response ) { const { status } = error . response ; if ( error . response . data ) { const { error : errorString , errors , message , } = error . response . data ; throw new APIError ( message || errorString || 'An unknown error has occurred.' , status , errors ) ; } throw new APIError ( 'An unknown error has occurred.' , status ) ; } throw error ; } ) ; if ( retry ) { return request . catch ( async ( err ) => this . handleRetry ( err , req , retryCount ) ) ; } return request ; } }