@graphcommerce/magento-customer 4.8.3 → 4.9.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 +22 -0
- package/components/WaitForCustomer/WaitForCustomer.tsx +76 -0
- package/hooks/useCustomerQuery.ts +2 -2
- package/hooks/useCustomerSession.ts +17 -13
- package/hooks/useFormIsEmailAvailable.tsx +2 -2
- package/hooks/useGuestQuery.ts +2 -2
- package/link/onAuthenticationError.ts +1 -0
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,27 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 4.9.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#1572](https://github.com/graphcommerce-org/graphcommerce/pull/1572) [`8e3b24500`](https://github.com/graphcommerce-org/graphcommerce/commit/8e3b24500a55fa2a1fb4a3ef08c1f1990a46a0ae) Thanks [@paales](https://github.com/paales)! - Added an WaitForCustomer component to allow for easy wrapping of pages and handle loading of queries, handle errors and make sure the customer is logged in.
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- [#1572](https://github.com/graphcommerce-org/graphcommerce/pull/1572) [`3c809a3a4`](https://github.com/graphcommerce-org/graphcommerce/commit/3c809a3a438995503f6d2290d6c0bb90fbc489be) Thanks [@paales](https://github.com/paales)! - Make sure the useCustomerSession returns the full query so it can be awaited
|
|
12
|
+
|
|
13
|
+
* [#1572](https://github.com/graphcommerce-org/graphcommerce/pull/1572) [`2c66cca15`](https://github.com/graphcommerce-org/graphcommerce/commit/2c66cca154098a09445977428983e05fe19b9510) Thanks [@paales](https://github.com/paales)! - useGuestQuery also should accept the hydration prop to allow it to return earlier
|
|
14
|
+
|
|
15
|
+
- [#1572](https://github.com/graphcommerce-org/graphcommerce/pull/1572) [`2c66cca15`](https://github.com/graphcommerce-org/graphcommerce/commit/2c66cca154098a09445977428983e05fe19b9510) Thanks [@paales](https://github.com/paales)! - useFormIsEmailAvailable now always checks if the email is available to prevent issues with it returning the wrong value.
|
|
16
|
+
|
|
17
|
+
* [#1572](https://github.com/graphcommerce-org/graphcommerce/pull/1572) [`2c66cca15`](https://github.com/graphcommerce-org/graphcommerce/commit/2c66cca154098a09445977428983e05fe19b9510) Thanks [@paales](https://github.com/paales)! - When an authentication error occurs, remove the invalid token from the storage.
|
|
18
|
+
|
|
19
|
+
* Updated dependencies [[`02023d8d8`](https://github.com/graphcommerce-org/graphcommerce/commit/02023d8d89c8138144243edce67290bd79ff49a7), [`87a188d6f`](https://github.com/graphcommerce-org/graphcommerce/commit/87a188d6f216b7f7b9ec95afbe74f1146cb07ce4), [`199dc8599`](https://github.com/graphcommerce-org/graphcommerce/commit/199dc859989c376281243b59a59addc35138f119), [`1eb131766`](https://github.com/graphcommerce-org/graphcommerce/commit/1eb131766c32db6fcb0a8e83dba2c3d241658595)]:
|
|
20
|
+
- @graphcommerce/react-hook-form@3.3.2
|
|
21
|
+
- @graphcommerce/next-ui@4.16.0
|
|
22
|
+
- @graphcommerce/ecommerce-ui@1.1.7
|
|
23
|
+
- @graphcommerce/magento-store@4.2.22
|
|
24
|
+
|
|
3
25
|
## 4.8.3
|
|
4
26
|
|
|
5
27
|
### Patch Changes
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { mergeErrors, WaitForQueries, WaitForQueriesProps } from '@graphcommerce/ecommerce-ui'
|
|
2
|
+
import { FullPageMessage, IconSvg, iconPerson } from '@graphcommerce/next-ui'
|
|
3
|
+
import { Trans } from '@lingui/react'
|
|
4
|
+
import { Button, CircularProgress } from '@mui/material'
|
|
5
|
+
import PageLink from 'next/link'
|
|
6
|
+
import { useCustomerSession } from '../../hooks/useCustomerSession'
|
|
7
|
+
import { ApolloCustomerErrorFullPage } from '../ApolloCustomerError/ApolloCustomerErrorFullPage'
|
|
8
|
+
|
|
9
|
+
type WaitForCustomerProps = Omit<WaitForQueriesProps, 'fallback' | 'waitFor'> & {
|
|
10
|
+
waitFor?: WaitForQueriesProps['waitFor']
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function nonNullable<T>(value: T): value is NonNullable<T> {
|
|
14
|
+
return value !== null && value !== undefined
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* A full page wrapper to render customer specific information.
|
|
19
|
+
*
|
|
20
|
+
* - Shows a loading spinner during: SSR, Hydration and Query Loading.
|
|
21
|
+
* - Will show a login message if the customer isn't logged in.
|
|
22
|
+
* - Will show an error message for any query that has that are passed.
|
|
23
|
+
* - Will show the contents if none of the above matches.
|
|
24
|
+
*
|
|
25
|
+
* ```tsx
|
|
26
|
+
* import { useQuery } from '@graphcommerce/graphql'
|
|
27
|
+
* import { WaitForCustomer } from '@graphcommerce/magento-customer'
|
|
28
|
+
*
|
|
29
|
+
* function MyComponent() {
|
|
30
|
+
* const optionalAdditionalQuery = useQuery(MyQueryDocument)
|
|
31
|
+
* return (
|
|
32
|
+
* <WaitForCustomer waitFor={optionalAdditionalQuery}>
|
|
33
|
+
* Customer logged in and {optionalAdditionalQuery.data.myField} data available
|
|
34
|
+
* </WaitForCustomer>
|
|
35
|
+
* )
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export function WaitForCustomer(props: WaitForCustomerProps) {
|
|
40
|
+
const { waitFor = [], children } = props
|
|
41
|
+
|
|
42
|
+
const session = useCustomerSession()
|
|
43
|
+
const queries = Array.isArray(waitFor) ? waitFor : [waitFor]
|
|
44
|
+
const error = mergeErrors(queries.map((query) => query.error).filter(nonNullable))
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<WaitForQueries
|
|
48
|
+
waitFor={!session.loggedIn ? session.query : queries}
|
|
49
|
+
fallback={
|
|
50
|
+
<FullPageMessage icon={<CircularProgress />} title={<Trans id='Loading your data' />}>
|
|
51
|
+
<Trans id='This may take a second' />
|
|
52
|
+
</FullPageMessage>
|
|
53
|
+
}
|
|
54
|
+
>
|
|
55
|
+
{!session.loggedIn && (
|
|
56
|
+
<FullPageMessage
|
|
57
|
+
icon={<IconSvg src={iconPerson} size='xxl' />}
|
|
58
|
+
title={<Trans id='You must sign in to continue' />}
|
|
59
|
+
button={
|
|
60
|
+
<PageLink href='/account/signin' passHref>
|
|
61
|
+
<Button variant='contained' color='secondary' size='large'>
|
|
62
|
+
{!session.valid ? (
|
|
63
|
+
<Trans id='Sign in' />
|
|
64
|
+
) : (
|
|
65
|
+
<Trans id='Sign in or create an account!' />
|
|
66
|
+
)}
|
|
67
|
+
</Button>
|
|
68
|
+
</PageLink>
|
|
69
|
+
}
|
|
70
|
+
/>
|
|
71
|
+
)}
|
|
72
|
+
{session.loggedIn && error && <ApolloCustomerErrorFullPage error={error} />}
|
|
73
|
+
{session.loggedIn && !error && children}
|
|
74
|
+
</WaitForQueries>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
@@ -22,7 +22,7 @@ export function useCustomerQuery<Q, V>(
|
|
|
22
22
|
options: QueryHookOptions<Q, V> & { hydration?: boolean } = {},
|
|
23
23
|
): QueryResult<Q, V> {
|
|
24
24
|
const { hydration, ...queryOptions } = options
|
|
25
|
-
const { loggedIn,
|
|
25
|
+
const { loggedIn, query } = useCustomerSession({ hydration })
|
|
26
26
|
|
|
27
27
|
const result = useQuery(document, {
|
|
28
28
|
...queryOptions,
|
|
@@ -32,6 +32,6 @@ export function useCustomerQuery<Q, V>(
|
|
|
32
32
|
|
|
33
33
|
return {
|
|
34
34
|
...result,
|
|
35
|
-
error: called && !loggedIn ? notLoggedInError : result.error,
|
|
35
|
+
error: query.called && !loggedIn ? notLoggedInError : result.error,
|
|
36
36
|
}
|
|
37
37
|
}
|
|
@@ -1,35 +1,39 @@
|
|
|
1
1
|
import { useIsomorphicLayoutEffect } from '@graphcommerce/framer-utils'
|
|
2
|
-
import { useQuery } from '@graphcommerce/graphql'
|
|
2
|
+
import { QueryResult, useQuery } from '@graphcommerce/graphql'
|
|
3
3
|
import { startTransition, useState } from 'react'
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
CustomerTokenDocument,
|
|
6
|
+
CustomerTokenQuery,
|
|
7
|
+
CustomerTokenQueryVariables,
|
|
8
|
+
} from './CustomerToken.gql'
|
|
5
9
|
|
|
6
10
|
export type UseCustomerSessionOptions = { hydration?: boolean }
|
|
7
11
|
|
|
8
12
|
export type UseCustomerSessionReturn =
|
|
9
|
-
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
| {
|
|
14
|
+
loggedIn: boolean
|
|
15
|
+
requireAuth: boolean
|
|
16
|
+
query: QueryResult<CustomerTokenQuery, CustomerTokenQueryVariables>
|
|
17
|
+
} & Partial<Omit<NonNullable<CustomerTokenQuery['customerToken']>, '__typename'>>
|
|
14
18
|
|
|
15
19
|
export function useCustomerSession(
|
|
16
20
|
options: UseCustomerSessionOptions = {},
|
|
17
21
|
): UseCustomerSessionReturn {
|
|
18
|
-
const { hydration =
|
|
22
|
+
const { hydration = true } = options
|
|
19
23
|
const [hydrating, setHydrating] = useState(!hydration)
|
|
24
|
+
|
|
20
25
|
useIsomorphicLayoutEffect(() => startTransition(() => setHydrating(false)), [])
|
|
21
|
-
const skip = hydrating
|
|
22
26
|
|
|
23
|
-
const
|
|
27
|
+
const skip = hydrating
|
|
24
28
|
|
|
25
|
-
const
|
|
29
|
+
const query = useQuery(CustomerTokenDocument, { skip })
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
const token = query.data?.customerToken
|
|
28
32
|
|
|
29
33
|
return {
|
|
30
34
|
...token,
|
|
31
|
-
called,
|
|
32
35
|
loggedIn: Boolean(token?.token && token.valid),
|
|
33
36
|
requireAuth: Boolean(!token || !token.valid),
|
|
37
|
+
query,
|
|
34
38
|
}
|
|
35
39
|
}
|
|
@@ -12,13 +12,13 @@ export type UseFormIsEmailAvailableProps = {
|
|
|
12
12
|
|
|
13
13
|
export function useFormIsEmailAvailable(props: UseFormIsEmailAvailableProps) {
|
|
14
14
|
const { email, onSubmitted } = props
|
|
15
|
-
const { loggedIn, requireAuth } = useCustomerSession()
|
|
15
|
+
const { loggedIn, requireAuth } = useCustomerSession({ hydration: false })
|
|
16
16
|
const customerQuery = useCustomerQuery(CustomerDocument)
|
|
17
17
|
|
|
18
18
|
const form = useFormGqlQuery(
|
|
19
19
|
IsEmailAvailableDocument,
|
|
20
20
|
{ mode: 'onChange', defaultValues: { email: email ?? '' } },
|
|
21
|
-
|
|
21
|
+
{ fetchPolicy: 'cache-and-network' },
|
|
22
22
|
)
|
|
23
23
|
const { formState, data, handleSubmit } = form
|
|
24
24
|
|
package/hooks/useGuestQuery.ts
CHANGED
|
@@ -4,8 +4,8 @@ import { useCustomerSession } from './useCustomerSession'
|
|
|
4
4
|
/** Will only execute when the customer is not signed in. */
|
|
5
5
|
export function useGuestQuery<Q, V>(
|
|
6
6
|
document: TypedDocumentNode<Q, V>,
|
|
7
|
-
queryOptions: QueryHookOptions<Q, V> = {},
|
|
7
|
+
queryOptions: QueryHookOptions<Q, V> & { hydration?: boolean } = {},
|
|
8
8
|
) {
|
|
9
|
-
const { token } = useCustomerSession()
|
|
9
|
+
const { token } = useCustomerSession({ hydration: queryOptions.hydration })
|
|
10
10
|
return useQuery(document, { ...queryOptions, ssr: false, skip: !!token })
|
|
11
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.
|
|
5
|
+
"version": "4.9.0",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
8
8
|
"eslintConfig": {
|
|
@@ -19,15 +19,15 @@
|
|
|
19
19
|
"type-fest": "^2.12.2"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@graphcommerce/ecommerce-ui": "1.1.
|
|
22
|
+
"@graphcommerce/ecommerce-ui": "1.1.7",
|
|
23
23
|
"@graphcommerce/framer-utils": "3.1.4",
|
|
24
24
|
"@graphcommerce/graphql": "3.4.3",
|
|
25
25
|
"@graphcommerce/graphql-mesh": "4.1.6",
|
|
26
26
|
"@graphcommerce/image": "3.1.7",
|
|
27
27
|
"@graphcommerce/magento-graphql": "3.1.3",
|
|
28
|
-
"@graphcommerce/magento-store": "4.2.
|
|
29
|
-
"@graphcommerce/next-ui": "4.
|
|
30
|
-
"@graphcommerce/react-hook-form": "3.3.
|
|
28
|
+
"@graphcommerce/magento-store": "4.2.22",
|
|
29
|
+
"@graphcommerce/next-ui": "4.16.0",
|
|
30
|
+
"@graphcommerce/react-hook-form": "3.3.2"
|
|
31
31
|
},
|
|
32
32
|
"peerDependencies": {
|
|
33
33
|
"@lingui/react": "^3.13.2",
|