UNPKG

@commercetools-frontend/application-shell-connectors

Version:
859 lines (812 loc) • 64 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var _Object$keys = require('@babel/runtime-corejs3/core-js-stable/object/keys'); var _Object$getOwnPropertySymbols = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols'); var _filterInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/filter'); var _Object$getOwnPropertyDescriptor = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor'); var _forEachInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/for-each'); var _Object$getOwnPropertyDescriptors = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors'); var _Object$defineProperties = require('@babel/runtime-corejs3/core-js-stable/object/define-properties'); var _Object$defineProperty = require('@babel/runtime-corejs3/core-js-stable/object/define-property'); var _defineProperty = require('@babel/runtime-corejs3/helpers/defineProperty'); var react = require('react'); var moment = require('moment-timezone'); var sentry = require('@commercetools-frontend/sentry'); var _URL = require('@babel/runtime-corejs3/core-js-stable/url'); var _concatInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/concat'); var _slicedToArray = require('@babel/runtime-corejs3/helpers/slicedToArray'); var _reduceInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/reduce'); var _Object$entries = require('@babel/runtime-corejs3/core-js-stable/object/entries'); var _valuesInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/values'); var jsxRuntime = require('@emotion/react/jsx-runtime'); var _includesInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/includes'); var constants = require('@commercetools-frontend/constants'); var react$1 = require('@apollo/client/react'); var warning = require('tiny-warning'); var _findInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/find'); var client = require('@apollo/client'); var loggerLink = require('apollo-link-logger'); var error = require('@apollo/client/link/error'); var history = require('@commercetools-frontend/browser-history'); var _Array$isArray = require('@babel/runtime-corejs3/core-js-stable/array/is-array'); var _someInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/some'); var _Object$values = require('@babel/runtime-corejs3/core-js-stable/object/values'); var _mapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/map'); var createHttpUserAgent = require('@commercetools/http-user-agent'); var omitEmpty = require('omit-empty-es'); var uuid = require('uuid'); var _Reflect$construct = require('@babel/runtime-corejs3/core-js-stable/reflect/construct'); var _createClass = require('@babel/runtime-corejs3/helpers/createClass'); var _classCallCheck = require('@babel/runtime-corejs3/helpers/classCallCheck'); var _possibleConstructorReturn = require('@babel/runtime-corejs3/helpers/possibleConstructorReturn'); var _getPrototypeOf = require('@babel/runtime-corejs3/helpers/getPrototypeOf'); var _inherits = require('@babel/runtime-corejs3/helpers/inherits'); var _wrapNativeSuper = require('@babel/runtime-corejs3/helpers/wrapNativeSuper'); var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify'); var retry = require('@apollo/client/link/retry'); function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; } var _Object$keys__default = /*#__PURE__*/_interopDefault(_Object$keys); var _Object$getOwnPropertySymbols__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertySymbols); var _filterInstanceProperty__default = /*#__PURE__*/_interopDefault(_filterInstanceProperty); var _Object$getOwnPropertyDescriptor__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptor); var _forEachInstanceProperty__default = /*#__PURE__*/_interopDefault(_forEachInstanceProperty); var _Object$getOwnPropertyDescriptors__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptors); var _Object$defineProperties__default = /*#__PURE__*/_interopDefault(_Object$defineProperties); var _Object$defineProperty__default = /*#__PURE__*/_interopDefault(_Object$defineProperty); var moment__default = /*#__PURE__*/_interopDefault(moment); var _URL__default = /*#__PURE__*/_interopDefault(_URL); var _concatInstanceProperty__default = /*#__PURE__*/_interopDefault(_concatInstanceProperty); var _reduceInstanceProperty__default = /*#__PURE__*/_interopDefault(_reduceInstanceProperty); var _Object$entries__default = /*#__PURE__*/_interopDefault(_Object$entries); var _valuesInstanceProperty__default = /*#__PURE__*/_interopDefault(_valuesInstanceProperty); var _includesInstanceProperty__default = /*#__PURE__*/_interopDefault(_includesInstanceProperty); var warning__default = /*#__PURE__*/_interopDefault(warning); var _findInstanceProperty__default = /*#__PURE__*/_interopDefault(_findInstanceProperty); var loggerLink__default = /*#__PURE__*/_interopDefault(loggerLink); var history__default = /*#__PURE__*/_interopDefault(history); var _Array$isArray__default = /*#__PURE__*/_interopDefault(_Array$isArray); var _someInstanceProperty__default = /*#__PURE__*/_interopDefault(_someInstanceProperty); var _Object$values__default = /*#__PURE__*/_interopDefault(_Object$values); var _mapInstanceProperty__default = /*#__PURE__*/_interopDefault(_mapInstanceProperty); var createHttpUserAgent__default = /*#__PURE__*/_interopDefault(createHttpUserAgent); var omitEmpty__default = /*#__PURE__*/_interopDefault(omitEmpty); var _Reflect$construct__default = /*#__PURE__*/_interopDefault(_Reflect$construct); var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify); // NOTE: This string will be replaced on build time with the package version. var version = "24.13.0"; // From https://github.com/acdlite/recompose/blob/master/src/packages/recompose/getDisplayName.js const getDisplayName = Component => { if (typeof Component === 'string') { return Component; } if (!Component) { return undefined; } return Component.displayName || Component.name || 'Component'; }; const mcHostnameRegex = /^mc(-(\d){4,})?\.(.*)$/; const mcPreviewHostnameRegex = /^.*\.mc-preview\.(.*)$/; const getMcOriginTld = host => { if (host.match(mcPreviewHostnameRegex)) { return host.replace(mcPreviewHostnameRegex, '$1'); } return host.replace(mcHostnameRegex, '$3'); }; const getMcApiUrlFromOrigin = origin => { var _context; const url = new _URL__default["default"](origin); const originTld = getMcOriginTld(url.host); return _concatInstanceProperty__default["default"](_context = "".concat(url.protocol, "//mc-api.")).call(_context, originTld); }; const parseAsBoolean = value => value === true || value === 'true'; function getMcApiUrl() { let environment = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.app; let origin = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window.origin; const isServedByProxy = parseAsBoolean(environment.servedByProxy); /** * Prefer using the origin URL for the MC API based on the origin value * of the browser's `window.location`. * This ensures that the application always uses the correct URL associated * with that environment, instead of relying on the config value. */ if (isServedByProxy) { return getMcApiUrlFromOrigin(origin); } return environment.mcApiUrl; } function ownKeys$7(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread$7(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context2 = ownKeys$7(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context3 = ownKeys$7(Object(t))).call(_context3, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; } // Permissions // Action rights // Data fences /** * NOTE: * * Permissions and menu visibilities are being fetched though the `allAppliedPermissions` * and the `allAppliedMenuVisibilities` which both return an array of `{ name: string, value: boolean }`. * This gives more flexibility to introduce new values to apps without having to release * the merchant-center-app-kit by adding/exposing them from the mc-be (our proxy service). * * The application below however expects both permissions an menu visibilities to be of the shape * `[name: string]: boolean` which is what the shape above is mapped into here. This object shape is easier * to work with in application level code (while be a non breaking change to other packages) as you can just * do `canViewProducts`. * * This function considering its concern belongs into the `permissions` package. However, * for now it doesn't have to be shared and as a result can be co-located with * the fetching logic. Given this mapping needs to be used elsewere feel free * to move this over to `permissions` and export it there. */ const normalizeAllAppliedPermissions = allAppliedPermissions => { if (!allAppliedPermissions || allAppliedPermissions.length === 0) { return null; } return _reduceInstanceProperty__default["default"](allAppliedPermissions).call(allAppliedPermissions, (transformedAllApplied, allApplied) => { if (!allApplied) return transformedAllApplied; return _objectSpread$7(_objectSpread$7({}, transformedAllApplied), {}, { [allApplied.name]: allApplied.value }); }, {}); }; const normalizeAllAppliedActionRights = allAppliedActionRights => { if (!allAppliedActionRights || allAppliedActionRights.length === 0) { return null; } return _reduceInstanceProperty__default["default"](allAppliedActionRights).call(allAppliedActionRights, (transformedAllApplied, allApplied) => { if (!allApplied) return transformedAllApplied; const previousAllAppliedGroup = transformedAllApplied[allApplied.group]; return _objectSpread$7(_objectSpread$7({}, transformedAllApplied), {}, { [allApplied.group]: _objectSpread$7(_objectSpread$7({}, previousAllAppliedGroup), {}, { [allApplied.name]: allApplied.value }) }); }, {}); }; const normalizeAppliedDataFencesForStoresByResourceType = dataFences => { var _context; const groupedByResourceType = _reduceInstanceProperty__default["default"](dataFences).call(dataFences, (previousGroupsOfSameType, appliedDataFence) => { if (!appliedDataFence) return previousGroupsOfSameType; const previousGroup = previousGroupsOfSameType[appliedDataFence.group]; return _objectSpread$7(_objectSpread$7({}, previousGroupsOfSameType), {}, { [appliedDataFence.group]: [...(previousGroup || []), appliedDataFence] }); }, {}); return _reduceInstanceProperty__default["default"](_context = _Object$entries__default["default"](groupedByResourceType)).call(_context, (previousGroupedByResourceType, _ref) => { let _ref2 = _slicedToArray(_ref, 2), resourceType = _ref2[0], dataFences = _ref2[1]; const groupByDataFenceName = _reduceInstanceProperty__default["default"](dataFences).call(dataFences, (nextDataFenceValues, dataFence) => { const dataFenceByName = nextDataFenceValues[dataFence.name] || { values: [] }; return _objectSpread$7(_objectSpread$7({}, nextDataFenceValues), {}, { [dataFence.name]: _objectSpread$7(_objectSpread$7({}, dataFenceByName), {}, { values: [..._valuesInstanceProperty__default["default"](dataFenceByName), dataFence.value] }) }); }, {}); return _objectSpread$7(_objectSpread$7({}, previousGroupedByResourceType), {}, { [resourceType]: groupByDataFenceName }); }, {}); }; // input: // [ // { // type: 'store', // name: 'canManageOrders', // value: 'usa', // group: 'orders', // }, // { // type: 'store', // name: 'canManageOrders', // value: 'germany', // group: 'orders', // }, // { // type: 'store', // name: 'canViewOrders', // value: 'canada', // group: 'orders', // }, // ] // output: // { // store: { // orders: { // canManageOrders: { values: ['usa', 'germany'] }, // canViewOrders: { values: ['canada'] }, // } // } // } const normalizeAllAppliedDataFences = allAppliedDataFences => { if (!allAppliedDataFences || allAppliedDataFences.length === 0) { return null; } const groupedByType = _reduceInstanceProperty__default["default"](allAppliedDataFences).call(allAppliedDataFences, (previousGroupsOfSameType, appliedDataFence) => { if (!appliedDataFence) return previousGroupsOfSameType; const previousGroup = previousGroupsOfSameType[appliedDataFence.type]; return _objectSpread$7(_objectSpread$7({}, previousGroupsOfSameType), {}, { [appliedDataFence.type]: [...(previousGroup || []), appliedDataFence] }); }, {}); const normalizedDataFences = _objectSpread$7({}, 'store' in groupedByType ? { store: normalizeAppliedDataFencesForStoresByResourceType(groupedByType.store) } : {}); if (_Object$keys__default["default"](normalizedDataFences).length > 0) return normalizedDataFences; return null; }; function ownKeys$6(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread$6(e) { for (var r = 1; r < arguments.length; r++) { var _context, _context2; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context = ownKeys$6(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context2 = ownKeys$6(Object(t))).call(_context2, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; } const Context$2 = /*#__PURE__*/react.createContext({}); const defaultTimeZone = moment__default["default"].tz.guess() || 'Etc/UTC'; // Expose only certain fields as some of them are only meant to // be used internally in the AppShell const mapUserToApplicationContextUser = user => { if (!user) return null; let applicationContextUser = { id: user.id, email: user.email, createdAt: user.createdAt, firstName: user.firstName, lastName: user.lastName, businessRole: user.businessRole, // NOTE: this is an alias for the original field `user.language` but it's actually // a locale (language + country). locale: user.language, timeZone: user.timeZone || defaultTimeZone, projects: user.projects }; // This property will only be populated when user has logged in using SSO if (user.idTokenUserInfo) { let additionalClaims = {}; try { additionalClaims = JSON.parse(user.idTokenUserInfo.additionalClaims || '{}'); } catch (error) { sentry.reportErrorToSentry(new Error('@commercetools-frontend/application-shell-connectors: Could not parse received user sso token additional claims from server.'), { extra: { receivedAdditionalClaims: user.idTokenUserInfo.additionalClaims } }); } applicationContextUser.idTokenUserInfo = _objectSpread$6(_objectSpread$6({}, user.idTokenUserInfo), {}, { additionalClaims }); } return applicationContextUser; }; // Adjust certain fields which depend e.g. on the origin const mapEnvironmentToApplicationContextEnvironment = (environment, origin) => _objectSpread$6(_objectSpread$6({}, environment), {}, { // NOTE: The `mcApiUrl` depends on `servedByProxy` mcApiUrl: getMcApiUrl(environment, origin) }); // Expose only certain fields as some of them are only meant to // be used internally in the AppShell const mapProjectToApplicationContextProject = project => { if (!project) return null; return { key: project.key, version: project.version, name: project.name, countries: project.countries, currencies: project.currencies, languages: project.languages, ownerId: project.owner.id, ownerName: project.owner.name, sampleDataImportDataset: project.sampleDataImportDataset, isUserAdminOfCurrentProject: project.isUserAdminOfCurrentProject, isProductionProject: project.isProductionProject }; }; const createApplicationContext = (environment, user, project, projectDataLocale) => ({ environment: mapEnvironmentToApplicationContextEnvironment(environment), user: mapUserToApplicationContextUser(user), project: mapProjectToApplicationContextProject(project), permissions: normalizeAllAppliedPermissions(project === null || project === void 0 ? void 0 : project.allAppliedPermissions), actionRights: normalizeAllAppliedActionRights(project === null || project === void 0 ? void 0 : project.allAppliedActionRights), dataFences: normalizeAllAppliedDataFences(project === null || project === void 0 ? void 0 : project.allAppliedDataFences), dataLocale: projectDataLocale || null }); const ApplicationContextProvider = props => jsxRuntime.jsx(Context$2.Provider, { value: createApplicationContext(props.environment, props.user, props.project, props.projectDataLocale), children: props.children }); ApplicationContextProvider.displayName = 'ApplicationContextProvider'; const ApplicationContext = props => jsxRuntime.jsx(Context$2.Consumer, { children: context => { // Because of the way the ApplicationShell configures the Context.Provider, // we ensure that, when we read from the context, we always get actual // context object and not the initial value. // Therefore, we can safely cast the value to be out `TApplicationContext` type. const applicationContext = context; return props.render(applicationContext); } }); ApplicationContext.displayName = 'ApplicationContext'; function withApplicationContext(mapApplicationContextToProps) { return Component => { const WrappedComponent = props => jsxRuntime.jsx(ApplicationContext, { render: applicationContext => { const mappedProps = mapApplicationContextToProps ? mapApplicationContextToProps(applicationContext) : { applicationContext }; // @ts-ignore: relates to https://github.com/emotion-js/emotion/issues/3245 return jsxRuntime.jsx(Component, _objectSpread$6(_objectSpread$6({}, props), mappedProps)); } }); WrappedComponent.displayName = "withApplicationContext(".concat(getDisplayName(Component), ")"); return WrappedComponent; }; } // Use function overloading to declare two possible signatures with two // distict return types, based on the selector function argument. // Then implement the function. Typescript will pick the appropriate signature // based on the function arguments. function useApplicationContextHook(selector) { const context = react.useContext(Context$2); // Because of the way the ApplicationShell configures the Context.Provider, // we ensure that, when we read from the context, we always get actual // context object and not the initial value. // Therefore, we can safely cast the value to be out `TApplicationContext` type. const applicationContext = context; return selector ? selector(applicationContext) : applicationContext; } // This is a workaround to trick babel/rollup to correctly export the function. // Most likely the problem arises with the use of overloading. // See related issue: https://github.com/babel/babel/issues/8361 const useApplicationContext = useApplicationContextHook; const useCustomViewParentDataRefresher = params => { const onCustomViewEventHandler = react.useCallback(event => { var _context; const originLocatorCode = event.detail.originLocatorCode; if (_includesInstanceProperty__default["default"](_context = params.locators).call(_context, originLocatorCode)) { params.onRefreshDataRequested(event.detail); } }, []); react.useEffect(() => { window.addEventListener(constants.CUSTOM_VIEWS_EVENTS_NAMES.CUSTOM_VIEW_ON_CLOSE_AFTER, onCustomViewEventHandler); return () => { window.removeEventListener(constants.CUSTOM_VIEWS_EVENTS_NAMES.CUSTOM_VIEW_ON_CLOSE_AFTER, onCustomViewEventHandler); }; }, [onCustomViewEventHandler]); }; function ownKeys$5(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread$5(e) { for (var r = 1; r < arguments.length; r++) { var _context, _context2; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context = ownKeys$5(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context2 = ownKeys$5(Object(t))).call(_context2, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; } const Context$1 = /*#__PURE__*/react.createContext({}); const CustomViewContextProvider = props => { const contextValue = react.useMemo(() => ({ hostUrl: props.hostUrl, customViewConfig: props.customViewConfig }), [props.hostUrl, props.customViewConfig]); return jsxRuntime.jsx(Context$1.Provider, { value: contextValue, children: props.children }); }; // Use function overloading to declare two possible signatures with two // distict return types, based on the selector function argument. // Then implement the function. Typescript will pick the appropriate signature // based on the function arguments. function useCustomViewContextHook(selector) { // Because of the way the CustomViewShell configures the Context.Provider, // we ensure that, when we read from the context, we always get actual // context object and not the initial value. // Therefore, we can safely cast the value to be out `TCustomViewContext` type. const customViewContext = react.useContext(Context$1); const applicationContext = useApplicationContext(); const mergedContext = _objectSpread$5(_objectSpread$5({}, applicationContext), customViewContext); return selector ? selector(mergedContext) : mergedContext; } // This is a workaround to trick babel/rollup to correctly export the function. // Most likely the problem arises with the use of overloading. // See related issue: https://github.com/babel/babel/issues/8361 const useCustomViewContext = useCustomViewContextHook; function ownKeys$4(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread$4(e) { for (var r = 1; r < arguments.length; r++) { var _context, _context2; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context = ownKeys$4(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context2 = ownKeys$4(Object(t))).call(_context2, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; } var FetchProjectExtensionImageRegex = { kind: "Document", definitions: [{ kind: "OperationDefinition", operation: "query", name: { kind: "Name", value: "FetchProjectExtensionImageRegex" }, variableDefinitions: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "projectExtension" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "id" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "imageRegex" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "thumb" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "FragmentSpread", name: { kind: "Name", value: "ImageRegex" }, directives: [] }] } }, { kind: "Field", name: { kind: "Name", value: "small" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "FragmentSpread", name: { kind: "Name", value: "ImageRegex" }, directives: [] }] } }] } }] } }] } }, { kind: "FragmentDefinition", name: { kind: "Name", value: "ImageRegex" }, typeCondition: { kind: "NamedType", name: { kind: "Name", value: "ImageRegexOptions" } }, directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "flag" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "search" }, arguments: [], directives: [] }, { kind: "Field", name: { kind: "Name", value: "replace" }, arguments: [], directives: [] }] } }], loc: { start: 0, end: 256, source: { body: "query FetchProjectExtensionImageRegex {\n projectExtension {\n id\n imageRegex {\n thumb {\n ...ImageRegex\n }\n small {\n ...ImageRegex\n }\n }\n }\n}\nfragment ImageRegex on ImageRegexOptions {\n flag\n search\n replace\n}\n", name: "GraphQL request", locationOffset: { line: 1, column: 1 } } } }; const useWarning = (condition, message) => { react.useEffect(() => { process.env.NODE_ENV !== "production" ? warning__default["default"](condition, message) : void 0; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); }; const Context = /*#__PURE__*/react.createContext({ isLoading: false }); const useProjectExtensionImageRegex = () => { const _useContext = react.useContext(Context), isLoading = _useContext.isLoading, imageRegex = _useContext.imageRegex; return { isLoading, imageRegex }; }; const ProjectExtensionProviderForImageRegex = props => { const _useQuery = react$1.useQuery(FetchProjectExtensionImageRegex, { skip: props.skip, context: { target: constants.GRAPHQL_TARGETS.SETTINGS_SERVICE } }), loading = _useQuery.loading, data = _useQuery.data; return jsxRuntime.jsx(Context.Provider, { value: { isLoading: loading, imageRegex: data && data.projectExtension && data.projectExtension.imageRegex }, children: props.children }); }; ProjectExtensionProviderForImageRegex.displayName = 'ProjectExtensionProviderForImageRegex'; const GetProjectExtensionImageRegex = props => { useWarning(false, "@commercetools-frontend/application-shell-connectors: It is not recommended to use the 'GetProjectExtensionImageRegex' anymore. Please use the 'useProjectExtensionImageRegex' hook instead."); return jsxRuntime.jsx(Context.Consumer, { children: imageRegexContext => props.render(imageRegexContext) }); }; GetProjectExtensionImageRegex.displayName = 'GetProjectExtensionImageRegex'; function withProjectExtensionImageRegex() { let propKey = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'imageRegexData'; return Component => { const WrappedComponent = props => { useWarning(false, "@commercetools-frontend/application-shell-connectors: It is not recommended to use the 'withProjectExtensionImageRegex' high order component anymore. Please use the 'useProjectExtensionImageRegex' hook instead."); const imageregexContext = useProjectExtensionImageRegex(); return jsxRuntime.jsx(GetProjectExtensionImageRegex, { render: () => // @ts-ignore: relates to https://github.com/emotion-js/emotion/issues/3245 jsxRuntime.jsx(Component, _objectSpread$4(_objectSpread$4({}, props), {}, { [propKey]: imageregexContext })) }); }; WrappedComponent.displayName = "withProjectExtensionImageRegex(".concat(getDisplayName(Component), ")"); return WrappedComponent; }; } function ownKeys$3(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread$3(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context2 = ownKeys$3(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context3 = ownKeys$3(Object(t))).call(_context3, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; } const getSkipTokenRetry = context => { const skipTokenRetry = Boolean(context.skipTokenRetry); return skipTokenRetry; }; const forwardTokenRetryHeader = headers => _objectSpread$3(_objectSpread$3({}, headers), {}, { [constants.SUPPORTED_HEADERS.X_TOKEN_RETRY]: 'true' }); // This link retries requests to the CTP API that have been rejected // because of an invalid/expired oauth token. // To do so, we resend the request with the header "X-Force-Token: true" // so that the MC BE can issue a new token. // NOTE: the retry is not meant to work for the MC access token. const getDoesGraphQLTargetSupportTokenRetry = context => { var _context$headers, _context$headers2, _context; const graphQLTarget = ((_context$headers = context.headers) === null || _context$headers === void 0 ? void 0 : _context$headers[constants.SUPPORTED_HEADERS.X_GRAPHQL_TARGET]) || ((_context$headers2 = context.headers) === null || _context$headers2 === void 0 ? void 0 : _context$headers2[constants.SUPPORTED_HEADERS.X_GRAPHQL_TARGET.toLowerCase()]); return Boolean(graphQLTarget && _includesInstanceProperty__default["default"](_context = [constants.GRAPHQL_TARGETS.COMMERCETOOLS_PLATFORM, constants.GRAPHQL_TARGETS.ADMINISTRATION_SERVICE, constants.GRAPHQL_TARGETS.SETTINGS_SERVICE, constants.GRAPHQL_TARGETS.MERCHANT_CENTER_BACKEND]).call(_context, graphQLTarget)); }; const isHttpError = error => error.statusCode !== undefined || error.statusCode !== undefined; const isGraphQLError = error => _Array$isArray__default["default"](error) && _someInstanceProperty__default["default"](error).call(error, err => err.message !== undefined || err.extensions !== undefined); // Checks response from GraphQL in order to scan 401 errors and redirect the // user to the login page resetting the store and showing the proper message const errorLink = error.onError(_ref => { let graphQLErrors = _ref.graphQLErrors, networkError = _ref.networkError, operation = _ref.operation, forward = _ref.forward; if (networkError && isHttpError(networkError) && networkError.statusCode === constants.STATUS_CODES.UNAUTHORIZED) { history__default["default"].push("/logout?reason=".concat(constants.LOGOUT_REASONS.UNAUTHORIZED)); return; } // In case of graphql errors, we want to retry unauthenticated requests by // forcing our API to fetch a new token, using the `X-Force-Token` header. // https://www.apollographql.com/docs/link/links/error/#retrying-failed-requests // We need to do this as the `token-retry-link` only works for network errors. // https://www.apollographql.com/docs/link/links/retry/ const context = operation.getContext(); if (graphQLErrors && isGraphQLError(graphQLErrors)) { for (const err of graphQLErrors) { var _err$extensions; const isNonAuthenticatedViaExtensionCode = (err === null || err === void 0 || (_err$extensions = err.extensions) === null || _err$extensions === void 0 ? void 0 : _err$extensions.code) === 'UNAUTHENTICATED'; /** * NOTE: * Not not all GraphQL APIs expose an `extensions` field in * each error. For those we have to use the `message` * property until they introduced support for the `extensions` * field. */ const isNonAuthenticatedViaCode = (err === null || err === void 0 ? void 0 : err.message) === 'invalid_token'; if ((isNonAuthenticatedViaExtensionCode || isNonAuthenticatedViaCode) && getDoesGraphQLTargetSupportTokenRetry(context) && !getSkipTokenRetry(context)) { operation.setContext(_ref2 => { let headers = _ref2.headers; return { headers: forwardTokenRetryHeader(headers) }; }); // retry the request, returning the new observable return forward(operation); } } } // Report unhandled errors to Sentry if (context.enableSentryErrorReporting && networkError) { sentry.reportErrorToSentry(networkError, { extra: { operationName: operation.operationName } }); } if (context.enableSentryErrorReporting && graphQLErrors) { for (const err of graphQLErrors) { sentry.reportErrorToSentry(err, { extra: { operationName: operation.operationName } }); } } return; }); // Attempt to load the `teamId` from sessionStorage function selectTeamIdFromStorage() { var _window$app$__DEVELOP; return window.sessionStorage.getItem(constants.STORAGE_KEYS.ACTIVE_TEAM_ID) || ((_window$app$__DEVELOP = window.app.__DEVELOPMENT__) === null || _window$app$__DEVELOP === void 0 || (_window$app$__DEVELOP = _window$app$__DEVELOP.oidc) === null || _window$app$__DEVELOP === void 0 ? void 0 : _window$app$__DEVELOP.teamId); } const staticUrlPathsInPositionOfProjectKey = ['login', 'logout', 'account']; // Attempt to extract the `:projectKey` from the URL. // If the value matches one of the values in the list above, // return `undefined` as we're not within a project context. function selectProjectKeyFromUrl() { let locationPath = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.location.pathname; let possibleProjectKey = ''; const pathParts = locationPath.split('/'); if (pathParts[1] === 'custom-views') { // Custom Views paths: /custom-views/:customViewId/projects/:projectKey possibleProjectKey = pathParts[4]; } else { // Application paths: /:projectKey/:applicationId possibleProjectKey = pathParts[1]; } return _includesInstanceProperty__default["default"](staticUrlPathsInPositionOfProjectKey).call(staticUrlPathsInPositionOfProjectKey, possibleProjectKey) ? undefined : possibleProjectKey; } // Keep an in-memory reference to the apollo client that would be initialized // by the application. This is useful to retrieve on runtime the reference // to the apollo client in other static modules. let cachedApolloClient; const setCachedApolloClient = apolloClient => { cachedApolloClient = apolloClient; }; const getCachedApolloClient = () => cachedApolloClient; var FetchUserId = { kind: "Document", definitions: [{ kind: "OperationDefinition", operation: "query", name: { kind: "Name", value: "FetchUserId" }, variableDefinitions: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", alias: { kind: "Name", value: "user" }, name: { kind: "Name", value: "me" }, arguments: [], directives: [], selectionSet: { kind: "SelectionSet", selections: [{ kind: "Field", name: { kind: "Name", value: "id" }, arguments: [], directives: [] }] } }] } }], loc: { start: 0, end: 46, source: { body: "query FetchUserId {\n user: me {\n id\n }\n}\n", name: "GraphQL request", locationOffset: { line: 1, column: 1 } } } }; function selectUserId() { const apolloClient = getCachedApolloClient(); if (!apolloClient) { return null; } try { const queryResult = apolloClient.readQuery({ query: FetchUserId }); if (queryResult && queryResult.user) { return queryResult.user.id; } } catch (e) { return null; } return null; } const VALID_ID_PART_FORMAT = /^[\w-/]+$/; const skipMalformedPart = part => part && VALID_ID_PART_FORMAT.test(part); function getCorrelationId() { var _context; let _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, userId = _ref.userId; return _filterInstanceProperty__default["default"](_context = ['mc', selectProjectKeyFromUrl(), userId, uuid.v4()]).call(_context, skipMalformedPart).join('/'); } const createApolloContextForProxyForwardTo = proxyForwardTocontext => ({ // Send the request to the forward-to endpoint. uri: "".concat(getMcApiUrl(), "/proxy/forward-to"), // Custom properties to be used by the "header-link". forwardToConfig: proxyForwardTocontext, skipGraphQlTargetCheck: true }); /* eslint-disable no-console */ const isLoggerEnabled = () => { if (process.env.DEBUG === 'true') return true; if (process.env.NODE_ENV === 'development') return true; const queryParams = new _URL__default["default"](window.location.href); if (process.env.NODE_ENV === 'production' && queryParams.searchParams.get('debug') === 'true') return true; return false; }; const logger = { groupCollapsed: function () { return isLoggerEnabled() && console.groupCollapsed(...arguments); }, groupEnd: () => isLoggerEnabled() && console.groupEnd(), info: function () { return isLoggerEnabled() && console.info(...arguments); }, log: function () { return isLoggerEnabled() && console.log(...arguments); }, error: function () { return isLoggerEnabled() && console.error(...arguments); }, warn: function () { return isLoggerEnabled() && console.warn(...arguments); } }; // Attempt to load the `user language` from sessionStorage function selectUserLanguageFromStorage() { return window.sessionStorage.getItem(constants.STORAGE_KEYS.ACTIVE_USER_LANGUAGE) || null; } const getSessionToken = () => window.sessionStorage.getItem(constants.STORAGE_KEYS.SESSION_TOKEN); const setActiveSession = sessionToken => { if (!sessionToken) return; window.sessionStorage.setItem(constants.STORAGE_KEYS.SESSION_TOKEN, sessionToken !== null && sessionToken !== void 0 ? sessionToken : ''); window.localStorage.setItem(constants.STORAGE_KEYS.LOGIN_STRATEGY, constants.LOGIN_STRATEGY_OIDC); // Remove flag for original workflow window.localStorage.removeItem(constants.STORAGE_KEYS.IS_AUTHENTICATED); }; const clearSession = () => { window.sessionStorage.removeItem(constants.STORAGE_KEYS.SESSION_TOKEN); window.sessionStorage.removeItem(constants.STORAGE_KEYS.SESSION_SCOPE); window.sessionStorage.removeItem(constants.STORAGE_KEYS.IS_AUTHENTICATED); }; const getActiveProjectKey = () => window.localStorage.getItem(constants.STORAGE_KEYS.ACTIVE_PROJECT_KEY); const removeActiveProjectKey = () => { window.localStorage.removeItem(constants.STORAGE_KEYS.ACTIVE_PROJECT_KEY); }; const setActiveProjectKey = projectKey => { window.localStorage.setItem(constants.STORAGE_KEYS.ACTIVE_PROJECT_KEY, projectKey); }; const getSessionScope = () => window.sessionStorage.getItem(constants.STORAGE_KEYS.SESSION_SCOPE); const setSessionScope = scope => { window.sessionStorage.setItem(constants.STORAGE_KEYS.SESSION_SCOPE, scope); }; const getSessionState = stateId => { var _context; const sessionStateKey = _concatInstanceProperty__default["default"](_context = "".concat(constants.STORAGE_KEYS.NONCE, "_")).call(_context, stateId); const unparsedSessionState = window.sessionStorage.getItem(sessionStateKey); if (unparsedSessionState) { try { const parsedSessionState = JSON.parse(unparsedSessionState); return parsedSessionState; } catch (error) { if (process.env.NODE_ENV !== 'production') { var _context2; // eslint-disable-next-line no-console console.warn(_concatInstanceProperty__default["default"](_context2 = "Cannot parse session state for \"".concat(sessionStateKey, "\".\n")).call(_context2, unparsedSessionState)); } } } return null; }; const setSessionState = (stateId, state) => { var _context3; const sessionStateKey = _concatInstanceProperty__default["default"](_context3 = "".concat(constants.STORAGE_KEYS.NONCE, "_")).call(_context3, stateId); window.sessionStorage.setItem(sessionStateKey, _JSON$stringify__default["default"](state)); }; const removeSessionState = stateId => { var _context4; const sessionStateKey = _concatInstanceProperty__default["default"](_context4 = "".concat(constants.STORAGE_KEYS.NONCE, "_")).call(_context4, stateId); window.sessionStorage.removeItem(sessionStateKey); }; var oidcStorage = /*#__PURE__*/Object.freeze({ __proto__: null, getSessionToken: getSessionToken, setActiveSession: setActiveSession, clearSession: clearSession, getSessionState: getSessionState, setSessionState: setSessionState, removeSessionState: removeSessionState, getActiveProjectKey: getActiveProjectKey, setActiveProjectKey: setActiveProjectKey, removeActiveProjectKey: removeActiveProjectKey, getSessionScope: getSessionScope, setSessionScope: setSessionScope }); function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? _Reflect$construct__default["default"](o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(_Reflect$construct__default["default"](Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function () { return !!t; })(); } function ownKeys$2(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread$2(e) { for (var r = 1; r < arguments.length; r++) { var _context3, _context4; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context3 = ownKeys$2(Object(t), !0)).call(_context3, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context4 = ownKeys$2(Object(t))).call(_context4, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; } let _userAgent$1; const getUserAgent$1 = () => { if (!_userAgent$1) { var _window$app$applicati, _window$app; _userAgent$1 = createHttpUserAgent__default["default"]({ name: 'unknown-http-client', libraryName: typeof window !== 'undefined' ? (_window$app$applicati = (_window$app = window.app) === null || _window$app === void 0 ? void 0 : _window$app.applicationName) !== null && _window$app$applicati !== void 0 ? _window$app$applicati : 'unknown-application-name' : undefined }); } return _userAgent$1; }; const defaultForwardToVersion = 'v2'; const defaultForwardToAudiencePolicy = 'forward-url-full-path'; function buildApiUrl(endpoint) { var _context; const apiUrl = getMcApiUrl().replace(/\/$/, ''); return _concatInstanceProperty__default["default"](_context = "".concat(apiUrl)).call(_context, endpoint); } const getAppliedForwardToHeaders = forwardToConfig => { var _context2, _forwardToConfig$head, _forwardToConfig$vers, _forwardToConfig$audi; if (!forwardToConfig) { return {}; } if (!forwardToConfig.uri) { throw new Error("Missing required \"uri\" option."); } const exchangeTokenClaims = []; if (forwardToConfig.includeUserPermissions) { exchangeTokenClaims.push('permissions'); } return _objectSpread$2(_objectSpread$2({}, _reduceInstanceProperty__default["default"](_context2 = _Object$entries__default["default"]((_forwardToConfig$head = forwardToConfig.headers) !== null && _forwardToConfig$head !== void 0 ? _forwardToConfig$head : {})).call(_context2, (customForwardHeaders, _ref) => { let _ref2 = _slicedToArray(_ref, 2), headerName = _ref2[0], headerValue = _ref2[1]; return _objectSpread$2(_objectSpread$2({}, customForwardHeaders), {}, { // Prefix headers so that the MC API can allow and forward them. ["x-forward-header-".concat(headerName)]: headerValue }); }, {})), {}, { [constants.SUPPORTED_HEADERS.ACCEPT_VERSION]: (_forwardToConfig$vers = forwardToConfig.version) !== null && _forwardToConfig$vers !== void 0 ? _forwardToConfig$vers : defaultForwardToVersion, [constants.SUPPORTED_HEADERS.X_FORWARD_TO]: forwardToConfig.uri, [constants.SUPPORTED_HEADERS.X_FORWARD_TO_AUDIENCE_POLICY]: (_forwardToConfig$audi = forwardToConfig.audiencePolicy) !== null && _forwardToConfig$audi !== void 0 ? _forwardToConfig$audi : defaultForwardToAudiencePolicy, [constants.SUPPORTED_HEADERS.X_FORWARD_TO_CLAIMS]: exchangeTokenClaims.join(' ') }); }; function createHttpClientOptions() { var _config$projectKey, _window$app$__DEVELOP; let config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; const sessionToken = getSessionToken(); const projectKey = (_config$projectKey = config.projectKey) !== null && _config$projectKey !== void 0 ? _config$projectKey : selectProjectKeyFromUrl(); const userId = selectUserId(); const userAgent = (config === null || config === void 0 ? void 0 : config.userAgent) || getUserAgent$1(); return { credentials: 'include', headers: omitEmpty__default["default"](_objectSpread$2(_objectSpread$2({}, config.headers), {}, { // Required headers [constants.SUPPORTED_HEADERS.ACCEPT]: 'application/json', [constants.SUPPORTED_HEADERS.AUTHORIZATION]: sessionToken ? "Bearer ".concat(sessionToken) : undefined, [constants.SUPPORTED_HEADERS.X_APPLICATION_ID]: window.app.applicationIdentifier, [constants.SUPPORTED_HEADERS.X_CUSTOM_VIEW_ID]: window.app.customViewId, [constants.SUPPORTED_HEADERS.X_CORRELATION_ID]: getCorrelationId({ userId }), [constants.SUPPORTED_HEADERS.X_PROJECT_KEY]: projectKey, [constants.SUPPORTED_HEADERS.X_USER_AGENT]: userAgent, // MC Identity Login Mode Override header for development [constants.SUPPORTED_HEADERS.X_MC_IDENTITY_LOGIN_MODE_OVERRIDE]: (_window$app$__DEVELOP = window.app.__DEVELOPMENT__) === null || _window$app$__DEVELOP === void 0 ? void 0 : _window$app$__DEVELOP.mcIdentityLoginModeOverride }, getAppliedForwardToHeaders(config.forwardToConfig))) }; } let RenewTokenError = /*#__PURE__*/function (_Error) { function RenewTokenError(message) { var _this; _classCallCheck(this, RenewTokenError); _this = _callSuper(this, RenewTokenError, [message]); _Object$defineProperty__default["default"](_this, 'name', { value: 'RenewTokenError' }); return _this; } _inherits(RenewTokenError, _Error); return _createClass(RenewTokenError); }(/*#__PURE__*/_wrapNativeSuper(Error)); async function executeHttpClientRequest(fetcher) { let config = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; // Wrapper function to be called again (once) on retry. async function sendRequest() { let _ref3 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}, shouldRenewToken = _ref3.shouldRenewToken; const requestOptions = createHttpClientOptions(config); const response = await fetcher(_objectSpread$2(_objectSpread$2({}, requestOptions), {}, { headers: omitEmpty__default["default"](_objectSpread$2(_objectSpread$2({}, requestOptions.headers), {}, { // Passing this header forces a token renewal. [constants.SUPPORTED_HEADERS.X_TOKEN_RETRY]: shouldRenewToken })) })); if (response.statusCode === constants.STATUS_CODES.UNAUTHORIZED) { throw new RenewTokenError("Unauthorized response, attempting retry."); } // In case