You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/source/api/link/introduction.mdx
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -517,6 +517,12 @@ const link = new OperationCountLink();
517
517
518
518
As an operation moves along the link chain, it maintains a `context` that each link can read and modify. This enables both links and request-based APIs (such as [`useQuery`](../react/useQuery)) to pass metadata along the chain that other links use in their execution logic. Context is not included in the terminating link's request to the GraphQL server or other destination.
519
519
520
+
<Note>
521
+
522
+
If your application is built using TypeScript, we recommend reading the [Defining context types](../../development-testing/static-typing#defining-context-types) guide to learn how to provide types for the context object.
523
+
524
+
</Note>
525
+
520
526
### Reading context
521
527
522
528
You get the current context object by calling `operation.getContext()` in a [request handler](#the-request-handler).
Copy file name to clipboardExpand all lines: docs/source/data/fragments.mdx
+159Lines changed: 159 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1286,6 +1286,31 @@ To migrate from CodeGen's fragment masking feature to Apollo Client's data maski
1286
1286
1287
1287
3. [Enable data masking](#enabling-data-masking) in Apollo Client.
1288
1288
1289
+
#### Setting data masking types
1290
+
1291
+
By default, Apollo Client makes no modification to the operation types provided to its APIs, regardless of whether the type definitions are masked or unmasked. This provides a simpler upgrade path when you're ready to [incrementally adopt](#incremental-adoption-in-an-existing-application) data masking.
1292
+
1293
+
To use GraphQL Codegen's masking format with your operation types, you need to tell Apollo Client to use the associated GraphQL Codegen masking types. You do this by defining a [type override](../development-testing/static-typing#overriding-type-implementations-of-built-in-types) that uses the GraphQL Codegen masking format.
1294
+
1295
+
Create a TypeScript file that will be used to modify the `TypeOverrides` interface. Extend `TypeOverrides` with the `GraphQLCodegenDataMasking.TypeOverrides` interface.
1296
+
1297
+
```ts title="apollo-client.d.ts"
1298
+
// This import is necessary to ensure all Apollo Client imports
1299
+
// are still available to the rest of the application.
This example uses `apollo-client.d.ts` as the file name to make it easily identifiable. You can give this file any name.
1311
+
1312
+
</Note>
1313
+
1289
1314
#### Using with fragments
1290
1315
1291
1316
When using [colocated fragments](#colocating-fragments) with your components, it's best to ensure the object passed to your component is done in a type-safe way. This means:
@@ -1519,3 +1544,137 @@ query GetPosts {
1519
1544
Repeat this process until all `@unmask` directives have been removed from your codebase.
1520
1545
1521
1546
Congratulations 🎉! Your application is now using data masking everywhere 😎.
1547
+
1548
+
### Defining your own masking types using higher-kinded types
1549
+
1550
+
<Note>
1551
+
1552
+
If you are using the [data masking types generated from GraphQL Codegen](#setting-data-masking-types), you can safely skip this section.
1553
+
1554
+
</Note>
1555
+
1556
+
Apollo Client provides an [integration](#setting-data-masking-types) with GraphQL Codegen's [fragment masking](https://the-guild.dev/graphql/codegen/plugins/presets/preset-client#fragment-masking) output and orients its masking utility types around this format. If you aren't using GraphQL Codegen to generate your types, or your types are generated in a different format, the type implementations built into Apollo Client might be incompatible which results in inaccurate types.
1557
+
1558
+
You can use a technique called _higher-kinded types_ (HKT) to provide your own type implementations for Apollo Client's masking types. You can think of higher-kinded types as a way to define types and interfaces with generics that can be filled in by Apollo Client internals at a later time. Passing around un-evaluated types is otherwise not possible in TypeScript.
1559
+
1560
+
#### Example
1561
+
1562
+
Let's add our own type overrides for the `MaybeMasked` and `Unmasked` utility types.
1563
+
1564
+
The `MaybeMasked` type is used throughout Apollo Client to return the masked or unmasked type definition for a given type, assuming they have data masking types enabled and are maskable. Otherwise, it returns the unmasked type that is passed in.
1565
+
1566
+
The `Unmasked` type unwraps a masked type to its full result type and is used throughout Apollo Client where the full data type is needed for a given API (e.g. `client.writeQuery`).
1567
+
1568
+
For this example, we'll assume the data masking types are enabled and the operation types are generated using two variations:
1569
+
1570
+
1. Data masked types are generated with a `__masked` virtual property. Its value is the operation type with any masked fields removed from the type.
1571
+
1572
+
```ts
1573
+
type MaskedQuery = {
1574
+
// The masked variant of the operation type is provided under the
1575
+
// `__masked` virtual property
1576
+
__masked?: { user: { __typename:"User"; id: number } };
1577
+
1578
+
// The full result type includes all other fields in the type
This is a hypothetical format that doesn't exist in Apollo Client or any known code generation tool. This format is used specifically for this example to illustrate how to provide type overrides to Apollo Client.
1594
+
1595
+
</Note>
1596
+
1597
+
First, let's define our custom implementation of the `MaybeMasked` type. The implementation works by checking if the `__masking` virtual property exists on the type. If so, it returns the value on the `__masked` property as the type, otherwise it returns the input type unmodified.
Now let's provide an implementation for the `Unmasked` type that works in contrast to `MaybeMasked` by returning the unwrapped full result type. The implementation works by removing the `__masked` virtual property on the input type. This can be accomplished using the built-in [`Omit`](https://www.typescriptlang.org/docs/handbook/utility-types.html#omittype-keys) type.
Now that our custom type implementations are in place, we need to define higher-kinded types for each of these custom types. This provides the bridge needed by Apollo Client to use our custom type implementations. This is done by extending the `HKT` interface exported by `@apollo/client/utilities`.
1614
+
1615
+
Let's provide HKTs for our `MaybeMasked` and `Unmasked` types. We'll put these in the same file as our type implementations.
With our HKT types in place, we now need to tell Apollo Client about them.
1637
+
1638
+
Apollo Client uses [declaration merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) to provide a hook point for overridable types. The `TypeOverrides` interface exported by the `@apollo/client` package is used for this purpose. Each property in the `TypeOverrides` interface corresponds to an overridable type in Apollo Client.
1639
+
1640
+
Let's add type overrides for our custom type implementations. Create a TypeScript file and define a `TypeOverrides` interface for the `@apollo/client` module.
1641
+
1642
+
```ts title=apollo-client.d.ts
1643
+
// This import is necessary to ensure all Apollo Client imports
1644
+
// are still available to the rest of the application.
1645
+
import"@apollo/client";
1646
+
1647
+
declare module"@apollo/client" {
1648
+
exportinterfaceTypeOverrides {
1649
+
// Type overrides will go here
1650
+
}
1651
+
}
1652
+
```
1653
+
1654
+
Now we'll import our HKT types and add them as keys in the `TypeOverrides` interface.
1655
+
1656
+
```ts {4,8-9} title=apollo-client.d.ts
1657
+
// This import is necessary to ensure all Apollo Client imports
1658
+
// are still available to the rest of the application.
And that's it! Now when Apollo Client uses the `MaybeMasked` or `Unmasked` types in its APIs, our custom implementation will be used instead 🎉.
1671
+
1672
+
#### Available type overrides
1673
+
1674
+
The following masking utility types are available to override:
1675
+
1676
+
- `FragmentType<TFragmentData>` - Type used with [fragments](#using-with-fragments) to ensure parent objects contain the fragment spread from the type.
1677
+
- `MaybeMasked<TData>` - Conditionally returns `TData` as either its masked type or unmasked type
1678
+
- `Unmasked<TData>` - Unwraps `TData` into the full result type
1679
+
1680
+
For more information about other overridable types in Apollo Client, see the [TypeScript guide](../development-testing/static-typing).
Copy file name to clipboardExpand all lines: docs/source/data/mutations.mdx
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -13,6 +13,12 @@ This article demonstrates how to send updates to your GraphQL server with the `u
13
13
14
14
## Prerequisites
15
15
16
+
<Note>
17
+
18
+
If your application is built using TypeScript, we recommend reading the [TypeScript guide](../development-testing/static-typing) to learn how to use TypeScript with Apollo Client.
19
+
20
+
</Note>
21
+
16
22
This article assumes you're familiar with building basic GraphQL mutations. If you need a refresher, we recommend that you
17
23
[read this guide](http://graphql.org/learn/queries/#mutations).
Copy file name to clipboardExpand all lines: docs/source/data/queries.mdx
+12Lines changed: 12 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,6 +16,12 @@ This article shows how to fetch GraphQL data in React with the `useQuery` hook a
16
16
17
17
## Prerequisites
18
18
19
+
<Note>
20
+
21
+
If your application is built using TypeScript, we recommend reading the [TypeScript guide](../development-testing/static-typing) to learn how to use TypeScript with Apollo Client.
22
+
23
+
</Note>
24
+
19
25
This article assumes you're familiar with building basic GraphQL queries. If you need a refresher, we recommend [this guide](http://graphql.org/learn/queries/). You can also build example queries against Apollo's [full-stack tutorial server](https://apollo-fullstack-tutorial.herokuapp.com/graphql).
20
26
21
27
This article also assumes that you've already set up Apollo Client and have wrapped your React app in an `ApolloProvider` component. For more information, see the [getting started guide](../get-started/).
@@ -70,6 +76,12 @@ As our query executes and the values of `loading`, `error`, and `data` change, t
70
76
71
77
When the user selects a dog breed from the populated dropdown, the selection is sent to the parent component via the provided `onDogSelected` function.
72
78
79
+
<Note>
80
+
81
+
If you are using TypeScript, `data` is typed as `unknown` when the query type is unknown. Accessing fields on `data` results in a TypeScript error. See the [TypeScript with Apollo Client](../development-testing/static-typing) guide to learn how to add types for your queries.
82
+
83
+
</Note>
84
+
73
85
In the next step, we'll associate the dropdown with a more sophisticated query that uses GraphQL variables.
0 commit comments