import type _https from 'https' ; import { getJSRuntimeName } from './getJSRuntimeName' ; import type { O } from 'ts-toolbelt' ; import type { IncomingMessage } from 'http' ; export type RequestOptions = O . Patch < { headers ? : { [ k ] : string ; } ; body ? : string ; } , RequestInit > ; export type RequestResponse = O . Required < O . Optional < Response > , 'json' | 'url' | 'ok' | 'status' > ; param url param options returns export async function request ( url , options = { } ) { const jsRuntimeName = getJSRuntimeName ( ) ; if ( jsRuntimeName === 'browser' ) { return fetch ( url , options ) ; } else { return nodeFetch ( url , options ) ; } } param options returns function buildHeaders ( options ) { return { ... options . headers , 'Content-Type' : 'application/json' , } ; } param options returns function buildOptions ( options ) { return { method : options . method , headers : buildHeaders ( options ) , } ; } param incomingData param response returns function buildResponse ( incomingData , response ) { return { json : ( ) => JSON . parse ( Buffer . concat ( incomingData ) . toString ( ) ) , ok : response . statusCode ! >= 200 && response . statusCode ! < 300 , status : response . statusCode ! , url : response . url ! , } ; } param url param options returns function nodeFetch ( url , options = { } ) { const httpsOptions = buildOptions ( options ) ; const incomingData = [ ] as Buffer [ ] ; return new Promise ( ( resolve , reject ) => { const https = eval ( `require('https')` ) ; const request = https . request ( url , httpsOptions , ( response ) => { response . on ( 'data' , ( chunk ) => incomingData . push ( chunk ) ) ; response . on ( 'end' , ( ) => resolve ( buildResponse ( incomingData , response ) ) ) ; response . on ( 'error' , reject ) ; } ) ; request . on ( 'error' , reject ) ; request . write ( options . body ?? '' ) ; request . end ( ) ; } ) ; }