import { HttpHeaders , HttpResponse , HttpClient } from '@angular/common/http' ; import { Observable } from 'rxjs' ; import { Request , Body , ExtractFiles } from './types' ; export const fetch = ( req , httpClient , extractFiles ) : Observable < HttpResponse < Object > > => { const shouldUseBody = [ 'POST' , 'PUT' , 'PATCH' ] . indexOf ( req . method . toUpperCase ( ) ) !== - 1 ; const shouldStringify = ( param ) => [ 'variables' , 'extensions' ] . indexOf ( param . toLowerCase ( ) ) !== - 1 ; const isBatching = ( req . body as Body [ ] ) . length ; let shouldUseMultipart = req . options && req . options . useMultipart ; let multipartInfo ; if ( shouldUseMultipart ) { if ( isBatching ) { return new Observable ( ( observer ) => observer . error ( new Error ( 'File upload is not available when combined with Batching' ) ) ) ; } if ( ! shouldUseBody ) { return new Observable ( ( observer ) => observer . error ( new Error ( 'File upload is not available when GET is used' ) ) ) ; } multipartInfo = extractFiles ( req . body ) ; shouldUseMultipart = ! ! multipartInfo . files . size ; } let bodyOrParams = { } ; if ( isBatching ) { if ( ! shouldUseBody ) { return new Observable ( ( observer ) => observer . error ( new Error ( 'Batching is not available for GET requests' ) ) ) ; } bodyOrParams = { body : req . body , } ; } else { const body = shouldUseMultipart ? multipartInfo ! . clone : req . body ; if ( shouldUseBody ) { bodyOrParams = { body , } ; } else { const params = Object . keys ( req . body ) . reduce ( ( obj , param ) => { const value = ( req . body as any ) [ param ] ; obj [ param ] = shouldStringify ( param ) ? JSON . stringify ( value ) : value ; return obj ; } , { } ) ; bodyOrParams = { params : params } ; } } if ( shouldUseMultipart && shouldUseBody ) { const form = new FormData ( ) ; form . append ( 'operations' , JSON . stringify ( ( bodyOrParams as any ) . body ) ) ; const map = { } ; const files = multipartInfo ! . files ; let i = 0 ; files . forEach ( ( paths ) => { map [ ++ i ] = paths ; } ) ; form . append ( 'map' , JSON . stringify ( map ) ) ; i = 0 ; files . forEach ( ( _ , file ) => { form . append ( ++ i + '' , file , file . name ) ; } ) ; ( bodyOrParams as any ) . body = form ; } return httpClient . request < Object > ( req . method , req . url , { observe : 'response' , responseType : 'json' , reportProgress : false , ... bodyOrParams , ... req . options , } ) ; } ; export const mergeHeaders = ( source , destination ) : HttpHeaders => { if ( source && destination ) { const merged = destination . keys ( ) . reduce ( ( headers , name ) => headers . set ( name , destination . getAll ( name ) ) , source ) ; return merged ; } return destination || source ; } ; export function prioritize < T > ( ... values ) { const picked = values . find ( ( val ) => typeof val !== 'undefined' ) ; if ( typeof picked === 'undefined' ) { return values [ values . length - 1 ] ; } return picked ; } export function createHeadersWithClientAwereness ( context ) { let headers = context . headers && context . headers instanceof HttpHeaders ? context . headers : new HttpHeaders ( context . headers ) ; if ( context . clientAwareness ) { const { name , version } = context . clientAwareness ; if ( name && ! headers . has ( 'apollographql-client-name' ) ) { headers = headers . set ( 'apollographql-client-name' , name ) ; } if ( version && ! headers . has ( 'apollographql-client-version' ) ) { headers = headers . set ( 'apollographql-client-version' , version ) ; } } return headers ; }