import fetch from 'cross-fetch' ; import { stringify } from 'qs' ; import { Options , Body , Params } from './types' ; const methods = [ 'POST' , 'PUT' , 'PATCH' , 'DELETE' ] ; function last < T > ( arr ) { return arr [ arr . length - 1 ] ; } function getMethod ( url , options = { } ) { const arr = url . split ( /\s+/ ) ; if ( arr . length === 2 ) return arr [ 0 ] ; const { method = 'GET' } = options ; return method ; } function getDefaultOpt ( url , options = { } ) { const method = getMethod ( url , options ) ; const baseOpt = { method , headers : { } } as Options ; const isJsonTypeMethod = method && methods . includes ( method ) ; if ( isJsonTypeMethod ) { baseOpt . headers = { 'content-type' : 'application/json; charset=utf-8' } ; } return baseOpt as RequestInit ; } function setUrlParam ( url = '' , params ) { return url . split ( '/' ) . map ( item => { if ( item . startsWith ( ':' ) ) { return params [ item . replace ( /^\:/ , '' ) ] ; } return item ; } ) . join ( '/' ) ; } function getURL ( url , options ? ) { url = last ( url . split ( /\s+/ ) ) ; if ( options && options . params ) url = setUrlParam ( url , options . params ) ; const qs = getQueryString ( options ) ; if ( ! qs ) return url ; const connector = url . indexOf ( '?' ) > - 1 ? '' : '?' ; return url + connector + qs ; } function getQueryString ( options ? ) { if ( ! options || ! options . query ) return null ; return stringify ( options . query ) ; } function getBody ( body ? ) { if ( ! body ) return null ; const isJsonObject = typeof body && ( body . constructor . name === 'Object' || body . constructor . name === 'Array' ) ; if ( isJsonObject ) return JSON . stringify ( body ) ; return body ; } function getOpt ( url , options ? ) { const defaultOpt = getDefaultOpt ( url , options ) ; if ( ! options ) return defaultOpt ; const body = getBody ( options . body ) ; if ( body ) options . body = body ; const { headers } = options ; options . headers = { ... defaultOpt . headers , ... headers } ; return { ... defaultOpt , ... options } as RequestInit ; } async function getErrorMsg ( error ) { if ( ! error ) throw 'network error!' ; if ( typeof error !== 'object' ) throw error ; if ( 'json' in error ) { const msg = await error . json ( ) ; if ( msg ) return msg ; } if ( 'blob' in error ) { const msg = await error . blob ( ) ; if ( msg ) return msg ; } return error ; } export async function request < T = any > ( url , options ? ) { const input = getURL ( url , options ) ; const init = getOpt ( url , options ) ; try { const response = await fetch ( input , init ) ; if ( response . status >= 200 && response . status < 300 ) { const { type = 'json' } = options || ( { } as Options ) ; const data = await response [ type ] ( ) ; return data ; } else { throw response ; } } catch ( error ) { throw await getErrorMsg ( error ) ; } }