import { AxiosRequestConfig } from 'axios' ; import { APIHandler , APIResponse , HashMap , RequestConfig , Resource , } from './api_types' ; import { GET } from './constants' ; import { solveURLParams , toQueryString } from './utils' ; export const apiMethod = ( options = { } ) : APIHandler => async function apiHandler ( this , ... args ) : Promise < APIResponse > { const { method = GET , path = '' , urlParams = [ ] , validator , defaultData = { } , retry = false , } = options ; if ( urlParams . length > 0 && args . length < urlParams . length ) { return Promise . reject ( new Error ( `This endpoint must be supplied with the following parameters: ${ urlParams . toString ( ) }` ) ) ; } const data = { ... defaultData , ... ( args . length > urlParams . length && typeof args [ urlParams . length ] === 'object' ? ( args [ urlParams . length ] as object ) : { } ) , } ; if ( validator ) { try { validator ( data ) ; } catch ( err ) { return Promise . reject ( err ) ; } } const resolvedURLObject = urlParams . reduce ( ( accumulator , param , i ) : HashMap => { const value = args [ i ] ; if ( typeof value !== 'string' && typeof value !== 'number' ) { throw new Error ( 'Parameter must be a string or a number' ) ; } return { ... accumulator , [ param ] : typeof value === 'number' ? value . toString ( ) : value , } ; } , { } ) ; const requestData = { headers : this . headers , method , url : solveURLParams ( `${ this . resourcePath }${ path }` , resolvedURLObject ) , } ; if ( Object . keys ( data ) . length > 0 ) { if ( method === GET ) { requestData . url += `?${ toQueryString ( data ) }` ; } else { requestData . data = data ; } } return this . request ( requestData , retry ) ; } ;