UNPKG

alistair

Version:
104 lines (98 loc) 3.55 kB
// Copyright 2026 Alistair Smith https://github.com/alii/alistair // package.json var version = "1.17.0"; // src/constants.ts var IS_BROWSER = typeof window !== "undefined"; // src/http/utils.ts function join(base, path) { const finalBase = base.charCodeAt(base.length - 1) === 47 ? base : base + "/"; const finalPath = path.charCodeAt(0) === 47 ? path.substring(1) : path; return finalBase + finalPath; } function isBodyInit(body) { return typeof body === "string" || body instanceof ReadableStream || body instanceof Blob || body instanceof FormData || body instanceof URLSearchParams || typeof ArrayBuffer !== "undefined" && (ArrayBuffer.isView(body) || body instanceof ArrayBuffer); } function streamToBody(stream) { return new Response(stream).text(); } // src/http/client.ts var HTTPClientError = class _HTTPClientError extends Error { constructor(count, request, response) { super(_HTTPClientError.getErrorMessage(count, response)); this.count = count; this.request = request; this.response = response; } static getErrorMessage = (count, response) => `Request failed after ${count} attempts with status ${response.status}`; }; var defaultLifecycle = { before: async (req) => req, failure: async (count, request, response) => { throw new HTTPClientError(count, request, response); } }; function createHTTPClient(rootOptions) { const options = { transform: (res) => res.json(), ...rootOptions, lifecycle: { ...defaultLifecycle, ...rootOptions.lifecycle } }; const run = async (count, request) => { const response = await fetch(request); if (!response.ok) { const failure = await options.lifecycle.failure(count, request, response); if (failure instanceof Request) { return run(count + 1, failure); } else { throw new HTTPClientError(count, request, response); } } return response; }; const createMethod = (method) => { return async (path, config = {}) => { const { body: userBody = undefined, headers: userHeaders, ...userInit } = config; const headers = new Headers(userHeaders); const init = { ...userInit, headers, method }; if (!IS_BROWSER && !headers.has("User-Agent")) { headers.set("User-Agent", `alistair-http/${version}`); } if (userBody !== undefined) { const setContentType = headers.get("Content-Type"); if (setContentType === null || setContentType === "application/json") { if (setContentType === null) { headers.set("Content-Type", "application/json"); } init.body = JSON.stringify(userBody); } else if (userBody === null || isBodyInit(userBody)) { init.body = userBody; } else { throw new Error( "Cannot serialize body when a Content-Type header was set. Maybe you forgot to stringify?" ); } } const request = await options.lifecycle.before(new Request(join(options.base, path), init)); const response = await run(1, request); const transformed = await options.transform(response); return transformed; }; }; return { get: createMethod("get"), post: createMethod("post"), put: createMethod("put"), patch: createMethod("patch"), delete: createMethod("delete"), head: createMethod("head"), options: createMethod("options") }; } export { HTTPClientError, createHTTPClient, defaultLifecycle, isBodyInit, join, streamToBody };