UNPKG

@hyper-fetch/core

Version:

Cache, Queue and Persist your requests no matter if you are online or offline!

103 lines (100 loc) 3.76 kB
import { getResponseHeaders, parseErrorResponse, parseResponse, stringifyQueryParams } from "./http-adapter.utils"; import { defaultTimeout, xhrExtra } from "./http-adapter.constants"; import { Adapter } from "../adapter/adapter"; import { HttpMethods } from "constants/http.constants"; import { HttpMethodsType, HttpStatusType } from "types"; import { HttpAdapterOptionsType, HttpAdapterExtraType } from "./http-adapter.types"; import { QueryParamsType } from "adapter"; export const getAdapter = () => new Adapter< HttpAdapterOptionsType, HttpMethodsType, HttpStatusType, HttpAdapterExtraType, QueryParamsType | string | null, undefined, string >({ name: "http-browser", defaultMethod: HttpMethods.GET, defaultExtra: xhrExtra, systemErrorStatus: 0 as number, systemErrorExtra: xhrExtra, }) .setQueryParamsMapper(stringifyQueryParams) .setFetcher( async ({ request, adapterOptions, headers, payload, onError, onResponseEnd, onTimeoutError, onRequestEnd, createAbortListener, onResponseProgress, onResponseStart, onBeforeRequest, onRequestStart, onRequestProgress, onSuccess, }) => { const { method, client, endpoint, queryParams } = request; const queryString = queryParams ? stringifyQueryParams(queryParams) : ""; const fullUrl = `${client.url}${endpoint}${queryString}`; const xhr = new XMLHttpRequest(); xhr.timeout = defaultTimeout; const onAbort = () => xhr.abort(); // Inject xhr options if (adapterOptions) { Object.entries(adapterOptions).forEach(([name, value]) => { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore xhr[name] = value; }); } // Open connection xhr.open(method, fullUrl, true); // Set Headers Object.entries(headers).forEach(([name, value]) => xhr.setRequestHeader(name, value as string)); // Listen to abort signal const unmountListener = createAbortListener({ status: 0, extra: xhrExtra, onAbort }); // Request handlers xhr.upload.onprogress = onRequestProgress; // Response handlers xhr.onloadstart = (): void => { onRequestEnd(); onResponseStart(); }; xhr.onprogress = onResponseProgress; xhr.onloadend = () => { onResponseEnd(); unmountListener(); }; /* istanbul ignore next */ xhr.ontimeout = () => onTimeoutError({ status: 0, extra: xhrExtra }); // Data handler xhr.onreadystatechange = (e: Event) => { const event = e as unknown as ProgressEvent<XMLHttpRequest>; const finishedState = 4; if (event.target && event.target.readyState === finishedState) { const { status } = event.target; const success = String(status).startsWith("2") || String(status).startsWith("3"); const responseHeaders = getResponseHeaders(xhr.getAllResponseHeaders()); if (success) { const data = parseResponse(event.target.response); onSuccess({ data, status, extra: { headers: responseHeaders } }); } else { // delay to finish after onabort/ontimeout const error = parseErrorResponse(event.target.response); onError({ error, status, extra: { headers: responseHeaders } }); } } }; // Start request onBeforeRequest(); onRequestStart(); xhr.send(payload as XMLHttpRequestBodyInit); }, );