UNPKG

@clickup/rest-client

Version:

A syntax sugar tool around Node fetch() API, tailored to work with TypeScript and response validators

50 lines (47 loc) 2.04 kB
import type { Agent as HttpAgent } from "http"; import { Memoize } from "fast-typescript-memoize"; import type { Headers } from "node-fetch"; import type RestRequest from "./RestRequest"; /** * RestResponse is intentionally not aware of the data structure it carries, and * it doesn't do any assertions/validations which is the responsibility of * RestRequest helper methods. * * We also use a concept of "body preloading". Sometimes, e.g. on non-successful * HTTP status codes, we also need to know the body content (at least its * beginning), do double check whether should we retry, throw through or through * a user-friendly error. To do this, we need to preload the beginning of the * body and make it a part of RestResponse abstraction. */ export default class RestResponse { constructor( public readonly req: RestRequest, public readonly agent: HttpAgent | null, public readonly status: number, public readonly headers: Headers, public readonly text: string, public readonly textIsPartial: boolean, ) {} /** * A safe way to treat the response as JSON. * - Never throws, i.e. we imply that the caller will verify the structure of * the response and do its own errors processing. * - It's a getter, so we can use typescript-is'es is<xyz>() type guard, e.g.: * `if (is<{ errors: any[] }>(res.json) && res.json.errors.length) { ... }` * * Notice that there is NO `assert()` abstraction inside RestResponse class. * This is because RestClient sometimes substitutes the response with some * sub-field (e.g. see writeGraphQLX() method), and we still need to run the * assertion in such cases. By not having strong typing here, we intentionally * make the use of this method harder, so people will prefer using * RestRequest.json() instead. */ @Memoize() get json(): object | string | number | boolean | null | undefined { try { return this.text ? JSON.parse(this.text) : undefined; } catch (e: any) { return undefined; } } }