+2
-3
docs/advanced/authentication.md
+2
-3
docs/advanced/authentication.md
···in front of all `fetchExchange`s but after all other synchronous exchanges, like the `cacheExchange`.
+4
-4
docs/advanced/auto-populate-mutations.md
+4
-4
docs/advanced/auto-populate-mutations.md
···The `populateExchange` should be placed in front of the `cacheExchange`, especially if you're using[Graphcache](../graphcache/README.md), since it won't understand the `@populate` directive on itsAdding the `populateExchange` now enables us to use the `@populate` directive in our mutations.
+1
-1
docs/advanced/debugging.md
+1
-1
docs/advanced/debugging.md
+34
-34
docs/advanced/persistence-and-uploads.md
+34
-34
docs/advanced/persistence-and-uploads.md
···-Queries](https://www.apollographql.com/docs/apollo-server/performance/apq/), Persisted Queries, and-While File Uploads should work without any modifications, an additional exchange must be installed···easier for a CDN to cache, as by default most caches would not cache POST requests automatically.-implement Automatic Persisted Queries. This exchange works alongside the default `fetchExchange`······As we can see, typically it's recommended to set `preferGetForPersistedQueries` to `true` to force-`preferGetMethod`](../api/core.md#client) but only switches persisted queries to use GET requests-instead. This is preferable since sometimes the GraphQL query can grow too large for a simple GET·········-Spec](https://github.com/jaydenseric/graphql-multipart-request-spec) to allow files to be uploaded.-This allows us to pass a `File` or `Blob` directly to our GraphQL requests as variables, and the+spec](https://github.com/jaydenseric/graphql-multipart-request-spec) to allow for File Uploads-Files are often handled in the browser via the [File API](https://developer.mozilla.org/en-US/docs/Web/API/File),-which we may typically get to via a [file input](https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications)+If a GraphQL API supports this, we can pass a [`File`](https://developer.mozilla.org/en-US/docs/Web/API/File)+or a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob) directly into our variables and+[file input](https://developer.mozilla.org/en-US/docs/Web/API/File/Using_files_from_web_applications),-In `urql`, these are supported natively, so as long as your JS environment supports either `File` or+The `@urql/core@4` package supports File Uploads natively, so we won't have to do any installation+or setup work. When `urql` sees a `File` or a `Blob` anywhere in your `variables`, it switches to+a `multipart/form-data` request, converts the request to a `FormData` object, according to the-Previously, this worked by installing the [`@urql/multipart-fetch-exchange` package](../api/multipart-fetch-exchange.md),+> **Note:** Previously, this worked by installing the `@urql/multipart-fetch-exchange` package.+> however, this package has been deprecated and file uploads are now built into `@urql/core@4`.
+5
-7
docs/advanced/retry-operations.md
+5
-7
docs/advanced/retry-operations.md
·········
+6
-7
docs/advanced/server-side-rendering.md
+6
-7
docs/advanced/server-side-rendering.md
···-import { createClient, dedupExchange, cacheExchange, fetchExchange, ssrExchange } from '@urql/core';·········
+13
-18
docs/advanced/subscriptions.md
+13
-18
docs/advanced/subscriptions.md
···-import { Client, dedupExchange, cacheExchange, fetchExchange, subscriptionExchange } from 'urql';···For backends supporting `graphql-ws`, we recommend using the [graphql-ws](https://github.com/enisdenjo/graphql-ws) client.-import { createClient, dedupExchange, cacheExchange, fetchExchange, subscriptionExchange } from 'urql';···> The `subscriptions-transport-ws` package isn't actively maintained. If your API supports the new protocol or you can swap the package out, consider using [`graphql-ws`](#setting-up-graphql-ws) instead.-import { Client, dedupExchange, cacheExchange, fetchExchange, subscriptionExchange } from 'urql';const subscriptionClient = new SubscriptionClient('ws://localhost/graphql', { reconnect: true });···············
+5
-1
docs/api/README.md
+5
-1
docs/api/README.md
···Most of these packages will refer to or use utilities and types from the `@urql/core` package. [Read···
+5
docs/api/auth-exchange.md
+5
docs/api/auth-exchange.md
···The `@urql/exchange-auth` package contains an addon `authExchange` for `urql` that aims to make iteasy to implement complex authentication and reauthentication flows as are typically found with JWT
+6
-1
docs/api/core.md
+6
-1
docs/api/core.md
···like [`urql` for React](./urql.md) or [`@urql/preact`](./preact.md), will reuse the core logic and···| ----------------- | ------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- || `fetchOptions` | `RequestInit \| () => RequestInit` | Additional `fetchOptions` that `fetch` in `fetchExchange` should use to make a request |
+5
docs/api/execute-exchange.md
+5
docs/api/execute-exchange.md
···The `@urql/exchange-execute` package contains an addon `executeExchange` for `urql` that may be used to
+5
docs/api/graphcache.md
+5
docs/api/graphcache.md
···The `@urql/exchange-graphcache` package contains an addon `cacheExchange` for `urql` that may beused to replace the default [`cacheExchange`](./core.md#cacheexchange), which switches `urql` from
-46
docs/api/multipart-fetch-exchange.md
-46
docs/api/multipart-fetch-exchange.md
···-The `@urql/exchange-multipart-fetch` package contains an addon `multipartFetchExchange` for `urql`-This exchange uses the same fetch logic as the [`fetchExchange`](./core.md#fetchexchange) and by reusing logic from `@urql/core/internal`.-[`fetchExchange`](./core.md#fetchexchange) and will act exactly like the `fetchExchange` unless the-`variables` that it receives for mutations contain any `File`s as detected by the `extract-files` package.
+5
docs/api/preact.md
+5
docs/api/preact.md
···
+5
docs/api/refocus-exchange.md
+5
docs/api/refocus-exchange.md
···`@urql/exchange-refocus` is an exchange for the `urql` that tracks currently active operations and redispatches them when the
+5
docs/api/request-policy-exchange.md
+5
docs/api/request-policy-exchange.md
···The `@urql/exchange-request-policy` package contains an addon `requestPolicyExchange` for `urql`
+5
docs/api/retry-exchange.md
+5
docs/api/retry-exchange.md
···The `@urql/exchange-retry` package contains an addon `retryExchange` for `urql` that may be used tolet failed operations be retried, typically when a previous operation has failed with a network
+5
docs/api/svelte.md
+5
docs/api/svelte.md
···
+12
-7
docs/api/urql.md
+12
-7
docs/api/urql.md
······| `query` | `string \| DocumentNode` | The query to be executed. Accepts as a plain string query or GraphQL DocumentNode. || `requestPolicy` | `?RequestPolicy` | An optional [request policy](./core.md#requestpolicy) that should be used specifying the cache strategy. |-| `pause` | `?boolean` | A boolean flag instructing [execution to be paused](../basics/react-preact.md#pausing-usequery). |+| `pause` | `?boolean` | A boolean flag instructing [execution to be paused](../basics/react-preact.md#pausing-usequery). |···-| ---------------------------------------------------- | ------------------------ | ---------------------------------------------------------------------------------- |-| `query` | `string \| DocumentNode` | The query to be executed. Accepts as a plain string query or GraphQL DocumentNode. |-| `pause` | `?boolean` | A boolean flag instructing [execution to be paused](../basics/react-preact.md#pausing-usequery). |+| ----------- | ------------------------ | ------------------------------------------------------------------------------------------------ |+| `query` | `string \| DocumentNode` | The query to be executed. Accepts as a plain string query or GraphQL DocumentNode. |+| `pause` | `?boolean` | A boolean flag instructing [execution to be paused](../basics/react-preact.md#pausing-usequery). |The hook optionally accepts a second argument, which may be a handler function with a type signature
+5
docs/api/vue.md
+5
docs/api/vue.md
···
+110
-91
docs/architecture.md
+110
-91
docs/architecture.md
···-`urql` is a highly customizable and flexible GraphQL client, that happens to come with some default+- The Client — as created [with the core `@urql/core` package](./basics/code.md), which interacts with "exchanges" to execute GraphQLBy default, `urql` aims to provide the minimal amount of features that allow us to build an app···If `urql` was a train it would take several stops to arrive at its terminus, our API. It starts with us-defining queries or mutations. Any GraphQL request can be abstracted into their query documents and-their variables. In `urql`, these GraphQL requests are treated as unique objects, which are uniquely-identified by the query document and variables (which is why a `key` is generated from the two). This+In `urql`, these GraphQL requests are treated as unique objects and each GraphQL request will have+a `key` generated for them. This `key` is a hash of the query document and the variables you provide-[`Client`](./api/core.md#client). It accepts several options like `url` or `requestPolicy` which are+The `Client` accepts several options to configure its behaviour and the behaviour of exchanges,-`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"+The bindings that we've seen in [the "Basics" section](./basics/README.md), like `useQuery` for-[`Operation`](./api/core.md#operation)s. An "Operation" is an extension of `GraphQLRequest`s. Not+[`GraphQLRequest`s](./api/core.md#graphqlrequest). However, since we have more metadata that is+needed, like our `url` option on the `Client`, `urql` internally creates [`Operation`s](./api/core.md#operation)+An "Operation" is an extension of `GraphQLRequest`s. Not only do they carry the `query`, `variables`,-It's the `Client`s responsibility to accept an `Operation` and execute it. The bindings internally-call the `client.executeQuery`, `client.executeMutation`, or `client.executeSubscription` methods,+This means, once we hand over a GraphQL request to the `Client`, it will create an `Operation`,-In the diagram we can see that each operation is a signal for our request to start at which point-we can expect to receive our results eventually on a callback. Once we're not interested in results-anymore a special "teardown" signal is issued on the `Client`. While we don't see operations outside+As shown in the diagram, each operation is like an event or signal for a GraphQL request to start,+However, because the cache can send updates to us whenever it detects a change, or you could cancel+a GraphQL request before it finishes, a special "teardown" `Operation` also exists, which cancelsTo reiterate, when we use `urql`'s bindings for our framework of choice, methods are called on the`Client`, but we never see the operations that are created in the background from our bindings. Wecall a method like `client.executeQuery` (or it's called for us in the bindings), an operation is-issued internally when we subscribe with a callback, and later our callback is called with results.···+By default, the `Client` doesn't do anything with GraphQL requests. It contains only the logic to+manage and differentiate between active and inactive requests and converts them to operations.+To actually do something with our GraphQL requests, it needs _exchanges_, which are like plugins+By default, you may want to add the `cacheExchange` and the `fetchExchange` from `@urql/core`:-- `cacheExchange`: The default caching logic with ["Document Caching"](./basics/document-caching.md)-- `fetchExchange`: Sends an operation to the API using `fetch` and adds results to the output stream+- `cacheExchange`: Caches GraphQL results with ["Document Caching"](./basics/document-caching.md)-When we don't pass the `exchanges` option manually to our `Client` then these are the ones that will-be applied. As we can see, an exchange exerts a lot of power over our operations and results. They-determine a lot of the logic of the `Client`, taking care of things like deduplication, caching, and-- [`mapExchange`](./api/core.md#mapexchange): Allows reacting to operations, results, and errors+As we can tell, exchanges define not only how GraphQL requests are executed and handled, but also+get control over caching. Exchanges can be used to change almost any behaviour in the `Client`,+although internally they only handle incoming & outgoing requests and incoming & outgoing results.+- [`mapExchange`](./api/core.md#mapexchange): Allows changing and reacting to operations, results, and errors- [`ssrExchange`](./advanced/server-side-rendering.md): Allows for a server-side renderer to-- [`multipartFetchExchange`](./advanced/persistence-and-uploads.md#file-uploads): Provides multipart file upload capability+- [`retryExchange`](./advanced/retry-operations.md): Allows operations to be retried on errors- [`persistedFetchExchange`](./advanced/persistence-and-uploads.md#automatic-persisted-queries): Provides support for Automatic-- [`authExchange`](./advanced/authentication.md): Allows complex authentication flows to be implemented-- [`requestPolicyExchange`](./api/request-policy-exchange.md): Automatically upgrades `cache-only` and `cache-first` operations to `cache-and-network` after a given amount of time.+- [`authExchange`](./advanced/authentication.md): Allows refresh authentication to be implemented easily.+- [`requestPolicyExchange`](./api/request-policy-exchange.md): Automatically refreshes results given a TTL.- `devtoolsExchange`: Provides the ability to use the [urql-devtools](https://github.com/urql-graphql/urql-devtools)We can even swap out our [document cache](./basics/document-caching.md), which is implemented by···directly](./basics/core.md#one-off-queries-and-mutations) or write exchanges then we'll see streams-`urql` utilises the [Wonka](https://github.com/kitten/wonka) library for its streams. It has a-In Wonka, like with Observables, streams are cancellable by calling the `unsubscribe` method that aWhen we call methods on the `Client` like [`client.executeQuery`](./api/core.md#clientexecutequery)-or [`client.query`](./api/core.md#clientquery) then these will return a Wonka stream. Those are-We can use [`wonka`'s `subscribe`](https://wonka.kitten.sh/api/sinks#subscribe) function to start-this stream. We pass this function a callback and will receive results back from the `Client`, as it-starts our operation. When we unsubscribe then the `Client` will stop this operation by sending a+It's normal for GraphQL subscriptions to deliver multiple results, however, even GraphQL queries can+give you multiple results in `urql`. This is because operations influence one another. When a cache+invalidates a query, this query may refetch, and a new result is delivered to your application.+Multiple results mean that once you subscribe to a GraphQL query via the `Client`, you may receive···+library. It is used to write exchanges and when we interact with the `Client` it is used internally
+56
-32
docs/basics/core.md
+56
-32
docs/basics/core.md
···Since all bindings and all exchanges depend on `@urql/core`, we may sometimes run into problems······create the GraphQL client. This central `Client` manages all of our GraphQL requests and results.-At the bare minimum we'll need to pass an API's `url` when we create a `Client` to get started.Another common option is `fetchOptions`. This option allows us to customize the options that will bepassed to `fetch` when a request is sent to the given API `url`. We may pass in an options object, or······-This option passes a list of exchanges to the `Client`, which tell it how to execute our requests+The `exchanges` option is of particular importance however because it tells the `Client` what to do+For instance, here, the `Client`'s caching and fetching features are only available because we're+passing it exchanges. In the above example, the `Client` will try to first read a GraphQL request+The caching in `urql` is also implemented as an exchange, so for instance, the behavior described+on the ["Document Caching" page](./document-caching.md) is all contained within the `cacheExchange`Later, [in the "Advanced" section](../advanced/README.md) we'll see many more features that `urql`supports by adding new exchanges to this list. On [the "Architecture" page](../architecture.md)-exchanges in order. First, the `dedupExchange` deduplicates requests if we send the same queries-twice, the `cacheExchange` implements the default "document caching" behaviour (as we'll learn about···result as a promise. This may be useful when we don't plan on cancelling queries, or we don't+This can also be written using async/await by simply awaiting the return value of `client.query`:+It's worth noting that promisifying a query result will always only give us _one_ result, because+we're not calling `subscribe`. This means that we'll never see cache updates when we're asking forSimilarly there's a way to read data from the cache synchronously, provided that the cache hasreceived a result for a given query before. The `Client` has a `readQuery` method, which is a···somewhere else then we'll get notified of the new API result as well, as long as we're subscribed.···
+21
-21
docs/basics/react-preact.md
+21
-21
docs/basics/react-preact.md
···To use `urql` with Preact, we have to install `@urql/preact` instead of `urql` and import from···-The `urql` and `@urql/preact` packages export a method called `createClient` which we can use tocreate the GraphQL client. This central `Client` manages all of our GraphQL requests and results.-At the bare minimum we'll need to pass an API's `url` when we create a `Client` to get started.+At the bare minimum we'll need to pass an API's `url` and `exchanges` when we create a `Client`Another common option is `fetchOptions`. This option allows us to customize the options that will bepassed to `fetch` when a request is sent to the given API `url`. We may pass in an options object, or···············+const shouldPause = from === undefined || from === null || limit === undefined || limit === null;···
+17
-16
docs/basics/svelte.md
+17
-16
docs/basics/svelte.md
······-At the bare minimum we'll need to pass an API's `url` when we create a `Client` to get started.Another common option is `fetchOptions`. This option allows us to customize the options that will bepassed to `fetch` when a request is sent to the given API `url`. We may pass in an options object or······-import { createClient, setContextClient, dedupExchange, cacheExchange, fetchExchange } from '@urql/svelte';······
+6
-5
docs/basics/typescript-integration.md
+6
-5
docs/basics/typescript-integration.md
······-const [{ data }] = useQuery({ query: allFilmsWithVariablesQueryDocument, variables: { first: 10 } });
+3
-3
docs/basics/ui-patterns.md
+3
-3
docs/basics/ui-patterns.md
···
+42
-41
docs/basics/vue.md
+42
-41
docs/basics/vue.md
···-At the bare minimum we'll need to pass an API's `url` when we create a `Client` to get started.+At the bare minimum we'll need to pass an API's `url` and `exchanges` when we create a `Client`Another common option is `fetchOptions`. This option allows us to customize the options that will bepassed to `fetch` when a request is sent to the given API `url`. We may pass in an options object or······The first method is to use `@urql/vue`'s `provideClient` function. This must be called in any ofyour parent components and accepts either a `Client` directly or just the options that you'd pass to-import { createClient, provideClient, dedupExchange, cacheExchange, fetchExchange } from '@urql/vue';····································
+46
-47
docs/comparison.md
+46
-47
docs/comparison.md
···-| ------------------------------------------ | ---------------------------------- | -------------------------------------------------------------------------- | ------------------------------ |-| Base Bundle Size | **5.9kB** (7.1kB with bindings) | 32.9kB | 27.7kB (34.1kB with bindings) |-| Defer & Stream Directives | ✅ | ✅ / 🛑 (`@defer` is supported in >=3.7.0, `@stream` is not yet supported) | 🟡 (unreleased) |-| Retrying Failed Queries | ✅ `@urql/exchange-retry` | ✅ `apollo-link-retry` | ✅ `DefaultNetworkLayer` |-| Easy Authentication Flows | ✅ `@urql/exchange-auth` | 🛑 (no docs for refresh-based authentication) | 🟡 `react-relay-network-layer` |+| ------------------------------------------ | ---------------------------------------------- | ------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |+| Base Bundle Size | **10kB** (11kB with bindings) | ~50kB (55kB with React hooks) | 45kB (66kB with bindings) |+| Subscriptions | 🔶 [Docs](./advanced/subscriptions.md) | 🔶 [Docs](https://www.apollographql.com/docs/react/data/subscriptions/#setting-up-the-transport) | 🔶 [Docs](https://relay.dev/docs/guided-tour/updating-data/graphql-subscriptions/#configuring-the-network-layer) |+| Client-side Rehydration | ✅ [Docs](./advanced/server-side-rendering.md) | ✅ [Docs](https://www.apollographql.com/docs/react/performance/server-side-rendering) | 🛑 |+| Defer & Stream Directives | ✅ | ✅ / 🛑 (`@defer` is supported in >=3.7.0, `@stream` is not yet supported) | 🟡 (unreleased) |+| Retrying Failed Queries | ✅ `@urql/exchange-retry` | ✅ `apollo-link-retry` | ✅ `DefaultNetworkLayer` |+| Easy Authentication Flows | ✅ `@urql/exchange-auth` | 🛑 (no docs for refresh-based authentication) | 🟡 `react-relay-network-layer` |Typically these are all additional addon features that you may expect from a GraphQL client, nomatter which framework you use it with. It's worth mentioning that all three clients support some···| ------------------------------ | -------------- | ------------------- | ------------------ |···-| ------------------------------------------------------- | --------------------------------------------------------------------- | ------------------------- | ---------------------------------------------- |-| Caching Strategy | Document Caching, Normalized Caching with `@urql/exchange-graphcache` | Normalized Caching | Normalized Caching (schema restrictions apply) |+| ------------------------------------------------------- | --------------------------------------------------------------------- | ----------------------------------- | ---------------------------------------------- |+| Caching Strategy | Document Caching, Normalized Caching with `@urql/exchange-graphcache` | Normalized Caching | Normalized Caching (schema restrictions apply) |caching](./graphcache/normalized-caching.md) as its default caching strategy. Typically this is seen···but often this comparison is hard to make. When you start comparing bundle sizes of these three-- All packages in `urql` reuse parts of `@urql/core` and `wonka`, which means adding all their total+- Some dependencies may be external and the above sizes listed are total minified+gzipped sizes+- `@urql/core` imports from `wonka` for stream utilities and `@0no-co/graphql.web` for GraphQL query+- All `urql` packages reuse parts of `@urql/core` and `wonka`, which means adding all their total-- These sizes may change drastically given the code you write and add yourself, but can be managed-via precompilation (e.g. with `babel-plugin-graphql-tag` or GraphQL Code Generator for Apollo and
+3
-3
docs/graphcache/README.md
+3
-3
docs/graphcache/README.md
···
+6
-6
docs/graphcache/offline.md
+6
-6
docs/graphcache/offline.md
············