UNPKG

cloudflare-client

Version:
133 lines (132 loc) 5.2 kB
/* SPDX-FileCopyrightText: 2022-present Kriasoft */ /* SPDX-License-Identifier: MIT */ // #region TypeScript export var HttpMethod; (function (HttpMethod) { HttpMethod["GET"] = "GET"; HttpMethod["PUT"] = "PUT"; HttpMethod["POST"] = "POST"; HttpMethod["PATCH"] = "PATCH"; HttpMethod["DELETE"] = "DELETE"; })(HttpMethod || (HttpMethod = {})); // #endregion export const baseUrl = `https://api.cloudflare.com/client/v4`; export function createFetch(init) { function createRequest(...args) { const options = init(...args); const { searchParams, credentials } = options; const url = new URL(options.url); // Append URL (search) arguments to the URL if (typeof searchParams === "object") { Object.keys(searchParams).forEach((key) => { if (searchParams[key] !== undefined) { url.searchParams.set(key, String(searchParams[key])); } }); } const req = new Request(url, { method: options.method }); const contentType = "contentType" in options ? options.contentType : "application/json"; if (contentType) { req.headers.set("Content-Type", contentType); } // Set authentication header(s) if ("accessToken" in credentials) { req.headers.set("Authorization", `Bearer ${credentials.accessToken}`); } else { req.headers.set("X-Auth-Key", credentials.authKey); req.headers.set("X-Auth-Email", credentials.authEmail); } return [req, options]; } return { response() { return async function (...args) { const [req, options] = createRequest(...args); // Make an HTTP request const res = options.body ? await fetch(new Request(req, { body: options.body })) : await fetch(req); if (res.status === 404 && "notFoundResponse" in options) { return options.notFoundResponse; } if (!res.ok) { const body = await res.json(); throw new FetchError(body, res); } const data = options.type === "text" ? await res.text() : options.type === "binary" ? await res.arrayBuffer() : await res.json(); if (options.type) return data; if (data?.success === false) { throw new FetchError(data, res); } return data.result; }; }, query() { return function (...args) { const [req, options] = createRequest(...args); const promise = (async () => { // Make an HTTP request const res = options.body ? await fetch(new Request(req, { body: options.body })) : await fetch(req); if (res.status === 404 && "notFoundResponse" in options) { return options.notFoundResponse; } const data = options.type === "text" ? await res.text() : await res.json(); if (options.single && Array.isArray(data.result)) { data.result = data.result[0]; delete data.result_info; } return data; })(); const result = { async *[Symbol.asyncIterator]() { const res = await promise; if (Array.isArray(res.result)) { for (const item of res.result) { yield item; } } }, async all() { const items = []; for await (const item of this) { items.push(item); } return items; }, async first() { for await (const item of this) { return item; } }, }; return Object.assign(promise.then(() => result), result); }; }, // TEMP // eslint-disable-next-line @typescript-eslint/no-explicit-any }; } export class FetchError extends Error { code; errors; messages; response; constructor(data, res) { super(data.errors[0]?.message ?? "HTTP request failed"); this.name = "FetchError"; this.code = data.errors[0]?.code ?? 0; this.errors = data.errors ?? []; this.messages = data.messages ?? []; this.response = res; // https://www.typescriptlang.org/docs/handbook/2/classes.html#inheriting-built-in-types Object.setPrototypeOf(this, FetchError.prototype); } }