import { AxiosRequestConfig } from "axios" import { BehaviorSubject, Observable } from "rxjs" import { cloneDeep } from "lodash-es" import * as E from "fp-ts/Either" import * as TE from "fp-ts/TaskEither" import { HoppRESTResponse } from "./types/HoppRESTResponse" import { EffectiveHoppRESTRequest } from "./utils/EffectiveURL" import { getService } from "~/modules/dioc" import { InterceptorService, NetworkResponse, } from "~/services/interceptor.service" export type NetworkStrategy = ( req: AxiosRequestConfig ) => TE.TaskEither export const cancelRunningRequest = () => { // TODO: Implement } function processResponse( res: NetworkResponse, req: EffectiveHoppRESTRequest, backupTimeStart: number, backupTimeEnd: number, successState: HoppRESTResponse["type"] ) { const contentLength = res.headers["content-length"] ? parseInt(res.headers["content-length"]) : (res.data as ArrayBuffer).byteLength return { type: successState, statusCode: res.status, statusText: res.statusText, body: res.data, headers: Object.keys(res.headers).map((x) => ({ key: x, value: res.headers[x], })), meta: { responseSize: contentLength, responseDuration: backupTimeEnd - backupTimeStart, }, req, } } export function createRESTNetworkRequestStream( request: EffectiveHoppRESTRequest ): [Observable, () => void] { const response = new BehaviorSubject({ type: "loading", req: request, }) const req = cloneDeep(request) const headers = req.effectiveFinalHeaders.reduce((acc, { key, value }) => { return Object.assign(acc, { [key]: value }) }, {}) const params = new URLSearchParams() for (const param of req.effectiveFinalParams) { params.append(param.key, param.value) } const backupTimeStart = Date.now() const service = getService(InterceptorService) const res = service.runRequest({ method: req.method as any, url: req.effectiveFinalURL.trim(), headers, params, data: req.effectiveFinalBody, }) res.response.then((res) => { const backupTimeEnd = Date.now() if (E.isRight(res)) { const processedRes = processResponse( res.right, req, backupTimeStart, backupTimeEnd, "success" ) response.next(processedRes) response.complete() return } response.next({ type: "network_fail", req, error: res.left, }) response.complete() }) return [response, () => res.cancel()] }