package.initializers.axiosInitializer.index.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of neeto-commons-frontend Show documentation
Show all versions of neeto-commons-frontend Show documentation
A package encapsulating common code across neeto projects including initializers, utility functions, common components and hooks and so on.
import _defineProperty from "@babel/runtime/helpers/defineProperty";
import _typeof from "@babel/runtime/helpers/typeof";
import axios from "axios";
import i18next from "i18next";
import { isNotEmpty, keysToCamelCase, matches, serializeKeysToSnakeCase } from "@bigbinary/neeto-cist";
import Toastr from "@bigbinary/neetoui/Toastr";
import { dissoc, evolve, omit } from "ramda";
import { toast } from "react-toastify";
import { useErrorDisplayStore } from "../../react-utils/useDisplayErrorPage";
import { resetAuthTokens } from "../../utils/axios";
import setParamsSerializer from "./paramsSerializer";
import { HEADERS_KEYS, MAXIMUM_OFFLINE_DURATION } from "../constants";
var checkOnlineInterval = null;
var requestErrorToasts = {};
var shouldNot = function shouldNot(skip) {
return _typeof(skip) === "object" || !skip;
};
var shouldShowToastr = function shouldShowToastr(response) {
return typeof response === "string" && isNotEmpty(response) || _typeof(response) === "object" && ((response === null || response === void 0 ? void 0 : response.notice) || (response === null || response === void 0 ? void 0 : response.noticeCode));
};
var setAuthHeaders = function setAuthHeaders() {
var _document$querySelect, _axios$defaults$heade;
// @ts-ignore
axios.defaults.headers = (_axios$defaults$heade = {}, _defineProperty(_axios$defaults$heade, HEADERS_KEYS.accept, "application/json"), _defineProperty(_axios$defaults$heade, HEADERS_KEYS.contentType, "application/json"), _defineProperty(_axios$defaults$heade, HEADERS_KEYS.xCsrfToken, (_document$querySelect = document.querySelector('[name="csrf-token"]')) === null || _document$querySelect === void 0 ? void 0 : _document$querySelect.getAttribute("content")), _axios$defaults$heade);
};
// pipe function from ramda doesn't accept array of functions.
// We can't use spread operator too. So this is a workaround.
var createPipe = function createPipe(functions) {
return function (data) {
return functions.reduce(function (acc, fn) {
return fn(acc);
}, data);
};
};
var transformResponseKeysToCamelCase = function transformResponseKeysToCamelCase(response) {
var _response$config$tran = response.config.transformResponseCase,
transformResponseCase = _response$config$tran === void 0 ? true : _response$config$tran;
if (response.data && transformResponseCase) {
response.data = keysToCamelCase(response.data);
}
return response;
};
var transformErrorKeysToCamelCase = function transformErrorKeysToCamelCase(error) {
var _error$config, _error$response;
var _ref = (_error$config = error.config) !== null && _error$config !== void 0 ? _error$config : {},
_ref$transformRespons = _ref.transformResponseCase,
transformResponseCase = _ref$transformRespons === void 0 ? true : _ref$transformRespons;
if ((_error$response = error.response) !== null && _error$response !== void 0 && _error$response.data && transformResponseCase) {
error.response.data = keysToCamelCase(error.response.data);
}
return error;
};
var showSuccessToastr = function showSuccessToastr(response) {
var _response$config = response.config,
_response$config$show = _response$config.showToastr,
showToastr = _response$config$show === void 0 ? true : _response$config$show,
requestUrl = _response$config.url,
requestMethod = _response$config.method;
if (!showToastr) return response;
var toastIdKey = "".concat(requestMethod, ":").concat(requestUrl);
var errorToastId = requestErrorToasts[toastIdKey];
if (errorToastId) {
toast.dismiss(errorToastId);
requestErrorToasts = dissoc(toastIdKey, requestErrorToasts);
}
if (matches({
showThumbsUpToastr: true
}, response.data)) {
// @ts-ignore
Toastr.success("", {
icon: "👍",
className: "w-20"
});
} else if (matches({
noticeCode: "thumbs_up"
}, response.data)) {
// @ts-ignore
Toastr.success("", {
icon: "👍",
className: "w-20"
});
} else if (shouldShowToastr(response.data)) {
Toastr.success(response.data);
}
return response;
};
var pullDataFromResponse = function pullDataFromResponse(response) {
var _response$config$incl = response.config.includeMetadataInResponse,
includeMetadataInResponse = _response$config$incl === void 0 ? false : _response$config$incl;
return includeMetadataInResponse ? response : response.data;
};
var buildSuccessResponseHandler = function buildSuccessResponseHandler(skip) {
var interceptors = [];
if (!(skip !== null && skip !== void 0 && skip.transformCase)) interceptors.push(transformResponseKeysToCamelCase);
if (!(skip !== null && skip !== void 0 && skip.showToastr)) interceptors.push(showSuccessToastr);
if (!(skip !== null && skip !== void 0 && skip.pullDataFromResponse)) interceptors.push(pullDataFromResponse);
return createPipe(interceptors);
};
var handleUnauthorizedErrorResponse = function handleUnauthorizedErrorResponse(error) {
var _error$response2, _error$config2;
if (((_error$response2 = error.response) === null || _error$response2 === void 0 ? void 0 : _error$response2.status) !== 401) return error;
resetAuthTokens();
var _ref2 = (_error$config2 = error.config) !== null && _error$config2 !== void 0 ? _error$config2 : {},
_ref2$redirectOnError = _ref2.redirectOnError,
redirectOnError = _ref2$redirectOnError === void 0 ? true : _ref2$redirectOnError;
if (redirectOnError) {
setTimeout(function () {
var redirectTo = window.location.pathname === "/login" ? "/login" : "/login?redirect_uri=".concat(encodeURIComponent(window.location.href));
// eslint-disable-next-line xss/no-location-href-assign
window.location.href = redirectTo;
}, 300);
}
return error;
};
var isOnline = function isOnline() {
return window.navigator.onLine;
};
var showOfflineToastr = function showOfflineToastr() {
var toastId = Toastr.error(i18next.t("neetoCommons.toastr.error.networkError"));
if (toastId) {
var dismissToastInterval = setInterval(function () {
if (!isOnline()) return;
toast.dismiss(toastId);
clearInterval(dismissToastInterval);
checkOnlineInterval = null;
}, 1000);
}
};
var handleNetworkError = function handleNetworkError(error) {
if (checkOnlineInterval) return error;
var startTime = Date.now();
checkOnlineInterval = setInterval(function () {
var elapsedTime = Date.now() - startTime;
if (isOnline()) {
clearInterval(checkOnlineInterval);
checkOnlineInterval = null;
} else if (elapsedTime >= MAXIMUM_OFFLINE_DURATION) {
clearInterval(checkOnlineInterval);
showOfflineToastr();
}
}, 1000);
return error;
};
var showErrorToastr = function showErrorToastr(error) {
var _error$config3, _error$response3;
var _ref3 = (_error$config3 = error.config) !== null && _error$config3 !== void 0 ? _error$config3 : {},
_ref3$showToastr = _ref3.showToastr,
showToastr = _ref3$showToastr === void 0 ? true : _ref3$showToastr,
_ref3$show422ErrorToa = _ref3.show422ErrorToastr,
show422ErrorToastr = _ref3$show422ErrorToa === void 0 ? true : _ref3$show422ErrorToa,
_ref3$url = _ref3.url,
requestUrl = _ref3$url === void 0 ? "" : _ref3$url,
_ref3$method = _ref3.method,
requestMethod = _ref3$method === void 0 ? "" : _ref3$method;
var _ref4 = (_error$response3 = error.response) !== null && _error$response3 !== void 0 ? _error$response3 : {},
status = _ref4.status;
if (!showToastr) return error;
if (error.message === "Network Error") return handleNetworkError(error);
if (error.code === "ECONNABORTED") {
return error;
}
var shouldShowToastr = false,
toastrContent = error;
var skippedStatusCodes = [403, 404, 520, 422];
if (!skippedStatusCodes.includes(status) && !axios.isCancel(error)) {
// we already display a page in case of 403 & 404 and we don't want to show a toastr for cancelled requests.
// We handle cloudflare error differently for production and other environments.
shouldShowToastr = true;
}
if (status === 422 && show422ErrorToastr) shouldShowToastr = true;
if (status === 520) {
shouldShowToastr = true;
if (globalProps.railsEnv === "production") {
toastrContent = i18next.t("generic.error");
}
}
var toastIdKey = "".concat(requestMethod, ":").concat(requestUrl);
var errorToastId = requestErrorToasts[toastIdKey];
if (errorToastId) toast.dismiss(errorToastId);
if (shouldShowToastr) {
if (errorToastId) {
// if there's an existing toastr with the same message, the onClose callback in the neetoUI which
// removes the toastr from the unique list will be fired only after the toast is completely removed
// from the UI. If there's no delay, the new toastr will be considered as duplicate and ignored.
setTimeout(function () {
requestErrorToasts[toastIdKey] = Toastr.error(toastrContent);
}, 1200);
} else requestErrorToasts[toastIdKey] = Toastr.error(toastrContent);
}
return error;
};
var getUrlPathName = function getUrlPathName(url) {
try {
return new URL(url).pathname;
} catch (_unused) {
return url;
}
};
var handle404ErrorResponse = function handle404ErrorResponse(error) {
var _error$config4, _error$response4;
var _ref5 = (_error$config4 = error.config) !== null && _error$config4 !== void 0 ? _error$config4 : {},
_ref5$show404ErrorPag = _ref5.show404ErrorPage,
show404ErrorPage = _ref5$show404ErrorPag === void 0 ? true : _ref5$show404ErrorPag,
_ref5$show403ErrorPag = _ref5.show403ErrorPage,
show403ErrorPage = _ref5$show403ErrorPag === void 0 ? true : _ref5$show403ErrorPag;
var status = (_error$response4 = error.response) === null || _error$response4 === void 0 ? void 0 : _error$response4.status;
if (status === 404 && show404ErrorPage || status === 403 && show403ErrorPage) {
var _error$request;
var fullUrl = ((_error$request = error.request) === null || _error$request === void 0 ? void 0 : _error$request.responseURL) || error.config.url;
useErrorDisplayStore.setState({
showErrorPage: true,
statusCode: status,
failedApiUrl: fullUrl,
failedApiPath: getUrlPathName(fullUrl)
});
}
return error;
};
var buildErrorResponseHandler = function buildErrorResponseHandler(skip) {
var interceptors = [];
if (!(skip !== null && skip !== void 0 && skip.transformCase)) interceptors.push(transformErrorKeysToCamelCase);
if (!(skip !== null && skip !== void 0 && skip.show404ErrorPage)) interceptors.push(handle404ErrorResponse);
if (!(skip !== null && skip !== void 0 && skip.logoutOn401)) interceptors.push(handleUnauthorizedErrorResponse);
if (!(skip !== null && skip !== void 0 && skip.showToastr)) interceptors.push(showErrorToastr);
interceptors.push(Promise.reject.bind(Promise));
return createPipe(interceptors);
};
var cleanupCredentialsForCrossOrigin = function cleanupCredentialsForCrossOrigin(request) {
if (!request.url.includes("://")) return request;
if (request.url.includes(window.location.hostname)) return request;
return evolve({
headers: omit([HEADERS_KEYS.xCsrfToken])
})(request);
};
var transformDataToSnakeCase = function transformDataToSnakeCase(request) {
var _request$transformReq = request.transformRequestCase,
transformRequestCase = _request$transformReq === void 0 ? true : _request$transformReq;
if (!transformRequestCase) return request;
return evolve({
data: serializeKeysToSnakeCase,
params: serializeKeysToSnakeCase
}, request);
};
var addRequestInterceptors = function addRequestInterceptors(skip) {
if (!(skip !== null && skip !== void 0 && skip.cleanCredentialsForCrossOrigin)) {
axios.interceptors.request.use(cleanupCredentialsForCrossOrigin);
}
if (!(skip !== null && skip !== void 0 && skip.transformCase)) {
axios.interceptors.request.use(transformDataToSnakeCase);
}
};
var addResponseInterceptors = function addResponseInterceptors(skip) {
axios.interceptors.response.use(buildSuccessResponseHandler(skip), buildErrorResponseHandler(skip));
};
var registerIntercepts = function registerIntercepts(skip) {
if (shouldNot(skip === null || skip === void 0 ? void 0 : skip.request)) addRequestInterceptors(skip === null || skip === void 0 ? void 0 : skip.request);
if (shouldNot(skip === null || skip === void 0 ? void 0 : skip.response)) addResponseInterceptors(skip === null || skip === void 0 ? void 0 : skip.response);
};
export default function initializeAxios(skip) {
if (!(skip !== null && skip !== void 0 && skip.baseURL)) axios.defaults.baseURL = "/";
if (!(skip !== null && skip !== void 0 && skip.authHeaders)) setAuthHeaders();
if (!(skip !== null && skip !== void 0 && skip.paramsSerializer)) setParamsSerializer();
if (shouldNot(skip === null || skip === void 0 ? void 0 : skip.interceptors)) registerIntercepts(skip === null || skip === void 0 ? void 0 : skip.interceptors);
}
//# sourceMappingURL=index.js.map