@graphcommerce/magento-customer 4.6.2 → 4.7.1
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 +38 -0
- package/components/AddressFields/AddressFields.tsx +1 -1
- package/components/ApolloCustomerError/ApolloCustomerErrorFullPage.tsx +2 -2
- package/components/ApolloCustomerError/useAuthorizationErrorMasked.ts +2 -2
- package/components/ChangePasswordForm/ChangePasswordForm.tsx +1 -1
- package/components/CreateCustomerAddressForm/CreateCustomerAddressForm.tsx +1 -1
- package/components/CustomerFab/CustomerFab.tsx +1 -1
- package/components/EditAddressForm/EditAddressForm.tsx +1 -1
- package/components/ForgotPasswordForm/ForgotPasswordForm.tsx +1 -1
- package/components/NameFields/NameFields.tsx +3 -3
- package/components/SignUpForm/SignUpForm.tsx +2 -2
- package/components/SignUpForm/SignUpFormInline.tsx +1 -1
- package/components/UpdateCustomerEmailForm/UpdateCustomerEmailForm.tsx +1 -1
- package/hooks/useCustomerQuery.ts +29 -4
- package/hooks/useCustomerSession.ts +20 -4
- package/link/createCustomerTokenLink.ts +2 -2
- package/link/onAuthenticationError.ts +2 -2
- package/package.json +10 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 4.7.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies [[`8d8fda262`](https://github.com/graphcommerce-org/graphcommerce/commit/8d8fda2623e561cb43441110c67ffa34b692668a), [`d41cff721`](https://github.com/graphcommerce-org/graphcommerce/commit/d41cff7211230561ceeb7786cf75790efd6377cd), [`cefa7b365`](https://github.com/graphcommerce-org/graphcommerce/commit/cefa7b3652b55108d2178927e3c5d98a111cf373)]:
|
|
8
|
+
- @graphcommerce/next-ui@4.13.0
|
|
9
|
+
- @graphcommerce/magento-store@4.2.16
|
|
10
|
+
- @graphcommerce/ecommerce-ui@1.1.1
|
|
11
|
+
|
|
12
|
+
## 4.7.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- [#1544](https://github.com/graphcommerce-org/graphcommerce/pull/1544) [`5f927ebdc`](https://github.com/graphcommerce-org/graphcommerce/commit/5f927ebdc6f0331833e02b96e4f169bfe475ac6b) Thanks [@mikekeehnen](https://github.com/mikekeehnen)! - Fixed hydration errors on account, cart and wishlist
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- [#1545](https://github.com/graphcommerce-org/graphcommerce/pull/1545) [`c87a28e7d`](https://github.com/graphcommerce-org/graphcommerce/commit/c87a28e7dad87bffd0bd125ad5fdca65aaa389cc) Thanks [@paales](https://github.com/paales)! - Faster hydration with useLayoutEffect
|
|
21
|
+
|
|
22
|
+
- Updated dependencies [[`5f927ebdc`](https://github.com/graphcommerce-org/graphcommerce/commit/5f927ebdc6f0331833e02b96e4f169bfe475ac6b), [`c756f42e5`](https://github.com/graphcommerce-org/graphcommerce/commit/c756f42e503761a497e4a5a7a02d02141df231c3)]:
|
|
23
|
+
- @graphcommerce/ecommerce-ui@1.1.0
|
|
24
|
+
- @graphcommerce/graphql@3.4.0
|
|
25
|
+
- @graphcommerce/magento-graphql@3.1.0
|
|
26
|
+
- @graphcommerce/react-hook-form@3.3.0
|
|
27
|
+
- @graphcommerce/next-ui@4.12.0
|
|
28
|
+
- @graphcommerce/magento-store@4.2.15
|
|
29
|
+
|
|
30
|
+
## 4.6.3
|
|
31
|
+
|
|
32
|
+
### Patch Changes
|
|
33
|
+
|
|
34
|
+
- [#1538](https://github.com/graphcommerce-org/graphcommerce/pull/1538) [`fe4baa42d`](https://github.com/graphcommerce-org/graphcommerce/commit/fe4baa42db0081ed960d62aef688bd36a7ac974f) Thanks [@paales](https://github.com/paales)! - add missing translations
|
|
35
|
+
|
|
36
|
+
- Updated dependencies [[`fe4baa42d`](https://github.com/graphcommerce-org/graphcommerce/commit/fe4baa42db0081ed960d62aef688bd36a7ac974f)]:
|
|
37
|
+
- @graphcommerce/next-ui@4.11.2
|
|
38
|
+
- @graphcommerce/ecommerce-ui@1.0.23
|
|
39
|
+
- @graphcommerce/magento-store@4.2.14
|
|
40
|
+
|
|
3
41
|
## 4.6.2
|
|
4
42
|
|
|
5
43
|
### Patch Changes
|
|
@@ -80,7 +80,7 @@ export function AddressFields(props: AddressFieldsProps) {
|
|
|
80
80
|
required: required?.houseNumber,
|
|
81
81
|
pattern: {
|
|
82
82
|
value: houseNumberPattern,
|
|
83
|
-
message: i18n._(/* i18n */
|
|
83
|
+
message: i18n._(/* i18n */ 'Please provide a valid house number'),
|
|
84
84
|
},
|
|
85
85
|
})}
|
|
86
86
|
helperText={formState.isSubmitted && formState.errors.houseNumber?.message}
|
|
@@ -16,7 +16,7 @@ export type ApolloCustomerErrorFullPageProps = {
|
|
|
16
16
|
|
|
17
17
|
export function ApolloCustomerErrorFullPage(props: ApolloCustomerErrorFullPageProps) {
|
|
18
18
|
const { error, icon, altButton, button, ...alertProps } = props
|
|
19
|
-
const [newError, unauthorized] = useAuthorizationErrorMasked()
|
|
19
|
+
const [newError, unauthorized] = useAuthorizationErrorMasked(error)
|
|
20
20
|
const { token } = useCustomerSession()
|
|
21
21
|
|
|
22
22
|
return (
|
|
@@ -28,7 +28,7 @@ export function ApolloCustomerErrorFullPage(props: ApolloCustomerErrorFullPagePr
|
|
|
28
28
|
unauthorized ? (
|
|
29
29
|
<PageLink href='/account/signin' passHref>
|
|
30
30
|
<Button variant='contained' color='primary' size='large'>
|
|
31
|
-
{token ? <Trans id='Sign in' /> : <Trans id='
|
|
31
|
+
{token ? <Trans id='Sign in' /> : <Trans id='Sign in or create an account!' />}
|
|
32
32
|
</Button>
|
|
33
33
|
</PageLink>
|
|
34
34
|
) : (
|
|
@@ -10,8 +10,8 @@ export function useAuthorizationErrorMasked(error?: ApolloError) {
|
|
|
10
10
|
category: 'graphql-authorization',
|
|
11
11
|
error,
|
|
12
12
|
mask: token
|
|
13
|
-
? i18n._(/* i18n */
|
|
14
|
-
: i18n._(/* i18n */
|
|
13
|
+
? i18n._(/* i18n */ 'Please reauthenticate and try again')
|
|
14
|
+
: i18n._(/* i18n */ 'You must sign in to continue'),
|
|
15
15
|
extract: false,
|
|
16
16
|
})
|
|
17
17
|
}
|
|
@@ -61,7 +61,7 @@ export function ChangePasswordForm() {
|
|
|
61
61
|
required
|
|
62
62
|
{...muiRegister('confirmPassword', {
|
|
63
63
|
required: true,
|
|
64
|
-
validate: (value) => value === pass || i18n._(/* i18n */
|
|
64
|
+
validate: (value) => value === pass || i18n._(/* i18n */ "Passwords don't match"),
|
|
65
65
|
})}
|
|
66
66
|
helperText={formState.errors.confirmPassword?.message}
|
|
67
67
|
disabled={formState.isSubmitting}
|
|
@@ -69,7 +69,7 @@ export function CreateCustomerAddressForm() {
|
|
|
69
69
|
label={<Trans id='Telephone' />}
|
|
70
70
|
{...muiRegister('telephone', {
|
|
71
71
|
required: required.telephone,
|
|
72
|
-
pattern: { value: phonePattern, message: i18n._(/* i18n */
|
|
72
|
+
pattern: { value: phonePattern, message: i18n._(/* i18n */ 'Invalid phone number') },
|
|
73
73
|
})}
|
|
74
74
|
helperText={formState.isSubmitted && formState.errors.telephone?.message}
|
|
75
75
|
disabled={formState.isSubmitting}
|
|
@@ -92,7 +92,7 @@ export function EditAddressForm(props: EditAddressFormProps) {
|
|
|
92
92
|
label={<Trans id='Telephone' />}
|
|
93
93
|
{...muiRegister('telephone', {
|
|
94
94
|
required: required.telephone,
|
|
95
|
-
pattern: { value: phonePattern, message: i18n._(/* i18n */
|
|
95
|
+
pattern: { value: phonePattern, message: i18n._(/* i18n */ 'Invalid phone number') },
|
|
96
96
|
})}
|
|
97
97
|
helperText={formState.isSubmitted && formState.errors.telephone?.message}
|
|
98
98
|
disabled={formState.isSubmitting}
|
|
@@ -44,7 +44,7 @@ export function ForgotPasswordForm(props: { sx?: SxProps<Theme> }) {
|
|
|
44
44
|
required={required.email}
|
|
45
45
|
{...muiRegister('email', {
|
|
46
46
|
required: required.email,
|
|
47
|
-
pattern: { value: emailPattern, message: i18n._(/* i18n */
|
|
47
|
+
pattern: { value: emailPattern, message: i18n._(/* i18n */ 'Invalid email address') },
|
|
48
48
|
})}
|
|
49
49
|
helperText={formState.errors.email?.message}
|
|
50
50
|
disabled={formState.isSubmitting}
|
|
@@ -20,9 +20,9 @@ type NameFieldProps = {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export function NameFields(props: NameFieldProps) {
|
|
23
|
-
const mr = i18n._(/* i18n */
|
|
24
|
-
const mrs = i18n._(/* i18n */
|
|
25
|
-
const other = i18n._(/* i18n */
|
|
23
|
+
const mr = i18n._(/* i18n */ 'Mr')
|
|
24
|
+
const mrs = i18n._(/* i18n */ 'Mrs')
|
|
25
|
+
const other = i18n._(/* i18n */ 'Other')
|
|
26
26
|
|
|
27
27
|
const { prefix, form, readOnly, prefixes = [mr, mrs, other] } = props
|
|
28
28
|
assertFormGqlOperation<NameFieldValues>(form)
|
|
@@ -62,7 +62,7 @@ export function SignUpForm(props: SignUpFormProps) {
|
|
|
62
62
|
required: required.password,
|
|
63
63
|
minLength: {
|
|
64
64
|
value: Number(storeConfig?.minimum_password_length ?? 8),
|
|
65
|
-
message: i18n._(/* i18n */
|
|
65
|
+
message: i18n._(/* i18n */ 'Password must have at least 8 characters'),
|
|
66
66
|
},
|
|
67
67
|
})}
|
|
68
68
|
helperText={formState.errors.password?.message || inputError?.message}
|
|
@@ -78,7 +78,7 @@ export function SignUpForm(props: SignUpFormProps) {
|
|
|
78
78
|
{...muiRegister('confirmPassword', {
|
|
79
79
|
required: true,
|
|
80
80
|
validate: (value) =>
|
|
81
|
-
value === watchPassword || i18n._(/* i18n */
|
|
81
|
+
value === watchPassword || i18n._(/* i18n */ "Passwords don't match"),
|
|
82
82
|
})}
|
|
83
83
|
helperText={formState.errors.confirmPassword?.message}
|
|
84
84
|
disabled={formState.isSubmitting}
|
|
@@ -67,7 +67,7 @@ export function SignUpFormInline({
|
|
|
67
67
|
required: required.password,
|
|
68
68
|
minLength: {
|
|
69
69
|
value: minPasswordLength,
|
|
70
|
-
message: i18n._(/* i18n */
|
|
70
|
+
message: i18n._(/* i18n */ 'Password must have at least 8 characters'),
|
|
71
71
|
},
|
|
72
72
|
})}
|
|
73
73
|
helperText={error?.message}
|
|
@@ -90,7 +90,7 @@ export function UpdateCustomerEmailForm(props: UpdateCustomerEmailFormProps) {
|
|
|
90
90
|
required
|
|
91
91
|
{...muiRegister('confirmEmail', {
|
|
92
92
|
required: true,
|
|
93
|
-
validate: (value) => value === watchNewEmail || i18n._(/* i18n */
|
|
93
|
+
validate: (value) => value === watchNewEmail || i18n._(/* i18n */ "Emails don't match"),
|
|
94
94
|
})}
|
|
95
95
|
/>
|
|
96
96
|
</FormRow>
|
|
@@ -1,11 +1,36 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
useQuery,
|
|
3
|
+
TypedDocumentNode,
|
|
4
|
+
QueryHookOptions,
|
|
5
|
+
QueryResult,
|
|
6
|
+
ApolloError,
|
|
7
|
+
} from '@graphcommerce/graphql'
|
|
8
|
+
import { GraphQLError } from 'graphql'
|
|
2
9
|
import { useCustomerSession } from './useCustomerSession'
|
|
3
10
|
|
|
11
|
+
const notLoggedInError = new ApolloError({
|
|
12
|
+
graphQLErrors: [
|
|
13
|
+
new GraphQLError('Not authorized', {
|
|
14
|
+
extensions: { category: 'graphql-authorization' },
|
|
15
|
+
}),
|
|
16
|
+
],
|
|
17
|
+
})
|
|
18
|
+
|
|
4
19
|
/** Will only execute when the customer is signed in. */
|
|
5
20
|
export function useCustomerQuery<Q, V>(
|
|
6
21
|
document: TypedDocumentNode<Q, V>,
|
|
7
22
|
queryOptions: QueryHookOptions<Q, V> = {},
|
|
8
|
-
) {
|
|
9
|
-
const { loggedIn } = useCustomerSession()
|
|
10
|
-
|
|
23
|
+
): QueryResult<Q, V> {
|
|
24
|
+
const { loggedIn, called } = useCustomerSession()
|
|
25
|
+
|
|
26
|
+
const result = useQuery(document, {
|
|
27
|
+
...queryOptions,
|
|
28
|
+
ssr: false,
|
|
29
|
+
skip: !loggedIn,
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
...result,
|
|
34
|
+
error: called && !loggedIn ? notLoggedInError : result.error,
|
|
35
|
+
}
|
|
11
36
|
}
|
|
@@ -1,19 +1,35 @@
|
|
|
1
|
+
import { useIsomorphicLayoutEffect } from '@graphcommerce/framer-utils'
|
|
1
2
|
import { useQuery } from '@graphcommerce/graphql'
|
|
3
|
+
import { useState } from 'react'
|
|
2
4
|
import { CustomerTokenDocument, CustomerTokenQuery } from './CustomerToken.gql'
|
|
3
5
|
|
|
4
|
-
type TokenResponse = Omit<NonNullable<CustomerTokenQuery['customerToken']>, '__typename'>
|
|
6
|
+
type TokenResponse = Omit<NonNullable<CustomerTokenQuery['customerToken']>, '__typename'> & {
|
|
7
|
+
called: boolean
|
|
8
|
+
}
|
|
5
9
|
|
|
6
10
|
export type UseCustomerSessionReturn =
|
|
7
11
|
| Partial<TokenResponse> & { loggedIn: boolean; requireAuth: boolean }
|
|
8
12
|
|
|
9
13
|
export function useCustomerSession(): UseCustomerSessionReturn {
|
|
10
|
-
const
|
|
11
|
-
|
|
14
|
+
const [skip, setSkip] = useState(true)
|
|
15
|
+
|
|
16
|
+
const { called, data } = useQuery(CustomerTokenDocument, {
|
|
17
|
+
ssr: false,
|
|
18
|
+
fetchPolicy: 'cache-only',
|
|
19
|
+
skip,
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
const token = data?.customerToken
|
|
23
|
+
|
|
24
|
+
useIsomorphicLayoutEffect(() => {
|
|
25
|
+
if (skip) setSkip(false)
|
|
26
|
+
}, [skip])
|
|
12
27
|
|
|
13
|
-
if (!token) return { loggedIn: false, requireAuth: true }
|
|
28
|
+
if (!token) return { called, loggedIn: false, requireAuth: true }
|
|
14
29
|
|
|
15
30
|
return {
|
|
16
31
|
...token,
|
|
32
|
+
called,
|
|
17
33
|
loggedIn: Boolean(token?.token && token.valid),
|
|
18
34
|
requireAuth: Boolean(!token || !token.valid),
|
|
19
35
|
}
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
setContext,
|
|
7
7
|
} from '@graphcommerce/graphql'
|
|
8
8
|
import { CustomerTokenDocument } from '../hooks'
|
|
9
|
-
import {
|
|
9
|
+
import { onAuthorizationError } from './onAuthenticationError'
|
|
10
10
|
|
|
11
11
|
export const addTokenHeader = setContext((_, context: ClientContext) => {
|
|
12
12
|
if (!context.headers) context.headers = {}
|
|
@@ -22,7 +22,7 @@ export const addTokenHeader = setContext((_, context: ClientContext) => {
|
|
|
22
22
|
}
|
|
23
23
|
})
|
|
24
24
|
|
|
25
|
-
export const customerTokenLink = ApolloLink.from([addTokenHeader,
|
|
25
|
+
export const customerTokenLink = ApolloLink.from([addTokenHeader, onAuthorizationError])
|
|
26
26
|
|
|
27
27
|
/** Not really required anymore, you can use customerTokenLink directly */
|
|
28
28
|
export const createCustomerTokenLink = (_: ApolloCache<NormalizedCacheObject>) => customerTokenLink
|
|
@@ -22,14 +22,14 @@ function invalidateToken(cache: InMemoryCache) {
|
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export const
|
|
25
|
+
export const onAuthorizationError = onError(({ graphQLErrors, operation }) => {
|
|
26
26
|
const { cache } = operation.getContext()
|
|
27
27
|
if (graphQLErrors) {
|
|
28
28
|
for (const err of graphQLErrors) {
|
|
29
29
|
if (err.extensions?.category === 'graphql-authorization') {
|
|
30
30
|
// Modify the operation context with a new token
|
|
31
31
|
invalidateToken(cache as InMemoryCache)
|
|
32
|
-
break
|
|
32
|
+
break
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
35
|
}
|
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.7.1",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
8
8
|
"eslintConfig": {
|
|
@@ -19,14 +19,15 @@
|
|
|
19
19
|
"type-fest": "^2.12.2"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@graphcommerce/ecommerce-ui": "1.
|
|
23
|
-
"@graphcommerce/
|
|
22
|
+
"@graphcommerce/ecommerce-ui": "1.1.1",
|
|
23
|
+
"@graphcommerce/framer-utils": "3.1.4",
|
|
24
|
+
"@graphcommerce/graphql": "3.4.0",
|
|
24
25
|
"@graphcommerce/graphql-mesh": "4.1.4",
|
|
25
26
|
"@graphcommerce/image": "3.1.7",
|
|
26
|
-
"@graphcommerce/magento-graphql": "3.0
|
|
27
|
-
"@graphcommerce/magento-store": "4.2.
|
|
28
|
-
"@graphcommerce/next-ui": "4.
|
|
29
|
-
"@graphcommerce/react-hook-form": "3.
|
|
27
|
+
"@graphcommerce/magento-graphql": "3.1.0",
|
|
28
|
+
"@graphcommerce/magento-store": "4.2.16",
|
|
29
|
+
"@graphcommerce/next-ui": "4.13.0",
|
|
30
|
+
"@graphcommerce/react-hook-form": "3.3.0"
|
|
30
31
|
},
|
|
31
32
|
"peerDependencies": {
|
|
32
33
|
"@lingui/react": "^3.13.2",
|
|
@@ -35,6 +36,7 @@
|
|
|
35
36
|
"framer-motion": "^6.2.4",
|
|
36
37
|
"next": "^12.1.2",
|
|
37
38
|
"react": "^18.0.0",
|
|
38
|
-
"react-dom": "^18.0.0"
|
|
39
|
+
"react-dom": "^18.0.0",
|
|
40
|
+
"graphql": "16.5.0"
|
|
39
41
|
}
|
|
40
42
|
}
|