import { Injectable } from '@angular/core' ; import { HttpClient } from '@angular/common/http' ; import { ApolloLink , Observable as LinkObservable , Operation , FetchResult , } from '@apollo/client/core' ; import { print } from 'graphql' ; import { extractFiles } from 'extract-files' ; import { Options , Body , Request , Context , OperationPrinter } from './types' ; import { createHeadersWithClientAwereness , fetch , mergeHeaders , prioritize , } from './utils' ; export class HttpLinkHandler extends ApolloLink { public requester : ( operation : Operation ) => LinkObservable < FetchResult > | null ; private print : OperationPrinter = print ; constructor ( private httpClient , private options ) { super ( ) ; if ( this . options . operationPrinter ) { this . print = this . options . operationPrinter ; } this . requester = ( operation ) => new LinkObservable ( ( observer ) => { const context = operation . getContext ( ) ; const pick = < K extends keyof Context > ( key , init ? ) : Context [ K ] | Options [ K ] => { return prioritize ( context [ key ] , this . options [ key ] , init ) ; } ; let method = pick ( 'method' , 'POST' ) ; const includeQuery = pick ( 'includeQuery' , true ) ; const includeExtensions = pick ( 'includeExtensions' , false ) ; const url = pick ( 'uri' , 'graphql' ) ; const withCredentials = pick ( 'withCredentials' ) ; const useMultipart = pick ( 'useMultipart' ) ; const useGETForQueries = this . options . useGETForQueries === true ; const isQuery = operation . query . definitions . some ( ( def ) => def . kind === 'OperationDefinition' && def . operation === 'query' ) ; if ( useGETForQueries && isQuery ) { method = 'GET' ; } const req = { method , url : typeof url === 'function' ? url ( operation ) : url , body : { operationName : operation . operationName , variables : operation . variables , } , options : { withCredentials , useMultipart , headers : this . options . headers , } , } ; if ( includeExtensions ) { ( req . body as Body ) . extensions = operation . extensions ; } if ( includeQuery ) { ( req . body as Body ) . query = this . print ( operation . query ) ; } const headers = createHeadersWithClientAwereness ( context ) ; req . options . headers = mergeHeaders ( req . options . headers , headers ) ; const sub = fetch ( req , this . httpClient , extractFiles ) . subscribe ( { next : ( response ) => { operation . setContext ( { response } ) ; observer . next ( response . body ) ; } , error : ( err ) => observer . error ( err ) , complete : ( ) => observer . complete ( ) , } ) ; return ( ) => { if ( ! sub . closed ) { sub . unsubscribe ( ) ; } } ; } ) ; } public request ( op ) { return this . requester ( op ) ; } } @ Injectable ( { providedIn : 'root' , } ) export class HttpLink { constructor ( private httpClient ) { } public create ( options ) { return new HttpLinkHandler ( this . httpClient , options ) ; } }