import { WebClient , HeaderDecorator , RequestForm , RequestHeader , RequestMethod , FileRequestData , } from './web-client' ; import { convertToFormData } from './web-api-util' ; /**
 * WebClient implementation wrapped with fetch api
 */ export class FetchWebClient implements WebClient , HeaderDecorator { constructor ( public scheme , public host , private _decorator ? ) { } get url ( ) : string { return `${ this . scheme }://${ this . host }` ; } toApiURL ( path ) { return `${ this . url }/${ path }` ; } fillHeader ( header ) { header [ 'Host' ] = this . host ; this . _decorator ?. fillHeader ( header ) ; } private buildFetchReqData ( method , header ? ) { const headers = { } ; this . fillHeader ( headers ) ; if ( header ) Object . assign ( headers , header ) ; const reqData = { headers , method , } ; return reqData ; } async request ( method , path , form ? , headers ? ) { const reqData = this . buildFetchReqData ( method , headers ) ; const url = this . toApiURL ( path ) ; if ( form ) { reqData . body = convertToFormData ( form ) ; } const res = await fetch ( url , reqData ) ; if ( ! res . ok ) { throw new Error ( `Web request failed with status ${ res . status } ${ res . statusText }` ) ; } return await res . arrayBuffer ( ) ; } async requestMultipart ( method , path , form ? , headers ? ) { const reqData = this . buildFetchReqData ( method , headers ) ; const url = this . toApiURL ( path ) ; if ( form ) { reqData . body = this . convertToMultipart ( form ) ; } const res = await fetch ( url , reqData ) ; if ( ! res . ok ) { throw new Error ( `Web request failed with status ${ res . status } ${ res . statusText }` ) ; } return await res . arrayBuffer ( ) ; } protected convertToMultipart ( form ) { const formData = new FormData ( ) ; for ( const [ key , value ] of Object . entries ( form ) ) { if ( value && ( value as FileRequestData ) . value && ( value as FileRequestData ) . options ) { const file = value as FileRequestData ; formData . append ( key , new File ( [ new Blob ( [ file . value ] ) ] , file . options . filename , { type : file . options . contentType } ) ) ; } else { formData . append ( key , value + '' ) ; } } return formData ; } }