Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

(docs) - Replace "Main Concepts" section with "Architecture" and "Authoring Exchanges" pages (#1418)

* Move "Document Caching" and "Errors" to "Basics"

* Add new "Architecture" page

* Move "Exchanges" page to "Advanced"

* Remove "Main Concepts" section

* Apply suggestions from code review

Co-authored-by: Will Golledge <35961363+wgolledge@users.noreply.github.com>

Co-authored-by: Will Golledge <35961363+wgolledge@users.noreply.github.com>

authored by

Phil Pluckthun
Will Golledge
and committed by
GitHub
3933e2d8 7b46acd8

+349 -355
+4 -5
docs/README.md
··· 11 11 customized GraphQL infrastructure. In short, `urql` prioritizes usability and adaptability. 12 12 13 13 As you're adopting GraphQL, `urql` becomes your primary data layer and can handle content-heavy 14 - pages through ["Document Caching"](./concepts/document-caching.md) as well as dynamic and data-heavy 14 + pages through ["Document Caching"](./basics/document-caching.md) as well as dynamic and data-heavy 15 15 apps through ["Normalized Caching"](./graphcache/normalized-caching.md). 16 16 17 17 `urql` can be understood as a collection of connected parts and packages. ··· 21 21 `@urql/core`](./basics/core.md), which we can imagine as the brain 22 22 of `urql` with most of its logic. As we progress with implementing `urql` into our application, 23 23 we're later able to extend it by adding ["addon packages", which we call 24 - _Exchanges_](./concepts/exchanges.md) 24 + _Exchanges_](./advanced/authoring-exchanges.md) 25 25 26 26 If at this point you're still unsure of whether to use `urql`, [have a look at the **Comparison** 27 27 page](./comparison.md) and check whether `urql` supports all features you're looking for. ··· 46 46 47 47 - **Basics** is the section where we'll want to start learning about `urql` as it contains "Getting 48 48 Started" guides for our framework of choice. 49 - - **Main Concepts** then explains more about how `urql` functions, what it's made up of, and covers 50 - the main aspects of the `Client` and GraphQL clients in general, on the ["Philosophy" 51 - page](./concepts/philosophy.md). 49 + - **Architecture** then explains more about how `urql` functions, what it's made up of, and covers 50 + the main aspects of the `Client` and exchanges. 52 51 - **Advanced** covers all more uncommon use-cases and contains guides that we won't need immediately 53 52 when we get started with `urql`. 54 53 - **Graphcache** documents one of the most important addons to `urql`, which adds ["Normalized
+5 -2
docs/advanced/README.md
··· 6 6 # Advanced 7 7 8 8 In this chapter we'll dive into various topics of "advanced" `urql` usage. This is admittedly a 9 - catch-all chapter of various use-cases that can only be covered after [the "Concepts" 10 - chapter.](../concepts/README.md) 9 + catch-all chapter of various use-cases that can only be covered after [the "Architecture" 10 + chapter.](../architecture.md) 11 11 12 12 - [**Subscriptions**](./subscriptions.md) covers how to use `useSubscription` and how to set up GraphQL subscriptions with 13 13 `urql`. ··· 20 20 - [**Retrying operations**](./retry-operations.md) shows the `retryExchange` which allows you to retry operations when they've failed. 21 21 - [**Authentication**](./authentication.md) describes how to implement authentication using the `authExchange` 22 22 - [**Testing**](./testing.md) covers how to test components that use `urql` particularly in React. 23 + - [**Authoring Exchanges**](./authoring-exchanges.md) describes how to implement exchanges from 24 + scratch and how they work internally. This is a good basis to understanding how some of the 25 + features in this section function. 23 26 - [**Auto-populate Mutations**](./auto-populate-mutations.md) presents the `populateExchange` addon which can make it easier to 24 27 update normalized data after mutations.
+1 -1
docs/advanced/auto-populate-mutations.md
··· 1 1 --- 2 2 title: Auto-populate Mutations 3 - order: 8 3 + order: 9 4 4 --- 5 5 6 6 # Automatically populating Mutations
+2 -2
docs/advanced/debugging.md
··· 54 54 55 55 As demonstrated above, the `client.subscribeToDebugTarget` accepts a callback function and returns 56 56 a subscription with an `unsubscribe` method. We've seen this pattern in the prior ["Stream Patterns" 57 - section.](../concepts/stream-patterns.md#the-wonka-library) 57 + section on the "Architecture" page.](../architecture.md) 58 58 59 59 ## Adding your own Debug Events 60 60 ··· 64 64 65 65 #### Dispatching an event 66 66 67 - In the ["Exchanges" section](../concepts/exchanges.md) we've learned about the [`ExchangeInput` 67 + [On the "Authoring Exchanges" page](./authoring-exchanges.md) we've learned about the [`ExchangeInput` 68 68 object](../api/core.md#exchangeinput), which comes with a `client` and a `forward` property. 69 69 It also contains a `dispatchDebug` property. 70 70
+7 -3
docs/advanced/subscriptions.md
··· 26 26 }); 27 27 ``` 28 28 29 - [Read more about _Exchanges_ and how they work on the "Exchanges" page.](../concepts/exchanges.md) 29 + Read more about Exchanges and how they work [on the "Authoring Exchanges" 30 + page.](./authoring-exchanges.md) or what they are [on the "Architecture" 31 + page.](../architecture.md) 30 32 31 33 In the above example, we add the `subscriptionExchange` to the `Client` with the default exchanges 32 34 add before it. The `subscriptionExchange` is a factory that accepts additional options and returns ··· 298 300 299 301 ## One-off Subscriptions 300 302 301 - When you're using subscriptions directly without `urql`'s framework bindings, you can use the `Client`'s `subscription` method for one-off subscriptions. This method is similar to the ones for mutations and subscriptions [that we've seen before on the "Core Package" page.](../concepts/core-package.md#one-off-queries-and-mutations) 303 + When you're using subscriptions directly without `urql`'s framework bindings, you can use the 304 + `Client`'s `subscription` method for one-off subscriptions. This method is similar to the ones for 305 + mutations and subscriptions [that we've seen before on the "Core Package" page.](../basics/core.md) 302 306 303 - This method will always [returns a Wonka stream](../concepts/stream-patterns.md#the-wonka-library) and doesn't have a `.toPromise()` shortcut method, since promises won't return the multiple values that a subscription may deliver. Let's convert the above example to one without framework code, as we may use subscriptions in a Node.js environment. 307 + This method will always [returns a Wonka stream](../architecture.md#the-wonka-library) and doesn't have a `.toPromise()` shortcut method, since promises won't return the multiple values that a subscription may deliver. Let's convert the above example to one without framework code, as we may use subscriptions in a Node.js environment. 304 308 305 309 ```js 306 310 import { pipe, subscribe } from 'wonka';
+4 -1
docs/advanced/testing.md
··· 21 21 - `useMutation` calls `executeMutation` 22 22 - `useSubscription` calls `executeSubscription` 23 23 24 - In the section [Stream Patterns](../concepts/stream-patterns.md) we've seen, that all methods on the client operate with and return streams. These streams are created using the [Wonka](../concepts/stream-patterns.md#the-wonka-library) library and we're able to create streams ourselves to mock the different states of our operations, e.g. fetching, errors, or success with data. 24 + In the section ["Stream Patterns" on the "Architecture" page](../architecture.md) we've seen, that 25 + all methods on the client operate with and return streams. These streams are created using 26 + [the Wonka library](../architecture.md#the-wonka-library) and we're able to create streams 27 + ourselves to mock the different states of our operations, e.g. fetching, errors, or success with data. 25 28 26 29 You'll probably use one of these utility functions to create streams: 27 30
+1 -1
docs/api/README.md
··· 9 9 package or exchange packages, which are all listed in this section. 10 10 11 11 Most of these packages will refer to or use utilities and types from the `@urql/core` package. [Read 12 - more about the core package on the "Core Package" page.](../concepts/core-package.md) 12 + more about the core package on the "Core" page.](../basics/core.md) 13 13 14 14 - [`@urql/core` API docs](./core.md) 15 15 - [`urql` React API docs](./urql.md)
+9 -9
docs/api/core.md
··· 11 11 Therefore if you're not accessing utilities directly, aren't in a Node.js environment, and are using 12 12 framework bindings, you'll likely want to import from your framework bindings package directly. 13 13 14 - [Read more about `urql`'s core on the "Core Package" page.](../concepts/core-package.md) 14 + [Read more about `urql`'s core on the "Core Package" page.](../basics/core.md) 15 15 16 16 ## Client 17 17 ··· 89 89 ``` 90 90 91 91 [Read more about how to use this API on the "Core Package" 92 - page.](../concepts/core-package.md#one-off-queries-and-mutations) 92 + page.](../basics/core.md#one-off-queries-and-mutations) 93 93 94 94 ### client.mutation 95 95 96 96 This is similar to [`client.query`](#clientquery), but dispatches mutations instead. 97 97 98 98 [Read more about how to use this API on the "Core Package" 99 - page.](../concepts/core-package.md#one-off-queries-and-mutations) 99 + page.](../basics/core.md#one-off-queries-and-mutations) 100 100 101 101 ### client.subscription 102 102 ··· 128 128 | `graphQLErrors` | `?Array<string \| GraphQLError>` | GraphQL Errors (if any) that were returned by the GraphQL API | 129 129 | `response` | `?any` | The raw response object (if any) from the `fetch` call | 130 130 131 - [Read more about errors in `urql` on the "Error" page.](../concepts/errors.md) 131 + [Read more about errors in `urql` on the "Error" page.](../basics/errors.md) 132 132 133 133 ## Types 134 134 ··· 188 188 - `'network-only'` 189 189 - `'cache-and-network'` 190 190 191 - [Read more about request policies on the "Document Caching" page.](../concepts/document-caching.md#request-policies) 191 + [Read more about request policies on the "Document Caching" page.](../basics/document-caching.md#request-policies) 192 192 193 193 ### OperationContext 194 194 ··· 241 241 An exchange represents abstractions of small chunks of logic in `urql`. 242 242 They're small building blocks and similar to "middleware". 243 243 244 - [Read more about _Exchanges_ on the "Exchanges" page.](../concepts/exchanges.md) 244 + [Read more about _Exchanges_ on the "Authoring Exchanges" page.](../advanced/authoring-exchanges.md) 245 245 246 246 An exchange is defined to be a function that receives [`ExchangeInput`](#exchangeinput) and returns 247 247 an `ExchangeIO` function. The `ExchangeIO` function in turn will receive a stream of operations, and ··· 254 254 type Exchange = ExchangeInput => ExchangeIO; 255 255 ``` 256 256 257 - [If you haven't yet seen `Source`, read more about "Stream 258 - Patterns".](../concepts/stream-patterns.md) 257 + [If you haven't yet seen streams you can read more about "Stream Patterns" on the "Architecture" 258 + page.](../architecture.md) 259 259 260 260 ## Exchanges 261 261 262 262 ### cacheExchange 263 263 264 - The `cacheExchange` as [described on the "Document Caching" page.](../concepts/document-caching.md). It's of type `Exchange`. 264 + The `cacheExchange` as [described on the "Document Caching" page.](../basics/document-caching.md). It's of type `Exchange`. 265 265 266 266 ### subscriptionExchange 267 267
+1 -1
docs/api/request-policy-exchange.md
··· 9 9 that may be used to upgrade [Operations' Request Policies](./core.md#requestpolicy) on a 10 10 time-to-live basis. 11 11 12 - [Read more about request policies on the "Document Caching" page.](../concepts/document-caching.md#request-policies) 12 + [Read more about request policies on the "Document Caching" page.](../basics/document-caching.md#request-policies) 13 13 14 14 This exchange will conditionally upgrade `cache-first` and `cache-only` operations to use 15 15 `cache-and-network`, so that the client gets an opportunity to update its cached data, when the
+245
docs/architecture.md
··· 1 + --- 2 + title: Architecture 3 + order: 3 4 + --- 5 + 6 + # Architecture 7 + 8 + `urql` is a highly customizable and flexible GraphQL client, that happens to come with some default 9 + [core behavior in the core package](./core-package.md). 10 + 11 + By default, `urql` aims to provide the minimal amount of features that allow us to build an app 12 + quickly. However, `urql` has also been designed to be a GraphQL Client 13 + that grows with our usage and demands. As we go from building our smallest or first GraphQL apps to 14 + utilising its full functionality, we have tools at our disposal to extend and customize `urql` to 15 + our liking. 16 + 17 + ## Using GraphQL Clients 18 + 19 + You may have worked with a GraphQL API previously and noticed that using GraphQL in your app can be 20 + as straightforward as sending a plain HTTP request with your query to fetch some data. 21 + 22 + GraphQL also provides an opportunity to abstract away a lot of the manual work that goes with 23 + sending these queries and managing the data. Ultimately, this lets you focus on building 24 + your app without having to handle the technical details of state management in detail. 25 + 26 + Specifically, `urql` simplifies three common aspects of using GraphQL: 27 + 28 + - Sending queries and mutations and receiving results _declaratively_ 29 + - Abstracting _caching_ and state management internally 30 + - Providing a central point of _extensibility_ and integration with your API 31 + 32 + In the following sections we'll talk about the way that `urql` solves these three problems and how the logic abstracted away internally. 33 + 34 + ## Requests and Operations on the Client 35 + 36 + If `urql` was a train it would take several stops to arrive at its terminus, our API. It starts with us 37 + defining queries or mutations. Any GraphQL request can be abstracted into their query documents and 38 + their variables. In `urql`, these GraphQL requests are treated as unique objects which are uniquely 39 + identified by the query document and variables (which is why a `key` is generated from the two). This 40 + `key` is a hash number of the query document and variables and uniquely identifies our 41 + [`GraphQLRequest`](./api/core.md#graphqlrequest). 42 + 43 + Whenever we decide to send a request to our API we start by using `urql`'s 44 + [`Client`](./api/core.md#client). It accepts several options like `url` or `requestPolicy` which are 45 + extra information on how the GraphQL requests are executed. 46 + 47 + ```js 48 + import { Client } from '@urql/core'; 49 + 50 + new Client({ 51 + url: '/graphql', 52 + requestPolicy: 'cache-first', 53 + }) 54 + ``` 55 + 56 + The bindings that we've seen in [the "Basics" section](./basics/README.md) interact with [the 57 + `Client`](./api/core.md#client) directly and are a thin abstraction on top of it. Though some methods can be called on it directly, as seen [on the "Core Usage" 58 + page](./basics/core.md#one-off-queries-and-mutations). 59 + 60 + When we send our queries or mutations to the `Client`, internally they will be managed as 61 + [`Operation`s.](./api/core.md#operation). An "Operation" is an extension of `GraphQLRequest`s. Not 62 + only do they carry the `query`, `variables`, and a `key` property, they will also identify the 63 + `kind` of operation that is executed, like `"query"` or `"mutation"`. We can also find the 64 + `Client`'s options on `operation.context` which carries an operation's metadata. 65 + 66 + ![Operations and Results](./assets/urql-event-hub.png) 67 + 68 + It's the `Client`s responsibility to accept an `Operation` and execute it. The bindings interally 69 + call the `client.executeQuery`, `client.executeMutation`, or `client.executeSubscription` methods 70 + and we'll get a "stream" of results. This "stream" allows us to register a callback with it to 71 + receive results. 72 + 73 + In the diagram we can see that each operation is a signal for our request to start at which point 74 + we can expect to receive our results eventually on a callback. Once we're not interested in results 75 + anymore a special "teardown" signal is issued on the `Client`. While we don't see operations outside 76 + of the `Client`, they're what travel through the "Exchanges" on the `Client`. 77 + 78 + ## The Client and Exchanges 79 + 80 + To reiterate, when we use `urql`'s bindings for our framework of choice, methods are called on the 81 + `Client` but we never see the operations that are created in the background from our bindings. We 82 + call a method like `client.executeQuery` (or it's called for us in the bindings), an operation is 83 + issued internally when we subscribe with a callback, and later our callback is called with results. 84 + 85 + ![Operations stream and results stream](./assets/urql-client-architecture.png) 86 + 87 + While we know that, for us, we're only interested in a single [`Operation`](./api/core.md#operation) 88 + and its [`OperationResult`s](./api/core.md#operationresult) at a time, the `Client` treats these as 89 + one big stream. The `Client` sees an incoming flow of all of our operations. 90 + 91 + As we've learned before, each operation carries a `key` and each result we receive carries the 92 + original `operation`. Because an `OperationResult` also carries an `operation` property the `Client` 93 + will always know which results correspond to an individual operation. 94 + However, internally, all of our operations are processed at the same time concurrently. However from 95 + our perspective: 96 + 97 + - We subscribe to a "stream" and expect to get results on a callback 98 + - The `Client` issues the operation and we'll receive some results back eventually as either the 99 + cache responds (synchronously) or the request gets sent to our API. 100 + - We eventually unsubscribe and the `Client` issues a "teardown" operation with the same `key` as 101 + the original operation, which concludes our flow. 102 + 103 + The `Client` itself doesn't actually know what to do with operations. Instead, it sends them through 104 + "exchanges". Exchanges are akin to [middleware in Redux](https://redux.js.org/advanced/middleware) 105 + and have access to all operations and all results. Multiple exchanges are chained to process our 106 + operations and to execute logic on them, one of them being the `fetchExchange`, which as the name 107 + implies sends our requests to our API. 108 + 109 + ### How operations get to exchanges 110 + 111 + We now know how we get to operations and to the `Client`: 112 + 113 + - Any bindings or calls to the `Client` create an **operation** 114 + - This operation identifies itself as either a `"query"`, `"mutation"` or `"subscription"` and has a 115 + unique `key`. 116 + - This operation is sent into the **exchanges** and eventually ends up at the `fetchExchange` 117 + (or a similar exchange) 118 + - The operation is sent to the API and a **result** comes back which is wrapped in an `OperationResult` 119 + - The `Client` filters the `OperationResult` by the `operation.key` and — via a callback — gives us 120 + a **stream of results**. 121 + 122 + To come back to our train analogy from earlier, an operation, like a train, travels from one end 123 + of the track to the terminus — our API. The results then come back on the same path as they're just 124 + travelling the same line in reverse. 125 + 126 + ### The Exchanges 127 + 128 + The default set of exchanges that `@urql/core` contains and applies to a `Client` are: 129 + 130 + - `dedupExchange`: Deduplicates pending operations (pending = waiting for a result) 131 + - `cacheExchange`: The default caching logic with ["Document Caching"](../basics/document-caching.md) 132 + - `fetchExchange`: Sends an operation to the API using `fetch` and adds results to the output stream 133 + 134 + When we don't pass the `exchanges` option manually to our `Client` then these are the ones that will 135 + be applied. As we can see, an exchange exters a lot of power over our operations and results. They 136 + determine a lot of the logic of the `Client`, taking care of things like deduplication, caching, and 137 + sending requests to our API. 138 + 139 + Some of the exchanges that are available to us are: 140 + 141 + - [`errorExchange`](./api/core.md#errorexchange): Allows a global callback to be called when any error occurs 142 + - [`ssrExchange`](./advanced/server-side-rendering.md): Allows for a server-side renderer to 143 + collect results for client-side rehydration. 144 + - [`retryExchange`](./advanced/retry-operations.md): Allows operations to be retried 145 + - [`multipartFetchExchange`](./advanced/persistence-and-uploads.md#file-uploads): Provides multipart file upload capability 146 + - [`persistedFetchExchange`](./advanced/persistence-and-uploads.md#automatic-persisted-queries): Provides support for Automatic 147 + Persisted Queries 148 + - [`authExchange`](./advanced/authentication.md): Allows complex authentication flows to be implemented 149 + easily. 150 + - [`requestPolicyExchange`](../api/request-policy-exchange.md): Automatically upgrades `cache-only` and `cache-first` operations to `cache-and-network` after a given amount of time. 151 + - [`refocusExchange`](../api/refocus-exchange.md): Tracks open queries and refetches them 152 + when the window regains focus. 153 + - `devtoolsExchange`: Provides the ability to use the [urql-devtools](https://github.com/FormidableLabs/urql-devtools) 154 + 155 + We can even swap out our [document cache](./basics/document-caching.md), which is implemented by 156 + `@urql/core`'s `cacheExchange`, with `urql`'s [normalized cache, 157 + Graphcache](./graphcache/README.md). 158 + 159 + [Read more about exchanges and how to write them from scratch on the "Authoring Exchanges" 160 + page.](./advanced/authoring-exchanges.md) 161 + 162 + ## Stream Patterns in `urql` 163 + 164 + In the previous sections we've learned a lot about how the `Client` works, but we've always learned 165 + it in vague terms — for instance, we've learned that we get a "stream of results" or `urql` sees all 166 + operations as "one stream of operations" that it sends to the exchanges. 167 + But, **what are streams?** 168 + 169 + Generally we refer to _streams_ as abstractions that allow us to program with asynchronous events 170 + over time. Within the JavaScript context we're thinking specifically in terms of of 171 + [Observables](https://github.com/tc39/proposal-observable) 172 + and [Reactive Programming with Observables.](http://reactivex.io/documentation/observable.html) 173 + These concepts may sound initimidating, but from a high-level view what we're talking about can be 174 + thought of as a combination of promises and iterables (e.g. arrays). We're dealing with multiple 175 + events but our callback is called over time. It's like calling `forEach` on an array but expecting 176 + the results to come in asynchronously. 177 + 178 + As a user, if we're using the one framework bindings that we've seen in [the "Basics" 179 + section](./basics/README.md), we may never see these streams in action or may never use them even, 180 + since the bindings internally use them for us. But if we [use the `Client` 181 + directly](./basics/core.md#one-off-queries-and-mutations) or write exchanges then we'll see streams 182 + and wil have to deal with their API. 183 + 184 + ### The Wonka library 185 + 186 + `urql` utilises the [Wonka](https://github.com/kitten/wonka) library for its streams. It has a 187 + few advantages that are specifically tailored for the `urql` library and ecosystem: 188 + 189 + - It is extremely lightweight and treeshakeable, with a size of around 3.7kB minzipped. 190 + - It's cross-platform and cross-language compatible, having been written in 191 + [Reason](https://reasonml.github.io/) and provides support for [Flow](https://flow.org/) 192 + and [TypeScript](https://www.typescriptlang.org/v2/). 193 + - It's a predictable and iterable toolchain, emitting synchronous events whenever possible. 194 + 195 + Typical usage of Wonka will involve creating a _source_ of some values and a _sink_. 196 + 197 + ```js 198 + import { fromArray, map, subscribe, pipe } from 'wonka'; 199 + 200 + const { unsubscribe } = pipe( 201 + fromArray([1, 2, 3]), 202 + map(x => x * 2), 203 + subscribe(x => { 204 + console.log(x); // 2, 4, 6 205 + }) 206 + ); 207 + ``` 208 + 209 + In Wonka, like with Observables, streams are cancellable by calling the `unsubscribe` method that a 210 + subscription returns. 211 + 212 + [Read more about Wonka in its documentation](https://wonka.kitten.sh/basics/background). 213 + 214 + ### Stream patterns with the client 215 + 216 + When we call methods on the `Client` like [`client.executeQuery`](./api/core.md#clientexecutequery) 217 + or [`client.query`](./api/core.md#clientquery) then these will return a Wonka stream. Those are 218 + essentially just a bunch of callbacks. 219 + 220 + We can use [`wonka`'s `subscribe`](https://wonka.kitten.sh/api/sinks#subscribe) function to start 221 + this stream. We pass this function a callback and will receive results back from the `Client`, as it 222 + starts our operation. When we unsubscribe then the `Client` will stop this operation by sending a 223 + special "teardown" operation to our exchanges. 224 + 225 + ```js 226 + import { pipe, subscribe } from 'wonka'; 227 + 228 + const QUERY = ` 229 + query Test($id: ID!) { 230 + getUser(id: $id) { 231 + id 232 + name 233 + } 234 + } 235 + `; 236 + 237 + const { unsubscribe } = pipe( 238 + client.query(QUERY, { id: 'test' }), 239 + subscribe(result => { 240 + console.log(result); // { data: ... } 241 + }) 242 + ); 243 + ``` 244 + 245 + Read more about the available APIs on the `Client` in the [Core API docs](../api/core.md).
+4 -5
docs/basics/README.md
··· 14 14 - [**Core Package**](./core-package.md) defines why a shared package exists that contains the main 15 15 logic of `urql`, and how we can use it directly in Node.js. 16 16 17 - After reading "Basics" you may want to [read the "Concepts" chapter of the 18 - documentation](../concepts/README.md) as it explains the motivation and architecture that drives 19 - `urql`. Two notable sections there include: 17 + After reading the page for your bindings and the "Core" page you may want to the next two pages in 18 + this section of the documentation: 20 19 21 - - [**Document Caching**](../concepts/document-caching.md) explains the default cache mechanism of `urql`, as opposed to the opt-in 20 + - [**Document Caching**](./document-caching.md) explains the default cache mechanism of `urql`, as opposed to the opt-in 22 21 [Normalized Cache](../graphcache/normalized-caching.md). 23 - - [**Errors**](../concepts/errors.md) contains information on error handling in `urql`. 22 + - [**Errors**](../basics/errors.md) contains information on error handling in `urql`.
+5 -5
docs/basics/core.md
··· 1 1 --- 2 - title: Core 2 + title: Core Usage 3 3 order: 3 4 4 --- 5 5 ··· 156 156 157 157 This concludes the introduction for using `@urql/core` without any framework bindings. This showed 158 158 just a couple of ways to use `gql` or the `Client`, however you may also want to learn more about 159 - [how to use `urql`'s streams](../concepts/stream-patterns.md). Furthermore, apart from the framework 159 + [how to use `urql`'s streams](../architecture.md#stream-patterns-in-urql). Furthermore, apart from the framework 160 160 binding introductions, there are some other pages that provide more information on how to get fully 161 161 set up with `urql`: 162 162 163 - - [How does the default "document cache" work?](../concepts/document-caching.md) 164 - - [How are errors handled and represented?](../concepts/errors.md) 165 - - [A quick overview of `urql`'s philosophy and structure.](../concepts/philosophy.md) 163 + - [How does the default "document cache" work?](./document-caching.md) 164 + - [How are errors handled and represented?](./errors.md) 165 + - [A quick overview of `urql`'s architecture and structure.](../architecture.md) 166 166 - [Setting up other features, like authentication, uploads, or persisted queries.](../advanced/README.md)
+7 -7
docs/basics/react-preact.md
··· 1 1 --- 2 - title: React/Preact 2 + title: React/Preact Bindings 3 3 order: 0 4 4 --- 5 5 ··· 142 142 The result object contains several properties. The `fetching` field indicates whether we're currently 143 143 loading data, `data` contains the actual `data` from the API's result, and `error` is set when either 144 144 the request to the API has failed or when our API result contained some `GraphQLError`s, which 145 - we'll get into later on the ["Errors" page](../concepts/errors.md). 145 + we'll get into later on the ["Errors" page](./errors.md). 146 146 147 147 ### Variables 148 148 ··· 220 220 221 221 Request policies aren't specific to `urql`'s React API, but are a common feature in its core. [You 222 222 can learn more about how the cache behaves given the four different policies on the "Document 223 - Caching" page.](../concepts/document-caching.md) 223 + Caching" page.](../basics/document-caching.md) 224 224 225 225 ### Reexecuting Queries 226 226 ··· 322 322 323 323 If you're checking for errors, you should use `result.error` instead, which will be set 324 324 to a `CombinedError` when any kind of errors occurred while executing your mutation. 325 - [Read more about errors on our "Errors" page.](../concepts/errors.md) 325 + [Read more about errors on our "Errors" page.](./errors.md) 326 326 327 327 ```jsx 328 328 const Todo = ({ id, title }) => { ··· 349 349 which is the same between all framework bindings. Hence, next we may want to learn more about one of 350 350 the following to learn more about the internals: 351 351 352 - - [How does the default "document cache" work?](../concepts/document-caching.md) 353 - - [How are errors handled and represented?](../concepts/errors.md) 354 - - [A quick overview of `urql`'s philosophy and structure.](../concepts/philosophy.md) 352 + - [How does the default "document cache" work?](./document-caching.md) 353 + - [How are errors handled and represented?](./errors.md) 354 + - [A quick overview of `urql`'s architecture and structure.](../architecture.md) 355 355 - [Setting up other features, like authentication, uploads, or persisted queries.](../advanced/README.md)
+6 -6
docs/basics/svelte.md
··· 1 1 --- 2 - title: Svelte 2 + title: Svelte Bindings 3 3 order: 2 4 4 --- 5 5 ··· 10 10 This "Getting Started" guide covers how to install and set up `urql` and provide a `Client` for 11 11 Svelte. The `@urql/svelte` package, which provides bindings for Svelte, doesn't fundamentally 12 12 function differently from `@urql/preact` or `urql` and uses the same [Core Package and 13 - `Client`](../concepts/core-package.md). 13 + `Client`](./core.md). 14 14 15 15 ### Installation 16 16 ··· 460 460 461 461 If you're checking for errors, you should use `operationStore.error` instead, which will be set 462 462 to a `CombinedError` when any kind of errors occurred while executing your mutation. 463 - [Read more about errors on our "Errors" page.](../concepts/errors.md) 463 + [Read more about errors on our "Errors" page.](./errors.md) 464 464 465 465 ```jsx 466 466 mutateTodo({ id, title: newTitle }).then(result => { ··· 477 477 which is the same between all framework bindings. Hence, next we may want to learn more about one of 478 478 the following to learn more about the internals: 479 479 480 - - [How does the default "document cache" work?](../concepts/document-caching.md) 481 - - [How are errors handled and represented?](../concepts/errors.md) 482 - - [A quick overview of `urql`'s philosophy and structure.](../concepts/philosophy.md) 480 + - [How does the default "document cache" work?](./document-caching.md) 481 + - [How are errors handled and represented?](./errors.md) 482 + - [A quick overview of `urql`'s architecture and structure.](../architecture.md) 483 483 - [Setting up other features, like authentication, uploads, or persisted queries.](../advanced/README.md)
+6 -6
docs/basics/vue.md
··· 1 1 --- 2 - title: Vue 2 + title: Vue Bindings 3 3 order: 1 4 4 --- 5 5 ··· 163 163 The result object contains several properties. The `fetching` field indicates whether we're currently 164 164 loading data, `data` contains the actual `data` from the API's result, and `error` is set when either 165 165 the request to the API has failed or when our API result contained some `GraphQLError`s, which 166 - we'll get into later on the ["Errors" page](../concepts/errors.md). 166 + we'll get into later on the ["Errors" page](./errors.md). 167 167 168 168 All of these properties on the result are derived from the [shape of 169 169 `OperationResult`](../api/core.md#operationresult) and are marked as [reactive ··· 560 560 561 561 If you're checking for errors, you should use `result.error` instead, which will be set 562 562 to a `CombinedError` when any kind of errors occurred while executing your mutation. 563 - [Read more about errors on our "Errors" page.](../concepts/errors.md) 563 + [Read more about errors on our "Errors" page.](./errors.md) 564 564 565 565 ```js 566 566 import { useMutation } from '@urql/vue'; ··· 600 600 which is the same between all framework bindings. Hence, next we may want to learn more about one of 601 601 the following to learn more about the internals: 602 602 603 - - [How does the default "document cache" work?](../concepts/document-caching.md) 604 - - [How are errors handled and represented?](../concepts/errors.md) 605 - - [A quick overview of `urql`'s philosophy and structure.](../concepts/philosophy.md) 603 + - [How does the default "document cache" work?](./document-caching.md) 604 + - [How are errors handled and represented?](./errors.md) 605 + - [A quick overview of `urql`'s architecture and structure.](../architecture.md) 606 606 - [Setting up other features, like authentication, uploads, or persisted queries.](../advanced/README.md)
-27
docs/concepts/README.md
··· 1 - --- 2 - title: Main Concepts 3 - order: 3 4 - --- 5 - 6 - # Main Concepts 7 - 8 - In this chapter we'll learn about the motivation behind `urql`, the architecture that drives it, the 9 - inner workings of the `Client`, and how to write extensions and addons, also known as _Exchanges_. 10 - 11 - Each page goes a little further in explaining a core concept of `urql`. 12 - 13 - - [**Document Caching**](./document-caching.md) explains the default cache mechanism of `urql`, as opposed to the opt-in 14 - [Normalized Cache](../graphcache/normalized-caching.md). 15 - - [**Errors**](./errors.md) contains information on error handling in `urql`. 16 - - [**Philosophy**](./philosophy.md) gives a quick overview of the different aspects of GraphQL clients and `urql` in 17 - particular, which shines a light on why you may want to use `urql`. 18 - - [**Stream Pattern**](./stream-patterns.md) explains the inner working of `urql`, which is _stream-based_, also known as 19 - Observable patterns in JS. 20 - - [**Exchanges**](./exchanges.md) finally introduces _Exchanges_ and how to write extensions or addons and use them 21 - in `urql`. 22 - 23 - Finally, some _Exchanges_ are covered in different sections of the documentation, like 24 - ["Subscriptions"](../advanced/subscriptions.md), ["Server-side 25 - Rendering"](../advanced/server-side-rendering.md), or ["Normalized 26 - Caching"](../graphcache/normalized-caching.md). It's advisable to read this chapter before moving on 27 - to using _Exchanges_.
+2 -2
docs/concepts/document-caching.md docs/basics/document-caching.md
··· 1 1 --- 2 2 title: Document Caching 3 - order: 1 3 + order: 4 4 4 --- 5 5 6 6 # Document Caching ··· 12 12 a query and its variables. 13 13 14 14 The default _document caching_ logic is implemented in the default `cacheExchange`. We'll learn more 15 - about ["Exchanges" on a later page.](../concepts/exchanges.md) 15 + about ["Exchanges" on the "Architecture" page.](../architecture.md) 16 16 17 17 ## Operation Keys 18 18
+1 -1
docs/concepts/errors.md docs/basics/errors.md
··· 1 1 --- 2 2 title: Errors 3 - order: 2 3 + order: 5 4 4 --- 5 5 6 6 # Error handling
+11 -32
docs/concepts/exchanges.md docs/advanced/authoring-exchanges.md
··· 1 1 --- 2 - title: Exchanges 3 - order: 5 2 + title: Authoring Exchanges 3 + order: 8 4 4 --- 5 5 6 - # Exchanges 6 + # Exchange Author Guide 7 7 8 - As we've learned on the [Stream Patterns](./stream-patterns.md) page, `urql`'s `Client` structures 8 + As we've learned [on the "Architecture" page](../architecture.md) page, `urql`'s `Client` structures 9 9 its data as an event hub. We have an input stream of operations, which are instructions for the 10 10 `Client` to provide a result. These results then come from an output stream of operation results. 11 11 12 - _Exchanges_ are responsible for performing the important transform from the operations (input) stream to the results stream. Exchanges are handler functions that deal with these input and 13 - output streams. They're one of `urql`'s key components, and are needed to implement vital pieces of logic such as 14 - caching, fetching, deduplicating requests, and more. In other words, Exchanges are handlers that 15 - fulfill our GraphQL requests and can change the stream of operations or results. 12 + _Exchanges_ are responsible for performing the important transform from the operations (input) stream 13 + to the results stream. Exchanges are handler functions that deal with these input and 14 + output streams. They're one of `urql`'s key components, and are needed to implement vital pieces of 15 + logic such as caching, fetching, deduplicating requests, and more. In other words, Exchanges are 16 + handlers that fulfill our GraphQL requests and can change the stream of operations or results. 16 17 17 - The default set of exchanges that `@urql/core` contains and applies to a `Client` are: 18 - 19 - - `dedupExchange`: Deduplicates pending operations (pending = waiting for a result) 20 - - `cacheExchange`: The default caching logic with ["Document Caching"](../concepts/document-caching.md) 21 - - `fetchExchange`: Sends an operation to the API using `fetch` and adds results to the output stream 22 - 23 - Other available exchanges: 24 - 25 - - [`errorExchange`](../api/core.md#errorexchange): Allows a global callback to be called when any error occurs 26 - - [`ssrExchange`](../advanced/server-side-rendering.md): Allows for a server-side renderer to 27 - collect results for client-side rehydration. 28 - - [`retryExchange`](../api/retry-exchange.md): Allows operations to be retried 29 - - [`multipartFetchExchange`](../api/multipart-fetch-exchange.md): Provides multipart file upload capability 30 - - [`persistedFetchExchange`](../api/persisted-fetch-exchange.md): Provides support for Automatic 31 - Persisted Queries 32 - - [`authExchange`](../api/auth-exchange.md): Allows complex authentication flows to be implemented 33 - easily. 34 - - [`requestPolicyExchange`](../api/request-policy-exchange.md): Automatically upgrades `cache-only` and `cache-first` operations to `cache-and-network` after a given amount of time. 35 - - [`refocusExchange`](../api/refocus-exchange.md): Tracks open queries and refetches them 36 - when the window regains focus. 37 - - `devtoolsExchange`: Provides the ability to use the [urql-devtools](https://github.com/FormidableLabs/urql-devtools) 38 - 39 - It is also possible to apply custom exchanges to override the default logic. 18 + In this guide we'll learn more about how exchanges work and how we can write our own exchanges. 40 19 41 20 ## An Exchange Signature 42 21 ··· 57 36 [_Operations_](../api/core.md#operation) and returns a source of [_Operation 58 37 Results_](../api/core.md#operationresult). 59 38 60 - - [Read more about streams on the "Stream Patterns" page.](../concepts/stream-patterns.md) 39 + - [Read more about streams on the "Architecture" page.](../architecture.md#stream-patterns-in-urql) 61 40 - [Read more about the _Exchange_ type signature on the API docs.](../api/core.md#exchange) 62 41 63 42 ## Using Exchanges
-111
docs/concepts/philosophy.md
··· 1 - --- 2 - title: Philosophy 3 - order: 3 4 - --- 5 - 6 - # Philosophy 7 - 8 - `urql` is a highly customizable and flexible GraphQL client, that happens to come with some default 9 - [core behavior in the core package](./core-package.md). 10 - 11 - By default, we aim to provide features that allow you to build your app quickly with minimal 12 - configuration. `urql` is designed to be a client that grows with you. As you go from building your first 13 - GraphQL app to a utilising the full functionality, the tools are available to extend and customize `urql` based on 14 - your needs. 15 - 16 - In this guide, we will walk through how `urql` is set up internally and how all pieces of the puzzle 17 - — the building blocks of `urql` — interact with one another. 18 - 19 - ## Hello World 20 - 21 - When you use `urql` you will always create and set up a `Client`. There is a `createClient` 22 - convenience helper to do just that. 23 - 24 - ```js 25 - import { Client } from 'urql'; 26 - 27 - const client = new Client({ 28 - url: 'http://localhost:3000/graphql', 29 - }); 30 - ``` 31 - 32 - In `urql`, the client is the first step towards managing the complexity of GraphQL automatically. 33 - 34 - ## Using GraphQL Clients 35 - 36 - You may have worked with a GraphQL API previously and noticed that using GraphQL in your app can be 37 - as straightforward as sending a plain HTTP request with your query to fetch some data. 38 - 39 - GraphQL also provides an opportunity to abstract away a lot of the manual work that goes with 40 - sending these queries and managing the data. Ultimately, this lets you focus on building 41 - your app without having to handle the technical details of state management in detail. 42 - 43 - Specifically, `urql` simplifies three common aspects of using GraphQL: 44 - 45 - - Sending queries and mutations and receiving results _declaratively_ 46 - - Abstracting _caching_ and state management internally 47 - - Providing a central point of _extensibility_ and integration with your API 48 - 49 - In the following sections we'll talk about how `urql` solves these three problems, and how this is 50 - accomplished and abstracted internally. 51 - 52 - ## Declarative Queries 53 - 54 - When you implement queries or mutations with `urql` the `Client` will internally manage the 55 - lifetime and updates for these _operations_. 56 - 57 - Such an _operation_ may be sent to your GraphQL API and you'll subsequently receive results. 58 - When a _cache_ invalidates this result you may receive updated results. When your app 59 - stops being interested in results for an _operation_ (e.g. React unmounts your component) then 60 - the `Client` knows to _teardown_ the _operation_ and stops requesting new data or sending you 61 - results. 62 - 63 - ![Operations and Results](../assets/urql-event-hub.png) 64 - 65 - This all happens in the background, allowing you to simply declare that you'd like to have data for a given 66 - query. 67 - 68 - ## Caching and State 69 - 70 - When we use GraphQL queries and mutations declaratively with `urql`, we expect them to interact 71 - and update automatically. 72 - 73 - Furthermore, when we've already received the results from a query, we may not wish to send another request. To solve this, results can be cached in-memory and notifications can be sent to other parts of an app when the results change or 74 - are invalidated by mutations/subscriptions. 75 - 76 - GraphQL clients have access to some type information for any GraphQL API and hence can 77 - cache the results of queries automatically. In `urql` the `Client` can be extended with several 78 - cache implementations; all of them allow you to prevent mixing your declarative query or mutation 79 - code with cache-implementation details, as they mostly happen behind the scenes. 80 - 81 - We previously read about the default [Document Caching](../concepts/document-caching.md). 82 - 83 - Some GraphQL clients also resort to caching data in a normalized format. This is similar to 84 - [how you may store data in Redux.](https://redux.js.org/recipes/structuring-reducers/normalizing-state-shape/) 85 - Using this approach the cache uses more type information to reference parts of the GraphQL only once 86 - in the cache and structures it in a graph, which leads to more shared data, and hence more shared 87 - updates in your UI! 88 - 89 - [Read more](../graphcache/normalized-caching.md) on how to add Normalized Caching to an app. 90 - 91 - ## Extensibility and Integration 92 - 93 - With any kind of API there can be concerns outside of caching and state management. For example, 94 - the global behavior or business logic of your application. For instance, you may want to add authentication, retry-logic for failed requests, or a global 95 - error handler. 96 - 97 - `urql` introduces the concept of _Exchanges_ in order to abstract the details of how the `Client` interacts with 98 - your framework of choice, your app, and your GraphQL API. They are akin to 99 - [middleware in Redux](https://redux.js.org/advanced/middleware) and have access to all operations 100 - and all results. 101 - 102 - Read more about [Exchanges](./exchanges.md) later on in the documentation. 103 - 104 - All default behavior in the [core package](./core-package.md) is implemented using 105 - Exchanges. This is possible as all operations and all results are treated as a stream 106 - of events; we call these events "Operations". 107 - 108 - ![Operation Signature](../assets/urql-signals.png) 109 - 110 - Thinking about GraphQL queries and results in 111 - streams of operations and results allow us to implement complex behaviour in addition to allowing deep customisation over how the operations/results are handled. We'll learn more about this in the next section - [the Core Package](./core-package.md).
-120
docs/concepts/stream-patterns.md
··· 1 - --- 2 - title: Stream Patterns 3 - order: 4 4 - --- 5 - 6 - # Stream Patterns 7 - 8 - As we've learned in the previous section on [philosophy](./philosophy.md), `urql`'s main way of handling GraphQL requests 9 - is by abstracting them as streams of operations and results. 10 - 11 - ## Streams on the Client 12 - 13 - The client abstracts GraphQL requests in a number of ways: 14 - 15 - - as _Operations_ 16 - - descriptions of the GraphQL request 17 - - the query and related variables 18 - - additional information that is configured on the `Client`, such as 19 - the `url` and `fetchOptions`. 20 - 21 - ![Operations stream and results stream](../assets/urql-client-architecture.png) 22 - 23 - Internally the `Client` is an event hub. It defines a stream of operations as inputs, sends them 24 - through a layer that will ultimately send GraphQL requests to an API, and then send the corresponding results 25 - to another stream. 26 - 27 - As a user working with framework code we never interact with these streams directly, but it's helpful to know that they describe 28 - every interaction between the declarative queries we write and the way that `urql` fulfills them. 29 - 30 - ## Streams in JavaScript 31 - 32 - Generally we refer to _streams_ as abstractions that allow us to program with asynchronous streams of 33 - events over time. Within the JavaScript context we're thinking specifically in terms of of 34 - [Observables](https://github.com/tc39/proposal-observable) 35 - and [Reactive Programming with Observables.](http://reactivex.io/documentation/observable.html) 36 - 37 - These concepts can be quite intimidating, if you're new to them, but from a high-level view what 38 - we're talking about can be thought of as a "combination of Promises and Arrays". 39 - Arrays because we're dealing with multiple items, and Promises because these items arrive 40 - asynchronously. 41 - 42 - Also most Observable libraries come with a toolkit of helper functions that are similar to the 43 - methods on arrays, so you're likely to see `map` and `filter` — amongst other utilities — in those 44 - libraries. 45 - 46 - Read [this Gist](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754) for a more in-depth 47 - explanation. 48 - 49 - ## The Wonka library 50 - 51 - `urql` utilises the [Wonka](https://github.com/kitten/wonka) library for its streams. It has a 52 - few advantages that are specifically tailored for the `urql` library and ecosystem: 53 - 54 - - It is extremely lightweight and treeshakeable, with a size of around 3.7kB minzipped. 55 - - It's cross-platform and cross-language compatible, having been written in 56 - [Reason](https://reasonml.github.io/) and provides support for [Flow](https://flow.org/) 57 - and [TypeScript](https://www.typescriptlang.org/v2/). 58 - - It's a predictable and iterable toolchain, emitting synchronous events whenever possible. 59 - 60 - Typical usage of Wonka will involve creating a _source_ of some values and a _sink_. 61 - 62 - ```js 63 - import { fromArray, map, subscribe, pipe } from 'wonka'; 64 - 65 - const { unsubscribe } = pipe( 66 - fromArray([1, 2, 3]), 67 - map(x => x * 2), 68 - subscribe(x => { 69 - console.log(x); // 2, 4, 6 70 - }) 71 - ); 72 - ``` 73 - 74 - In Wonka, like with Observables, streams are cancellable by calling the `unsubscribe` method that a 75 - subscription returns. 76 - 77 - Read more about Wonka in its [documentation](https://wonka.kitten.sh/basics/background). 78 - 79 - ## Client Query Streams 80 - 81 - Internally the `Client` has methods that may be used to execute queries, mutations, and 82 - subscriptions. These methods typically return `Wonka` streams that, when subscribed to, will 83 - emit results for a given query. 84 - 85 - When a result can be retrieved from an in-memory cache, the stream may even emit the result 86 - synchronously — rather than asynchronously. 87 - 88 - There are three methods for each type of operation that GraphQL supports; 89 - `executeQuery`, `executeMutation`, and `executeSubscription`. All these methods are 90 - convenience wrappers around `executeRequestOperation` that create an operation and return a stream. 91 - 92 - There are also convenience wrappers around the "execute" methods that are useful when using `urql` 93 - in a Node.js environment. They are the `query`, `mutation`, and `subscription` methods. 94 - 95 - ```js 96 - import { pipe, subscribe } from 'wonka'; 97 - 98 - const QUERY = ` 99 - query Test($id: ID!) { 100 - getUser(id: $id) { 101 - id 102 - name 103 - } 104 - } 105 - `; 106 - 107 - const { unsubscribe } = pipe( 108 - client.query(QUERY, { id: 'test' }), 109 - subscribe(result => { 110 - console.log(result); // { data: ... } 111 - }) 112 - ); 113 - ``` 114 - 115 - All methods on the `Client` internally emit an operation on an "operations stream" and the result 116 - for this operation will be filtered out of all results and delivered to your stream. 117 - There are several of these convenience methods in `urql` that make it easier to work with the 118 - concept of GraphQL operation and result streams. 119 - 120 - Read more about the available APIs on the `Client` in the [Core API docs](../api/core.md).
+3 -3
docs/graphcache/README.md
··· 5 5 6 6 # Graphcache 7 7 8 - In `urql`, caching is fully configurable via [_Exchanges_](../concepts/exchanges.md) and the default 9 - `cacheExchange` in `urql` offers a ["Document Cache"](../concepts/document-caching.md), which is 8 + In `urql`, caching is fully configurable via [exchanges](../architecture.md) and the default 9 + `cacheExchange` in `urql` offers a ["Document Cache"](../basics/document-caching.md), which is 10 10 sufficient for sites that heavily rely and render static content. However as an app grows more 11 11 complex it's likely that the data and state that `urql` manages, will also grow more complex and 12 12 introduce interdependencies between data. ··· 21 21 ## Features 22 22 23 23 The following pages introduce different features in _Graphcache_ which together make it a compelling 24 - alternative to the standard [document cache](../concepts/document-caching.md) that `urql` uses by 24 + alternative to the standard [document cache](../basics/document-caching.md) that `urql` uses by 25 25 default. 26 26 27 27 - 🔁 [**Fully reactive, normalized caching.**](./normalized-caching.md) _Graphcache_ stores data in
+1 -1
docs/graphcache/offline.md
··· 102 102 offline error — the `offlineExchange` won't deliver the error for this query to avoid it from being 103 103 surfaced to the user. This works particularly well in combination with ["Schema 104 104 Awareness"](./schema-awareness.md) which will deliver as much of a partial query result as possible. 105 - In combination with the [`cache-and-network` request policy](../concepts/document-caching.md#request-policies) 105 + In combination with the [`cache-and-network` request policy](../basics/document-caching.md#request-policies) 106 106 we can now ensure that we display as much data as possible when the user is offline while still 107 107 keeping the cache up-to-date when the user is online. 108 108
+24 -4
packages/site/static.config.js
··· 67 67 redirect: '/docs/basics', 68 68 }, 69 69 { 70 - path: '/docs/basics/document-caching', 71 - redirect: '/docs/concepts/document-caching', 72 - }, 73 - { 74 70 path: '404', 75 71 template: require.resolve('./src/screens/404'), 76 72 }, ··· 85 81 { 86 82 path: '/docs/graphcache/under-the-hood', 87 83 redirect: '/docs/graphcache/normalized-caching', 84 + }, 85 + { 86 + path: '/docs/concepts/document-caching', 87 + redirect: '/docs/basics/document-caching', 88 + }, 89 + { 90 + path: '/docs/concepts/errors', 91 + redirect: '/docs/basics/errors', 92 + }, 93 + { 94 + path: '/docs/concepts', 95 + redirect: '/docs/architecture', 96 + }, 97 + { 98 + path: '/docs/concepts/stream-patterns', 99 + redirect: '/docs/architecture', 100 + }, 101 + { 102 + path: '/docs/concepts/philosophy', 103 + redirect: '/docs/architecture', 104 + }, 105 + { 106 + path: '/docs/concepts/exchanges', 107 + redirect: '/docs/advanced/authoring-exchanges', 88 108 }, 89 109 ], 90 110 };