@graphcommerce/magento-cart 8.1.0-canary.2 → 8.1.0-canary.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Change Log
2
2
 
3
+ ## 8.1.0-canary.3
4
+
5
+ ### Patch Changes
6
+
7
+ - [#2205](https://github.com/graphcommerce-org/graphcommerce/pull/2205) [`d67c89d`](https://github.com/graphcommerce-org/graphcommerce/commit/d67c89d464a60f0e2618dab670b63a39f6291341) - Deprecate the allowUrl option for useCartQuery, it was already enabled by default and should never be set to false.
8
+ ([@paales](https://github.com/paales))
9
+
10
+ - [#2205](https://github.com/graphcommerce-org/graphcommerce/pull/2205) [`3fbf3da`](https://github.com/graphcommerce-org/graphcommerce/commit/3fbf3da8a67f2fbaa7fa974a37cbbf34613844e4) - Solve an issue where the user would be presented with the Session expired dialog when the user would be logging in during the checkout process.
11
+ ([@paales](https://github.com/paales))
12
+
3
13
  ## 8.1.0-canary.2
4
14
 
5
15
  ## 8.0.3-canary.1
@@ -1,6 +1,6 @@
1
1
  import { useApolloClient } from '@graphcommerce/graphql'
2
2
  import { Button } from '@mui/material'
3
- import { CurrentCartIdDocument } from '../../hooks/CurrentCartId.gql'
3
+ import { readCartId, writeCartId } from '../../hooks'
4
4
 
5
5
  export function CartDebugger() {
6
6
  const client = useApolloClient()
@@ -12,24 +12,14 @@ export function CartDebugger() {
12
12
  variant='text'
13
13
  size='small'
14
14
  onClick={() => {
15
- const currentCardId = client.readQuery({ query: CurrentCartIdDocument })
16
- if (!currentCardId?.currentCartId) {
15
+ const currentCartId = readCartId(client.cache)
16
+ if (!currentCartId) {
17
17
  // eslint-disable-next-line no-console
18
18
  console.log('No customerToken available, nothing to break')
19
19
  } else {
20
20
  // eslint-disable-next-line no-console
21
21
  console.log(`Changing current token to a random one`)
22
-
23
- client.writeQuery({
24
- query: CurrentCartIdDocument,
25
- data: {
26
- currentCartId: {
27
- ...currentCardId.currentCartId,
28
- id: `${Math.random().toString(36).slice(2)}random-cardId`,
29
- },
30
- },
31
- broadcast: true,
32
- })
22
+ writeCartId(client.cache, `${Math.random().toString(36).slice(2)}random-cardId`)
33
23
  }
34
24
  }}
35
25
  >
@@ -38,10 +38,7 @@ type OrderSummaryProps = ActionCardLayoutProps & {
38
38
 
39
39
  export function CartItemSummary(props: OrderSummaryProps) {
40
40
  const { sx = [], size, layout = 'list', itemProps, ...cardLayout } = props
41
- const { data } = useCartQuery(CartItemSummaryDocument, {
42
- allowUrl: true,
43
- fetchPolicy: 'cache-only',
44
- })
41
+ const { data } = useCartQuery(CartItemSummaryDocument, { fetchPolicy: 'cache-only' })
45
42
 
46
43
  if (!data?.cart) return null
47
44
 
@@ -85,7 +82,7 @@ export function CartItemSummary(props: OrderSummaryProps) {
85
82
  className={classes.scrollerContainer}
86
83
  {...cardLayout}
87
84
  >
88
- {items?.filter(nonNullable).map((item) => (
85
+ {(items ?? []).filter(nonNullable).map((item) => (
89
86
  <CartItemActionCard
90
87
  readOnly
91
88
  key={item.uid}
@@ -31,7 +31,7 @@ const { withState } = extendableComponent<OwnerProps, typeof name, typeof parts>
31
31
  * @see https://github.com/magento/magento2/issues/33848
32
32
  */
33
33
  export function CartTotals(props: CartTotalsProps) {
34
- const { data } = useCartQuery(GetCartTotalsDocument, { allowUrl: true })
34
+ const { data } = useCartQuery(GetCartTotalsDocument)
35
35
  const { containerMargin, additionalSubtotals, additionalTotals, sx = [] } = props
36
36
 
37
37
  const classes = withState({ containerMargin })
@@ -2,5 +2,6 @@ query CurrentCartId {
2
2
  currentCartId @client {
3
3
  __typename
4
4
  id
5
+ locked
5
6
  }
6
7
  }
@@ -4,6 +4,7 @@ extend type Query {
4
4
 
5
5
  type CurrentCartId {
6
6
  id: String
7
+ locked: Boolean
7
8
  }
8
9
 
9
10
  input RegisterCartIdInput {
@@ -2,6 +2,5 @@ query CustomerCart {
2
2
  customerCart {
3
3
  id
4
4
  __typename
5
- ...CartItemCountChanged
6
5
  }
7
6
  }
@@ -1,7 +1,6 @@
1
- mutation UseMergeCustomerCart($sourceCartId: String!, $destinationCartId: String!) {
1
+ mutation MergeCarts($sourceCartId: String!, $destinationCartId: String!) {
2
2
  mergeCarts(source_cart_id: $sourceCartId, destination_cart_id: $destinationCartId) {
3
3
  __typename
4
4
  id
5
- ...CartItemCountChanged
6
5
  }
7
6
  }
@@ -8,11 +8,26 @@ export const CART_ID_COOKIE = 'cart'
8
8
  export function writeCartId(cache: ApolloCache<object>, id: string | null = null) {
9
9
  cache.writeQuery({
10
10
  query: CurrentCartIdDocument,
11
- data: { currentCartId: { __typename: 'CurrentCartId', id } },
11
+ data: { currentCartId: { __typename: 'CurrentCartId', locked: false, id } },
12
12
  broadcast: true,
13
13
  })
14
14
  }
15
15
 
16
+ export function readCartId(cache: ApolloCache<object>) {
17
+ return cache.readQuery({ query: CurrentCartIdDocument })?.currentCartId
18
+ }
19
+
20
+ export function cartLock(cache: ApolloCache<object>, locked: boolean) {
21
+ const currentCartId = cache.readQuery({ query: CurrentCartIdDocument })?.currentCartId
22
+ if (currentCartId?.id && currentCartId.locked !== locked) {
23
+ cache.writeQuery({
24
+ query: CurrentCartIdDocument,
25
+ data: { currentCartId: { ...currentCartId, locked } },
26
+ broadcast: true,
27
+ })
28
+ }
29
+ }
30
+
16
31
  export function useAssignCurrentCartId() {
17
32
  const { cache } = useApolloClient()
18
33
 
@@ -1,16 +1,14 @@
1
1
  import { useApolloClient } from '@graphcommerce/graphql'
2
2
  import { i18n } from '@lingui/core'
3
3
  import { CreateEmptyCartDocument } from './CreateEmptyCart.gql'
4
- import { CurrentCartIdDocument } from './CurrentCartId.gql'
5
- import { useAssignCurrentCartId } from './useAssignCurrentCartId'
4
+ import { readCartId, useAssignCurrentCartId } from './useAssignCurrentCartId'
6
5
 
7
6
  export function useCartIdCreate() {
8
7
  const client = useApolloClient()
9
8
  const assignCurrentCartId = useAssignCurrentCartId()
10
9
 
11
10
  return async (): Promise<string> => {
12
- const currentCartId = client.cache.readQuery({ query: CurrentCartIdDocument })?.currentCartId
13
- ?.id
11
+ const currentCartId = readCartId(client.cache)?.id
14
12
 
15
13
  if (currentCartId) return currentCartId
16
14
 
@@ -15,18 +15,21 @@ import { useCurrentCartId } from './useCurrentCartId'
15
15
  export function useCartQuery<Q, V extends { cartId: string; [index: string]: unknown }>(
16
16
  document: TypedDocumentNode<Q, V>,
17
17
  options: QueryHookOptions<Q, Omit<V, 'cartId'>> & {
18
+ /**
19
+ * @deprecated Not used anymore, when the cart_id is in the URL, it will always be used.
20
+ */
18
21
  allowUrl?: boolean
19
22
  } = {},
20
23
  ) {
21
- const { allowUrl = true, ...queryOptions } = options
24
+ const { allowUrl, ...queryOptions } = options
22
25
  const router = useRouter()
23
- const { currentCartId } = useCurrentCartId()
26
+ const { currentCartId, locked } = useCurrentCartId()
24
27
 
25
28
  const urlCartId = router.query.cart_id
26
- const usingUrl = allowUrl && typeof urlCartId === 'string'
29
+ const usingUrl = typeof urlCartId === 'string'
27
30
  const cartId = usingUrl ? urlCartId : currentCartId
28
31
 
29
- if (usingUrl) queryOptions.fetchPolicy = 'cache-first'
32
+ if (usingUrl || locked) queryOptions.fetchPolicy = 'cache-only'
30
33
 
31
34
  if (usingUrl && typeof queryOptions.returnPartialData === 'undefined')
32
35
  queryOptions.returnPartialData = true
@@ -34,10 +37,5 @@ export function useCartQuery<Q, V extends { cartId: string; [index: string]: unk
34
37
  queryOptions.variables = { cartId, ...options?.variables } as V
35
38
  queryOptions.skip = queryOptions?.skip || !cartId
36
39
 
37
- const result = useQuery(document, queryOptions as QueryHookOptions<Q, V>)
38
-
39
- return {
40
- ...result,
41
- // error: called && !currentCartId ? noCartError : result.error,
42
- }
40
+ return useQuery(document, queryOptions as QueryHookOptions<Q, V>)
43
41
  }
@@ -1,20 +1,12 @@
1
1
  import { useApolloClient } from '@graphcommerce/graphql'
2
2
  import { cookie } from '@graphcommerce/next-ui'
3
- import { CurrentCartIdDocument } from './CurrentCartId.gql'
4
3
  import { CART_ID_COOKIE } from './useAssignCurrentCartId'
5
4
 
6
5
  export function useClearCurrentCartId() {
7
6
  const { cache } = useApolloClient()
8
7
 
9
8
  return () => {
10
- const id = cache.readQuery({ query: CurrentCartIdDocument })?.currentCartId?.id
11
- if (!id) return
12
-
13
- cache.writeQuery({
14
- query: CurrentCartIdDocument,
15
- data: { currentCartId: { __typename: 'CurrentCartId', id: null } },
16
- broadcast: true,
17
- })
9
+ cache.evict({ fieldName: 'currentCartId', broadcast: true })
18
10
  cookie(CART_ID_COOKIE, null)
19
11
  }
20
12
  }
@@ -10,5 +10,10 @@ export function useCurrentCartId<
10
10
  V extends CurrentCartIdQueryVariables,
11
11
  >(options: QueryHookOptions<Q, V> = {}) {
12
12
  const queryResults = useQuery<Q, V>(CurrentCartIdDocument, options)
13
- return { currentCartId: queryResults.data?.currentCartId?.id || '', ...queryResults }
13
+
14
+ return {
15
+ currentCartId: queryResults.data?.currentCartId?.id || '',
16
+ locked: queryResults.data?.currentCartId?.locked || false,
17
+ ...queryResults,
18
+ }
14
19
  }
@@ -1,43 +1,6 @@
1
- import { useMutation } from '@graphcommerce/graphql'
2
- import { useCustomerQuery } from '@graphcommerce/magento-customer'
3
- import { useEffect } from 'react'
4
- import { CustomerCartDocument } from './CustomerCart.gql'
5
- import { UseMergeCustomerCartDocument } from './UseMergeCustomerCart.gql'
6
- import { useAssignCurrentCartId } from './useAssignCurrentCartId'
7
- import { useCurrentCartId } from './useCurrentCartId'
8
-
9
1
  /**
10
- * - Automatically assign the customer cart as the current cart
11
- * - Merge the guest cart into the customer cart
2
+ * @deprecated Is replaced by the useSignInFormMergeCart plugin.
12
3
  */
13
4
  export function useMergeCustomerCart() {
14
- const { currentCartId } = useCurrentCartId()
15
- const assignCurrentCartId = useAssignCurrentCartId()
16
- const [merge] = useMutation(UseMergeCustomerCartDocument, { errorPolicy: 'all' })
17
-
18
- const destinationCartId = useCustomerQuery(CustomerCartDocument, { fetchPolicy: 'network-only' })
19
- ?.data?.customerCart.id
20
-
21
- useEffect(() => {
22
- // If we don't have a customer cart, we're done
23
- // If the vistor cart is the same as the customer cart, we're done
24
- if (!destinationCartId || currentCartId === destinationCartId) return
25
-
26
- // If the visitor has a guest cart, try merging it into the customer cart
27
- if (currentCartId) {
28
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
29
- merge({ variables: { sourceCartId: currentCartId, destinationCartId } })
30
- // We're not handling exceptions here:
31
- // If the merge returns an error, we'll use the customer cart without merging the guest cart.
32
- .catch((e) => {
33
- console.error('Error merging carts', e)
34
- })
35
- .finally(() => {
36
- // Assign the customer cart as the new cart id
37
- assignCurrentCartId(destinationCartId)
38
- })
39
- } else {
40
- assignCurrentCartId(destinationCartId)
41
- }
42
- }, [assignCurrentCartId, destinationCartId, merge, currentCartId])
5
+ return null
43
6
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@graphcommerce/magento-cart",
3
3
  "homepage": "https://www.graphcommerce.org/",
4
4
  "repository": "github:graphcommerce-org/graphcommerce",
5
- "version": "8.1.0-canary.2",
5
+ "version": "8.1.0-canary.3",
6
6
  "sideEffects": false,
7
7
  "prettier": "@graphcommerce/prettier-config-pwa",
8
8
  "eslintConfig": {
@@ -12,20 +12,20 @@
12
12
  }
13
13
  },
14
14
  "peerDependencies": {
15
- "@graphcommerce/ecommerce-ui": "^8.1.0-canary.2",
16
- "@graphcommerce/eslint-config-pwa": "^8.1.0-canary.2",
17
- "@graphcommerce/framer-next-pages": "^8.1.0-canary.2",
18
- "@graphcommerce/framer-scroller": "^8.1.0-canary.2",
19
- "@graphcommerce/framer-utils": "^8.1.0-canary.2",
20
- "@graphcommerce/graphql": "^8.1.0-canary.2",
21
- "@graphcommerce/image": "^8.1.0-canary.2",
22
- "@graphcommerce/magento-customer": "^8.1.0-canary.2",
23
- "@graphcommerce/magento-graphql": "^8.1.0-canary.2",
24
- "@graphcommerce/magento-store": "^8.1.0-canary.2",
25
- "@graphcommerce/next-ui": "^8.1.0-canary.2",
26
- "@graphcommerce/prettier-config-pwa": "^8.1.0-canary.2",
27
- "@graphcommerce/react-hook-form": "^8.1.0-canary.2",
28
- "@graphcommerce/typescript-config-pwa": "^8.1.0-canary.2",
15
+ "@graphcommerce/ecommerce-ui": "^8.1.0-canary.3",
16
+ "@graphcommerce/eslint-config-pwa": "^8.1.0-canary.3",
17
+ "@graphcommerce/framer-next-pages": "^8.1.0-canary.3",
18
+ "@graphcommerce/framer-scroller": "^8.1.0-canary.3",
19
+ "@graphcommerce/framer-utils": "^8.1.0-canary.3",
20
+ "@graphcommerce/graphql": "^8.1.0-canary.3",
21
+ "@graphcommerce/image": "^8.1.0-canary.3",
22
+ "@graphcommerce/magento-customer": "^8.1.0-canary.3",
23
+ "@graphcommerce/magento-graphql": "^8.1.0-canary.3",
24
+ "@graphcommerce/magento-store": "^8.1.0-canary.3",
25
+ "@graphcommerce/next-ui": "^8.1.0-canary.3",
26
+ "@graphcommerce/prettier-config-pwa": "^8.1.0-canary.3",
27
+ "@graphcommerce/react-hook-form": "^8.1.0-canary.3",
28
+ "@graphcommerce/typescript-config-pwa": "^8.1.0-canary.3",
29
29
  "@lingui/core": "^4.2.1",
30
30
  "@lingui/macro": "^4.2.1",
31
31
  "@lingui/react": "^4.2.1",
@@ -0,0 +1,50 @@
1
+ import { useApolloClient } from '@graphcommerce/graphql'
2
+ import type { useSignInForm } from '@graphcommerce/magento-customer/hooks/useSignInForm'
3
+ import type { MethodPlugin } from '@graphcommerce/next-config'
4
+ import { cartLock, readCartId, useAssignCurrentCartId } from '../hooks'
5
+ import { CustomerCartDocument } from '../hooks/CustomerCart.gql'
6
+ import { MergeCartsDocument } from '../hooks/MergeCarts.gql'
7
+
8
+ export const func = 'useSignInForm'
9
+ export const exported = '@graphcommerce/magento-customer/hooks/useSignInForm'
10
+
11
+ const useSignInFormMergeCart: MethodPlugin<typeof useSignInForm> = (useSignInForm, options) => {
12
+ const client = useApolloClient()
13
+ const assignCurrentCartId = useAssignCurrentCartId()
14
+
15
+ return useSignInForm({
16
+ ...options,
17
+ onComplete: async (data, variables) => {
18
+ await options.onComplete?.(data, variables)
19
+
20
+ cartLock(client.cache, true)
21
+
22
+ const destinationCartId = (
23
+ await client.query({
24
+ query: CustomerCartDocument,
25
+ fetchPolicy: 'network-only',
26
+ })
27
+ ).data.customerCart.id
28
+
29
+ try {
30
+ const sourceCartId = readCartId(client.cache)?.id
31
+ if (sourceCartId && sourceCartId !== destinationCartId) {
32
+ await client.mutate({
33
+ mutation: MergeCartsDocument,
34
+ variables: { sourceCartId, destinationCartId },
35
+ })
36
+ }
37
+ } catch (error) {
38
+ console.error(
39
+ 'Error merging carts, continuing without merging, this might cause issues.',
40
+ error,
41
+ )
42
+ } finally {
43
+ // Assign the customer cart as the new cart id
44
+ assignCurrentCartId(destinationCartId)
45
+ }
46
+ },
47
+ })
48
+ }
49
+
50
+ export const plugin = useSignInFormMergeCart
package/typePolicies.ts CHANGED
@@ -2,7 +2,7 @@ import { ApolloCache, NormalizedCacheObject } from '@graphcommerce/graphql'
2
2
  import type { StrictTypedTypePolicies } from '@graphcommerce/graphql'
3
3
  import type { CartPrices, QuerycartArgs, ShippingCartAddress } from '@graphcommerce/graphql-mesh'
4
4
  import { CartFabDocument } from './components/CartFab/CartFab.gql'
5
- import { CurrentCartIdDocument } from './hooks/CurrentCartId.gql'
5
+ import { readCartId, writeCartId } from './hooks'
6
6
 
7
7
  export const cartTypePolicies: StrictTypedTypePolicies = {
8
8
  CurrentCartId: { keyFields: [] },
@@ -53,11 +53,10 @@ export const migrateCart = (
53
53
  oldCache: ApolloCache<NormalizedCacheObject>,
54
54
  newCache: ApolloCache<NormalizedCacheObject>,
55
55
  ) => {
56
- const currentCartId = oldCache.readQuery({ query: CurrentCartIdDocument })
57
- const cartId = currentCartId?.currentCartId?.id
56
+ const cartId = readCartId(oldCache)?.id
58
57
 
59
58
  if (cartId) {
60
- newCache.writeQuery({ query: CurrentCartIdDocument, data: currentCartId, broadcast: true })
59
+ writeCartId(newCache, cartId)
61
60
 
62
61
  // We have special handling for the CartFab because it tries to load data only from the cache.
63
62
  const cartFab = oldCache.readQuery({ query: CartFabDocument })