import { Disposable } from '@typed/disposable'
import { Left, Right } from '@typed/either'
import { Resume } from '@typed/env'
import { ArgsOf, Fn } from '@typed/lambda'
import { isValidStatus } from './isValidStatus'
import { HttpEnv, HttpOptions, HttpRequest, HttpResponse } from './types'
export function* http(url: string, options: HttpOptions = {}): HttpRequest {
return yield ({ http }: HttpEnv) =>
Resume.create((f) => {
let hasLoaded = false
const ifNotLoaded = (f: A) => (...args: ArgsOf): Disposable => {
if (!hasLoaded) {
hasLoaded = true
return f(...args)
}
return Disposable.None
}
return http(url, options, {
success: ifNotLoaded((response: HttpResponse) => f(handleSuccess(response))),
failure: ifNotLoaded((error: Error) => f(Left.of(error))),
})
})
}
function handleSuccess(response: HttpResponse) {
if (isValidStatus(response)) {
return Right.of(response)
}
const errorMessage = response.responseText || response.statusText
return Left.of(new Error(errorMessage))
}