import { IResponse , IHeader , IHttpService , IQueryParameter , urlHelper } from '@kentico/kontent-core' ; import { AxiosError } from 'axios' ; import { waitForLoadingNewContentHeader , IQueryConfig , ISDKInfo , IDeliveryErrorRaw , DeliveryError , sdkVersionHeader , staleContentHeaderName , continuationTokenHeaderName , IDeliveryNetworkResponse } from '../models' ; import { IDeliveryClientConfig } from '../config' ; import { IMappingService } from './mapping.service' ; export abstract class BaseDeliveryQueryService { /**
     * Default base Url to Kentico Delivery API
     */ private readonly defaultBaseDeliveryApiUrl : string = 'https://deliver.kontent.ai' ; /**
     * Default preview url to Kentico Delivery API
     */ private readonly defaultPreviewDeliveryApiUrl : string = 'https://preview-deliver.kontent.ai' ; constructor ( /**
     * Delivery client configuration
     */ public readonly config , /**
     * Http service for fetching data
     */ public readonly httpService , /**
     * Information about the SDK
     */ public readonly sdkInfo , /**
     * Mapping service
     */ public readonly mappingService ) { } param action param queryConfig param options getUrl ( action , queryConfig , options ? ) { if ( ! this . config . proxy || ! this . config . proxy . advancedProxyUrlResolver ) { return urlHelper . addOptionsToUrl ( this . getBaseUrl ( queryConfig ) + action , options ) ; } return this . config . proxy . advancedProxyUrlResolver ( { queryParameters : options ? options : [ ] , queryString : urlHelper . addOptionsToUrl ( '' , options ) , action : action , domain : this . getDomain ( queryConfig ) , queryConfig : queryConfig , projectId : this . config . projectId } ) ; } param queryConfig param additionalHeaders getHeaders ( queryConfig , additionalHeaders ? ) { const headers = [ ] ; if ( additionalHeaders ) { headers . push ( ... additionalHeaders ) ; } headers . push ( this . getSdkIdHeader ( ) ) ; if ( this . config . globalHeaders ) { headers . push ( ... this . config . globalHeaders ( queryConfig ) ) ; } headers . push ( ... this . getQueryHeaders ( queryConfig ) ) ; if ( this . isPreviewModeEnabled ( queryConfig ) && this . isSecuredModeEnabled ( queryConfig ) ) { throw Error ( `Preview & secured modes cannot be used at the same time.` ) ; } if ( this . isPreviewModeEnabled ( queryConfig ) && this . config . previewApiKey ) { headers . push ( this . getAuthorizationHeader ( this . config . previewApiKey ) ) ; } if ( this . isSecuredModeEnabled ( queryConfig ) && this . config . secureApiKey ) { headers . push ( this . getAuthorizationHeader ( this . config . secureApiKey ) ) ; } if ( this . shouldAddWaitForLoadingNewContentHeader ( queryConfig ) ) { headers . push ( { header : waitForLoadingNewContentHeader , value : 'true' } ) ; } return headers ; } param url param queryConfig protected async getResponseAsync < TRawData > ( url , queryConfig ? , serviceConfig ? ) { if ( ! queryConfig ) { queryConfig = { } ; } if ( ! serviceConfig ) { serviceConfig = { } ; } try { return await this . httpService . getAsync < TRawData > ( { url : url } , { cancelToken : queryConfig ?. cancelToken , responseType : 'json' , retryStrategy : this . config . retryStrategy , headers : this . getHeaders ( queryConfig , serviceConfig . headers ? serviceConfig . headers : [ ] ) } ) ; } catch ( error ) { throw this . mapDeliveryError ( error ) ; } } param queryConfig protected getBaseUrl ( queryConfig ) { return this . getDomain ( queryConfig ) + '/' + this . config . projectId ; } protected mapNetworkResponse < TData , TContract > ( data , response ) { return { data : data , response : response , hasStaleContent : this . getHasStaleContent ( response . headers ) , xContinuationToken : this . getContinuationToken ( response . headers ) } ; } param queryConfig private isPreviewModeEnabled ( queryConfig ) { if ( queryConfig . usePreviewMode !== undefined ) { return queryConfig . usePreviewMode ; } if ( ! this . config . defaultQueryConfig ) { return false ; } if ( this . config . defaultQueryConfig . usePreviewMode === true ) { return true ; } return false ; } private getQueryHeaders ( queryConfig ) { if ( queryConfig . customHeaders ) { return queryConfig . customHeaders ; } if ( this . config . defaultQueryConfig ?. customHeaders ) { return this . config . defaultQueryConfig . customHeaders ; } return [ ] ; } private shouldAddWaitForLoadingNewContentHeader ( queryConfig ) { if ( queryConfig . waitForLoadingNewContent !== undefined ) { return queryConfig . waitForLoadingNewContent ; } if ( ! this . config . defaultQueryConfig ) { return false ; } if ( this . config . defaultQueryConfig . waitForLoadingNewContent === true ) { return true ; } return false ; } param queryConfig private isSecuredModeEnabled ( queryConfig ) { if ( queryConfig . useSecuredMode !== undefined ) { return queryConfig . useSecuredMode ; } if ( ! this . config . defaultQueryConfig ) { return false ; } if ( this . config . defaultQueryConfig . useSecuredMode === true ) { return true ; } return false ; } param queryConfig private getDomain ( queryConfig ) { if ( this . isPreviewModeEnabled ( queryConfig ) ) { if ( ! this . config . previewApiKey ) { throw Error ( `Preview API key is not configured.` ) ; } if ( this . config . proxy && this . config . proxy . basePreviewUrl ) { return this . config . proxy . basePreviewUrl ; } return this . defaultPreviewDeliveryApiUrl ; } if ( this . config . proxy && this . config . proxy . baseUrl ) { return this . config . proxy . baseUrl ; } return this . defaultBaseDeliveryApiUrl ; } /**
     * Gets authorization header. This is used for 'preview' functionality
     */ private getAuthorizationHeader ( key ? ) { if ( ! key ) { throw Error ( `Cannot get authorization header because key is invalid` ) ; } return { header : 'authorization' , value : `bearer ${ key }` } ; } /**
     * Header identifying SDK type & version for internal purposes of Kentico
     */ private getSdkIdHeader ( ) { return { header : sdkVersionHeader , value : `${ this . sdkInfo . host };${ this . sdkInfo . name };${ this . sdkInfo . version }` } ; } private mapDeliveryError ( error ) { let axiosError ; if ( error . error ) { axiosError = error . error ; } else { axiosError = error ; } if ( ! axiosError || ! axiosError . isAxiosError ) { return error ; } const deliveryErrorData = axiosError . response ?. data as IDeliveryErrorRaw ; if ( ! deliveryErrorData || ! deliveryErrorData . error_code ) { return error ; } return new DeliveryError ( { errorCode : deliveryErrorData . error_code , message : deliveryErrorData . message , specificCode : deliveryErrorData . specific_code , requestId : deliveryErrorData . request_id } ) ; } private getHasStaleContent ( headers ) { const hasStaleContentHeader = headers . find ( ( m ) => m . header . toLowerCase ( ) === staleContentHeaderName . toLowerCase ( ) ) ; if ( hasStaleContentHeader ) { if ( hasStaleContentHeader . value . toString ( ) === '1' ) { return true ; } } return false ; } private getContinuationToken ( headers ) { const header = headers . find ( ( m ) => m . header . toLowerCase ( ) === continuationTokenHeaderName . toLowerCase ( ) ) ; return header ? header . value : undefined ; } }