@graphcommerce/magento-customer 10.0.0-canary.68 → 10.0.0-canary.72
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 +12 -0
- package/components/ApolloCustomerError/useAuthorizationErrorMasked.ts +2 -2
- package/components/ContactForm/ContactForm.tsx +29 -26
- package/components/CustomerForms/useCustomerCreateForm.ts +2 -2
- package/components/CustomerForms/useCustomerUpdateForm.ts +2 -2
- package/components/SignOutForm/signOut.ts +1 -1
- package/hooks/useCustomerQuery.ts +10 -9
- package/hooks/useCustomerSession.ts +1 -2
- package/hooks/useGuestQuery.ts +8 -7
- package/link/customerLink.ts +40 -31
- package/link/xMagentoCacheIdHeader.ts +22 -19
- package/package.json +15 -15
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Change Log
|
|
2
2
|
|
|
3
|
+
## 10.0.0-canary.72
|
|
4
|
+
|
|
5
|
+
## 10.0.0-canary.71
|
|
6
|
+
|
|
7
|
+
## 10.0.0-canary.70
|
|
8
|
+
|
|
9
|
+
### Major Changes
|
|
10
|
+
|
|
11
|
+
- [#2565](https://github.com/graphcommerce-org/graphcommerce/pull/2565) [`c96dfcd`](https://github.com/graphcommerce-org/graphcommerce/commit/c96dfcdca981baca387c270ad9e2b9515cdd00cc) - Updated to Apollo Client 4 ([@paales](https://github.com/paales))
|
|
12
|
+
|
|
13
|
+
## 10.0.0-canary.69
|
|
14
|
+
|
|
3
15
|
## 10.0.0-canary.68
|
|
4
16
|
|
|
5
17
|
### Major Changes
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { ApolloError } from '@graphcommerce/graphql'
|
|
2
1
|
import { graphqlErrorByCategory } from '@graphcommerce/magento-graphql'
|
|
2
|
+
import type { ErrorLike } from '@apollo/client'
|
|
3
3
|
import { t } from '@lingui/core/macro'
|
|
4
4
|
import { useCustomerSession } from '../../hooks/useCustomerSession'
|
|
5
5
|
|
|
6
|
-
export function useAuthorizationErrorMasked(error?:
|
|
6
|
+
export function useAuthorizationErrorMasked(error?: ErrorLike | null) {
|
|
7
7
|
const { token } = useCustomerSession()
|
|
8
8
|
|
|
9
9
|
return graphqlErrorByCategory({
|
|
@@ -7,12 +7,13 @@ import {
|
|
|
7
7
|
import { Button, Form, FormRow, MessageSnackbar } from '@graphcommerce/next-ui'
|
|
8
8
|
import { FormPersist, useFormGqlMutation } from '@graphcommerce/react-hook-form'
|
|
9
9
|
import { Trans } from '@lingui/react/macro'
|
|
10
|
+
import { useEffect } from 'react'
|
|
10
11
|
import type { CustomerQuery } from '../../hooks'
|
|
11
12
|
import { CustomerDocument, useCustomerQuery } from '../../hooks'
|
|
12
13
|
import type { ContactUsMutationVariables } from './ContactUsMutation.gql'
|
|
13
14
|
import { ContactUsDocument } from './ContactUsMutation.gql'
|
|
14
15
|
|
|
15
|
-
function findTelephone(data: CustomerQuery): string | undefined {
|
|
16
|
+
function findTelephone(data: Partial<CustomerQuery>): string | undefined {
|
|
16
17
|
const { customer } = data
|
|
17
18
|
if (!customer) return undefined
|
|
18
19
|
|
|
@@ -48,31 +49,33 @@ export function ContactForm() {
|
|
|
48
49
|
|
|
49
50
|
const { control, formState, error, handleSubmit, setValue, getValues } = form
|
|
50
51
|
|
|
51
|
-
useCustomerQuery(CustomerDocument
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
52
|
+
const customerQuery = useCustomerQuery(CustomerDocument)
|
|
53
|
+
|
|
54
|
+
// Handle customer data when it's loaded
|
|
55
|
+
useEffect(() => {
|
|
56
|
+
const data = customerQuery.data
|
|
57
|
+
if (!data?.customer) return
|
|
58
|
+
|
|
59
|
+
const telephone = findTelephone(data)
|
|
60
|
+
|
|
61
|
+
if (!getValues('input.telephone') && telephone) {
|
|
62
|
+
setValue('input.telephone', telephone)
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!getValues('input.email') && data.customer?.email) {
|
|
66
|
+
setValue('input.email', data.customer?.email)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (!getValues('input.name') && data.customer) {
|
|
70
|
+
setValue(
|
|
71
|
+
'input.name',
|
|
72
|
+
`${data.customer?.firstname ?? ''} ${data.customer?.middlename ?? ''} ${data.customer?.lastname ?? ''}`.replaceAll(
|
|
73
|
+
' ',
|
|
74
|
+
' ',
|
|
75
|
+
),
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
}, [customerQuery.data, getValues, setValue])
|
|
76
79
|
|
|
77
80
|
const submit = handleSubmit(() => {})
|
|
78
81
|
|
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
type UseAttributesFormConfig,
|
|
7
7
|
} from '@graphcommerce/magento-store'
|
|
8
8
|
import { useFormGqlMutation, type UseFormGraphQlOptions } from '@graphcommerce/react-hook-form'
|
|
9
|
-
import type {
|
|
9
|
+
import type { useMutation } from '@apollo/client/react'
|
|
10
10
|
import {
|
|
11
11
|
UseCustomerCreateFormDocument,
|
|
12
12
|
type UseCustomerCreateFormMutation,
|
|
@@ -46,7 +46,7 @@ export function useCustomerCreateForm(
|
|
|
46
46
|
UseCustomerCreateFormMutation,
|
|
47
47
|
CreateCustomerFormValues
|
|
48
48
|
>,
|
|
49
|
-
mutationOptions?:
|
|
49
|
+
mutationOptions?: useMutation.Options<UseCustomerCreateFormMutation, CreateCustomerFormValues>,
|
|
50
50
|
) {
|
|
51
51
|
const attributes = useAttributesForm({
|
|
52
52
|
formCode: 'customer_account_create',
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type UseAttributesFormConfig,
|
|
8
8
|
} from '@graphcommerce/magento-store'
|
|
9
9
|
import { useFormGqlMutation, type UseFormGraphQlOptions } from '@graphcommerce/react-hook-form'
|
|
10
|
-
import type {
|
|
10
|
+
import type { useMutation } from '@apollo/client/react'
|
|
11
11
|
import type { OmitDeep } from 'type-fest'
|
|
12
12
|
import type { CustomerInfoFragment } from '../../hooks'
|
|
13
13
|
import {
|
|
@@ -93,7 +93,7 @@ export function useCustomerUpdateForm(
|
|
|
93
93
|
UseCustomerUpdateFormMutation,
|
|
94
94
|
UpdateCustomerFormValues
|
|
95
95
|
>,
|
|
96
|
-
mutationOptions?:
|
|
96
|
+
mutationOptions?: useMutation.Options<UseCustomerUpdateFormMutation, UpdateCustomerFormValues>,
|
|
97
97
|
) {
|
|
98
98
|
const { customer, ...attributeFormConfig } = config
|
|
99
99
|
const attributes = useAttributesForm({
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ApolloClient } from '@graphcommerce/graphql'
|
|
2
2
|
import { removeCssFlag } from '@graphcommerce/next-ui'
|
|
3
3
|
|
|
4
|
-
export function signOut(client: ApolloClient
|
|
4
|
+
export function signOut(client: ApolloClient) {
|
|
5
5
|
removeCssFlag('private-query')
|
|
6
6
|
globalThis?.sessionStorage?.clear()
|
|
7
7
|
client.cache.evict({ fieldName: 'currentCartId' })
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
OperationVariables,
|
|
3
|
-
QueryHookOptions,
|
|
4
|
-
QueryResult,
|
|
5
|
-
TypedDocumentNode,
|
|
6
|
-
} from '@graphcommerce/graphql'
|
|
1
|
+
import type { OperationVariables, TypedDocumentNode } from '@graphcommerce/graphql'
|
|
7
2
|
import { useQuery } from '@graphcommerce/graphql'
|
|
3
|
+
import type { useQuery as useQueryType } from '@apollo/client/react'
|
|
8
4
|
import { useCustomerSession } from './useCustomerSession'
|
|
9
5
|
|
|
10
6
|
/** Will only execute when the customer is signed in. */
|
|
11
7
|
export function useCustomerQuery<Q, V extends OperationVariables>(
|
|
12
8
|
document: TypedDocumentNode<Q, V>,
|
|
13
|
-
options
|
|
14
|
-
)
|
|
9
|
+
options?: Omit<useQueryType.Options<Q, V>, 'query'>,
|
|
10
|
+
) {
|
|
15
11
|
const { loggedIn } = useCustomerSession()
|
|
16
|
-
return useQuery(document, {
|
|
12
|
+
return useQuery(document, {
|
|
13
|
+
...options,
|
|
14
|
+
ssr: false,
|
|
15
|
+
returnPartialData: false,
|
|
16
|
+
skip: options?.skip || !loggedIn,
|
|
17
|
+
} as useQueryType.Options<Q, V>)
|
|
17
18
|
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { QueryResult } from '@graphcommerce/graphql'
|
|
2
1
|
import { useQuery } from '@graphcommerce/graphql'
|
|
3
2
|
import type { CustomerTokenQuery, CustomerTokenQueryVariables } from './CustomerToken.gql'
|
|
4
3
|
import { CustomerTokenDocument } from './CustomerToken.gql'
|
|
@@ -7,7 +6,7 @@ export type UseCustomerSessionOptions = Record<string, unknown>
|
|
|
7
6
|
|
|
8
7
|
export type UseCustomerSessionReturn = {
|
|
9
8
|
loggedIn: boolean
|
|
10
|
-
query:
|
|
9
|
+
query: useQuery.Result<CustomerTokenQuery, CustomerTokenQueryVariables>
|
|
11
10
|
} & Partial<Omit<NonNullable<CustomerTokenQuery['customerToken']>, '__typename'>>
|
|
12
11
|
|
|
13
12
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
package/hooks/useGuestQuery.ts
CHANGED
|
@@ -1,16 +1,17 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
OperationVariables,
|
|
3
|
-
QueryHookOptions,
|
|
4
|
-
TypedDocumentNode,
|
|
5
|
-
} from '@graphcommerce/graphql'
|
|
1
|
+
import type { OperationVariables, TypedDocumentNode } from '@graphcommerce/graphql'
|
|
6
2
|
import { useQuery } from '@graphcommerce/graphql'
|
|
3
|
+
import type { useQuery as useQueryType } from '@apollo/client/react'
|
|
7
4
|
import { useCustomerSession } from './useCustomerSession'
|
|
8
5
|
|
|
9
6
|
/** Will only execute when the customer is not signed in. */
|
|
10
7
|
export function useGuestQuery<Q, V extends OperationVariables>(
|
|
11
8
|
document: TypedDocumentNode<Q, V>,
|
|
12
|
-
queryOptions
|
|
9
|
+
queryOptions?: Omit<useQueryType.Options<Q, V>, 'query'>,
|
|
13
10
|
) {
|
|
14
11
|
const { token } = useCustomerSession()
|
|
15
|
-
return useQuery(document, {
|
|
12
|
+
return useQuery(document, {
|
|
13
|
+
...queryOptions,
|
|
14
|
+
ssr: false,
|
|
15
|
+
skip: queryOptions?.skip || !!token,
|
|
16
|
+
} as useQueryType.Options<Q, V>)
|
|
16
17
|
}
|
package/link/customerLink.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { globalApolloClient } from '@graphcommerce/graphql'
|
|
2
2
|
import type { ApolloCache } from '@graphcommerce/graphql/apollo'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
ApolloLink,
|
|
5
|
+
CombinedGraphQLErrors,
|
|
6
|
+
ErrorLink,
|
|
7
|
+
SetContextLink,
|
|
8
|
+
} from '@graphcommerce/graphql/apollo'
|
|
9
|
+
import { from, switchMap } from '@graphcommerce/graphql/rxjs'
|
|
4
10
|
import { magentoVersion } from '@graphcommerce/next-config/config'
|
|
5
11
|
import type { GraphQLFormattedError } from 'graphql'
|
|
6
12
|
import type { NextRouter } from 'next/router'
|
|
@@ -11,7 +17,7 @@ export type PushRouter = Pick<NextRouter, 'push' | 'events' | 'locale'>
|
|
|
11
17
|
|
|
12
18
|
declare module '@apollo/client' {
|
|
13
19
|
interface DefaultContext {
|
|
14
|
-
cache?: ApolloCache
|
|
20
|
+
cache?: ApolloCache
|
|
15
21
|
headers?: Record<string, string>
|
|
16
22
|
}
|
|
17
23
|
}
|
|
@@ -45,31 +51,32 @@ export async function pushWithPromise(router: Pick<NextRouter, 'push' | 'events'
|
|
|
45
51
|
})
|
|
46
52
|
}
|
|
47
53
|
|
|
48
|
-
const addTokenHeader =
|
|
49
|
-
|
|
54
|
+
const addTokenHeader = new SetContextLink((prevContext) => {
|
|
55
|
+
const headers: Record<string, string> = { ...prevContext.headers }
|
|
50
56
|
|
|
51
57
|
try {
|
|
52
|
-
const query =
|
|
58
|
+
const query = prevContext.cache?.readQuery({ query: CustomerTokenDocument })
|
|
53
59
|
|
|
54
60
|
if (query?.customerToken?.token && query?.customerToken?.valid !== false) {
|
|
55
|
-
|
|
56
|
-
return context
|
|
61
|
+
headers.authorization = `Bearer ${query?.customerToken?.token}`
|
|
57
62
|
}
|
|
58
|
-
return
|
|
63
|
+
return { headers }
|
|
59
64
|
} catch (error) {
|
|
60
|
-
return
|
|
65
|
+
return { headers }
|
|
61
66
|
}
|
|
62
67
|
})
|
|
63
68
|
|
|
64
69
|
const customerErrorLink = (router: PushRouter) =>
|
|
65
|
-
|
|
66
|
-
const { graphQLErrors, operation, forward } = context
|
|
70
|
+
new ErrorLink(({ error, operation, forward }) => {
|
|
67
71
|
const client = globalApolloClient.current
|
|
68
72
|
if (!client) return undefined
|
|
69
73
|
|
|
74
|
+
// Check if this is a GraphQL error
|
|
75
|
+
if (!CombinedGraphQLErrors.is(error)) return undefined
|
|
76
|
+
|
|
70
77
|
const oldHeaders = operation.getContext().headers
|
|
71
78
|
|
|
72
|
-
const authError =
|
|
79
|
+
const authError = error.errors.find(
|
|
73
80
|
(err: GraphQLFormattedError) =>
|
|
74
81
|
err.extensions?.category ===
|
|
75
82
|
(magentoVersion >= 248 ? 'graphql-authentication' : 'graphql-authorization'),
|
|
@@ -99,25 +106,27 @@ const customerErrorLink = (router: PushRouter) =>
|
|
|
99
106
|
|
|
100
107
|
const signInAgainPromise = pushWithPromise(router, '/account/signin')
|
|
101
108
|
|
|
102
|
-
return
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
109
|
+
return from(signInAgainPromise).pipe(
|
|
110
|
+
switchMap(() => {
|
|
111
|
+
const tokenQuery = client.cache.readQuery({ query: CustomerTokenDocument })
|
|
112
|
+
|
|
113
|
+
if (tokenQuery?.customerToken?.valid) {
|
|
114
|
+
// Customer is reauthenticated, retrying request.
|
|
115
|
+
operation.setContext({
|
|
116
|
+
headers: {
|
|
117
|
+
...oldHeaders,
|
|
118
|
+
authorization: `Bearer ${tokenQuery?.customerToken?.token}`,
|
|
119
|
+
},
|
|
120
|
+
})
|
|
121
|
+
} else {
|
|
122
|
+
// Customer has not reauthenticated, clearing all customer data.
|
|
123
|
+
signOut(client)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// retry the request, returning the new observable
|
|
127
|
+
return forward(operation)
|
|
128
|
+
}),
|
|
129
|
+
)
|
|
121
130
|
})
|
|
122
131
|
|
|
123
132
|
export const customerLink = (router: PushRouter) =>
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { DefaultContext } from '@graphcommerce/graphql'
|
|
2
2
|
import { ApolloLink } from '@graphcommerce/graphql'
|
|
3
|
+
import { map } from '@graphcommerce/graphql/rxjs'
|
|
3
4
|
import { CustomerTokenDocument } from '../hooks'
|
|
4
5
|
|
|
5
6
|
export const xMagentoCacheIdHeader = new ApolloLink((operation, forward) => {
|
|
@@ -11,28 +12,30 @@ export const xMagentoCacheIdHeader = new ApolloLink((operation, forward) => {
|
|
|
11
12
|
return { ...context, headers: { ...context.headers, 'x-magento-cache-id': xMagentoCacheId } }
|
|
12
13
|
})
|
|
13
14
|
|
|
14
|
-
return forward(operation).
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
return forward(operation).pipe(
|
|
16
|
+
map((data) => {
|
|
17
|
+
const { cache } = operation.getContext()
|
|
18
|
+
if (!cache) return data
|
|
17
19
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
const xMagentoCacheId = (
|
|
21
|
+
data.extensions as { forwardedHeaders: Record<string, string> } | undefined
|
|
22
|
+
)?.forwardedHeaders?.['x-magento-cache-id']
|
|
21
23
|
|
|
22
|
-
|
|
24
|
+
if (!xMagentoCacheId) return data
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
const tokenResult = cache.readQuery({ query: CustomerTokenDocument })
|
|
25
27
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
if (
|
|
29
|
+
!tokenResult?.customerToken ||
|
|
30
|
+
tokenResult.customerToken?.xMagentoCacheId === xMagentoCacheId
|
|
31
|
+
)
|
|
32
|
+
return data
|
|
31
33
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
34
|
+
cache.writeQuery({
|
|
35
|
+
query: CustomerTokenDocument,
|
|
36
|
+
data: { customerToken: { ...tokenResult.customerToken, xMagentoCacheId } },
|
|
37
|
+
})
|
|
38
|
+
return data
|
|
39
|
+
}),
|
|
40
|
+
)
|
|
38
41
|
})
|
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": "10.0.0-canary.
|
|
5
|
+
"version": "10.0.0-canary.72",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"prettier": "@graphcommerce/prettier-config-pwa",
|
|
8
8
|
"eslintConfig": {
|
|
@@ -21,20 +21,20 @@
|
|
|
21
21
|
"./plugins/magentoCustomerPrivateQueryContext": "./plugins/magentoCustomerPrivateQueryContext.ts"
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"@graphcommerce/ecommerce-ui": "^10.0.0-canary.
|
|
25
|
-
"@graphcommerce/eslint-config-pwa": "^10.0.0-canary.
|
|
26
|
-
"@graphcommerce/framer-next-pages": "^10.0.0-canary.
|
|
27
|
-
"@graphcommerce/framer-utils": "^10.0.0-canary.
|
|
28
|
-
"@graphcommerce/graphql": "^10.0.0-canary.
|
|
29
|
-
"@graphcommerce/graphql-mesh": "^10.0.0-canary.
|
|
30
|
-
"@graphcommerce/image": "^10.0.0-canary.
|
|
31
|
-
"@graphcommerce/magento-graphql": "^10.0.0-canary.
|
|
32
|
-
"@graphcommerce/magento-store": "^10.0.0-canary.
|
|
33
|
-
"@graphcommerce/next-config": "^10.0.0-canary.
|
|
34
|
-
"@graphcommerce/next-ui": "^10.0.0-canary.
|
|
35
|
-
"@graphcommerce/prettier-config-pwa": "^10.0.0-canary.
|
|
36
|
-
"@graphcommerce/react-hook-form": "^10.0.0-canary.
|
|
37
|
-
"@graphcommerce/typescript-config-pwa": "^10.0.0-canary.
|
|
24
|
+
"@graphcommerce/ecommerce-ui": "^10.0.0-canary.72",
|
|
25
|
+
"@graphcommerce/eslint-config-pwa": "^10.0.0-canary.72",
|
|
26
|
+
"@graphcommerce/framer-next-pages": "^10.0.0-canary.72",
|
|
27
|
+
"@graphcommerce/framer-utils": "^10.0.0-canary.72",
|
|
28
|
+
"@graphcommerce/graphql": "^10.0.0-canary.72",
|
|
29
|
+
"@graphcommerce/graphql-mesh": "^10.0.0-canary.72",
|
|
30
|
+
"@graphcommerce/image": "^10.0.0-canary.72",
|
|
31
|
+
"@graphcommerce/magento-graphql": "^10.0.0-canary.72",
|
|
32
|
+
"@graphcommerce/magento-store": "^10.0.0-canary.72",
|
|
33
|
+
"@graphcommerce/next-config": "^10.0.0-canary.72",
|
|
34
|
+
"@graphcommerce/next-ui": "^10.0.0-canary.72",
|
|
35
|
+
"@graphcommerce/prettier-config-pwa": "^10.0.0-canary.72",
|
|
36
|
+
"@graphcommerce/react-hook-form": "^10.0.0-canary.72",
|
|
37
|
+
"@graphcommerce/typescript-config-pwa": "^10.0.0-canary.72",
|
|
38
38
|
"@lingui/core": "^5",
|
|
39
39
|
"@lingui/macro": "^5",
|
|
40
40
|
"@lingui/react": "^5",
|