UNPKG

@xsai/shared

Version:

extra-small AI SDK.

63 lines (53 loc) 1.92 kB
class XSAIError extends Error { response; constructor(message, response, cause) { super(message, { cause }); this.name = "XSAIError"; this.response = response; } } const strCamelToSnake = (str) => str.replace(/[A-Z]/g, (s) => `_${s.toLowerCase()}`); const objCamelToSnake = (obj) => Object.fromEntries(Object.entries(obj).map(([k, v]) => [strCamelToSnake(k), v])); const clean = (obj) => Object.fromEntries( Object.entries(obj).filter(([, v]) => v !== void 0) ); const requestBody = (body) => JSON.stringify(objCamelToSnake(clean({ ...body, abortSignal: void 0, apiKey: void 0, baseURL: void 0, fetch: void 0, headers: void 0 }))); const requestHeaders = (headers, apiKey) => clean({ Authorization: apiKey !== void 0 ? `Bearer ${apiKey}` : void 0, ...headers }); const requestURL = (path, baseURL) => { const base = baseURL.toString(); return new URL(path, base.endsWith("/") ? base : `${base}/`); }; const responseCatch = async (res) => { if (!res.ok) throw new XSAIError(`Remote sent ${res.status} response: ${await res.text()}`, res); if (!res.body) throw new XSAIError("Response body is empty from remote server", res); if (!(res.body instanceof ReadableStream)) throw new XSAIError(`Expected Response body to be a ReadableStream, but got ${String(res.body)}; Content Type is ${res.headers.get("Content-Type")}`, res); return res; }; const responseJSON = async (res) => { const text = await res.text(); try { return JSON.parse(text); } catch (cause) { throw new XSAIError(`Failed to parse response, response body: ${text}`, res, cause); } }; const trampoline = async (fn) => { let result = await fn(); while (result instanceof Function) result = await result(); return result; }; export { XSAIError, clean, objCamelToSnake, requestBody, requestHeaders, requestURL, responseCatch, responseJSON, strCamelToSnake, trampoline };