diff --git a/.changeset/lazy-eggs-glow.md b/.changeset/lazy-eggs-glow.md new file mode 100644 index 0000000000..2e851e353f --- /dev/null +++ b/.changeset/lazy-eggs-glow.md @@ -0,0 +1,8 @@ +--- +'merchant-center-application-template-starter': patch +'@commercetools-frontend/application-shell': patch +'@commercetools-frontend/application-shell-connectors': patch +'@commercetools-frontend/mc-scripts': patch +--- + +Upgrade to [Apollo Client v3.4](https://github.com/apollographql/apollo-client/blob/main/CHANGELOG.md#apollo-client-340). diff --git a/application-templates/starter/package.json b/application-templates/starter/package.json index f45f001f1e..e6d30ffe90 100644 --- a/application-templates/starter/package.json +++ b/application-templates/starter/package.json @@ -16,7 +16,7 @@ "versions:uikit": "manypkg upgrade @commercetools-uikit" }, "dependencies": { - "@apollo/client": "3.3.21", + "@apollo/client": "3.4.5", "@commercetools-frontend/actions-global": "20.9.3", "@commercetools-frontend/application-components": "20.9.3", "@commercetools-frontend/application-shell": "20.9.3", diff --git a/packages/application-shell-connectors/package.json b/packages/application-shell-connectors/package.json index dd189f233f..8d7f58713d 100644 --- a/packages/application-shell-connectors/package.json +++ b/packages/application-shell-connectors/package.json @@ -39,7 +39,7 @@ "prop-types": "15.7.2" }, "devDependencies": { - "@apollo/client": "3.3.21", + "@apollo/client": "3.4.5", "@testing-library/react": "12.0.0", "react": "17.0.2" }, diff --git a/packages/application-shell/package.json b/packages/application-shell/package.json index 74e3367424..52eea050c8 100644 --- a/packages/application-shell/package.json +++ b/packages/application-shell/package.json @@ -99,7 +99,7 @@ "uuid": "8.3.2" }, "devDependencies": { - "@apollo/client": "3.3.21", + "@apollo/client": "3.4.5", "@testing-library/react": "12.0.0", "@testing-library/react-hooks": "7.0.1", "msw": "0.33.2", diff --git a/packages/application-shell/src/hooks/apollo-hooks/apollo-hooks.ts b/packages/application-shell/src/hooks/apollo-hooks/apollo-hooks.ts index 34357cd45b..a6d5849d03 100644 --- a/packages/application-shell/src/hooks/apollo-hooks/apollo-hooks.ts +++ b/packages/application-shell/src/hooks/apollo-hooks/apollo-hooks.ts @@ -20,7 +20,7 @@ type TQueryOptionsWithContext< type TMutationOptionsWithContext< TData = unknown, TVariables = OperationVariables -> = MutationHookOptions & { +> = MutationHookOptions & { context: TApolloContext; }; @@ -41,8 +41,8 @@ function useMcLazyQuery( function useMcMutation( mutation: DocumentNode, options?: TMutationOptionsWithContext -): MutationTuple { - return useMutation(mutation, options); +): MutationTuple { + return useMutation(mutation, options); } // Custom Apollo query/mutation wrappers, useful to take advantage diff --git a/packages/application-shell/src/hooks/use-applications-menu/use-applications-menu.ts b/packages/application-shell/src/hooks/use-applications-menu/use-applications-menu.ts index cf4a899353..955f92662e 100644 --- a/packages/application-shell/src/hooks/use-applications-menu/use-applications-menu.ts +++ b/packages/application-shell/src/hooks/use-applications-menu/use-applications-menu.ts @@ -14,7 +14,7 @@ import type { import { useEffect } from 'react'; import { useApolloClient } from '@apollo/client'; import { useApplicationContext } from '@commercetools-frontend/application-shell-connectors'; -import { useMcQuery } from '../../hooks/apollo-hooks'; +import { useMcLazyQuery } from '../../hooks/apollo-hooks'; import FetchApplicationsMenu from './fetch-applications-menu.proxy.graphql'; const supportedLocales = ['en', 'de', 'es', 'fr-FR', 'zh-CN', 'ja']; @@ -27,7 +27,9 @@ export type MenuLoaderResult = Key extends 'appBar' : never; export type Config = { environment: TApplicationContext<{}>['environment']; - queryOptions?: QueryFunctionOptions; + queryOptions?: { + onError?: QueryFunctionOptions['onError']; + }; /** * @deprecated The `menu.json` file has been deprecated in favor of defining the menu links * in the custom application config file. @@ -232,22 +234,23 @@ function useApplicationsMenu( const mcProxyApiUrl = useApplicationContext( (context) => context.environment.mcProxyApiUrl ); - const queryOptions = config.queryOptions || {}; // Fetch all menu links from the GraphQL API in the Merchant Center Proxy. // For local development, we don't fetch data from the remote server but use // only the configuration for the menu links defined for the application. // To do so, we manually write the data in the Apollo cache and use the // `fetchPolicy: cache-only` to instruct Apollo to read the data from the cache. - const { data: menuQueryResult } = useMcQuery< + // NOTE: we lazily execute the query to ensure that (for development) we can + // write the data into the cache BEFORE the query attempts to read from it. + // If not, Apollo throws an error like `Can't find field 'applicationMenu' on ROOT_QUERY object`. + const [executeQuery, { data: menuQueryResult, called }] = useMcLazyQuery< TFetchApplicationsMenuQuery, TFetchApplicationsMenuQueryVariables >(FetchApplicationsMenu, { - ...queryOptions, + onError: config.queryOptions?.onError, fetchPolicy: config.environment.servedByProxy - ? queryOptions.fetchPolicy || 'cache-first' + ? 'cache-first' : 'cache-only', - variables: {}, context: { // Allow to overwrite the API url from application config uri: `${mcProxyApiUrl || defaultApiUrl}/api/graphql`, @@ -284,6 +287,10 @@ function useApplicationsMenu( }); }); } + + if (!called) { + executeQuery(); + } // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // Make sure to run this effect only once, otherwise we might end up in an infinite loop! diff --git a/packages/application-shell/src/utils/select-user-id/select-user-id.spec.js b/packages/application-shell/src/utils/select-user-id/select-user-id.spec.js index ea919e810d..89cc1ffb82 100644 --- a/packages/application-shell/src/utils/select-user-id/select-user-id.spec.js +++ b/packages/application-shell/src/utils/select-user-id/select-user-id.spec.js @@ -11,6 +11,7 @@ afterEach(() => { describe('selectUserId', () => { describe('when `readQuery` throws', () => { beforeEach(() => { + console.error = jest.fn(); const apolloClient = createApolloClient(); apolloClient.writeQuery({ query: FetchUserId, @@ -23,6 +24,9 @@ describe('selectUserId', () => { setCachedApolloClient(apolloClient); }); it('should return `null`', () => { + expect(console.error).toHaveBeenCalledWith( + expect.stringContaining(`Missing field 'id'`) + ); expect(selectUserId()).toBeNull(); }); }); diff --git a/packages/mc-scripts/src/config/create-webpack-config-for-development.js b/packages/mc-scripts/src/config/create-webpack-config-for-development.js index 3e6b02fb1e..b5e8fc5990 100644 --- a/packages/mc-scripts/src/config/create-webpack-config-for-development.js +++ b/packages/mc-scripts/src/config/create-webpack-config-for-development.js @@ -159,6 +159,7 @@ module.exports = function createWebpackConfigForDevelopment(options = {}) { // Makes some environment variables available to the JS code, for example: // if (process.env.NODE_ENV === 'development') { ... }. new webpack.DefinePlugin({ + __DEV__: 'true', 'process.env': { NODE_ENV: JSON.stringify('development'), }, diff --git a/packages/mc-scripts/src/config/create-webpack-config-for-production.js b/packages/mc-scripts/src/config/create-webpack-config-for-production.js index 8f57214566..8c90cdbb7b 100644 --- a/packages/mc-scripts/src/config/create-webpack-config-for-production.js +++ b/packages/mc-scripts/src/config/create-webpack-config-for-production.js @@ -180,6 +180,7 @@ module.exports = function createWebpackConfigForProduction(options = {}) { // Makes some environment variables available to the JS code, for example: // if (process.env.NODE_ENV === 'production') { ... }. new webpack.DefinePlugin({ + __DEV__: 'false', 'process.env': { NODE_ENV: JSON.stringify('production'), }, diff --git a/yarn.lock b/yarn.lock index 2163938ad6..075efdabd1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -17,24 +17,23 @@ call-me-maybe "^1.0.1" js-yaml "^4.1.0" -"@apollo/client@3.3.21": - version "3.3.21" - resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.3.21.tgz#2862baa4e1ced8c5e89ebe6fc52877fc64a726aa" - integrity sha512-RAmZReFuKCKx0Rs5C0nVJwKomAHUHn+gGP/YvbEsXQWu0sXoncEUZa71UqlfCPVXa/0MkYOIbCXSQdOcuRrHgw== +"@apollo/client@3.4.5": + version "3.4.5" + resolved "https://registry.yarnpkg.com/@apollo/client/-/client-3.4.5.tgz#c6bc27e8a66c9ad4e27183d33cbefbb9e06d5e69" + integrity sha512-arvzqyh+SmcJ9jGmdP1QhboTCq6YoowidqbDTigJ8LqA4jywOvgy3GMSPKUtyyxter12rQ+42cXjGI9+ZMVuyA== dependencies: "@graphql-typed-document-node/core" "^3.0.0" - "@types/zen-observable" "^0.8.0" "@wry/context" "^0.6.0" "@wry/equality" "^0.5.0" - fast-json-stable-stringify "^2.0.0" - graphql-tag "^2.12.0" + "@wry/trie" "^0.3.0" + graphql-tag "^2.12.3" hoist-non-react-statics "^3.3.2" - optimism "^0.16.0" + optimism "^0.16.1" prop-types "^15.7.2" symbol-observable "^4.0.0" - ts-invariant "^0.8.0" - tslib "^1.10.0" - zen-observable "^0.8.14" + ts-invariant "^0.9.0" + tslib "^2.3.0" + zen-observable-ts "^1.1.0" "@ardatan/aggregate-error@0.0.6": version "0.0.6" @@ -6039,7 +6038,7 @@ resolved "https://registry.yarnpkg.com/@types/yoga-layout/-/yoga-layout-1.9.2.tgz#efaf9e991a7390dc081a0b679185979a83a9639a" integrity sha512-S9q47ByT2pPvD65IvrWp7qppVMpk9WGMbVq9wbWZOHg6tnXSD4vyhao6nOSBwwfDdV2p3Kx9evA9vI+XWTfDvw== -"@types/zen-observable@^0.8.0": +"@types/zen-observable@0.8.3": version "0.8.3" resolved "https://registry.yarnpkg.com/@types/zen-observable/-/zen-observable-0.8.3.tgz#781d360c282436494b32fe7d9f7f8e64b3118aa3" integrity sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw== @@ -13052,7 +13051,7 @@ graphql-subscriptions@^1.1.0: dependencies: iterall "^1.3.0" -graphql-tag@^2.11.0, graphql-tag@^2.12.0, graphql-tag@^2.9.2: +graphql-tag@^2.11.0, graphql-tag@^2.12.3, graphql-tag@^2.9.2: version "2.12.5" resolved "https://registry.yarnpkg.com/graphql-tag/-/graphql-tag-2.12.5.tgz#5cff974a67b417747d05c8d9f5f3cb4495d0db8f" integrity sha512-5xNhP4063d16Pz3HBtKprutsPrmHZi5IdUGOWRxA2B6VF7BIRGOHZ5WQvDmJXZuPcBg7rYwaFxvQYjqkSdR3TQ== @@ -18044,7 +18043,7 @@ opn@^5.5.0: dependencies: is-wsl "^1.1.0" -optimism@^0.16.0: +optimism@^0.16.1: version "0.16.1" resolved "https://registry.yarnpkg.com/optimism/-/optimism-0.16.1.tgz#7c8efc1f3179f18307b887e18c15c5b7133f6e7d" integrity sha512-64i+Uw3otrndfq5kaoGNoY7pvOhSsjFEN4bdEFh80MWVk/dbgJfMv7VFDeCT8LxNAlEVhQmdVEbfE7X2nWNIIg== @@ -23080,10 +23079,10 @@ ts-essentials@^2.0.3: resolved "https://registry.yarnpkg.com/ts-essentials/-/ts-essentials-2.0.12.tgz#c9303f3d74f75fa7528c3d49b80e089ab09d8745" integrity sha512-3IVX4nI6B5cc31/GFFE+i8ey/N2eA0CZDbo6n0yrz0zDX8ZJ8djmU1p+XRz7G3is0F3bB3pu2pAroFdAWQKU3w== -ts-invariant@^0.8.0: - version "0.8.2" - resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.8.2.tgz#62af654ebfb8b1eeb55bc9adc2f40c6b93b0ff7e" - integrity sha512-VI1ZSMW8soizP5dU8DsMbj/TncHf7bIUqavuE7FTeYeQat454HHurJ8wbfCnVWcDOMkyiBUWOW2ytew3xUxlRw== +ts-invariant@^0.9.0: + version "0.9.1" + resolved "https://registry.yarnpkg.com/ts-invariant/-/ts-invariant-0.9.1.tgz#87dfde9894a4ce3c7711b02b1b449e7fd7384b13" + integrity sha512-hSeYibh29ULlHkuEfukcoiyTct+s2RzczMLTv4x3NWC/YrBy7x7ps5eYq/b4Y3Sb9/uAlf54+/5CAEMVxPhuQw== dependencies: tslib "^2.1.0" @@ -23149,7 +23148,7 @@ tslib@^1.10.0, tslib@^1.6.0, tslib@^1.8.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1. resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== -tslib@^2, tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@~2.3.0: +tslib@^2, tslib@^2.0.0, tslib@^2.0.3, tslib@^2.1.0, tslib@^2.2.0, tslib@^2.3.0, tslib@~2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.0.tgz#803b8cdab3e12ba581a4ca41c8839bbb0dacb09e" integrity sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg== @@ -24914,7 +24913,15 @@ yurnalist@^2.1.0: read "^1.0.7" strip-ansi "^5.2.0" -zen-observable@^0.8.14: +zen-observable-ts@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz#2d1aa9d79b87058e9b75698b92791c1838551f83" + integrity sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA== + dependencies: + "@types/zen-observable" "0.8.3" + zen-observable "0.8.15" + +zen-observable@0.8.15: version "0.8.15" resolved "https://registry.yarnpkg.com/zen-observable/-/zen-observable-0.8.15.tgz#96415c512d8e3ffd920afd3889604e30b9eaac15" integrity sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==