import { BeforeRequest , UploadProps , UploadFunction , UseUploadState , Headers , } from "./types" ; type UseUploadCreatorProps < Response > = { beforeRequest : BeforeRequest ; setState : ( data : UseUploadState < Response > ) => any ; updateState : ( cb : ( data : UseUploadState < Response > ) => UseUploadState < Response > ) => any ; } ; export const useUploadCreator = < Response = any > ( { beforeRequest , setState , updateState , } ) : UploadFunction => { const upload = async ( { files } ) => { setState ( { loading : true , done : false } ) ; const xhr = new XMLHttpRequest ( ) ; let options = await beforeRequest ( { xhr , files } ) ; if ( ! options ) return setState ( { loading : false , done : false } ) ; xhr . open ( options . method , options . url ) ; if ( options . headers ) { let headers = options . headers ; Object . keys ( options . headers ) . forEach ( ( header ) => xhr . setRequestHeader ( header , headers [ header ] ) ) ; } xhr . upload . addEventListener ( "progress" , ( event ) => { updateState ( ( state ) => ( { ... state , progress : Math . round ( ( event . loaded / event . total ) * 100 ) , } ) ) ; } ) ; xhr . addEventListener ( "load" , ( ) => { let data ; try { data = JSON . parse ( xhr . response ) ; } catch ( e ) { data = xhr . response ; } let responseHeaders = xhr . getAllResponseHeaders ( ) . trim ( ) . split ( /[\r\n]+/ ) . map ( ( line ) => line . split ( ": " ) ) . reduce ( ( acc , [ header , value ] ) => { acc [ header ] = value ; return acc ; } , { } ) ; setState ( { data , loading : false , xhr , responseHeaders , done : true } ) ; } ) ; xhr . addEventListener ( "error" , ( error ) => { setState ( { error , xhr , loading : false , done : true } ) ; } ) ; xhr . addEventListener ( "abort" , ( error ) => { setState ( { error , xhr , loading : false , done : true } ) ; } ) ; xhr . send ( options . body ) ; } ; return upload ; } ;