UNPKG

@commercetools-frontend/application-shell-connectors

Version:
1,044 lines 53.9 kB
import _Object$keys from '@babel/runtime-corejs3/core-js-stable/object/keys';
import _Object$getOwnPropertySymbols from '@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols';
import _filterInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/filter';
import _Object$getOwnPropertyDescriptor from '@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor';
import _forEachInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/for-each';
import _Object$getOwnPropertyDescriptors from '@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors';
import _Object$defineProperties from '@babel/runtime-corejs3/core-js-stable/object/define-properties';
import _Object$defineProperty from '@babel/runtime-corejs3/core-js-stable/object/define-property';
import _defineProperty from '@babel/runtime-corejs3/helpers/esm/defineProperty';
import _pt from 'prop-types';
import { createContext, useContext, useMemo, useEffect } from 'react';
import moment from 'moment-timezone';
import { reportErrorToSentry } from '@commercetools-frontend/sentry';
import _URL from '@babel/runtime-corejs3/core-js-stable/url';
import _slicedToArray from '@babel/runtime-corejs3/helpers/esm/slicedToArray';
import _reduceInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/reduce';
import _Object$entries from '@babel/runtime-corejs3/core-js-stable/object/entries';
import _valuesInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/values';
import { jsx } from '@emotion/react/jsx-runtime';
import { useQuery, useLazyQuery, useMutation } from '@apollo/client/react';
import warning from 'tiny-warning';
import { GRAPHQL_TARGETS, SUPPORTED_HEADERS, STATUS_CODES, LOGOUT_REASONS, STORAGE_KEYS, LOGIN_STRATEGY_OIDC } from '@commercetools-frontend/constants';
import _findInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/find';
import { ApolloLink, ApolloClient, InMemoryCache, createHttpLink, from } from '@apollo/client';
import loggerLink from 'apollo-link-logger';
import { onError } from '@apollo/client/link/error';
import history from '@commercetools-frontend/browser-history';
import _includesInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/includes';
import _Array$isArray from '@babel/runtime-corejs3/core-js-stable/array/is-array';
import _someInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/some';
import _Object$values from '@babel/runtime-corejs3/core-js-stable/object/values';
import _mapInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/map';
import createHttpUserAgent from '@commercetools/http-user-agent';
import omitEmpty from 'omit-empty-es';
import { v4 } from 'uuid';
import _Reflect$construct from '@babel/runtime-corejs3/core-js-stable/reflect/construct';
import _createClass from '@babel/runtime-corejs3/helpers/esm/createClass';
import _classCallCheck from '@babel/runtime-corejs3/helpers/esm/classCallCheck';
import _assertThisInitialized from '@babel/runtime-corejs3/helpers/esm/assertThisInitialized';
import _inherits from '@babel/runtime-corejs3/helpers/esm/inherits';
import _possibleConstructorReturn from '@babel/runtime-corejs3/helpers/esm/possibleConstructorReturn';
import _getPrototypeOf from '@babel/runtime-corejs3/helpers/esm/getPrototypeOf';
import _wrapNativeSuper from '@babel/runtime-corejs3/helpers/esm/wrapNativeSuper';
import _JSON$stringify from '@babel/runtime-corejs3/core-js-stable/json/stringify';
import { RetryLink } from '@apollo/client/link/retry';

// NOTE: This string will be replaced on build time with the package version.
var version = "24.2.1";

// 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 => {
  const url = new _URL(origin);
  const originTld = getMcOriginTld(url.host);
  return `${url.protocol}//mc-api.${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(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(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(_context2 = ownKeys$7(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context3 = ownKeys$7(Object(t))).call(_context3, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
// Menu visibilities

// 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(allAppliedPermissions).call(allAppliedPermissions, (transformedAllApplied, allApplied) => {
    if (!allApplied) return transformedAllApplied;
    return _objectSpread$7(_objectSpread$7({}, transformedAllApplied), {}, {
      [allApplied.name]: allApplied.value
    });
  }, {});
};
const normalizeAllAppliedMenuVisibilities = allAppliedMenuVisibilities => {
  if (!allAppliedMenuVisibilities || allAppliedMenuVisibilities.length === 0) {
    return null;
  }
  return _reduceInstanceProperty(allAppliedMenuVisibilities).call(allAppliedMenuVisibilities, (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(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(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(_context = _Object$entries(groupedByResourceType)).call(_context, (previousGroupedByResourceType, _ref) => {
    let _ref2 = _slicedToArray(_ref, 2),
      resourceType = _ref2[0],
      dataFences = _ref2[1];
    const groupByDataFenceName = _reduceInstanceProperty(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(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(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(normalizedDataFences).length > 0) return normalizedDataFences;
  return null;
};

function ownKeys$6(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(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(_context = ownKeys$6(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context2 = ownKeys$6(Object(t))).call(_context2, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
const Context$2 = /*#__PURE__*/createContext({});
const defaultTimeZone = moment.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) {
      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?.allAppliedPermissions),
  actionRights: normalizeAllAppliedActionRights(project?.allAppliedActionRights),
  dataFences: normalizeAllAppliedDataFences(project?.allAppliedDataFences),
  dataLocale: projectDataLocale || null
});
const ApplicationContextProvider = props => jsx(Context$2.Provider, {
  value: createApplicationContext(props.environment, props.user, props.project, props.projectDataLocale),
  children: props.children
});
ApplicationContextProvider.propTypes = process.env.NODE_ENV !== "production" ? {
  projectDataLocale: _pt.string,
  children: _pt.node.isRequired
} : {};
ApplicationContextProvider.displayName = 'ApplicationContextProvider';
const ApplicationContext = props => 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.propTypes = process.env.NODE_ENV !== "production" ? {
  render: _pt.func.isRequired
} : {};
ApplicationContext.displayName = 'ApplicationContext';
function withApplicationContext(mapApplicationContextToProps) {
  return Component => {
    const WrappedComponent = props => jsx(ApplicationContext, {
      render: applicationContext => {
        const mappedProps = mapApplicationContextToProps ? mapApplicationContextToProps(applicationContext) : {
          applicationContext
        };
        // @ts-ignore: relates to https://github.com/emotion-js/emotion/issues/3245
        return jsx(Component, _objectSpread$6(_objectSpread$6({}, props), mappedProps));
      }
    });
    WrappedComponent.displayName = `withApplicationContext(${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 = 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;

function ownKeys$5(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(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(_context = ownKeys$5(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context2 = ownKeys$5(Object(t))).call(_context2, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
const Context$1 = /*#__PURE__*/createContext({});
const CustomViewContextProvider = props => {
  const contextValue = useMemo(() => ({
    hostUrl: props.hostUrl,
    customViewConfig: props.customViewConfig
  }), [props.hostUrl, props.customViewConfig]);
  return 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.
CustomViewContextProvider.propTypes = process.env.NODE_ENV !== "production" ? {
  hostUrl: _pt.string.isRequired,
  customViewConfig: _pt.any.isRequired,
  children: _pt.node.isRequired
} : {};
// 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 = 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(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(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(_context = ownKeys$4(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context2 = ownKeys$4(Object(t))).call(_context2, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(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) => {
  useEffect(() => {
    process.env.NODE_ENV !== "production" ? warning(condition, message) : void 0;
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);
};
const Context = /*#__PURE__*/createContext({
  isLoading: false
});
const useProjectExtensionImageRegex = () => {
  const _useContext = useContext(Context),
    isLoading = _useContext.isLoading,
    imageRegex = _useContext.imageRegex;
  return {
    isLoading,
    imageRegex
  };
};
const ProjectExtensionProviderForImageRegex = props => {
  const _useQuery = useQuery(FetchProjectExtensionImageRegex, {
      skip: props.skip,
      context: {
        target: GRAPHQL_TARGETS.SETTINGS_SERVICE
      }
    }),
    loading = _useQuery.loading,
    data = _useQuery.data;
  return jsx(Context.Provider, {
    value: {
      isLoading: loading,
      imageRegex: data && data.projectExtension && data.projectExtension.imageRegex
    },
    children: props.children
  });
};
ProjectExtensionProviderForImageRegex.propTypes = process.env.NODE_ENV !== "production" ? {
  skip: _pt.bool,
  children: _pt.node.isRequired
} : {};
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 jsx(Context.Consumer, {
    children: imageRegexContext => props.render(imageRegexContext)
  });
};
GetProjectExtensionImageRegex.propTypes = process.env.NODE_ENV !== "production" ? {
  render: _pt.func.isRequired
} : {};
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 jsx(GetProjectExtensionImageRegex, {
        render: () =>
        // @ts-ignore: relates to https://github.com/emotion-js/emotion/issues/3245
        jsx(Component, _objectSpread$4(_objectSpread$4({}, props), {}, {
          [propKey]: imageregexContext
        }))
      });
    };
    WrappedComponent.displayName = `withProjectExtensionImageRegex(${getDisplayName(Component)})`;
    return WrappedComponent;
  };
}

function ownKeys$3(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(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(_context2 = ownKeys$3(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context3 = ownKeys$3(Object(t))).call(_context3, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
const getSkipTokenRetry = context => {
  const skipTokenRetry = Boolean(context.skipTokenRetry);
  return skipTokenRetry;
};
const forwardTokenRetryHeader = headers => _objectSpread$3(_objectSpread$3({}, headers), {}, {
  [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;
  const graphQLTarget = context.headers?.[SUPPORTED_HEADERS.X_GRAPHQL_TARGET] || context.headers?.[SUPPORTED_HEADERS.X_GRAPHQL_TARGET.toLowerCase()];
  return Boolean(graphQLTarget && _includesInstanceProperty(_context = [GRAPHQL_TARGETS.COMMERCETOOLS_PLATFORM, GRAPHQL_TARGETS.ADMINISTRATION_SERVICE, GRAPHQL_TARGETS.SETTINGS_SERVICE, GRAPHQL_TARGETS.MERCHANT_CENTER_BACKEND]).call(_context, graphQLTarget));
};
const isHttpError = error => error.statusCode !== undefined || error.statusCode !== undefined;
const isGraphQLError = error => _Array$isArray(error) && _someInstanceProperty(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 = onError(_ref => {
  let graphQLErrors = _ref.graphQLErrors,
    networkError = _ref.networkError,
    operation = _ref.operation,
    forward = _ref.forward;
  if (networkError && isHttpError(networkError) && networkError.statusCode === STATUS_CODES.UNAUTHORIZED) {
    history.push(`/logout?reason=${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) {
      const isNonAuthenticatedViaExtensionCode = 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?.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) {
    reportErrorToSentry(networkError, {
      extra: {
        operationName: operation.operationName
      }
    });
  }
  if (context.enableSentryErrorReporting && graphQLErrors) {
    for (const err of graphQLErrors) {
      reportErrorToSentry(err, {
        extra: {
          operationName: operation.operationName
        }
      });
    }
  }
  return;
});

// Attempt to load the `teamId` from sessionStorage
function selectTeamIdFromStorage() {
  return window.sessionStorage.getItem(STORAGE_KEYS.ACTIVE_TEAM_ID) || window.app.__DEVELOPMENT__?.oidc?.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(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(_context = ['mc', selectProjectKeyFromUrl(), userId, v4()]).call(_context, skipMalformedPart).join('/');
}

const createApolloContextForProxyForwardTo = proxyForwardTocontext => ({
  // Send the request to the forward-to endpoint.
  uri: `${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(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);
  }
};

const getSessionToken = () => window.sessionStorage.getItem(STORAGE_KEYS.SESSION_TOKEN);
const setActiveSession = sessionToken => {
  if (!sessionToken) return;
  window.sessionStorage.setItem(STORAGE_KEYS.SESSION_TOKEN, sessionToken ?? '');
  window.localStorage.setItem(STORAGE_KEYS.LOGIN_STRATEGY, LOGIN_STRATEGY_OIDC);
  // Remove flag for original workflow
  window.localStorage.removeItem(STORAGE_KEYS.IS_AUTHENTICATED);
};
const clearSession = () => {
  window.sessionStorage.removeItem(STORAGE_KEYS.SESSION_TOKEN);
  window.sessionStorage.removeItem(STORAGE_KEYS.SESSION_SCOPE);
  window.sessionStorage.removeItem(STORAGE_KEYS.IS_AUTHENTICATED);
};
const getActiveProjectKey = () => window.localStorage.getItem(STORAGE_KEYS.ACTIVE_PROJECT_KEY);
const removeActiveProjectKey = () => {
  window.localStorage.removeItem(STORAGE_KEYS.ACTIVE_PROJECT_KEY);
};
const setActiveProjectKey = projectKey => {
  window.localStorage.setItem(STORAGE_KEYS.ACTIVE_PROJECT_KEY, projectKey);
};
const getSessionScope = () => window.sessionStorage.getItem(STORAGE_KEYS.SESSION_SCOPE);
const setSessionScope = scope => {
  window.sessionStorage.setItem(STORAGE_KEYS.SESSION_SCOPE, scope);
};
const getSessionState = stateId => {
  const sessionStateKey = `${STORAGE_KEYS.NONCE}_${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') {
        // eslint-disable-next-line no-console
        console.warn(`Cannot parse session state for "${sessionStateKey}".\n${unparsedSessionState}`);
      }
    }
  }
  return null;
};
const setSessionState = (stateId, state) => {
  const sessionStateKey = `${STORAGE_KEYS.NONCE}_${stateId}`;
  window.sessionStorage.setItem(sessionStateKey, _JSON$stringify(state));
};
const removeSessionState = stateId => {
  const sessionStateKey = `${STORAGE_KEYS.NONCE}_${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 _createSuper(t) { var r = _isNativeReflectConstruct(); return function () { var e, o = _getPrototypeOf(t); if (r) { var s = _getPrototypeOf(this).constructor; e = _Reflect$construct(o, arguments, s); } else e = o.apply(this, arguments); return _possibleConstructorReturn(this, e); }; }
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(_Reflect$construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function () { return !!t; })(); }
function ownKeys$2(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread$2(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty(_context2 = ownKeys$2(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context3 = ownKeys$2(Object(t))).call(_context3, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
let _userAgent$1;
const getUserAgent$1 = () => {
  if (!_userAgent$1) {
    _userAgent$1 = createHttpUserAgent({
      name: 'unknown-http-client',
      libraryName: typeof window !== 'undefined' ? window.app?.applicationName ?? 'unknown-application-name' : undefined
    });
  }
  return _userAgent$1;
};
const defaultForwardToVersion = 'v2';
const defaultForwardToAudiencePolicy = 'forward-url-full-path';
function buildApiUrl(endpoint) {
  const apiUrl = getMcApiUrl().replace(/\/$/, '');
  return `${apiUrl}${endpoint}`;
}
const getAppliedForwardToHeaders = forwardToConfig => {
  var _context;
  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(_context = _Object$entries(forwardToConfig.headers ?? {})).call(_context, (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-${headerName}`]: headerValue
    });
  }, {})), {}, {
    [SUPPORTED_HEADERS.ACCEPT_VERSION]: forwardToConfig.version ?? defaultForwardToVersion,
    [SUPPORTED_HEADERS.X_FORWARD_TO]: forwardToConfig.uri,
    [SUPPORTED_HEADERS.X_FORWARD_TO_AUDIENCE_POLICY]: forwardToConfig.audiencePolicy ?? defaultForwardToAudiencePolicy,
    [SUPPORTED_HEADERS.X_FORWARD_TO_CLAIMS]: exchangeTokenClaims.join(' ')
  });
};
function createHttpClientOptions() {
  let config = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  const sessionToken = getSessionToken();
  const projectKey = config.projectKey ?? selectProjectKeyFromUrl();
  const userId = selectUserId();
  const userAgent = config?.userAgent || getUserAgent$1();
  return {
    credentials: 'include',
    headers: omitEmpty(_objectSpread$2(_objectSpread$2({}, config.headers), {}, {
      // Required headers
      [SUPPORTED_HEADERS.ACCEPT]: 'application/json',
      [SUPPORTED_HEADERS.AUTHORIZATION]: sessionToken ? `Bearer ${sessionToken}` : undefined,
      [SUPPORTED_HEADERS.X_APPLICATION_ID]: window.app.applicationIdentifier,
      [SUPPORTED_HEADERS.X_CUSTOM_VIEW_ID]: window.app.customViewId,
      [SUPPORTED_HEADERS.X_CORRELATION_ID]: getCorrelationId({
        userId
      }),
      [SUPPORTED_HEADERS.X_PROJECT_KEY]: projectKey,
      [SUPPORTED_HEADERS.X_USER_AGENT]: userAgent
    }, getAppliedForwardToHeaders(config.forwardToConfig)))
  };
}
let RenewTokenError = /*#__PURE__*/function (_Error) {
  _inherits(RenewTokenError, _Error);
  var _super = _createSuper(RenewTokenError);
  function RenewTokenError(message) {
    var _this;
    _classCallCheck(this, RenewTokenError);
    _this = _super.call(this, message);
    _Object$defineProperty(_assertThisInitialized(_this), 'name', {
      value: 'RenewTokenError'
    });
    return _this;
  }
  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(_objectSpread$2(_objectSpread$2({}, requestOptions.headers), {}, {
        // Passing this header forces a token renewal.
        [SUPPORTED_HEADERS.X_TOKEN_RETRY]: shouldRenewToken
      }))
    }));
    if (response.statusCode === STATUS_CODES.UNAUTHORIZED) {
      throw new RenewTokenError(`Unauthorized response, attempting retry.`);
    }

    // In case a new session token is returned from the server, save it.
    const refreshedSessionToken = response.getHeader('x-refreshed-session-token');
    if (refreshedSessionToken) {
      setActiveSession(refreshedSessionToken);
    }
    return response.data;
  }

  // Attempt to send the request.
  return sendRequest().catch(error => {
    if (error instanceof RenewTokenError) {
      // Retry the request and ask to renew the token.
      return sendRequest({
        shouldRenewToken: true
      });
    }
    throw error;
  });
}

function ownKeys$1(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread$1(e) { for (var r = 1; r < arguments.length; r++) { var _context4, _context5; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty(_context4 = ownKeys$1(Object(t), !0)).call(_context4, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context5 = ownKeys$1(Object(t))).call(_context5, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
let _userAgent;
const getUserAgent = () => {
  if (!_userAgent) {
    var _context;
    _userAgent = createHttpUserAgent({
      name: 'apollo-client',
      // version: apolloVersion,
      libraryName: _filterInstanceProperty(_context = [typeof window !== 'undefined' ? window.app?.applicationName ?? 'unknown-application-name' : undefined, 'application-shell']).call(_context, Boolean).join('/'),
      libraryVersion: version,
      contactUrl: 'https://git.io/fjuyC',
      // points to the appkit repo issues
      contactEmail: 'support@commercetools.com'
    });
  }
  return _userAgent;
};
const isKnownGraphQlTarget = target => {
  var _context2;
  return target ? _includesInstanceProperty(_context2 = _Object$values(GRAPHQL_TARGETS)).call(_context2, target) : false;
};
const extractSessionTokenFromResponse = context => {
  const refreshedSessionToken = context.response?.headers?.get('x-refreshed-session-token');
  if (refreshedSessionToken) {
    return refreshedSessionToken ?? null;
  }
  const restResponseWithRefreshTokenHeader = context.restResponses?.find(response => response.headers?.has('x-refreshed-session-token'));
  if (restResponseWithRefreshTokenHeader) {
    return restResponseWithRefreshTokenHeader.headers.get('x-refreshed-session-token') ?? null;
  }
  return null;
};

/* eslint-disable import/prefer-default-export */
// Use a middleware to update the request headers with the correct params.
const headerLink = new ApolloLink((operation, forward) => {
  var _context3;
  const apolloContext = operation.getContext();
  const variables = operation.variables;
  const graphQlTarget = apolloContext.target || variables.target;
  if (!apolloContext.skipGraphQlTargetCheck && !isKnownGraphQlTarget(graphQlTarget)) throw new Error(`GraphQL target "${graphQlTarget}" is missing (or is not supported) in operation "${operation.operationName}"`);

  /**
   * NOTE:
   *   The project key is read from the url in a project related application context.
   *   This holds for most applications like `application-categories`, `application-discounts` etc.
   *   However, the `application-account` does not run with the project key being part of the url.
   *   As a result we allow passing the project key as a variable on the operation allowing
   *   it to be the fallback.
   */
  const projectKey = apolloContext.projectKey || variables.projectKey || selectProjectKeyFromUrl();
  const teamId = apolloContext.teamId || variables.teamId || selectTeamIdFromStorage();
  const featureFlag = apolloContext.featureFlag || variables.featureFlag;
  operation.setContext(createHttpClientOptions({
    userAgent: getUserAgent(),
    headers: omitEmpty(_objectSpread$1(_objectSpread$1({}, apolloContext.headers), {}, {
      // Required headers for GraphQL API.
      [SUPPORTED_HEADERS.X_GRAPHQL_TARGET]: graphQlTarget,
      // For logging/debugging purposes.
      [SUPPORTED_HEADERS.X_GRAPHQL_OPERATION_NAME]: operation.operationName,
      // Experimental features, use with caution.
      [SUPPORTED_HEADERS.X_TEAM_ID]: teamId,
      [SUPPORTED_HEADERS.X_FEATURE_FLAG]: featureFlag
    })),
    forwardToConfig: apolloContext.forwardToConfig,
    projectKey
  }));
  return _mapInstanceProperty(_context3 = forward(operation)).call(_context3, response => {
    const context = operation.getContext();
    const refreshedSessionToken = extractSessionTokenFromResponse(context);
    if (refreshedSessionToken) {
      setActiveSession(refreshedSessionToken);
    }
    return response;
  });
});

const tokenRetryLink = new RetryLink({
  attempts: (count, operation, error) => {
    const context = operation.getContext();
    if (error?.statusCode === STATUS_CODES.UNAUTHORIZED && count === 1 && getDoesGraphQLTargetSupportTokenRetry(context) && !getSkipTokenRetry(context)) {
      operation.setContext(_ref => {
        let headers = _ref.headers;
        return {
          headers: forwardTokenRetryHeader(headers)
        };
      });
      return true;
    }
    return false;
  }
});

function ownKeys(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context, _context2; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty(_context = ownKeys(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context2 = ownKeys(Object(t))).call(_context2, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
const createApolloLink = function () {
  let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  const httpLink = createHttpLink({
    uri: `${getMcApiUrl()}/graphql`,
    fetch
  });

  // The order of links is IMPORTANT!
  // In the request-phase they are executed top to bottom.
  // In the response/phase they are executed bottom to top.
  // The `httpLink` is terminating so it must be last, while `tokenRetryLink` and `errorLink`
  // wrap the links the their right.
  return from([headerLink,
  // See https://www.apollographql.com/docs/react/api/link/apollo-link-rest/#link-order
  // State & context links should happen before (to the left of) `restLink`.
  ...(options.restLink ? [options.restLink] : []),
  // Must be before `tokenRetryLink`.
  errorLink,
  // Avoid logging queries in test environment
  ...(isLoggerEnabled() ? [loggerLink] : []),
  // Must be after `errorLink`.
  tokenRetryLink,
  // Must be last.
  httpLink]);
};

// This custom merge function allows to merge two arrays of objects.
// The incoming list is what we need to update to, but we still need
// to ensure that existing cache elements are not removed but updated.
// This is usually the case when elements get removed.
const mergeArraysObjects = function () {
  let existing = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
  let incoming = arguments.length > 1 ? arguments[1] : undefined;
  let _ref = arguments.length > 2 ? arguments[2] : undefined,
    mergeObjects = _ref.mergeObjects;
  return _reduceInstanceProperty(incoming).call(incoming, (mergedElements, elem) => {
    const existingElem = _findInstanceProperty(existing).call(existing, el => el.__ref === elem.__ref);
    if (existingElem) {
      const updatedElem = mergeObjects(existingElem, elem);
      if (updatedElem) {
        return [...mergedElements, updatedElem];
      }
    }
    return [...mergedElements, elem];
  }, []);
};
const createApolloClient = function () {
  let options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
  const customCacheConfig = options?.cache ?? {};
  return new ApolloClient({
    link: createApolloLink(options),
    // https://www.apollographql.com/docs/react/caching/cache-configuration/
    cache: new InMemoryCache(_objectSpread(_objectSpread({}, customCacheConfig), {}, {
      // https://www.apollographql.com/docs/react/caching/cache-configuration/#generating-unique-identifiers
      typePolicies: _objectSpread({
        // CTP types with `key` as identifier
        Project: {
          keyFields: ['key'],
          fields: {
            expiry: {
              merge: (existing, incoming, _ref2) => {
                let mergeObjects = _ref2.mergeObjects;
                return mergeObjects(existing, incoming);
              }
            },
            suspension: {
              merge: (existing, incoming, _ref3) => {
                let mergeObjects = _ref3.mergeObjects;
                return mergeObjects(existing, incoming);
              }
            }
          }
        },
        Store: {
          keyFields: ['key']
        },
        // Internal apps menu links representations
        ApplicationsMenu: {
          fields: {
            appBar: {
              merge: mergeArraysObjects
            },
            navBarGroups: {
              merge: mergeArraysObjects
            }
          }
        }
      }, customCacheConfig.typePolicies ?? {})
    }))
  });
};

function useMcQuery(query, options) {
  return useQuery(query, options);
}
function useMcLazyQuery(query, options) {
  return useLazyQuery(query, options);
}
function useMcMutation(mutation, options) {
  return useMutation(mutation, options);
}

export { ApplicationContext, ApplicationContextProvider, Context$2 as Context, CustomViewContextProvider, GetProjectExtensionImageRegex, ProjectExtensionProviderForImageRegex, buildApiUrl, createApolloClient, createApolloContextForProxyForwardTo, createHttpClientOptions, executeHttpClientRequest, getCachedApolloClient, getCorrelationId, getMcApiUrl, isLoggerEnabled, logger, normalizeAllAppliedActionRights, normalizeAllAppliedDataFences, normalizeAllAppliedMenuVisibilities, normalizeAllAppliedPermissions, oidcStorage, selectProjectKeyFromUrl, selectTeamIdFromStorage, selectUserId, setCachedApolloClient, useApplicationContext, useCustomViewContext, useMcLazyQuery, useMcMutation, useMcQuery, useProjectExtensionImageRegex, version, withApplicationContext, withProjectExtensionImageRegex };