Skip to content

Commit 8c6c6cd

Browse files
committed
Update SetContextLink
1 parent 3dd2b95 commit 8c6c6cd

2 files changed

Lines changed: 135 additions & 27 deletions

File tree

Lines changed: 87 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,55 @@
11
---
2-
title: Context Link
2+
title: SetContextLink
33
description: Easily set a context on your operation, which is used by other links further down the chain.
44
---
55

6-
## Overview
6+
<DocBlock
7+
canonicalReference="@apollo/client/link/context!SetContextLink:class"
8+
customOrder={["summary", "remarks", "example"]}
9+
/>
710

8-
The `setContext` function accepts a function that returns either an object or a promise, which then returns an object to set the new context of a request. It receives two arguments: the GraphQL request being executed, and the previous context. This link makes it easy to perform the asynchronous lookup of things like authentication tokens and more.
11+
## Constructor signature
912

10-
```js
11-
import { setContext } from "@apollo/client/link/context";
12-
13-
const setAuthorizationLink = setContext((request, previousContext) => ({
14-
headers: { authorization: "1234" },
15-
}));
16-
17-
const asyncAuthLink = setContext(
18-
(request) =>
19-
new Promise((success, fail) => {
20-
// do some async lookup here
21-
setTimeout(() => {
22-
success({ token: "async found token" });
23-
}, 10);
24-
})
25-
);
13+
```ts
14+
constructor(
15+
setter: SetContextLink.ContextSetter
16+
): SetContextLink
17+
```
18+
19+
## Usage examples
20+
21+
### Authentication
22+
23+
The most common use case is adding authentication headers to requests:
24+
25+
```ts
26+
const authLink = new SetContextLink((prevContext, operation) => {
27+
const token = getAuthToken();
28+
29+
return {
30+
headers: {
31+
...prevContext.headers,
32+
authorization: token ? `Bearer ${token}` : "",
33+
},
34+
};
35+
});
36+
```
37+
38+
### Asynchronous token lookup
39+
40+
You can also perform asynchronous operations to fetch tokens or other data:
41+
42+
```ts
43+
const asyncAuthLink = new SetContextLink(async (prevContext, operation) => {
44+
const token = await fetchAuthToken();
45+
46+
return {
47+
headers: {
48+
...prevContext.headers,
49+
authorization: `Bearer ${token}`,
50+
},
51+
};
52+
});
2653
```
2754

2855
## Caching lookups
@@ -33,19 +60,30 @@ Take for example a user auth token being found, cached, then removed on a 401 re
3360

3461
```js
3562
import { ServerError } from "@apollo/client";
36-
import { setContext } from "@apollo/client/link/context";
37-
import { ErrorLink } from "@apollo/client/link/error";
63+
import { SetContextLink } from "@apollo/client/link/context";
64+
import { onError } from "@apollo/client/link/error";
3865

3966
// cached storage for the user token
4067
let token;
41-
const withToken = setContext(() => {
68+
const withToken = new SetContextLink(async (prevContext, operation) => {
4269
// if you have a cached value, return it immediately
43-
if (token) return { token };
70+
if (token) {
71+
return {
72+
headers: {
73+
...prevContext.headers,
74+
authorization: `Bearer ${token}`,
75+
},
76+
};
77+
}
4478

45-
return AsyncTokenLookup().then((userToken) => {
46-
token = userToken;
47-
return { token };
48-
});
79+
const userToken = await AsyncTokenLookup();
80+
token = userToken;
81+
return {
82+
headers: {
83+
...prevContext.headers,
84+
authorization: `Bearer ${token}`,
85+
},
86+
};
4987
});
5088

5189
const resetToken = new ErrorLink(({ error }) => {
@@ -57,3 +95,25 @@ const resetToken = new ErrorLink(({ error }) => {
5795

5896
const authFlowLink = withToken.concat(resetToken);
5997
```
98+
99+
## Types
100+
101+
<FunctionDetails
102+
canonicalReference="@apollo/client/link/context!SetContextLink.SetContextLinkDocumentationTypes.ContextSetter:function(1)"
103+
headingLevel={3}
104+
result={false}
105+
displayName="SetContextLink.ContextSetter"
106+
/>
107+
108+
### `SetContextLink.SetContextOperation`
109+
110+
<DocBlock canonicalReference="@apollo/client/link/context!SetContextLink.SetContextOperation:type" />
111+
112+
#### Signature
113+
114+
```ts
115+
type SetContextOperation = Omit<
116+
ApolloLink.Operation,
117+
"getContext" | "setContext"
118+
>;
119+
```

src/link/context/index.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,31 @@ import { Observable } from "rxjs";
33
import { ApolloLink } from "@apollo/client/link";
44

55
export declare namespace SetContextLink {
6+
namespace SetContextLinkDocumentationTypes {
7+
/**
8+
* A function that returns an updated context object for an Apollo Link
9+
* operation.
10+
*
11+
* The context setter function is called for each operation and allows you to
12+
* modify the operation's context before it's passed to the next link in the
13+
* chain. The returned context object is shallowly merged with the previous
14+
* context object.
15+
*
16+
* @param prevContext - The previous context of the operation (e.g. the value
17+
* of `operation.getContext()`)
18+
* @param operation - The GraphQL operation being executed, without the
19+
* `getContext` and `setContext` methods
20+
* @returns A partial context object or a promise that resolves to a partial context object
21+
*/
22+
export function ContextSetter(
23+
prevContext: Readonly<ApolloLink.OperationContext>,
24+
operation: SetContextLink.SetContextOperation
25+
):
26+
| Promise<Partial<ApolloLink.OperationContext>>
27+
| Partial<ApolloLink.OperationContext>;
28+
}
29+
30+
/** {@inheritDoc @apollo/client/link/context!SetContextLink.SetContextLinkDocumentationTypes.ContextSetter:function(1)} */
631
export type ContextSetter = (
732
prevContext: Readonly<ApolloLink.OperationContext>,
833
operation: SetContextLink.SetContextOperation
@@ -22,6 +47,11 @@ export declare namespace SetContextLink {
2247
| Promise<Partial<ApolloLink.OperationContext>>
2348
| Partial<ApolloLink.OperationContext>;
2449

50+
/**
51+
* An `ApolloLink.Operation` object without the `getContext` and `setContext`
52+
* methods. This prevents context setters from directly manipulating the
53+
* context during the setter function execution.
54+
*/
2555
export type SetContextOperation = Omit<
2656
ApolloLink.Operation,
2757
"getContext" | "setContext"
@@ -45,6 +75,24 @@ export function setContext(setter: SetContextLink.LegacyContextSetter) {
4575
setter(operation, prevContext)
4676
);
4777
}
78+
/**
79+
* `SetContextLink` is a non-terminating link that allows you to modify the
80+
* context of GraphQL operations before they're passed to the next link in the
81+
* chain. This is commonly used for authentication, adding headers, and other
82+
* request-time configuration.
83+
*
84+
* @example
85+
*
86+
* ```ts
87+
* import { SetContextLink } from "@apollo/client/link/context";
88+
*
89+
* const link = new SetContextLink((prevContext, operation) => {
90+
* return {
91+
* // ...
92+
* };
93+
* });
94+
* ```
95+
*/
4896
export class SetContextLink extends ApolloLink {
4997
constructor(setter: SetContextLink.ContextSetter) {
5098
super((operation, forward) => {

0 commit comments

Comments
 (0)