UNPKG

fetch-buddy

Version:

A TypeScript API client that creates fetch requests from a staticly typed structured object

103 lines (102 loc) 3.32 kB
import { RequestError, formatStructuredApiRequest } from "./utils.js"; export class FetchBuddy { _baseUrl; _headers; constructor({ domain, version }) { this._baseUrl = `${domain}${version ? `/${version}` : ""}`; this._headers = new Headers(); } get headers() { return this._headers; } async getResponseError(res, error) { const errorText = await res.text(); return new RequestError({ code: res.status, data: { message: errorText }, message: error instanceof Error ? error.message : String(error), }); } getRequestError(error) { return new RequestError({ code: 500, data: {}, message: error instanceof Error ? error.message : String(error), }); } async handleResponseOk(res) { try { // Check if response is explicitly empty (No Content) if (res.status === 204 || res.status === 205) { return null; } // Check if Content-Length header is 0 (not guaranteed in all responses) const contentLength = res.headers.get("Content-Length"); if (contentLength === "0") { return null; } // Check Content-Type before parsing const contentType = res.headers.get("Content-Type") || ""; if (contentType.includes("application/json")) { return await res.json(); } if (contentType.includes("text/")) { return await res.text(); } return res; // Return raw response for unknown types } catch (error) { throw await this.getResponseError(res.clone(), error); } } async request(url, init) { try { const reqUrl = this._baseUrl.concat(url); const reqHeaders = Object.fromEntries(this.headers); const res = await fetch(reqUrl, { ...init, headers: { ...reqHeaders, ...(init?.headers ?? {}), }, }); if (res.ok) { return (await this.handleResponseOk(res)); } throw await this.getResponseError(res, res.statusText); } catch (error) { if (error instanceof RequestError) { throw error; } throw this.getRequestError(error); } } get(args, init) { const url = typeof args === "string" ? args : formatStructuredApiRequest(args); return this.request(url, { ...init, method: "GET", headers: { "Content-Type": "application/json", ...(init?.headers ?? {}), }, }); } post(args, body, init) { const url = typeof args === "string" ? args : formatStructuredApiRequest(args); return this.request(url, { ...init, method: "POST", body: JSON.stringify(body), headers: { "Content-Type": "application/json", ...(init?.headers ?? {}), }, }); } }