@apollo/client 4.2.0-alpha.2 → 4.2.0-alpha.4

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.
Files changed (147) hide show
  1. package/CHANGELOG.md +240 -0
  2. package/__cjs/cache/core/cache.cjs +1 -1
  3. package/__cjs/cache/inmemory/entityStore.cjs +3 -3
  4. package/__cjs/cache/inmemory/entityStore.cjs.map +1 -1
  5. package/__cjs/cache/inmemory/key-extractor.cjs +1 -1
  6. package/__cjs/cache/inmemory/policies.cjs +4 -4
  7. package/__cjs/cache/inmemory/readFromStore.cjs +2 -2
  8. package/__cjs/cache/inmemory/writeToStore.cjs +4 -4
  9. package/__cjs/core/ApolloClient.cjs +52 -20
  10. package/__cjs/core/ApolloClient.cjs.map +1 -1
  11. package/__cjs/core/ApolloClient.d.cts +159 -22
  12. package/__cjs/core/ObservableQuery.cjs +7 -7
  13. package/__cjs/core/ObservableQuery.cjs.map +1 -1
  14. package/__cjs/core/ObservableQuery.d.cts +20 -1
  15. package/__cjs/core/QueryManager.cjs +12 -12
  16. package/__cjs/core/QueryManager.cjs.map +1 -1
  17. package/__cjs/core/RefetchEventManager.cjs +134 -0
  18. package/__cjs/core/RefetchEventManager.cjs.map +1 -0
  19. package/__cjs/core/RefetchEventManager.d.cts +130 -0
  20. package/__cjs/core/index.cjs +7 -1
  21. package/__cjs/core/index.cjs.map +1 -1
  22. package/__cjs/core/index.d.cts +4 -1
  23. package/__cjs/core/refetchSources/onlineSource.cjs +10 -0
  24. package/__cjs/core/refetchSources/onlineSource.cjs.map +1 -0
  25. package/__cjs/core/refetchSources/onlineSource.d.cts +3 -0
  26. package/__cjs/core/refetchSources/windowFocusSource.cjs +13 -0
  27. package/__cjs/core/refetchSources/windowFocusSource.cjs.map +1 -0
  28. package/__cjs/core/refetchSources/windowFocusSource.d.cts +3 -0
  29. package/__cjs/core/types.d.cts +20 -0
  30. package/__cjs/invariantErrorCodes.cjs +69 -44
  31. package/__cjs/link/ws/index.cjs +9 -1
  32. package/__cjs/link/ws/index.cjs.map +1 -1
  33. package/__cjs/link/ws/index.d.cts +1 -1
  34. package/__cjs/react/hooks/useBackgroundQuery.cjs.map +1 -1
  35. package/__cjs/react/hooks/useBackgroundQuery.d.cts +1486 -66
  36. package/__cjs/react/hooks/useLazyQuery.cjs +1 -0
  37. package/__cjs/react/hooks/useLazyQuery.cjs.map +1 -1
  38. package/__cjs/react/hooks/useLazyQuery.d.cts +366 -40
  39. package/__cjs/react/hooks/useLoadableQuery.cjs.map +1 -1
  40. package/__cjs/react/hooks/useLoadableQuery.d.cts +512 -50
  41. package/__cjs/react/hooks/useMutation.cjs +5 -48
  42. package/__cjs/react/hooks/useMutation.cjs.map +1 -1
  43. package/__cjs/react/hooks/useMutation.d.cts +239 -130
  44. package/__cjs/react/hooks/useQuery.cjs.map +1 -1
  45. package/__cjs/react/hooks/useQuery.d.cts +590 -41
  46. package/__cjs/react/hooks/useSubscription.cjs +1 -1
  47. package/__cjs/react/hooks/useSubscription.cjs.map +1 -1
  48. package/__cjs/react/hooks/useSubscription.d.cts +2 -2
  49. package/__cjs/react/hooks/useSuspenseQuery.cjs.map +1 -1
  50. package/__cjs/react/hooks/useSuspenseQuery.d.cts +754 -46
  51. package/__cjs/react/internal/cache/QueryReference.cjs +1 -0
  52. package/__cjs/react/internal/cache/QueryReference.cjs.map +1 -1
  53. package/__cjs/react/internal/cache/QueryReference.d.cts +1 -1
  54. package/__cjs/react/query-preloader/createQueryPreloader.cjs.map +1 -1
  55. package/__cjs/react/query-preloader/createQueryPreloader.d.cts +20 -1
  56. package/__cjs/react/types/types.documentation.d.cts +19 -0
  57. package/__cjs/version.cjs +1 -1
  58. package/cache/core/cache.js +1 -1
  59. package/cache/inmemory/entityStore.js +3 -3
  60. package/cache/inmemory/entityStore.js.map +1 -1
  61. package/cache/inmemory/key-extractor.js +1 -1
  62. package/cache/inmemory/policies.js +4 -4
  63. package/cache/inmemory/readFromStore.js +2 -2
  64. package/cache/inmemory/writeToStore.js +4 -4
  65. package/core/ApolloClient.d.ts +159 -22
  66. package/core/ApolloClient.js +53 -21
  67. package/core/ApolloClient.js.map +1 -1
  68. package/core/ObservableQuery.d.ts +20 -1
  69. package/core/ObservableQuery.js +7 -7
  70. package/core/ObservableQuery.js.map +1 -1
  71. package/core/QueryManager.js +12 -12
  72. package/core/QueryManager.js.map +1 -1
  73. package/core/RefetchEventManager.d.ts +130 -0
  74. package/core/RefetchEventManager.js +126 -0
  75. package/core/RefetchEventManager.js.map +1 -0
  76. package/core/index.d.ts +4 -1
  77. package/core/index.js +3 -0
  78. package/core/index.js.map +1 -1
  79. package/core/refetchSources/onlineSource.d.ts +3 -0
  80. package/core/refetchSources/onlineSource.js +6 -0
  81. package/core/refetchSources/onlineSource.js.map +1 -0
  82. package/core/refetchSources/windowFocusSource.d.ts +3 -0
  83. package/core/refetchSources/windowFocusSource.js +9 -0
  84. package/core/refetchSources/windowFocusSource.js.map +1 -0
  85. package/core/types.d.ts +20 -0
  86. package/core/types.js.map +1 -1
  87. package/invariantErrorCodes.js +69 -44
  88. package/link/ws/index.d.ts +1 -1
  89. package/link/ws/index.js +9 -1
  90. package/link/ws/index.js.map +1 -1
  91. package/package.json +3 -7
  92. package/react/hooks/useBackgroundQuery.d.ts +1486 -66
  93. package/react/hooks/useBackgroundQuery.js.map +1 -1
  94. package/react/hooks/useLazyQuery.d.ts +366 -40
  95. package/react/hooks/useLazyQuery.js +1 -0
  96. package/react/hooks/useLazyQuery.js.map +1 -1
  97. package/react/hooks/useLoadableQuery.d.ts +512 -50
  98. package/react/hooks/useLoadableQuery.js.map +1 -1
  99. package/react/hooks/useMutation.d.ts +239 -130
  100. package/react/hooks/useMutation.js +5 -48
  101. package/react/hooks/useMutation.js.map +1 -1
  102. package/react/hooks/useQuery.d.ts +590 -41
  103. package/react/hooks/useQuery.js.map +1 -1
  104. package/react/hooks/useSubscription.d.ts +2 -2
  105. package/react/hooks/useSubscription.js +1 -1
  106. package/react/hooks/useSubscription.js.map +1 -1
  107. package/react/hooks/useSuspenseQuery.d.ts +754 -46
  108. package/react/hooks/useSuspenseQuery.js.map +1 -1
  109. package/react/hooks-compiled/useBackgroundQuery.d.ts +1486 -66
  110. package/react/hooks-compiled/useBackgroundQuery.js.map +1 -1
  111. package/react/hooks-compiled/useLazyQuery.d.ts +366 -40
  112. package/react/hooks-compiled/useLazyQuery.js +1 -0
  113. package/react/hooks-compiled/useLazyQuery.js.map +1 -1
  114. package/react/hooks-compiled/useLoadableQuery.d.ts +512 -50
  115. package/react/hooks-compiled/useLoadableQuery.js.map +1 -1
  116. package/react/hooks-compiled/useMutation.d.ts +239 -130
  117. package/react/hooks-compiled/useMutation.js +4 -47
  118. package/react/hooks-compiled/useMutation.js.map +1 -1
  119. package/react/hooks-compiled/useQuery.d.ts +590 -41
  120. package/react/hooks-compiled/useQuery.js.map +1 -1
  121. package/react/hooks-compiled/useSubscription.d.ts +2 -2
  122. package/react/hooks-compiled/useSubscription.js +1 -1
  123. package/react/hooks-compiled/useSubscription.js.map +1 -1
  124. package/react/hooks-compiled/useSuspenseQuery.d.ts +754 -46
  125. package/react/hooks-compiled/useSuspenseQuery.js.map +1 -1
  126. package/react/internal/cache/QueryReference.d.ts +1 -1
  127. package/react/internal/cache/QueryReference.js +1 -0
  128. package/react/internal/cache/QueryReference.js.map +1 -1
  129. package/react/query-preloader/createQueryPreloader.d.ts +20 -1
  130. package/react/query-preloader/createQueryPreloader.js.map +1 -1
  131. package/react/types/types.documentation.d.ts +19 -0
  132. package/react/types/types.documentation.js.map +1 -1
  133. package/skills/apollo-client/SKILL.md +168 -0
  134. package/skills/apollo-client/references/caching.md +560 -0
  135. package/skills/apollo-client/references/error-handling.md +350 -0
  136. package/skills/apollo-client/references/fragments.md +804 -0
  137. package/skills/apollo-client/references/integration-client.md +336 -0
  138. package/skills/apollo-client/references/integration-nextjs.md +325 -0
  139. package/skills/apollo-client/references/integration-react-router.md +256 -0
  140. package/skills/apollo-client/references/integration-tanstack-start.md +378 -0
  141. package/skills/apollo-client/references/mutations.md +549 -0
  142. package/skills/apollo-client/references/queries.md +416 -0
  143. package/skills/apollo-client/references/state-management.md +428 -0
  144. package/skills/apollo-client/references/suspense-hooks.md +773 -0
  145. package/skills/apollo-client/references/troubleshooting.md +487 -0
  146. package/skills/apollo-client/references/typescript-codegen.md +133 -0
  147. package/version.js +1 -1
@@ -0,0 +1,350 @@
1
+ # Error Handling Reference (Apollo Client 4.x)
2
+
3
+ Note that Apollo Client 4.x handles errors differently than Apollo Client 3.x.
4
+ This reference documents the updated error handling mechanisms, error types, and best practices for managing errors in your Apollo Client applications.
5
+ For older Apollo Client 3.x error handling documentation, see [Apollo Client 3.x Error Handling](https://www.apollographql.com/docs/react/v3/data/error-handling).
6
+
7
+ ## Table of Contents
8
+
9
+ - [Understanding Errors](#understanding-errors)
10
+ - [Error Types](#error-types)
11
+ - [Identifying Error Types](#identifying-error-types)
12
+ - [GraphQL Error Policies](#graphql-error-policies)
13
+ - [Error Links](#error-links)
14
+ - [Retry Link](#retry-link)
15
+ - [Error Boundaries](#error-boundaries)
16
+
17
+ ## Understanding Errors
18
+
19
+ Errors in Apollo Client fall into two main categories: **GraphQL errors** and **network errors**. Each category has specific error classes that provide detailed information about what went wrong.
20
+
21
+ ### GraphQL Errors
22
+
23
+ GraphQL errors are related to server-side execution of a GraphQL operation:
24
+
25
+ - **Syntax errors** (e.g., malformed query)
26
+ - **Validation errors** (e.g., query includes a non-existent schema field)
27
+ - **Resolver errors** (e.g., error while populating a query field)
28
+
29
+ If a syntax or validation error occurs, the server doesn't execute the operation. If resolver errors occur, the server can still return partial data.
30
+
31
+ Example server response with GraphQL error:
32
+
33
+ ```json
34
+ {
35
+ "errors": [
36
+ {
37
+ "message": "Cannot query field \"nonexistentField\" on type \"Query\".",
38
+ "locations": [{ "line": 2, "column": 3 }],
39
+ "extensions": {
40
+ "code": "GRAPHQL_VALIDATION_FAILED"
41
+ }
42
+ }
43
+ ],
44
+ "data": null
45
+ }
46
+ ```
47
+
48
+ In Apollo Client 4.x, GraphQL errors are represented by the [`CombinedGraphQLErrors`](https://apollographql.com/docs/react/api/errors/CombinedGraphQLErrors) error type.
49
+
50
+ ### Network Errors
51
+
52
+ Network errors occur when attempting to communicate with your GraphQL server:
53
+
54
+ - `4xx` or `5xx` HTTP response status codes
55
+ - Network unavailability
56
+ - JSON parsing failures
57
+ - Custom errors from Apollo Link request handlers
58
+
59
+ Network errors might be represented by special error types, but if an api such as the `fetch` API throws a native error (e.g., `TypeError`), Apollo Client will pass it through as-is.
60
+ Thrown values that don't fulfill the standard `ErrorLike` interface are wrapped in the [`UnconventionalError`](https://apollographql.com/docs/react/api/errors/UnconventionalError) class, which fulfills the `ErrorLike` interface. As such, you can expect any error returned by Apollo Client to fulfill the `ErrorLike` interface.
61
+
62
+ ```ts
63
+ export interface ErrorLike {
64
+ message: string;
65
+ name: string;
66
+ stack?: string;
67
+ }
68
+ ```
69
+
70
+ ## Error Types
71
+
72
+ Apollo Client 4.x provides specific error classes for different error scenarios:
73
+
74
+ ### CombinedGraphQLErrors
75
+
76
+ Represents GraphQL errors returned by the server. Most common error type in applications.
77
+
78
+ ```tsx
79
+ import { CombinedGraphQLErrors } from "@apollo/client/errors";
80
+
81
+ function UserProfile({ userId }: { userId: string }) {
82
+ const { data, error } = useQuery(GET_USER, {
83
+ variables: { id: userId },
84
+ });
85
+
86
+ // no need to check for nullishness of error, CombinedGraphQLErrors.is handles that
87
+ if (CombinedGraphQLErrors.is(error)) {
88
+ // Handle GraphQL errors
89
+ return (
90
+ <div>
91
+ {error.graphQLErrors.map((err, i) => (
92
+ <p key={i}>GraphQL Error: {err.message}</p>
93
+ ))}
94
+ </div>
95
+ );
96
+ }
97
+
98
+ return data ? <Profile user={data.user} /> : null;
99
+ }
100
+ ```
101
+
102
+ ### CombinedProtocolErrors
103
+
104
+ Represents fatal transport-level errors during multipart HTTP subscription execution.
105
+
106
+ ### ServerError
107
+
108
+ Occurs when the server responds with a non-200 HTTP status code.
109
+
110
+ ```tsx
111
+ import { ServerError } from "@apollo/client/errors";
112
+
113
+ if (ServerError.is(error)) {
114
+ console.error("Server error:", error.statusCode, error.result);
115
+ }
116
+ ```
117
+
118
+ ### ServerParseError
119
+
120
+ Occurs when the server response cannot be parsed as valid JSON.
121
+
122
+ ```tsx
123
+ import { ServerParseError } from "@apollo/client/errors";
124
+
125
+ if (ServerParseError.is(error)) {
126
+ console.error("Invalid JSON response:", error.bodyText);
127
+ }
128
+ ```
129
+
130
+ ### LocalStateError
131
+
132
+ Represents errors in local state configuration or execution.
133
+
134
+ ### UnconventionalError
135
+
136
+ Wraps non-standard errors (e.g., thrown symbols or objects) to ensure consistent error handling.
137
+
138
+ ## Identifying Error Types
139
+
140
+ Every Apollo Client error class provides a static `is` method that reliably determines whether an error is of that specific type. This is more robust than `instanceof` because it avoids false positives/negatives.
141
+
142
+ ```ts
143
+ import {
144
+ CombinedGraphQLErrors,
145
+ CombinedProtocolErrors,
146
+ LocalStateError,
147
+ ServerError,
148
+ ServerParseError,
149
+ UnconventionalError,
150
+ ErrorLike,
151
+ } from "@apollo/client/errors";
152
+
153
+ // Anything returned in the `error` field of Apollo Client hooks or methods is of type `ErrorLike` or `undefined`.
154
+ function handleError(error?: ErrorLike) {
155
+ if (CombinedGraphQLErrors.is(error)) {
156
+ // Handle GraphQL errors
157
+ console.error("GraphQL errors:", error.graphQLErrors);
158
+ } else if (CombinedProtocolErrors.is(error)) {
159
+ // Handle multipart subscription protocol errors
160
+ } else if (LocalStateError.is(error)) {
161
+ // Handle errors thrown by the LocalState class
162
+ } else if (ServerError.is(error)) {
163
+ // Handle server HTTP errors
164
+ console.error("Server error:", error.statusCode);
165
+ } else if (ServerParseError.is(error)) {
166
+ // Handle JSON parse errors
167
+ } else if (UnconventionalError.is(error)) {
168
+ // Handle errors thrown by irregular types
169
+ } else if (error) {
170
+ // Handle other errors
171
+ }
172
+ }
173
+ ```
174
+
175
+ ## GraphQL Error Policies
176
+
177
+ If a GraphQL operation produces errors, the server's response might still include partial data:
178
+
179
+ ```json
180
+ {
181
+ "data": {
182
+ "getInt": 12,
183
+ "getString": null
184
+ },
185
+ "errors": [
186
+ {
187
+ "message": "Failed to get string!"
188
+ }
189
+ ]
190
+ }
191
+ ```
192
+
193
+ By default, Apollo Client throws away partial data and populates the `error` field. You can use partial results by defining an **error policy**:
194
+
195
+ | Policy | Description |
196
+ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
197
+ | `none` | (Default) If the response includes errors, they are returned in `error` and response `data` is set to `undefined` even if the server returns `data`. |
198
+ | `ignore` | Errors are ignored (`error` is not populated), and any returned `data` is cached and rendered as if no errors occurred. `data` may be `undefined` if a network error occurs. |
199
+ | `all` | Both `data` and `error` are populated and any returned `data` is cached, enabling you to render both partial results and error information. |
200
+
201
+ ### Setting an Error Policy
202
+
203
+ ```tsx
204
+ const MY_QUERY = gql`
205
+ query WillFail {
206
+ badField # This field's resolver produces an error
207
+ goodField # This field is populated successfully
208
+ }
209
+ `;
210
+
211
+ function ShowingSomeErrors() {
212
+ const { loading, error, data } = useQuery(MY_QUERY, { errorPolicy: "all" });
213
+
214
+ if (loading) return <span>loading...</span>;
215
+
216
+ return (
217
+ <div>
218
+ <h2>Good: {data?.goodField}</h2>
219
+ {error && <pre>Bad: {error.message}</pre>}
220
+ </div>
221
+ );
222
+ }
223
+ ```
224
+
225
+ ### Avoid setting a Global Error Policy
226
+
227
+ While it is possible to set a global error policy using `defaultOptions`, in practice this is discouraged as it can lead to unexpected behavior and type safety issues. The return types of the TypeScript hooks may change depending on the `errorPolicy` passed into the hook, and this can conceptually not take global `defaultOptions` error policies into account. As such, it is best to set the `errorPolicy` per operation as needed.
228
+
229
+ ## Error Links
230
+
231
+ The `ErrorLink` can be used to e.g. log error globally or perform specific side effects based on errors happening.
232
+
233
+ An `ErrorLink` can't be used to swallow errors fully, but it can be used to retry an operation after handling an error, in which case the error wouldn't propagate. Otherwise, the most common use for `ErrorLink` is logging.
234
+
235
+ ```ts
236
+ import { ErrorLink } from "@apollo/client/link/error";
237
+
238
+ const errorLink = new ErrorLink(({ error, operation, forward }) => {
239
+ if (someCondition(error)) {
240
+ // Retry the request, returning the new observable
241
+ return forward(operation);
242
+ }
243
+
244
+ // Log the error for any unhandled GraphQL errors or network errors.
245
+ console.log(`[Error]: ${error.message}`);
246
+
247
+ // If nothing is returned from the error handler callback, the error will be
248
+ // emitted from the link chain as normal.
249
+ });
250
+ ```
251
+
252
+ ### Retry Link
253
+
254
+ Alternatively, you can use the `RetryLink` from `@apollo/client/link/retry` to implement retry logic for failed operations.
255
+
256
+ ```typescript
257
+ import { RetryLink } from "@apollo/client/link/retry";
258
+
259
+ const retryLink = new RetryLink({
260
+ delay: {
261
+ initial: 300,
262
+ max: Infinity,
263
+ jitter: true,
264
+ },
265
+ attempts: {
266
+ max: 5,
267
+ retryIf: (error, operation) => {
268
+ // Retry on network errors
269
+ return !!error && operation.operationName !== "SensitiveOperation";
270
+ },
271
+ },
272
+ });
273
+
274
+ const client = new ApolloClient({
275
+ cache: new InMemoryCache(),
276
+ link: from([retryLink, errorLink, httpLink]),
277
+ });
278
+ ```
279
+
280
+ ### Custom Retry Logic
281
+
282
+ ```typescript
283
+ const retryLink = new RetryLink({
284
+ attempts: (count, operation, error) => {
285
+ // Don't retry mutations
286
+ if (
287
+ operation.query.definitions.some(
288
+ (def) =>
289
+ def.kind === "OperationDefinition" && def.operation === "mutation"
290
+ )
291
+ ) {
292
+ return false;
293
+ }
294
+
295
+ // Retry up to 3 times on network errors
296
+ return count < 3 && !!error;
297
+ },
298
+ delay: (count) => {
299
+ // Exponential backoff
300
+ return Math.min(1000 * Math.pow(2, count), 30000);
301
+ },
302
+ });
303
+ ```
304
+
305
+ ## Error Boundaries
306
+
307
+ When using suspenseful hooks, you should use React Error Boundaries for graceful error handling.
308
+
309
+ ### Non-suspense per-Component Error Handling
310
+
311
+ ```tsx
312
+ import {
313
+ CombinedGraphQLErrors,
314
+ ServerError,
315
+ ServerParseError,
316
+ } from "@apollo/client/errors";
317
+
318
+ function SafeUserList() {
319
+ const { data, error, loading, refetch } = useQuery(GET_USERS, {
320
+ errorPolicy: "all",
321
+ notifyOnNetworkStatusChange: true,
322
+ });
323
+
324
+ // Handle network errors
325
+ if (ServerError.is(error) || ServerParseError.is(error)) {
326
+ return (
327
+ <Alert severity="error">
328
+ <AlertTitle>Connection Error</AlertTitle>
329
+ Failed to load users. Please check your internet connection.
330
+ <Button onClick={() => refetch()}>Retry</Button>
331
+ </Alert>
332
+ );
333
+ }
334
+
335
+ // Handle GraphQL errors but still show available data
336
+ return (
337
+ <div>
338
+ {CombinedGraphQLErrors.is(error) && (
339
+ <Alert severity="warning">
340
+ Some data may be incomplete: {error.graphQLErrors[0].message}
341
+ </Alert>
342
+ )}
343
+
344
+ {loading && <LinearProgress />}
345
+
346
+ {data?.users && <UserList users={data.users} />}
347
+ </div>
348
+ );
349
+ }
350
+ ```