@graphcommerce/graphql 10.0.0-canary.68 → 10.0.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,121 @@
1
1
  # Change Log
2
2
 
3
+ ## 10.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - [#2546](https://github.com/graphcommerce-org/graphcommerce/pull/2546) [`ed9332a`](https://github.com/graphcommerce-org/graphcommerce/commit/ed9332a7f78966d932041d9a7725641edc92b28d) - ## GraphCommerce 10 - Turbopack Support
8
+
9
+ This major release brings full Turbopack compatibility, dramatically improving development speed.
10
+
11
+ ### 🚀 Turbopack-Compatible Interceptor System
12
+
13
+ The entire plugin/interceptor system has been rewritten to work with Turbopack:
14
+
15
+ - **No more Webpack plugins** - Removed `InterceptorPlugin` webpack plugin entirely
16
+ - **File-based interception** - Original files are moved to `.original.tsx` and replaced with interceptor content
17
+ - **Direct imports** - Interceptors import from `.original` files instead of embedding source
18
+ - **New CLI commands**:
19
+ - `graphcommerce codegen-interceptors` - Generate interceptor files
20
+ - `graphcommerce cleanup-interceptors` - Reset interceptor system, restore original files
21
+ - **Stable file hashing** - Deterministic interceptor generation for better caching
22
+
23
+ ### ⚙️ Treeshakable Configuration System
24
+
25
+ Replaced Webpack `DefinePlugin`-based `import.meta.graphCommerce` with a new generated configuration system:
26
+
27
+ - **New `codegen-config-values` command** - Generates TypeScript files with precise typing
28
+ - **Schema-driven** - Dynamically introspects Zod schemas to determine all available properties
29
+ - **Fully treeshakable** - Unused config values are eliminated from the bundle
30
+ - **Type-safe** - Uses `Get<GraphCommerceConfig, 'path'>` for nested property access
31
+ - **Separate files for nested objects** - Optimal treeshaking for complex configurations
32
+
33
+ ### 🔧 withGraphCommerce Changes
34
+
35
+ - **Removed** `InterceptorPlugin` - No longer needed with file-based interception
36
+ - **Removed** `DefinePlugin` for `import.meta.graphCommerce` - Replaced with generated config
37
+ - **Removed** `@mui/*` alias rewrites - No longer required
38
+ - **Added** Turbopack loader rules for `.yaml`, `.yml`, and `.po` files
39
+ - **Added** `serverExternalPackages` for all `@whatwg-node/*` packages
40
+ - **Added** `optimizePackageImports` for better bundle optimization
41
+ - **Added** `images.qualities: [52, 75]` for Next.js image optimization
42
+
43
+ ### 📦 Lingui Configuration
44
+
45
+ - **Renamed** `lingui.config.js` → `lingui.config.ts` with TypeScript support
46
+ - **Updated** `@graphcommerce/lingui-next/config` to TypeScript with proper exports
47
+ - **Simplified** formatter options
48
+
49
+ ### ⚛️ React 19 & Next.js 16 Compatibility
50
+
51
+ - Updated `RefObject<T>` types for React 19 (now includes `null` by default)
52
+ - Replaced deprecated `React.VFC` with `React.FC`
53
+ - Fixed `useRef` calls to require explicit initial values
54
+ - Updated `MutableRefObject` usage in `framer-scroller`
55
+
56
+ ### 📋 ESLint 9 Flat Config
57
+
58
+ - Migrated from legacy `.eslintrc` to new flat config format (`eslint.config.mjs`)
59
+ - Updated `@typescript-eslint/*` packages to v8
60
+ - Fixed AST selector for `SxProps` rule (`typeParameters` → `typeArguments`)
61
+
62
+ ### 🔄 Apollo Client
63
+
64
+ - Fixed deprecated `name` option → `clientAwareness: { name: 'ssr' }`
65
+ - Updated error handling types to accept `ApolloError | null | undefined`
66
+
67
+ ### ⚠️ Breaking Changes
68
+
69
+ - **Node.js 24.x not supported** - Restricted to `>=20 <24.0.0` due to [nodejs/undici#4290](https://github.com/nodejs/undici/issues/4290)
70
+ - **Interceptor files changed** - Original components now at `.original.tsx`
71
+ - **Config access changed** - Use generated config values instead of `import.meta.graphCommerce`
72
+ - **ESLint config format** - Must use flat config (`eslint.config.mjs`)
73
+ - **Lingui config** - Rename `lingui.config.js` to `lingui.config.ts`
74
+
75
+ ### 🗑️ Removed
76
+
77
+ - `InterceptorPlugin` webpack plugin
78
+ - `configToImportMeta` utility
79
+ - Webpack `DefinePlugin` usage for config
80
+ - `@mui/*` modern alias rewrites
81
+ - Debug plugins (`CircularDependencyPlugin`, `DuplicatesPlugin`) ([@paales](https://github.com/paales))
82
+
83
+ - [#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))
84
+
85
+ ### Minor Changes
86
+
87
+ - [#2537](https://github.com/graphcommerce-org/graphcommerce/pull/2537) [`958dcb6`](https://github.com/graphcommerce-org/graphcommerce/commit/958dcb62d5abb3427a38e2a4583897f3e2043cc4) - Introduce a new Product-`uid` to solve an issue where cache normalization was not working properly on the frontend when viewing products with a differen curreny, etc.
88
+
89
+ Products now have a more detailed `uid` which will include the scope the product is retrieved from. For example: `NDg5MDM=?store=nl_NL&currencyCode=EUR`. This results in a better cache normalization in Apollo Client and allows for switching between scopes (store/currency/price views/accounts) without creating a broken cache state.
90
+
91
+ We have implemented this with a new resolver that rewrites the `uid` passed from Magento to the Mesh Resolver, and additing additonal data to the `uid` based on the headers passed from the client. This also requires each package to implement the `getPrivateQueryContextMesh` method to retrieve the current PrivateQuery context from the GraphQL request headers. ([@paales](https://github.com/paales))
92
+
93
+ ### Patch Changes
94
+
95
+ - [#2528](https://github.com/graphcommerce-org/graphcommerce/pull/2528) [`c52604f`](https://github.com/graphcommerce-org/graphcommerce/commit/c52604f89e1776fc1f0913f016b8b24fa194c6b7) - Solve issue where the persistenceMapper didn't use the same typePolicies and other configuration from the cache, causing potential issues. ([@paales](https://github.com/paales))
96
+
97
+ - [#2496](https://github.com/graphcommerce-org/graphcommerce/pull/2496) [`a261149`](https://github.com/graphcommerce-org/graphcommerce/commit/a261149b6b32ad6a35606da2d530b8e41bfa10a0) - ReCaptcha now using the `recaptchaV3Config` query and add a fallback for Magento 2.4.6 and earlier to still use the configuration. Magento 2.4.7 doesn't need that configuration anymore. ([@paales](https://github.com/paales))
98
+
99
+ - [#2525](https://github.com/graphcommerce-org/graphcommerce/pull/2525) [`e1e132d`](https://github.com/graphcommerce-org/graphcommerce/commit/e1e132d076fbc6b3a081a245e51cb2bc91b0c707) - usePrivateQuery now disables masking when an error occurs. ([@paales](https://github.com/paales))
100
+
101
+ - [#2528](https://github.com/graphcommerce-org/graphcommerce/pull/2528) [`529d7a8`](https://github.com/graphcommerce-org/graphcommerce/commit/529d7a88a4e010cb3e50c1358e2ac43e80e0bf38) - Solve issue where the ApolloClient cache wasn't scoped properly causing the wrong currency to be shown when switching currency. ([@paales](https://github.com/paales))
102
+
103
+ - [`62b71d5`](https://github.com/graphcommerce-org/graphcommerce/commit/62b71d5ed1d482fdb5b76dc19ac4d55fc41fb191) - Solve issue: TypeError: InMemoryLRUCache is not a constructor ([@paales](https://github.com/paales))
104
+
105
+ - [#2477](https://github.com/graphcommerce-org/graphcommerce/pull/2477) [`8015eab`](https://github.com/graphcommerce-org/graphcommerce/commit/8015eabc130dacf1f2703980cd5f0ad2c550aa4d) - Upgraded to @apollo/client 3.12.3 without impacting typescript compilation performance. ([@paales](https://github.com/paales))
106
+
107
+ ## 10.0.0-canary.72
108
+
109
+ ## 10.0.0-canary.71
110
+
111
+ ## 10.0.0-canary.70
112
+
113
+ ### Major Changes
114
+
115
+ - [#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))
116
+
117
+ ## 10.0.0-canary.69
118
+
3
119
  ## 10.0.0-canary.68
4
120
 
5
121
  ## 10.0.0-canary.67
@@ -3,28 +3,29 @@
3
3
  /* eslint-disable no-empty-pattern */
4
4
  import type { Page } from '@playwright/test'
5
5
  import { test as base } from '@playwright/test'
6
- import type { FetchResult, NormalizedCacheObject, TypedDocumentNode } from '../apollo'
6
+ import type { ApolloLink, TypedDocumentNode } from '../apollo'
7
7
  import { ApolloClient, getOperationName, InMemoryCache } from '../apollo'
8
8
 
9
9
  type ApolloClientTest = {
10
- apolloClient: ApolloClient<NormalizedCacheObject>
10
+ apolloClient: ApolloClient
11
11
  }
12
12
 
13
13
  export async function waitForGraphQlResponse<Q, V>(
14
14
  page: Page,
15
15
  docOrName: string | TypedDocumentNode<Q, V>,
16
- ): Promise<FetchResult<Q>> {
16
+ ): Promise<ApolloLink.Result<Q>> {
17
17
  const name = typeof docOrName === 'string' ? docOrName : getOperationName(docOrName)
18
18
 
19
19
  const response = await page.waitForResponse((r) => {
20
20
  try {
21
21
  return r.request().postDataJSON()?.operationName === name
22
22
  } catch (e) {
23
+ console.error(e)
23
24
  return false
24
25
  }
25
26
  })
26
27
 
27
- return (await response?.json()) as FetchResult<Q>
28
+ return (await response?.json()) as ApolloLink.Result<Q>
28
29
  }
29
30
 
30
31
  /** @public */
package/apollo.ts CHANGED
@@ -1,13 +1,34 @@
1
- export { cloneDeep, mergeDeep } from '@apollo/client/utilities'
1
+ export { cloneDeep, mergeDeep, getOperationName } from '@apollo/client/utilities/internal'
2
2
 
3
+ // Core Apollo Client exports
3
4
  export * from '@apollo/client'
5
+
6
+ // React hooks - exported explicitly
7
+ export {
8
+ ApolloProvider,
9
+ useApolloClient,
10
+ useQuery,
11
+ useLazyQuery,
12
+ useMutation,
13
+ useSubscription,
14
+ useFragment,
15
+ useSuspenseQuery,
16
+ useBackgroundQuery,
17
+ useReadQuery,
18
+ useLoadableQuery,
19
+ useSuspenseFragment,
20
+ useQueryRefHandlers,
21
+ useReactiveVar,
22
+ skipToken,
23
+ getApolloContext,
24
+ createQueryPreloader,
25
+ } from '@apollo/client/react'
26
+
4
27
  export * from '@apollo/client/link/schema'
5
28
  export * from '@apollo/client/link/context'
6
29
  export * from '@apollo/client/link/error'
7
30
  export * from '@apollo/client/utilities'
8
31
 
9
- export { getOperationName } from '@apollo/client/utilities'
10
-
11
32
  declare module '@apollo/client' {
12
33
  interface DataMasking {
13
34
  enabled: true
@@ -1,7 +1,9 @@
1
1
  // eslint-disable-next-line import/no-extraneous-dependencies
2
2
  import { useStorefrontConfig } from '@graphcommerce/next-ui/hooks/useStorefrontConfig'
3
- import type { DefaultOptions, NormalizedCacheObject } from '@apollo/client'
4
- import { ApolloClient, ApolloLink, ApolloProvider, HttpLink, InMemoryCache } from '@apollo/client'
3
+ import { ApolloClient, ApolloLink, HttpLink, InMemoryCache } from '@apollo/client'
4
+ import type { NormalizedCacheObject } from '@apollo/client'
5
+ import { LocalState } from '@apollo/client/local-state'
6
+ import { ApolloProvider } from '@apollo/client/react'
5
7
  import type { AppProps } from 'next/app'
6
8
  import { useCallback, useEffect, useRef, useState } from 'react'
7
9
  import type { ApolloClientConfig, ApolloClientConfigInput, PreviewConfig } from '../../config'
@@ -12,7 +14,7 @@ import { errorLink } from './errorLink'
12
14
  import { measurePerformanceLink } from './measurePerformanceLink'
13
15
  import { mergeTypePolicies } from './typePolicies'
14
16
 
15
- export const globalApolloClient: { current: ApolloClient<NormalizedCacheObject> | null } = {
17
+ export const globalApolloClient: { current: ApolloClient | null } = {
16
18
  current: null,
17
19
  }
18
20
 
@@ -27,7 +29,7 @@ export type GraphQLProviderProps = AppProps &
27
29
  */
28
30
  export function GraphQLProvider(props: GraphQLProviderProps) {
29
31
  const { children, links, migrations, policies, pageProps, router } = props
30
- const state = (pageProps as { apolloState?: NormalizedCacheObject }).apolloState
32
+ const state = (pageProps as { apolloState?: unknown }).apolloState
31
33
 
32
34
  const stateRef = useRef(state)
33
35
 
@@ -60,7 +62,7 @@ export function GraphQLProvider(props: GraphQLProviderProps) {
60
62
  ])
61
63
 
62
64
  const cache = createCache()
63
- if (stateRef.current) cache.restore(stateRef.current)
65
+ if (stateRef.current) cache.restore(stateRef.current as unknown as NormalizedCacheObject)
64
66
 
65
67
  const ssrMode = typeof window === 'undefined'
66
68
  return new ApolloClient({
@@ -68,11 +70,13 @@ export function GraphQLProvider(props: GraphQLProviderProps) {
68
70
  cache,
69
71
  clientAwareness: { name: 'web' },
70
72
  ssrMode,
73
+
71
74
  defaultOptions: {
72
75
  preview: {
73
76
  preview: router.isPreview,
74
77
  } as PreviewConfig,
75
- } as DefaultOptions,
78
+ } as ApolloClient.DefaultOptions,
79
+ localState: new LocalState({}),
76
80
  })
77
81
  })
78
82
 
@@ -9,14 +9,14 @@ import { getTypePoliciesVersion } from './typePolicies'
9
9
  const APOLLO_CACHE_PERSIST = 'apollo-cache-persist'
10
10
  const APOLLO_CACHE_VERSION = 'apollo-cache-version'
11
11
 
12
- let persistor: CachePersistor<NormalizedCacheObject> | null = null
12
+ let persistor: CachePersistor<unknown> | null = null
13
13
 
14
14
  /** Revives the cache from the localStorage if it is available. */
15
15
  export async function createCacheReviver(
16
- client: ApolloClient<NormalizedCacheObject>,
17
- createCache: () => ApolloCache<NormalizedCacheObject>,
16
+ client: ApolloClient,
17
+ createCache: () => ApolloCache,
18
18
  config: ApolloClientConfig,
19
- incomingState: NormalizedCacheObject = {},
19
+ incomingState: unknown = {},
20
20
  ) {
21
21
  let state = incomingState
22
22
  const typePoliciesVersion = getTypePoliciesVersion(config.policies)
@@ -1,17 +1,18 @@
1
- import { onError } from '@apollo/client/link/error'
1
+ import { CombinedGraphQLErrors } from '@apollo/client/errors'
2
+ import { ErrorLink } from '@apollo/client/link/error'
2
3
 
3
- export const errorLink = onError(({ graphQLErrors, networkError, operation }) => {
4
- if (graphQLErrors)
4
+ export const errorLink = new ErrorLink(({ error, operation }) => {
5
+ if (CombinedGraphQLErrors.is(error)) {
5
6
  console.error(
6
- `[GraphQL errors]: ${graphQLErrors
7
+ `[GraphQL errors]: ${error.errors
7
8
  .map(({ message, path }) => `${message} ${path?.join(',')}`)
8
9
  .join(', ')}`,
9
10
  )
11
+ } else if (error) {
12
+ console.error(`[Graphql error]: ${error}`)
13
+ }
10
14
 
11
- if (networkError)
12
- console.error(`[Graphql error]: ${networkError}`)
13
-
14
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
15
+ // eslint-disable-next-line @typescript-eslint/no-floating-promises
15
16
  ;(async () => {
16
17
  const graphql = await import('graphql')
17
18
 
@@ -1,11 +1,11 @@
1
1
  /* eslint-disable no-console */
2
2
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
3
+ import { map } from '@graphcommerce/graphql/rxjs'
3
4
  import { canonicalBaseUrl } from '@graphcommerce/next-config/config'
4
5
  import { ApolloLink } from '@apollo/client'
5
6
  import { print } from '@apollo/client/utilities'
6
7
  import type { MeshFetchHTTPInformation } from '@graphql-mesh/plugin-http-details-extensions'
7
8
  import { responsePathAsArray, stripIgnoredCharacters } from 'graphql'
8
- import { cliHyperlink } from '../../lib/hyperlinker'
9
9
 
10
10
  const running = new Map<
11
11
  string,
@@ -147,88 +147,93 @@ export const measurePerformanceLink = new ApolloLink((operation, forward) => {
147
147
  operation.setContext({ measurePerformanceLinkStart: new Date() })
148
148
  const vars =
149
149
  Object.keys(operation.variables).length > 0 ? `(${JSON.stringify(operation.variables)})` : ''
150
- const operationString = `${operation.operationName}${vars}`
150
+ const operationString = `${operation.operationName ?? 'anonymous'}${vars}`
151
151
 
152
152
  running.set(operationString, {
153
153
  start: new Date(),
154
- operationName: [operation.operationName, operation.operationName],
154
+ operationName: [
155
+ operation.operationName ?? 'anonymous',
156
+ operation.operationName ?? 'anonymous',
157
+ ],
155
158
  })
156
159
  markTimeout()
157
160
 
158
- return forward(operation).map((data) => {
159
- const httpDetails: MeshFetchHTTPInformation[] | undefined = data.extensions?.httpDetails
160
-
161
- const additional = ['', ''] as [string, string]
162
-
163
- // Called after server responds
164
- const query = [
165
- `# Variables: ${JSON.stringify(operation.variables)}`,
166
- `# Headers: ${JSON.stringify(operation.getContext().headers)}`,
167
- stripIgnoredCharacters(print(operation.query)),
168
- ].join('\n')
169
-
170
- const meshUrl = new URL(
171
- process.env.NODE_ENV === 'production'
172
- ? `${canonicalBaseUrl}/api/graphql`
173
- : 'http://localhost:3000/api/graphql',
174
- )
175
-
176
- meshUrl.searchParams.set('query', query)
177
-
178
- running.delete(operationString)
179
- running.set(operationString, {
180
- start: operation.getContext().measurePerformanceLinkStart as Date,
181
- end: new Date(),
182
- operationName: [
183
- operation.operationName,
184
- operation.operationName,
185
- // cliHyperlink(operation.operationName, meshUrl.toString()),
186
- ],
187
- additional,
188
- idx: 0,
189
- })
190
-
191
- if (httpDetails) {
192
- running.forEach((_, key) => {
193
- if (key.startsWith(operationString)) running.delete(key)
161
+ return forward(operation).pipe(
162
+ map((data) => {
163
+ const httpDetails: MeshFetchHTTPInformation[] | undefined = data.extensions?.httpDetails
164
+
165
+ const additional = ['', ''] as [string, string]
166
+
167
+ // Called after server responds
168
+ const query = [
169
+ `# Variables: ${JSON.stringify(operation.variables)}`,
170
+ `# Headers: ${JSON.stringify(operation.getContext().headers)}`,
171
+ stripIgnoredCharacters(print(operation.query)),
172
+ ].join('\n')
173
+
174
+ const meshUrl = new URL(
175
+ process.env.NODE_ENV === 'production'
176
+ ? `${canonicalBaseUrl}/api/graphql`
177
+ : 'http://localhost:3000/api/graphql',
178
+ )
179
+
180
+ meshUrl.searchParams.set('query', query)
181
+
182
+ running.delete(operationString)
183
+ running.set(operationString, {
184
+ start: operation.getContext().measurePerformanceLinkStart as Date,
185
+ end: new Date(),
186
+ operationName: [
187
+ operation.operationName ?? 'anonymous',
188
+ operation.operationName ?? 'anonymous',
189
+ // cliHyperlink(operation.operationName, meshUrl.toString()),
190
+ ],
191
+ additional,
192
+ idx: 0,
194
193
  })
195
194
 
196
- httpDetails.forEach((d) => {
197
- const requestUrl = new URL(d.request.url)
198
- requestUrl.searchParams.delete('extensions')
199
-
200
- const sourceName =
201
- !d.sourceName && URL.canParse(d.request.url)
202
- ? new URL(d.request.url).hostname
203
- : d.sourceName
204
-
205
- const key = `${operationString}.${responsePathAsArray(d.path).join('.')}`
206
- const name = `${operation.operationName}.${responsePathAsArray(d.path).join('.')} (${sourceName})`
207
-
208
- let start = new Date(d.request.timestamp)
209
- let end = new Date(d.response.timestamp)
210
- let operationName: [string, string] = [name, name]
211
- let idx = 0
212
-
213
- if (running.has(key)) {
214
- // Get the earliest start time and latest end time.
215
- const existing = running.get(key)
216
- if (existing) {
217
- idx = (existing.idx ?? 0) + 1
218
- start = existing.start < start ? existing.start : start
219
- end = existing?.end ? (existing.end > end ? existing.end : end) : end
220
- operationName = [`${name} ⨉ ${idx}`, `${name} ⨉ ${idx}`]
195
+ if (httpDetails) {
196
+ running.forEach((_, key) => {
197
+ if (key.startsWith(operationString)) running.delete(key)
198
+ })
199
+
200
+ httpDetails.forEach((d) => {
201
+ const requestUrl = new URL(d.request.url)
202
+ requestUrl.searchParams.delete('extensions')
203
+
204
+ const sourceName =
205
+ !d.sourceName && URL.canParse(d.request.url)
206
+ ? new URL(d.request.url).hostname
207
+ : d.sourceName
208
+
209
+ const key = `${operationString}.${responsePathAsArray(d.path).join('.')}`
210
+ const name = `${operation.operationName ?? 'anonymous'}.${responsePathAsArray(d.path).join('.')} (${sourceName})`
211
+
212
+ let start = new Date(d.request.timestamp)
213
+ let end = new Date(d.response.timestamp)
214
+ let operationName: [string, string] = [name, name]
215
+ let idx = 0
216
+
217
+ if (running.has(key)) {
218
+ // Get the earliest start time and latest end time.
219
+ const existing = running.get(key)
220
+ if (existing) {
221
+ idx = (existing.idx ?? 0) + 1
222
+ start = existing.start < start ? existing.start : start
223
+ end = existing?.end ? (existing.end > end ? existing.end : end) : end
224
+ operationName = [`${name} ⨉ ${idx}`, `${name} ⨉ ${idx}`]
225
+ }
221
226
  }
222
- }
223
227
 
224
- running.set(key, { start, end, operationName, idx })
225
- })
226
- }
228
+ running.set(key, { start, end, operationName, idx })
229
+ })
230
+ }
227
231
 
228
- markTimeout()
232
+ markTimeout()
229
233
 
230
- return data
231
- })
234
+ return data
235
+ }),
236
+ )
232
237
  }
233
238
  return forward(operation)
234
239
  })
@@ -1,13 +1,10 @@
1
- import type { ApolloCache, NormalizedCacheObject } from '../../apollo'
1
+ import type { ApolloCache } from '../../apollo'
2
2
 
3
- export type MigrateCache = (
4
- oldCache: ApolloCache<NormalizedCacheObject>,
5
- newCache: ApolloCache<NormalizedCacheObject>,
6
- ) => void
3
+ export type MigrateCache = (oldCache: ApolloCache, newCache: ApolloCache) => void
7
4
 
8
5
  export const migrateCacheHandler = (
9
- oldCache: ApolloCache<NormalizedCacheObject>,
10
- newCache: ApolloCache<NormalizedCacheObject>,
6
+ oldCache: ApolloCache,
7
+ newCache: ApolloCache,
11
8
  migrations: MigrateCache[],
12
9
  ) => {
13
10
  migrations.forEach((migration) => migration(oldCache, newCache))
@@ -22,7 +22,7 @@ function pruneCache(cacheObject: object, patterns: string[]) {
22
22
  }
23
23
 
24
24
  export const createPersistenceMapper =
25
- (createCache: () => ApolloCache<NormalizedCacheObject>) =>
25
+ (createCache: () => ApolloCache) =>
26
26
  (data: string): Promise<string> => {
27
27
  const parsedCache = JSON.parse(data) as NormalizedCacheObject
28
28
 
@@ -1,5 +1,4 @@
1
1
  import type { StrictTypedTypePolicies } from '@graphcommerce/graphql'
2
- import type { KeyFieldsFunction } from '@apollo/client/cache/inmemory/policies'
3
2
  import { mergeDeep } from '../../apollo'
4
3
 
5
4
  export const mergeTypePolicies = (policies: StrictTypedTypePolicies[]): StrictTypedTypePolicies =>
@@ -4,8 +4,8 @@ import { useIsSSR } from '@graphcommerce/next-ui/hooks/useIsSsr'
4
4
  // eslint-disable-next-line import/no-extraneous-dependencies
5
5
  import { getCssFlag, removeCssFlag, setCssFlag } from '@graphcommerce/next-ui/utils/cssFlags'
6
6
  import { useContext, useEffect } from 'react'
7
- import type { MaybeMasked, QueryHookOptions, QueryResult, TypedDocumentNode } from '../apollo'
8
- import { useQuery } from '../apollo'
7
+ import type { MaybeMasked, TypedDocumentNode, useQuery } from '../apollo'
8
+ import { useQuery as useQueryHook } from '../apollo'
9
9
  import { PrivateQueryMaskContext } from '../components/PrivateQueryMask/PrivateQueryMask'
10
10
  import { usePrivateQueryContext } from './usePrivateQueryContext'
11
11
 
@@ -30,9 +30,9 @@ export function usePrivateQuery<
30
30
  V extends { context?: InputMaybe<PrivateContext>; [index: string]: unknown },
31
31
  >(
32
32
  document: TypedDocumentNode<Q, V>,
33
- options: QueryHookOptions<Q, V>,
33
+ options: useQuery.Options<Q, V>,
34
34
  unscopedResult: Q,
35
- ): Omit<QueryResult<Q, V>, 'data'> & { data: Q | NonNullable<MaybeMasked<Q>>; mask: boolean } {
35
+ ): Omit<useQuery.Result<Q, V>, 'data'> & { data: Q | NonNullable<MaybeMasked<Q>>; mask: boolean } {
36
36
  const { skip = true } = options
37
37
  const context = usePrivateQueryContext()
38
38
  const isSsr = useIsSSR()
@@ -45,7 +45,7 @@ export function usePrivateQuery<
45
45
  else if (!context && getCssFlag('private-query')) removeCssFlag('private-query')
46
46
  }, [context, isSsr])
47
47
 
48
- const clientQuery = useQuery<Q, V>(document, {
48
+ const clientQuery = useQueryHook<Q, V>(document, {
49
49
  ...options,
50
50
  variables: { ...options.variables, context } as V,
51
51
  skip: !!privateContext || (skip && !context),
@@ -10,7 +10,7 @@ export function getPrivateQueryContextMesh(
10
10
  }
11
11
 
12
12
  /** Get the private context from the apollo client. */
13
- export function getPrivateQueryContext(_client: ApolloClient<any>): PrivateContext | null {
13
+ export function getPrivateQueryContext(_client: ApolloClient): PrivateContext | null {
14
14
  return null
15
15
  }
16
16
 
@@ -1,9 +1,38 @@
1
- import type { NextLink, Operation } from '../apollo'
2
- import { ApolloLink, removeArgumentsFromDocument, removeDirectivesFromDocument } from '../apollo'
1
+ import type { ApolloLink as ApolloLinkType } from '@apollo/client'
2
+ import { removeDirectivesFromDocument } from '@apollo/client/utilities/internal'
3
+ import type { DocumentNode } from 'graphql'
4
+ import { visit } from 'graphql'
5
+ import { ApolloLink } from '../apollo'
6
+
7
+ /**
8
+ * Remove arguments from a GraphQL document. This is a replacement for the removed
9
+ * removeArgumentsFromDocument from Apollo Client.
10
+ */
11
+ function removeArgumentsFromDocument(
12
+ args: Array<{ name: string }>,
13
+ doc: DocumentNode,
14
+ ): DocumentNode | null {
15
+ const argNames = new Set(args.map((a) => a.name))
16
+
17
+ return visit(doc, {
18
+ Argument(node) {
19
+ if (argNames.has(node.name.value)) {
20
+ return null
21
+ }
22
+ return undefined
23
+ },
24
+ VariableDefinition(node) {
25
+ if (argNames.has(node.variable.name.value)) {
26
+ return null
27
+ }
28
+ return undefined
29
+ },
30
+ })
31
+ }
3
32
 
4
33
  export class RemovePrivateContextDirectivesLink extends ApolloLink {
5
34
  // eslint-disable-next-line class-methods-use-this
6
- request(operation: Operation, forward?: NextLink) {
35
+ request(operation: ApolloLinkType.Operation, forward?: ApolloLinkType.ForwardFunction) {
7
36
  if (!forward) throw new Error('This is not a terminal link!')
8
37
 
9
38
  let modifiedQuery = operation.query
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@graphcommerce/graphql",
3
3
  "homepage": "https://www.graphcommerce.org/",
4
4
  "repository": "github:graphcommerce-org/graphcommerce",
5
- "version": "10.0.0-canary.68",
5
+ "version": "10.0.0",
6
6
  "sideEffects": false,
7
7
  "main": "index.ts",
8
8
  "prettier": "@graphcommerce/prettier-config-pwa",
@@ -13,25 +13,27 @@
13
13
  }
14
14
  },
15
15
  "dependencies": {
16
- "@apollo/client": "^3.14.0",
16
+ "@apollo/client": "^4.0.11",
17
17
  "@graphql-codegen/add": "6.0.0",
18
18
  "@graphql-codegen/fragment-matcher": "6.0.0",
19
19
  "@graphql-codegen/introspection": "5.0.0",
20
20
  "@graphql-codegen/schema-ast": "5.0.0",
21
- "@graphql-codegen/typed-document-node": "6.1.4",
22
- "@graphql-codegen/typescript": "5.0.6",
21
+ "@graphql-codegen/typed-document-node": "6.1.5",
22
+ "@graphql-codegen/typescript": "5.0.7",
23
23
  "@graphql-codegen/typescript-apollo-client-helpers": "3.0.1",
24
- "@graphql-codegen/typescript-document-nodes": "5.0.6",
25
- "@graphql-codegen/typescript-operations": "5.0.6",
24
+ "@graphql-codegen/typescript-document-nodes": "5.0.7",
25
+ "@graphql-codegen/typescript-operations": "5.0.7",
26
26
  "apollo3-cache-persist": "^0.15.0",
27
- "graphql": "^16.12.0"
27
+ "graphql": "^16.12.0",
28
+ "rxjs": "^7.8.2"
28
29
  },
29
30
  "peerDependencies": {
30
- "@graphcommerce/eslint-config-pwa": "^10.0.0-canary.68",
31
- "@graphcommerce/graphql-codegen-near-operation-file": "10.0.0-canary.68",
32
- "@graphcommerce/graphql-codegen-relay-optimizer-plugin": "10.0.0-canary.68",
33
- "@graphcommerce/prettier-config-pwa": "^10.0.0-canary.68",
34
- "@graphcommerce/typescript-config-pwa": "^10.0.0-canary.68",
31
+ "@graphcommerce/eslint-config-pwa": "^10.0.0",
32
+ "@graphcommerce/graphql-codegen-near-operation-file": "10.0.0",
33
+ "@graphcommerce/graphql-codegen-relay-optimizer-plugin": "10.0.0",
34
+ "@graphcommerce/next-config": "^10.0.0",
35
+ "@graphcommerce/prettier-config-pwa": "^10.0.0",
36
+ "@graphcommerce/typescript-config-pwa": "^10.0.0",
35
37
  "@graphql-mesh/plugin-http-details-extensions": "*",
36
38
  "react": "^19.2.0",
37
39
  "react-dom": "^19.2.0"
@@ -40,6 +42,7 @@
40
42
  ".": "./index.ts",
41
43
  "./apollo": "./apollo.ts",
42
44
  "./config": "./config.ts",
45
+ "./rxjs": "./rxjs.ts",
43
46
  "./generated/fragments.json": "./generated/fragments.json"
44
47
  }
45
48
  }
package/rxjs.ts ADDED
@@ -0,0 +1 @@
1
+ export * from 'rxjs'
@@ -1,15 +1,12 @@
1
1
  import type { ApolloClient, FetchPolicy } from '@apollo/client'
2
2
  import { getPreviewData } from './getPreviewData'
3
3
 
4
- export function cachePolicy(
5
- client: ApolloClient<object>,
6
- requestedCachePolicy: FetchPolicy,
7
- ): FetchPolicy {
4
+ export function cachePolicy(client: ApolloClient, requestedCachePolicy: FetchPolicy): FetchPolicy {
8
5
  return process.env.NODE_ENV !== 'development' && !getPreviewData(client)?.preview
9
6
  ? requestedCachePolicy
10
7
  : 'network-only'
11
8
  }
12
9
 
13
- export function cacheFirst(client: ApolloClient<object>) {
10
+ export function cacheFirst(client: ApolloClient) {
14
11
  return cachePolicy(client, 'cache-first')
15
12
  }
@@ -1,7 +1,7 @@
1
1
  import type { ApolloClient } from '@apollo/client'
2
2
  import type { PreviewConfig } from '../config'
3
3
 
4
- export function getPreviewData(client: ApolloClient<object>): PreviewConfig | undefined {
4
+ export function getPreviewData(client: ApolloClient): PreviewConfig | undefined {
5
5
  if ('preview' in client.defaultOptions) return client.defaultOptions.preview as PreviewConfig
6
6
  return undefined
7
7
  }