···11+---
22+'@urql/core': minor
33+---
44+55+Implement `mapExchange`, which replaces `errorExchange`, allowing `onOperation` and `onResult` to be called to either react to or replace operations and results. For backwards compatibility, this exchange is also exported as `errorExchange` and supports `onError`.
+12-10
docs/advanced/authentication.md
···325325326326[Read more about `@urql/exchange-auth`'s API in our API docs.](../api/auth-exchange.md)
327327328328-## Handling Logout with the Error Exchange
328328+## Handling Logout by reacting to Errors
329329330330-We can also handle authentication errors in an `errorExchange` instead of the `authExchange`. To do this, we'll need to add the
331331-`errorExchange` to the exchanges array, _before_ the `authExchange`. The order is very important here:
330330+We can also handle authentication errors in a `mapExchange` instead of the `authExchange`.
331331+To do this, we'll need to add the `mapExchange` to the exchanges array, _before_ the `authExchange`.
332332+The order is very important here:
332333333334```js
334335import { createClient, dedupExchange, cacheExchange, fetchExchange, errorExchange } from 'urql';
···339340 exchanges: [
340341 dedupExchange,
341342 cacheExchange,
342342- errorExchange({
343343- onError: error => {
343343+ mapExchange({
344344+ onError(error, _operation) {
344345 const isAuthError = error.graphQLErrors.some(e => e.extensions?.code === 'FORBIDDEN');
345345-346346 if (isAuthError) {
347347 logout();
348348 }
···356356});
357357```
358358359359-The `errorExchange` will only receive an auth error when the auth exchange has already tried and failed to handle it. This means we have
360360-either failed to refresh the token, or there is no token refresh functionality. If we receive an auth error in the `errorExchange` (as defined in
361361-the `didAuthError` configuration section above), then we can be confident that it is an auth error that the `authExchange` isn't able to recover
362362-from, and the user should be logged out.
359359+The `mapExchange` will only receive an auth error when the auth exchange has already tried and failed
360360+to handle it. This means we have either failed to refresh the token, or there is no token refresh
361361+functionality. If we receive an auth error in the `mapExchange`'s `onError` function
362362+(as defined in the `didAuthError` configuration section above), then we can be confident that it is
363363+an authentication error that the `authExchange` isn't able to recover from, and the user should be
364364+logged out.
363365364366## Cache Invalidation on Logout
365367
+58-6
docs/api/core.md
···322322An exchange that writes incoming `Operation`s to `console.log` and
323323writes completed `OperationResult`s to `console.log`.
324324325325+This exchange is disabled in production and is based on the `mapExchange`.
326326+If you'd like to customise it, you can replace it with a custom `mapExchange`.
327327+325328### dedupExchange
326329327330An exchange that keeps track of ongoing `Operation`s that haven't returned had
···334337The `fetchExchange` of type `Exchange` is responsible for sending operations of type `'query'` and
335338`'mutation'` to a GraphQL API using `fetch`.
336339337337-### errorExchange
340340+### mapExchange
338341339339-An exchange that lets you inspect errors. This can be useful for logging, or reacting to
340340-different types of errors (e.g. logging the user out in case of a permission error).
342342+The `mapExchange` allows you to:
343343+344344+- react to or replace operations with `onOperation`,
345345+- react to or replace results with `onResult`,
346346+- and; react to errors in results with `onError`.
347347+348348+It can therefore be used to quickly react to the core events in the `Client` without writing a custom
349349+exchange, effectively allowing you to ship your own `debugExchange`.
341350342351```ts
343343-errorExchange({
344344- onError: (error: CombinedError, operation: Operation) => {
345345- console.log('An error!', error);
352352+mapExchange({
353353+ onOperation(operation) {
354354+ console.log('operation', operation);
355355+ },
356356+ onResult(result) {
357357+ console.log('result', result);
346358 },
347359});
348360```
361361+362362+It can also be used to react only to errors, which is the same as checking for `result.error`:
363363+364364+```ts
365365+mapExchange({
366366+ onError(error, operation) {
367367+ console.log(`The operation ${operation.key} has errored with:`, error);
368368+ },
369369+});
370370+```
371371+372372+Lastly, it can be used to map operations and results, which may be useful to update the
373373+`OperationContext` or perform other standard tasks that require you to wait for a result:
374374+375375+```ts
376376+import { mapExchange, makeOperation } from '@urql/core';
377377+378378+mapExchange({
379379+ async onOperation(operation) {
380380+ // NOTE: This is only for illustration purposes
381381+ return makeOperation(operation.kind, operation, {
382382+ ...operation.context,
383383+ test: true,
384384+ });
385385+ },
386386+ async onResult(result) {
387387+ // NOTE: This is only for illustration purposes
388388+ if (result.data === undefined) result.data = null;
389389+ return result;
390390+ },
391391+});
392392+```
393393+394394+### errorExchange (deprecated)
395395+396396+An exchange that lets you inspect errors. This can be useful for logging, or reacting to
397397+different types of errors (e.g. logging the user out in case of a permission error).
398398+399399+In newer versions of `@urql/core`, it's identical to the `mapExchange` and its export has been
400400+replaced as the `mapExchange` also allows you to pass an `onError` function.
349401350402## Utilities
351403
+1-1
docs/architecture.md
···138138139139Some of the exchanges that are available to us are:
140140141141-- [`errorExchange`](./api/core.md#errorexchange): Allows a global callback to be called when any error occurs
141141+- [`mapExchange`](./api/core.md#mapexchange): Allows reacting to operations, results, and errors
142142- [`ssrExchange`](./advanced/server-side-rendering.md): Allows for a server-side renderer to
143143 collect results for client-side rehydration.
144144- [`retryExchange`](./advanced/retry-operations.md): Allows operations to be retried