UNPKG

@axiomhq/js

Version:

The official javascript bindings for the Axiom API

97 lines (94 loc) 3.8 kB
import fetchRetry from 'fetch-retry'; import { parseLimitFromResponse, LimitType } from './limit.js'; class FetchClient { config; constructor(config) { this.config = config; } async doReq(endpoint, method, init = {}, searchParams = {}, timeout = this.config.timeout, useAbsoluteUrl = false) { let finalUrl = useAbsoluteUrl ? endpoint : `${this.config.baseUrl}${endpoint}`; const params = this._prepareSearchParams(searchParams); if (params) { finalUrl += `?${params.toString()}`; } const headers = { ...this.config.headers, ...init.headers }; const resp = await fetchRetry(fetch)(finalUrl, { retries: 1, retryDelay: function (attempt, error, response) { return Math.pow(2, attempt) * 1000; // 1000, 2000, 4000 }, retryOn: [503, 502, 504, 500], headers, method, body: init.body ? init.body : undefined, signal: AbortSignal.timeout(timeout), cache: "no-store", }); if (resp.status === 204) { return resp; } else if (resp.status == 429) { const limit = parseLimitFromResponse(resp); return Promise.reject(new AxiomTooManyRequestsError(limit)); } else if (resp.status === 401) { return Promise.reject(new Error("forbidden")); } else if (resp.status >= 400) { const payload = (await resp.json()); return Promise.reject(new Error(payload.message)); } return (await resp.json()); } post(url, init = {}, searchParams = {}, timeout = this.config.timeout, useAbsoluteUrl = false) { return this.doReq(url, "POST", init, searchParams, timeout, useAbsoluteUrl); } get(url, init = {}, searchParams = {}, timeout = this.config.timeout) { return this.doReq(url, "GET", init, searchParams, timeout); } put(url, init = {}, searchParams = {}, timeout = this.config.timeout) { return this.doReq(url, "PUT", init, searchParams, timeout); } delete(url, init = {}, searchParams = {}, timeout = this.config.timeout) { return this.doReq(url, "DELETE", init, searchParams, timeout); } _prepareSearchParams = (searchParams) => { const params = new URLSearchParams(); let hasParams = false; Object.keys(searchParams).forEach((k) => { if (searchParams[k]) { params.append(k, searchParams[k]); hasParams = true; } }); return hasParams ? params : null; }; } class AxiomTooManyRequestsError extends Error { limit; shortcircuit; message = ""; constructor(limit, shortcircuit = false) { super(); this.limit = limit; this.shortcircuit = shortcircuit; Object.setPrototypeOf(this, AxiomTooManyRequestsError.prototype); // https://github.com/Microsoft/TypeScript/wiki/Breaking-Changes#extending-built-ins-like-error-array-and-map-may-no-longer-work const retryIn = AxiomTooManyRequestsError.timeUntilReset(limit); this.message = `${limit.type} limit exceeded, try again in ${retryIn.minutes}m${retryIn.seconds}s`; if (limit.type == LimitType.api) { this.message = `${limit.scope} ` + this.message; } } static timeUntilReset(limit) { const total = limit.reset.getTime() - new Date().getTime(); const seconds = Math.floor((total / 1000) % 60); const minutes = Math.floor((total / 1000 / 60) % 60); return { total, minutes, seconds, }; } } export { AxiomTooManyRequestsError, FetchClient }; //# sourceMappingURL=fetchClient.js.map