@graphcommerce/magento-customer 4.3.0 → 4.4.0

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,34 @@
1
1
  # Change Log
2
2
 
3
+ ## 4.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#1485](https://github.com/graphcommerce-org/graphcommerce/pull/1485) [`d6262de71`](https://github.com/graphcommerce-org/graphcommerce/commit/d6262de71d2254a2b0b492e1a60f9e141767470e) Thanks [@paales](https://github.com/paales)! - move to useCustomerSession instead of using the tokenquery directly and fix ssr issues
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`c8c246b8a`](https://github.com/graphcommerce-org/graphcommerce/commit/c8c246b8aaab0621b68a2fca2a1c529a56fad962)]:
12
+ - @graphcommerce/next-ui@4.8.2
13
+ - @graphcommerce/ecommerce-ui@1.0.14
14
+ - @graphcommerce/magento-store@4.2.6
15
+
16
+ ## 4.3.2
17
+
18
+ ### Patch Changes
19
+
20
+ - Updated dependencies [[`a9df81310`](https://github.com/graphcommerce-org/graphcommerce/commit/a9df81310c051876dd82fb2819105dece47cc213), [`f167f9963`](https://github.com/graphcommerce-org/graphcommerce/commit/f167f99630966a7de43717937d43669e66132494)]:
21
+ - @graphcommerce/next-ui@4.8.1
22
+ - @graphcommerce/ecommerce-ui@1.0.13
23
+ - @graphcommerce/magento-store@4.2.5
24
+ - @graphcommerce/image@3.1.6
25
+
26
+ ## 4.3.1
27
+
28
+ ### Patch Changes
29
+
30
+ - [#1476](https://github.com/graphcommerce-org/graphcommerce/pull/1476) [`a12db31b9`](https://github.com/graphcommerce-org/graphcommerce/commit/a12db31b9db9d27d86f59c1bfe58a0879999b9d3) Thanks [@paales](https://github.com/paales)! - make sure the SignUp and SignIn forms can handle changes to the email field
31
+
3
32
  ## 4.3.0
4
33
 
5
34
  ### Minor Changes
@@ -1,4 +1,3 @@
1
- import { useQuery } from '@graphcommerce/graphql'
2
1
  import {
3
2
  iconPerson,
4
3
  DesktopHeaderBadge,
@@ -9,14 +8,15 @@ import { i18n } from '@lingui/core'
9
8
  import { Fab, FabProps as FabPropsType, NoSsr, SxProps, Theme } from '@mui/material'
10
9
  import PageLink from 'next/link'
11
10
  import React from 'react'
12
- import { CustomerTokenDocument, CustomerTokenQuery, useCustomerSession } from '../../hooks'
11
+ import { useCustomerSession, UseCustomerSessionReturn } from '../../hooks'
13
12
 
14
- type CustomerFabContentProps = CustomerTokenQuery & {
13
+ type CustomerFabContentProps = {
15
14
  icon?: React.ReactNode
16
15
  authHref: string
17
16
  guestHref: string
18
17
  FabProps?: Omit<FabPropsType, 'children'>
19
18
  sx?: SxProps<Theme>
19
+ session?: UseCustomerSessionReturn
20
20
  }
21
21
 
22
22
  const name = 'CustomerFab'
@@ -24,11 +24,10 @@ const parts = ['root'] as const
24
24
  const { classes } = extendableComponent(name, parts)
25
25
 
26
26
  function CustomerFabContent(props: CustomerFabContentProps) {
27
- const { customerToken, icon, guestHref, authHref, FabProps, sx } = props
28
- const { requireAuth } = useCustomerSession()
27
+ const { session, icon, guestHref, authHref, FabProps, sx } = props
29
28
 
30
29
  return (
31
- <PageLink href={requireAuth ? guestHref : authHref} passHref>
30
+ <PageLink href={session?.requireAuth ? guestHref : authHref} passHref>
32
31
  <Fab
33
32
  color='inherit'
34
33
  id='account'
@@ -39,8 +38,8 @@ function CustomerFabContent(props: CustomerFabContentProps) {
39
38
  sx={sx}
40
39
  >
41
40
  <DesktopHeaderBadge
42
- badgeContent={customerToken?.token ? 1 : 0}
43
- color={customerToken?.valid ? 'primary' : 'error'}
41
+ badgeContent={session?.token ? 1 : 0}
42
+ color={session?.valid ? 'primary' : 'error'}
44
43
  variant='dot'
45
44
  overlap='circular'
46
45
  >
@@ -51,12 +50,14 @@ function CustomerFabContent(props: CustomerFabContentProps) {
51
50
  )
52
51
  }
53
52
 
54
- export function CustomerFab(props: CustomerFabContentProps) {
55
- const { data } = useQuery(CustomerTokenDocument)
53
+ export type CustomerFabProps = Omit<CustomerFabContentProps, 'session'>
54
+
55
+ export function CustomerFab(props: CustomerFabProps) {
56
+ const session = useCustomerSession()
56
57
 
57
58
  return (
58
59
  <NoSsr fallback={<CustomerFabContent {...props} />}>
59
- <CustomerFabContent customerToken={data?.customerToken} {...props} />
60
+ <CustomerFabContent session={session} {...props} />
60
61
  </NoSsr>
61
62
  )
62
63
  }
@@ -1,35 +1,34 @@
1
- import { useQuery } from '@graphcommerce/graphql'
2
1
  import { MenuFabSecondaryItem, iconPerson, IconSvg } from '@graphcommerce/next-ui'
3
2
  import { Badge, NoSsr, SxProps, Theme } from '@mui/material'
4
3
  import React from 'react'
5
- import { CustomerTokenDocument, CustomerTokenQuery } from '../../hooks'
4
+ import { useCustomerSession, UseCustomerSessionReturn } from '../../hooks/useCustomerSession'
6
5
 
7
- type CustomerMenuFabItemProps = CustomerTokenQuery & {
6
+ type CustomerMenuFabItemProps = {
8
7
  icon?: React.ReactNode
9
8
  children: React.ReactNode
10
9
  authHref: string
11
10
  guestHref: string
12
11
  sx?: SxProps<Theme>
12
+ session?: UseCustomerSessionReturn
13
13
  }
14
14
 
15
15
  function CustomerMenuFabItemContent(props: CustomerMenuFabItemProps) {
16
- const { customerToken, icon, children, guestHref, authHref, sx = [] } = props
17
- const requireAuth = Boolean(!customerToken || !customerToken.valid)
16
+ const { session, icon, children, guestHref, authHref, sx = [] } = props
18
17
 
19
18
  return (
20
19
  <MenuFabSecondaryItem
21
20
  sx={sx}
22
21
  icon={
23
22
  <Badge
24
- badgeContent={customerToken?.token ? 1 : 0}
25
- color={customerToken?.valid ? 'primary' : 'error'}
23
+ badgeContent={session?.token ? 1 : 0}
24
+ color={session?.valid ? 'primary' : 'error'}
26
25
  variant='dot'
27
26
  overlap='circular'
28
27
  >
29
28
  {icon ?? <IconSvg src={iconPerson} size='medium' />}
30
29
  </Badge>
31
30
  }
32
- href={requireAuth ? guestHref : authHref}
31
+ href={session?.requireAuth ? guestHref : authHref}
33
32
  >
34
33
  {children}
35
34
  </MenuFabSecondaryItem>
@@ -37,11 +36,11 @@ function CustomerMenuFabItemContent(props: CustomerMenuFabItemProps) {
37
36
  }
38
37
 
39
38
  export function CustomerMenuFabItem(props: CustomerMenuFabItemProps) {
40
- const { data } = useQuery(CustomerTokenDocument)
39
+ const session = useCustomerSession()
41
40
 
42
41
  return (
43
42
  <NoSsr fallback={<CustomerMenuFabItemContent {...props} />}>
44
- <CustomerMenuFabItemContent customerToken={data?.customerToken} {...props} />
43
+ <CustomerMenuFabItemContent session={session} {...props} />
45
44
  </NoSsr>
46
45
  )
47
46
  }
@@ -13,13 +13,7 @@ export function SignInForm(props: SignInFormProps) {
13
13
  const { email, sx } = props
14
14
  const form = useFormGqlMutation(
15
15
  SignInDocument,
16
- {
17
- defaultValues: { email },
18
- onBeforeSubmit: (values) => ({
19
- ...values,
20
- email,
21
- }),
22
- },
16
+ { defaultValues: { email }, onBeforeSubmit: (values) => ({ ...values, email }) },
23
17
  { errorPolicy: 'all' },
24
18
  )
25
19
 
@@ -14,7 +14,7 @@ export function SignInFormInline(props: PropsWithChildren<InlineSignInFormProps>
14
14
  const { email, sx = [] } = props
15
15
  const form = useFormGqlMutation(
16
16
  SignInDocument,
17
- { defaultValues: { email } },
17
+ { defaultValues: { email }, onBeforeSubmit: (values) => ({ ...values, email }) },
18
18
  { errorPolicy: 'all' },
19
19
  )
20
20
  const { muiRegister, handleSubmit, required, formState, error } = form
@@ -25,7 +25,11 @@ export function SignUpForm(props: SignUpFormProps) {
25
25
  const form = useFormGqlMutation<
26
26
  SignUpMutation,
27
27
  SignUpMutationVariables & { confirmPassword?: string }
28
- >(Mutation, { defaultValues: { email } }, { errorPolicy: 'all' })
28
+ >(
29
+ Mutation,
30
+ { defaultValues: { email }, onBeforeSubmit: (values) => ({ ...values, email }) },
31
+ { errorPolicy: 'all' },
32
+ )
29
33
 
30
34
  const { muiRegister, handleSubmit, required, watch, formState, error } = form
31
35
  const [remainingError, inputError] = graphqlErrorByCategory({ category: 'graphql-input', error })
@@ -40,7 +40,9 @@ export function SignUpFormInline({
40
40
  firstname: firstname ?? '-',
41
41
  lastname: lastname ?? '-',
42
42
  },
43
+ onBeforeSubmit: (values) => ({ ...values, email }),
43
44
  })
45
+
44
46
  const { muiRegister, watch, handleSubmit, required, formState, error } = form
45
47
  const submitHandler = handleSubmit(onSubmitted)
46
48
  const watchPassword = watch('password')
package/hooks/index.ts CHANGED
@@ -2,7 +2,8 @@ export * from './Customer.gql'
2
2
  export * from './CustomerInfo.gql'
3
3
  export * from './CustomerToken.gql'
4
4
  export * from './IsEmailAvailable.gql'
5
- export * from './useExtractCustomerErrors'
6
- export * from './useFormIsEmailAvailable'
7
5
  export * from './useCustomerQuery'
8
6
  export * from './useCustomerSession'
7
+ export * from './useExtractCustomerErrors'
8
+ export * from './useFormIsEmailAvailable'
9
+ export * from './useGuestQuery'
@@ -1,15 +1,15 @@
1
1
  import { useQuery } from '@graphcommerce/graphql'
2
- import { CustomerTokenDocument } from './CustomerToken.gql'
3
- import { CustomerTokenFragment } from './CustomerTokenFragment.gql'
2
+ import { CustomerTokenDocument, CustomerTokenQuery } from './CustomerToken.gql'
4
3
 
5
- export type UseCustomerTokenReturn =
6
- | (CustomerTokenFragment & {
4
+ type TokenResponse = Omit<NonNullable<CustomerTokenQuery['customerToken']>, '__typename'>
5
+
6
+ export type UseCustomerSessionReturn =
7
+ | TokenResponse & {
7
8
  loggedIn: boolean
8
9
  requireAuth: boolean
9
- })
10
- | (Partial<CustomerTokenFragment> & { loggedIn: false; requireAuth: true })
10
+ }
11
11
 
12
- export function useCustomerSession(): UseCustomerTokenReturn {
12
+ export function useCustomerSession(): UseCustomerSessionReturn {
13
13
  const token = useQuery(CustomerTokenDocument, { ssr: false, fetchPolicy: 'cache-only' }).data
14
14
  ?.customerToken
15
15
 
@@ -1,10 +1,9 @@
1
- import { useQuery } from '@graphcommerce/graphql'
2
1
  import { useFormAutoSubmit, useFormGqlQuery, useFormPersist } from '@graphcommerce/react-hook-form'
3
2
  import { useEffect, useState } from 'react'
4
3
  import { CustomerDocument } from './Customer.gql'
5
- import { CustomerTokenDocument } from './CustomerToken.gql'
6
4
  import { IsEmailAvailableDocument } from './IsEmailAvailable.gql'
7
5
  import { useCustomerQuery } from './useCustomerQuery'
6
+ import { useCustomerSession } from './useCustomerSession'
8
7
 
9
8
  export type UseFormIsEmailAvailableProps = {
10
9
  email?: string | null
@@ -13,7 +12,7 @@ export type UseFormIsEmailAvailableProps = {
13
12
 
14
13
  export function useFormIsEmailAvailable(props: UseFormIsEmailAvailableProps) {
15
14
  const { email, onSubmitted } = props
16
- const { data: token } = useQuery(CustomerTokenDocument)
15
+ const { loggedIn, requireAuth } = useCustomerSession()
17
16
  const customerQuery = useCustomerQuery(CustomerDocument)
18
17
 
19
18
  const form = useFormGqlQuery(
@@ -29,16 +28,14 @@ export function useFormIsEmailAvailable(props: UseFormIsEmailAvailableProps) {
29
28
  const hasAccount = data?.isEmailAvailable?.is_email_available === false
30
29
  const { isDirty, isSubmitSuccessful, isSubmitted, isSubmitting, isValid } = formState
31
30
 
32
- const isLoggedIn = token?.customerToken && token?.customerToken.valid
33
-
34
31
  const [mode, setMode] = useState<'email' | 'signin' | 'signup' | 'signedin' | 'session-expired'>(
35
- token?.customerToken && token?.customerToken.valid ? 'signedin' : 'email',
32
+ loggedIn ? 'signedin' : 'email',
36
33
  )
37
34
 
38
35
  useFormPersist({ form, name: 'IsEmailAvailable' })
39
36
 
40
37
  useEffect(() => {
41
- if (isLoggedIn) {
38
+ if (loggedIn) {
42
39
  setMode('signedin')
43
40
  return
44
41
  }
@@ -47,19 +44,19 @@ export function useFormIsEmailAvailable(props: UseFormIsEmailAvailableProps) {
47
44
  if (!isDirty && isSubmitted && isSubmitSuccessful && isValid)
48
45
  setMode(hasAccount ? 'signin' : 'signup')
49
46
 
50
- if (customerQuery.data?.customer && token && token.customerToken && !token.customerToken.valid)
47
+ if (customerQuery.data?.customer && requireAuth)
51
48
  setMode(isSubmitSuccessful ? 'signin' : 'session-expired')
52
49
  }, [
53
50
  customerQuery.data?.customer,
54
51
  hasAccount,
55
52
  isDirty,
56
- isLoggedIn,
57
53
  isSubmitSuccessful,
58
54
  isSubmitted,
59
55
  isSubmitting,
60
56
  isValid,
61
- token,
57
+ loggedIn,
58
+ requireAuth,
62
59
  ])
63
60
 
64
- return { mode, form, token, submit, autoSubmitting, hasAccount }
61
+ return { mode, form, submit, autoSubmitting, hasAccount }
65
62
  }
@@ -0,0 +1,11 @@
1
+ import { useQuery, TypedDocumentNode, QueryHookOptions } from '@graphcommerce/graphql'
2
+ import { useCustomerSession } from './useCustomerSession'
3
+
4
+ /** Will only execute when the customer is not signed in. */
5
+ export function useGuestQuery<Q, V>(
6
+ document: TypedDocumentNode<Q, V>,
7
+ queryOptions: QueryHookOptions<Q, V> = {},
8
+ ) {
9
+ const { token } = useCustomerSession()
10
+ return useQuery(document, { ...queryOptions, ssr: false, skip: !!token })
11
+ }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@graphcommerce/magento-customer",
3
3
  "homepage": "https://www.graphcommerce.org/",
4
4
  "repository": "github:graphcommerce-org/graphcommerce",
5
- "version": "4.3.0",
5
+ "version": "4.4.0",
6
6
  "sideEffects": false,
7
7
  "prettier": "@graphcommerce/prettier-config-pwa",
8
8
  "eslintConfig": {
@@ -18,13 +18,13 @@
18
18
  "@playwright/test": "^1.21.1"
19
19
  },
20
20
  "dependencies": {
21
- "@graphcommerce/ecommerce-ui": "1.0.12",
21
+ "@graphcommerce/ecommerce-ui": "1.0.14",
22
22
  "@graphcommerce/graphql": "3.1.3",
23
23
  "@graphcommerce/graphql-mesh": "4.1.3",
24
- "@graphcommerce/image": "3.1.5",
24
+ "@graphcommerce/image": "3.1.6",
25
25
  "@graphcommerce/magento-graphql": "3.0.12",
26
- "@graphcommerce/magento-store": "4.2.4",
27
- "@graphcommerce/next-ui": "4.8.0",
26
+ "@graphcommerce/magento-store": "4.2.6",
27
+ "@graphcommerce/next-ui": "4.8.2",
28
28
  "@graphcommerce/react-hook-form": "3.1.3"
29
29
  },
30
30
  "peerDependencies": {