import { Inject , Injectable } from '@angular/core' ; import { HttpClient , HttpEvent , HttpEventType , HttpHeaders , } from '@angular/common/http' ; import { Observable , throwError } from 'rxjs' ; import { CookieService } from '../services/cookie.service' ; import { environment } from '../../../environments/environment' ; import { map , retry } from 'rxjs/operators' ; /**
 * API request methods constants
 */ export enum ApiRequestMethod { GET = 'get' , POST = 'post' , PUT = 'put' , DELETE = 'delete' } /**
 * API request data structure
 */ export type ApiRequestData = { [ key ] : any ; } | null ; /**
 * API request query params structure
 */ export type ApiRequestQueryParams = { [ key ] : any ; } | null ; /**
 * API Response structure
 */ export interface ApiResponse { status : string ; [ key ] : any ; } /**
 * API request options passed to the methods
 */ export type ApiRequestOptions = { upload ? : boolean ; withCredentials ? : boolean ; headers ? : { [ name ] : string | string [ ] ; } ; } ; /**
 * API client class that uses Angular/HttpClient observables with our custom headers. Supports normal requests and uploads via POST.
 */ @ Injectable ( ) export class ApiService { protected baseUrl : string = '/' ; constructor ( @ Inject ( 'ORIGIN_URL' ) baseUrl , protected httpClient , protected cookie ) { if ( baseUrl ) { this . baseUrl = `${ baseUrl }/` ; } } get ( endpoint , queryParams = null , retryTimes = 0 , options = { } ) { const request = this . request ( ApiRequestMethod . GET , this . _buildQueryString ( endpoint , queryParams ) , { } , options ) ; if ( retryTimes ) { return request . pipe ( retry ( retryTimes ) ) ; } return request ; } post ( endpoint , data = null , options = { } ) { return this . request ( ApiRequestMethod . POST , this . baseUrl + endpoint , data , options ) ; } put ( endpoint , data = null , options = { } ) { return this . request ( ApiRequestMethod . PUT , this . baseUrl + endpoint , data , options ) ; } param endpoint param queryParams param options param data returns delete ( endpoint , queryParams = null , options = { } , payload = { } ) { return this . request ( ApiRequestMethod . DELETE , this . _buildQueryString ( endpoint , queryParams ) , payload , options ) ; } upload ( endpoint , data , options ) { return this . httpClient . request < ApiResponse > ( ApiRequestMethod . POST , this . baseUrl + endpoint , this . _buildOptions ( { ... options , upload : true , } , data , true ) ) . pipe ( map ( event => { if ( event . type === HttpEventType . Response ) { const response = event . body ; if ( ! response || ! response . status || response . status !== 'success' ) { throw new Error ( ( response && response . message ) || 'Internal server error' ) ; } } return event ; } ) ) ; } request ( method , endpoint , data , options ) { if ( options . upload ) { return throwError ( new Error ( 'Use the upload() method for uploads' ) ) ; } return this . httpClient . request < ApiResponse > ( method , endpoint , this . _buildOptions ( { ... options , upload : false , } , data , false ) ) . pipe ( map ( response => { if ( ! response || ( response . status && response . status !== 'success' ) ) { throw new Error ( ( response && response . message ) || 'Internal server error' ) ; } return response ; } ) ) ; } param endpoint param queryParams private protected _buildQueryString ( endpoint , queryParams ) { let output = endpoint ; if ( /^\/([^\/])/ . test ( output ) ) { output = output . substr ( 1 ) ; } output = this . baseUrl . replace ( /\/+$/ , '' ) + '/' + output ; if ( queryParams ) { const queryString = Object . keys ( queryParams ) . map ( key => `${ encodeURIComponent ( key ) }=${ encodeURIComponent ( queryParams [ key ] ) }` ) . join ( '&' ) ; if ( queryString ) { output += ( endpoint . indexOf ( '?' ) > - 1 ? '&' : '?' ) + queryString ; } } return output ; } param { ApiRequestOptions } options param { ApiRequestData } data param { boolean } withEvents private protected _buildOptions ( options , data , withEvents ) ; protected _buildOptions ( options , data , withEvents ) ; protected _buildOptions < T extends boolean > ( options , data , withEvents ) { const requestOptions = { observe : withEvents ? 'events' : 'body' , responseType : 'json' , reportProgress : options . upload , withCredentials : options . withCredentials , headers : this . _buildHeaders ( options ?. headers ?? { } ) , } ; if ( ! options . upload ) { if ( data ) { requestOptions . body = JSON . stringify ( data ) ; } } else { if ( ! data ) { throw new Error ( 'No data' ) ; } const formData = new FormData ( ) ; for ( const key in data ) { if ( data . hasOwnProperty ( key ) ) { } formData . append ( key , data [ key ] ) ; } requestOptions . body = formData ; } return requestOptions ; } private protected _buildHeaders ( customHeaders = { } ) { const XSRF_TOKEN = this . cookie . get ( 'XSRF-TOKEN' ) || '' ; return new HttpHeaders ( { 'X-XSRF-TOKEN' : XSRF_TOKEN , 'X-VERSION' : environment . version , ... customHeaders , } ) ; } }