import type { AxiosInstance , AxiosResponse } from 'axios' ; import { InvalidCredentialsException , UnsupportedAccuracyException } from '../../../../exception' ; import { AccuracyEnum } from '../../../../model' ; import { sliceFrom } from '../../../../util' ; import { MapQuestLocationTransformer } from '../../transformer' ; import type { AbstractCommand } from '../../../../command' ; import type { QueryInterface } from '../../../../interface' ; import type { AbstractLocationTransformer } from '../../../../transformer' ; import type { Constructor } from '../../../../types' ; import type { MapQuestProvider } from '../../map-quest.provider' ; export enum MapQuestLocationQualityEnum { COUNTRY = 'COUNTRY' , ZIP = 'ZIP' , ZIP_EXTENDED = 'ZIP_EXTENDED' , STATE = 'STATE' , COUNTY = 'COUNTY' , CITY = 'CITY' , NEIGHBORHOOD = 'NEIGHBORHOOD' , STREET = 'STREET' , ADDRESS = 'ADDRESS' , POINT = 'POINT' } export function MapQuestCommonCommandMixin < TBase extends Constructor < AbstractCommand > > ( Base ) { abstract class MapQuestCommonCommand extends Base { protected readonly apiKey : any ; protected constructor ( ... args ) { const [ httpClient , apiKey ] = args as any ; super ( httpClient ) ; this . apiKey = apiKey ; if ( ! this . apiKey ) { throw new InvalidCredentialsException ( 'Invalid or missing api key.' ) ; } } protected async validateResponse ( _response ) { } static getMaxAccuracy ( ) { return AccuracyEnum . STREET_NAME ; } protected async parseResponse ( response , query ) { if ( ! Array . isArray ( response . data . results ) || ! response . data . results . length ) { return [ ] ; } const locations = response . data . results [ 0 ] . locations . filter ( ( raw ) => this . accuracyFilter ( raw , query . accuracy ) ) ; if ( ! Array . isArray ( locations ) || ! locations . length ) { return [ ] ; } return Promise . all < AbstractLocationTransformer < MapQuestProvider > > ( locations . map ( async ( raw ) : Promise < AbstractLocationTransformer < MapQuestProvider > > => new MapQuestLocationTransformer ( raw ) ) ) ; } private accuracyFilter ( raw , accuracy ? ) { if ( ! accuracy ) { return true ; } switch ( accuracy ) { case AccuracyEnum . STREET_NAME : return this . isQualityAppropriate ( MapQuestLocationQualityEnum . STREET , raw . geocodeQuality ) ; case AccuracyEnum . CITY : return this . isQualityAppropriate ( MapQuestLocationQualityEnum . CITY , raw . geocodeQuality ) ; case AccuracyEnum . STATE : return this . isQualityAppropriate ( MapQuestLocationQualityEnum . STATE , raw . geocodeQuality ) ; case AccuracyEnum . COUNTRY : return this . isQualityAppropriate ( MapQuestLocationQualityEnum . COUNTRY , raw . geocodeQuality ) ; } throw new UnsupportedAccuracyException ( `Unsupported "${ accuracy }" accuracy.` ) ; } private isQualityAppropriate ( sliceToQuality , locationQuality ) { return sliceFrom ( Object . values ( MapQuestLocationQualityEnum ) , sliceToQuality ) . includes ( locationQuality ) ; } } return MapQuestCommonCommand ; }