import { fetch } from "./fetch" import { Method } from "./Method" import { Request } from "./Request" import { Response } from "./Response" export class Client { preprocess = async (request: Request): Promise => request getHeader? = async (request: Request) => ({ ...(request.body ? { contentType: "application/json; charset=utf-8" } : undefined), ...(this.key ? { authorization: `Bearer ${this.key}` } : undefined), ...this.appendHeader?.(request), ...request.header, }) appendHeader?: (request: Request) => Request.Header postprocess = async (response: Response): Promise => response onError?: (request: Request, response: Response) => Promise onUnauthorized?: (connection: Client) => Promise constructor( public url?: string, public key?: string, callbacks?: Partial< Pick, "preprocess" | "getHeader" | "appendHeader" | "postprocess" | "onError" | "onUnauthorized"> > ) { Object.assign(this, callbacks) } /** * @param path Note: Prior to version 0.1.0 this method inserted a `/` between url and path. */ private async fetch(path: string, method: Method, body?: any, header?: Request.Header): Promise { let request = Request.create({ url: `${this.url ?? ""}${path}`, method, header, body }) request = await this.preprocess({ ...request, header: (await this.getHeader?.(request)) ?? request.header }) const response = await this.postprocess( await fetch(request).catch(error => Response.create({ status: 601, body: error })) ) return (response.status == 401 && this.onUnauthorized && (await this.onUnauthorized(this))) || (response.status >= 300 && this.onError && (await this.onError(request, response))) ? await this.fetch(path, method, body, header) : ((await response.body) as R | Error) } async get(path: string, header?: Request.Header): Promise { return await this.fetch(path, "GET", undefined, header) } async post(path: string, request: any, header?: Request.Header): Promise { return await this.fetch(path, "POST", request, header) } async delete(path: string, header?: Request.Header): Promise { return await this.fetch(path, "DELETE", undefined, header) } async patch(path: string, request: any, header?: Request.Header): Promise { return await this.fetch(path, "PATCH", request, header) } async put(path: string, request: any, header?: Request.Header): Promise { return await this.fetch(path, "PUT", request, header) } }