UNPKG

@baqhub/sdk

Version:

The official JavaScript SDK for the BAQ federated app platform.

239 lines (238 loc) 7.26 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Http = exports.RequestFailedError = exports.RequestError = void 0; exports.setHttpApi = setHttpApi; const tslib_1 = require("tslib"); const memoize_js_1 = tslib_1.__importDefault(require("lodash/memoize.js")); const pickBy_js_1 = tslib_1.__importDefault(require("lodash/pickBy.js")); const snakeCase_js_1 = tslib_1.__importDefault(require("lodash/snakeCase.js")); const constants_js_1 = require("../constants.js"); const async_js_1 = require("../helpers/async.js"); const customError_js_1 = require("../helpers/customError.js"); const string_js_1 = require("../helpers/string.js"); const type_js_1 = require("../helpers/type.js"); const uuid_js_1 = require("../helpers/uuid.js"); const httpMethod_js_1 = require("../model/core/httpMethod.js"); const eventSource_js_1 = require("./eventSource.js"); const getClientId = (0, memoize_js_1.default)(() => uuid_js_1.Uuid.new()); let api = { fetch: (...args) => fetch(...args), eventSourceFetch: (...args) => fetch(...args), }; function setHttpApi(newApi) { api = newApi; } class RequestError extends customError_js_1.CustomError { options; status; headers; constructor(options, status, headers) { super("Request error."); this.options = options; this.status = status; this.headers = headers; } } exports.RequestError = RequestError; class RequestFailedError extends customError_js_1.CustomError { baseError; constructor(baseError) { super("Request failed."); this.baseError = baseError; } } exports.RequestFailedError = RequestFailedError; function isError(error, statuses) { if (error instanceof RequestFailedError && !statuses) { return true; } if (!(error instanceof RequestError)) { return false; } if (!statuses) { return true; } return statuses.includes(error.status); } async function httpHead(url, options) { const response = await sendAsync({ ...options, method: httpMethod_js_1.HttpMethod.HEAD, url, }); return response.headers; } async function httpGet(url, options) { const response = await sendAsync({ ...options, method: httpMethod_js_1.HttpMethod.GET, url, }); const json = await response.json(); return [response.headers, json]; } async function httpDownload(url, options) { const response = await sendAsync({ ...options, headers: { Accept: "*/*", ...options?.headers, }, method: httpMethod_js_1.HttpMethod.GET, url, }); const blob = await response.blob(); return [response.headers, blob]; } async function httpPost(body, url, options = {}) { const headers = { "Content-Type": "application/json; charset=utf-8", ...options.headers, }; const response = await sendAsync({ ...options, headers, method: httpMethod_js_1.HttpMethod.POST, url, body, }); const json = await response.json(); return [response.headers, json]; } async function httpPut(body, url, options = {}) { const headers = { "Content-Type": "application/json; charset=utf-8", ...options.headers, }; const response = await sendAsync({ ...options, headers, method: httpMethod_js_1.HttpMethod.PUT, url, body, }); const json = await response.json(); return [response.headers, json]; } async function httpPatch(body, url, options = {}) { const headers = { "Content-Type": "application/json; charset=utf-8", ...options.headers, }; const response = await sendAsync({ ...options, headers, method: httpMethod_js_1.HttpMethod.PATCH, url, body, }); const json = await response.json(); return [response.headers, json]; } async function httpDelete(url, options) { return sendAsync({ ...options, method: httpMethod_js_1.HttpMethod.DELETE, url, }); } async function httpDeleteBody(body, url, options = {}) { const headers = { "Content-Type": "application/json; charset=utf-8", ...options.headers, }; const response = await sendAsync({ ...options, headers, method: httpMethod_js_1.HttpMethod.DELETE, url, body, }); const json = await response.json(); return [response.headers, json]; } function buildUrl(url, query) { const queryArray = Object.entries(query || {}) .map(([key, value]) => value ? [(0, snakeCase_js_1.default)(key), value] : undefined) .filter(type_js_1.isDefined); return url + string_js_1.Str.buildQuery(queryArray); } function conformBody(body) { if (body instanceof File) { return body; } if (body instanceof Blob) { return body; } if (body) { return JSON.stringify(body); } return null; } async function sendAsync(options) { const { method, url, body } = options; const fullUrl = buildUrl(url, options.query); const initialHeaders = { Accept: "application/json", ...options.headers, [constants_js_1.Constants.clientIdHeader]: getClientId(), }; const headers = { ...initialHeaders, Authorization: options.authorizationBuilder?.(method, fullUrl, initialHeaders), }; try { const response = await api.fetch(fullUrl, { method, headers: (0, pickBy_js_1.default)(headers, type_js_1.isDefined), body: conformBody(body), signal: options.signal, }); if (!response.ok) { throw new RequestError(options, response.status, response.headers); } return response; } catch (error) { // If this request was aborted, throw a custom error. if (options.signal?.aborted) { throw new async_js_1.AbortedError(); } if (error instanceof RequestError) { throw error; } // Otherwise, bubble up. throw new RequestFailedError(error); } } function httpEventSource(onMessage, url, options = {}) { const buildHeaders = lastEventId => { const initialHeaders = (0, pickBy_js_1.default)({ ...options.headers, [constants_js_1.Constants.clientIdHeader]: getClientId(), [constants_js_1.Constants.lastEventIdHeader]: lastEventId, }, type_js_1.isDefined); return (0, pickBy_js_1.default)({ ...initialHeaders, Authorization: options.authorizationBuilder?.(httpMethod_js_1.HttpMethod.GET, url, initialHeaders), }, type_js_1.isDefined); }; (0, eventSource_js_1.fetchEventSource)(api.eventSourceFetch, buildUrl(url, options.query), { buildHeaders, onMessage: onMessage, openWhenHidden: true, signal: options.signal, }); } exports.Http = { isError, head: httpHead, get: httpGet, post: httpPost, put: httpPut, patch: httpPatch, delete: httpDelete, deleteBody: httpDeleteBody, download: httpDownload, eventSource: httpEventSource, };