UNPKG

@soleil-se/app-util

Version:

Utility functions for WebApps, RESTApps and Widgets in Sitevision.

97 lines (87 loc) 3.25 kB
import { getRouteUri, stringifyParams } from '../../common'; function getUrl(uri, params) { if (uri.startsWith('/rest-api') || uri.startsWith('/appresource') || uri.startsWith('/edit-app-config') || !uri.startsWith('/')) { return uri + stringifyParams(params, { addQueryPrefix: true }); } return getRouteUri(uri, params); } async function toJson(response) { const text = await response.text(); try { return JSON.parse(text); } catch (e) { return undefined; } } async function responseError(response) { const json = await toJson(response) || {}; const error = new Error(json?.message || response?.statusText); Object.entries(json).forEach(([key, value]) => { error[key] = value; }); error.status = response.status; return error; } async function handleResponse(response) { if (!response.ok) { throw await responseError(response); } const json = await toJson(response); if (!json) { throw new Error('Response could not be parsed as JSON.'); } return json; } function isWidget() { return !!window?.sv?.PageContext?.dashboardId; } function getWidgetOptions(options) { return { ...options, params: { svAjaxReqParam: 'ajax', ...options.params, }, headers: { ...options.headers, 'X-Requested-With': 'XMLHttpRequest', }, }; } /** * @typedef {Object} ExtensionOptions * @property {Object<string,any>} params - The parameters to be included in the request URL. * @property {number} retries - The number of retries to attempt in case of a timeout error. * * @typedef {RequestInit & ExtensionOptions} Options */ /** * Fetches JSON data from a specified URI. * URI:s starting with `/rest-api`, `/appresource`, `/edit-app-config` or a protocol, for example * `https://` will be left as is. Other URI:s willbe converted to match a route in the current app * with `getRouteUri`. * * @param {string} uri - The URI to fetch JSON data from. * @param {Options} options - The options for the fetch request with some extensions. * @param {string} options.method - The HTTP method to use in the request. * @param {object} options.params - The parameters to be included in the request URL. * @param {object} options.body - The body to include in the request. * @param {number} options.retries - The number of retries to attempt in case of a timeout error. * @param {object} options.headers - The headers to be included in the request. * @returns {Promise<Object>} A promise that resolves to the JSON response. * @throws {Error} If the response is not successful or cannot be parsed as JSON. */ export default function fetchJson(uri, options = {}) { const { params = {}, retries = 0, ...rest } = isWidget() ? getWidgetOptions(options) : options; return fetch(getUrl(uri, params), rest) .then(handleResponse) .catch((error) => { const isTimeout = error.status === 504 || error.status === 408 || error.message?.includes('SocketTimeoutException'); if (isTimeout && retries > 0) { return fetchJson(uri, { ...rest, params, retries: retries - 1 }); } // eslint-disable-next-line no-param-reassign error.aborted = error.name === 'AbortError'; return Promise.reject(error); }); }