aiwrapper
Version:
A Universal AI Wrapper for JavaScript & TypeScript
197 lines (196 loc) • 6.32 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
let _httpRequest = (_url, _options) => {
throw new Error("Not implemented");
};
const setHttpRequestImpl = (impl) => {
_httpRequest = impl;
};
const httpRequest = (url, options) => {
return _httpRequest(url, options);
};
async function parseResponseBody(response) {
const contentType = response.headers.get("content-type") || "";
const isJson = contentType.includes("application/json");
try {
const text = await response.text();
if (isJson && text) {
try {
return { json: JSON.parse(text), text };
} catch (e) {
return { text };
}
}
return { text };
} catch (e) {
return {};
}
}
class HttpRequestError extends Error {
constructor(message, response, action, bodyData) {
super(message);
this.response = response;
this.action = action;
/**
* Parsed JSON body if the response was JSON, otherwise undefined.
* Only available if response was present and parseable.
*/
__publicField(this, "body");
/**
* Raw text body if available.
* Only available if response was present and body could be read.
*/
__publicField(this, "bodyText");
if (bodyData) {
this.body = bodyData.json;
this.bodyText = bodyData.text;
}
}
}
function parseRetryAfter(retryAfter) {
const seconds = parseInt(retryAfter, 10);
if (!isNaN(seconds) && seconds > 0) {
return seconds * 1e3;
}
const date = new Date(retryAfter);
if (!isNaN(date.getTime())) {
const now = Date.now();
const delayMs = date.getTime() - now;
return Math.max(0, delayMs);
}
return 0;
}
function createAbortError() {
const abortError = new Error("The operation was aborted");
abortError.name = "AbortError";
return abortError;
}
const httpRequestWithRetry = async (url, options) => {
var _a, _b;
if ((_a = options.signal) == null ? void 0 : _a.aborted) {
throw createAbortError();
}
if (options.retries === void 0) {
options.retries = 6;
}
if (options.backoffMs === void 0) {
options.backoffMs = 100;
}
if (options.maxBackoffMs === void 0) {
options.maxBackoffMs = 3e3;
}
if (options._maxTotalAttempts === void 0) {
options._maxTotalAttempts = (options.retries || 6) + 1;
options._attemptCount = 0;
}
options._attemptCount = (options._attemptCount || 0) + 1;
try {
const response = await httpRequest(url, options);
if (!response.ok) {
const status = response.status;
const error = new Error(`HTTP error! status: ${status}`);
let responseForCallback = response;
try {
responseForCallback = response.clone();
} catch (e) {
}
const bodyData = await parseResponseBody(response).catch(() => ({}));
if (status === 400 && options.on400Error) {
try {
const action = await options.on400Error(responseForCallback, error, options);
throw new HttpRequestError(`HTTP error! status: ${status}`, response, action, bodyData);
} catch (customError) {
if (customError instanceof HttpRequestError) {
throw customError;
}
throw new HttpRequestError(`HTTP error! status: ${status}`, response, { retry: false }, bodyData);
}
}
let retry = true;
if (status >= 400 && status < 500 && status !== 429) {
retry = false;
}
throw new HttpRequestError(`HTTP error! status: ${status}`, response, { retry }, bodyData);
}
return response;
} catch (error) {
if ((error == null ? void 0 : error.name) === "AbortError") {
throw error;
}
if (!(error instanceof HttpRequestError)) {
throw new HttpRequestError(
error instanceof Error ? error.message : String(error),
null,
{ retry: true }
);
}
if (error instanceof HttpRequestError) {
if (error.action.retry) {
if (options._attemptCount >= options._maxTotalAttempts) {
throw error;
}
if (options.retries <= 0 && error.action.consumeRetry !== false) {
throw error;
}
if (error.action.consumeRetry !== false) {
options.retries -= 1;
}
let delayMs;
const targetBackoffMs = Math.min(options.backoffMs * 2, options.maxBackoffMs);
if (error.response) {
const retryAfter = error.response.headers.get("retry-after");
if (retryAfter) {
const retryAfterMs = parseRetryAfter(retryAfter);
delayMs = retryAfterMs > 0 ? retryAfterMs : targetBackoffMs;
} else {
delayMs = targetBackoffMs;
}
} else {
delayMs = targetBackoffMs;
}
if (delayMs === targetBackoffMs) {
options.backoffMs = targetBackoffMs;
}
await new Promise((resolve) => {
let timeout;
let onAbort;
if (options.signal) {
onAbort = () => {
var _a2;
if (timeout !== void 0) {
clearTimeout(timeout);
}
(_a2 = options.signal) == null ? void 0 : _a2.removeEventListener("abort", onAbort);
resolve(null);
};
if (options.signal.aborted) {
options.signal.removeEventListener("abort", onAbort);
resolve(null);
return;
}
options.signal.addEventListener("abort", onAbort, { once: true });
}
timeout = setTimeout(() => {
if (options.signal && onAbort) {
options.signal.removeEventListener("abort", onAbort);
}
resolve(null);
}, delayMs);
});
if ((_b = options.signal) == null ? void 0 : _b.aborted) {
throw createAbortError();
}
return httpRequestWithRetry(url, options);
}
}
throw error;
}
};
export {
HttpRequestError,
httpRequest,
httpRequestWithRetry,
setHttpRequestImpl
};
//# sourceMappingURL=http-request.js.map