diff --git a/.changeset/real-horses-cough.md b/.changeset/real-horses-cough.md
new file mode 100644
index 0000000000..ab3ab7846c
--- /dev/null
+++ b/.changeset/real-horses-cough.md
@@ -0,0 +1,12 @@
+---
+'@urql/svelte': major
+---
+
+Reimplement the `@urql/svelte` API, which is now marked as stable.
+The new `@urql/svelte` API features the `query`, `mutation`, and `subscription` utilities, which are
+called as part of a component's normal lifecycle and accept `operationStore` stores. These are
+writable stores that encapsulate both a GraphQL operation's inputs and outputs (the result)!
+
+Learn more about how to use `@urql/svelte` [in our new API
+docs](https://formidable.com/open-source/urql/docs/api/svelte/) or starting from the [Basics
+pages.](https://formidable.com/open-source/urql/docs/basics/)
diff --git a/docs/advanced/subscriptions.md b/docs/advanced/subscriptions.md
index 918eb6c1f2..e54d7c312a 100644
--- a/docs/advanced/subscriptions.md
+++ b/docs/advanced/subscriptions.md
@@ -72,7 +72,7 @@ we return to the `subscriptionExchange` inside `forwardSubscription`.
## React & Preact
The `useSubscription` hooks comes with a similar API to `useQuery`, which [we've learned about in
-the "Queries" page in the "Basics" section.](../basics/queries.md)
+the "Queries" page in the "Basics" section.](../basics/queries.md#react--preact)
Its usage is extremely similar in that it accepts options, which may contain `query` and
`variables`. However, it also accepts a second argument, which is a reducer function, similar to
@@ -130,6 +130,62 @@ the `handleSubscription` function. This works over time, so as
new messages come in, we will append them to the list of previous
messages.
+## Svelte
+
+The `subscription` function in `@urql/svelte` comes with a similar API to `query`, which [we've
+learned about in the "Queries" page in the "Basics" section.](../basics/queries.md#svelte)
+
+Its usage is extremely similar in that it accepts an `operationStore`, which will typically contain
+our GraphQL subscription query. However, `subscription` also accepts a second argument, which is
+a reducer function, similar to what you would pass to `Array.prototype.reduce`.
+
+It receives the previous set of data that this function has returned or `undefined`.
+As the second argument, it receives the event that has come in from the subscription.
+You can use this to accumulate the data over time, which is useful for a
+list for example.
+
+In the following example, we create a subscription that informs us of
+new messages. We will concatenate the incoming messages so that we
+can display all messages that have come in over the subscription across
+events.
+
+```js
+
+
+{#if !$result.data}
+
No new messages
+{:else}
+
+ {#each $messages.data as message}
+
{message.from}: "{message.text}"
+ {/each}
+
+{/if}
+
+```
+
+As we can see, the `$result.data` is being updated and transformed by the `handleSubscription`
+function. This works over time, so as new messages come in, we will append them to
+the list of previous messages.
+
## One-off Subscriptions
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)
@@ -155,3 +211,4 @@ const { unsubscribe } = pipe(
console.log(result); // { data: ... }
})
);
+```
diff --git a/docs/api/README.md b/docs/api/README.md
index eea0220f2d..2f8d1ad777 100644
--- a/docs/api/README.md
+++ b/docs/api/README.md
@@ -14,6 +14,7 @@ more about the core package on the "Core Package" page.](../concepts/core-packag
- [`@urql/core` API docs](./core.md)
- [`urql` React API docs](./urql.md)
- [`@urql/preact` Preact API docs](./preact.md)
+- [`@urql/svelte` Svelte API docs](./svelte.md)
- [`@urql/exchange-graphcache` API docs](./graphcache.md)
- [`@urql/exchange-retry` API docs](./retry-exchange.md)
- [`@urql/exchange-execute` API docs](./execute-exchange.md)
diff --git a/docs/api/auth-exchange.md b/docs/api/auth-exchange.md
index ee3cb8f12e..5b69d5e147 100644
--- a/docs/api/auth-exchange.md
+++ b/docs/api/auth-exchange.md
@@ -1,6 +1,6 @@
---
title: '@urql/exchange-auth'
-order: 9
+order: 10
---
# Authentication Exchange
diff --git a/docs/api/execute-exchange.md b/docs/api/execute-exchange.md
index b3635a2436..e014ce93fd 100644
--- a/docs/api/execute-exchange.md
+++ b/docs/api/execute-exchange.md
@@ -1,6 +1,6 @@
---
title: '@urql/exchange-execute'
-order: 5
+order: 6
---
# Execute Exchange
diff --git a/docs/api/graphcache.md b/docs/api/graphcache.md
index 56560e381f..4b492e9473 100644
--- a/docs/api/graphcache.md
+++ b/docs/api/graphcache.md
@@ -1,6 +1,6 @@
---
title: '@urql/exchange-graphcache'
-order: 3
+order: 4
---
# @urql/exchange-graphcache
diff --git a/docs/api/multipart-fetch-exchange.md b/docs/api/multipart-fetch-exchange.md
index 074f254a4d..e54e796129 100644
--- a/docs/api/multipart-fetch-exchange.md
+++ b/docs/api/multipart-fetch-exchange.md
@@ -1,6 +1,6 @@
---
title: '@urql/exchange-multipart-fetch'
-order: 6
+order: 7
---
# Multipart Fetch Exchange
diff --git a/docs/api/persisted-fetch-exchange.md b/docs/api/persisted-fetch-exchange.md
index cd86b5c57b..28c33ef6de 100644
--- a/docs/api/persisted-fetch-exchange.md
+++ b/docs/api/persisted-fetch-exchange.md
@@ -1,6 +1,6 @@
---
title: '@urql/exchange-persisted-fetch'
-order: 7
+order: 8
---
# Persisted Fetch Exchange
diff --git a/docs/api/refocus-exchange.md b/docs/api/refocus-exchange.md
index 268f0b3751..2323cd8880 100644
--- a/docs/api/refocus-exchange.md
+++ b/docs/api/refocus-exchange.md
@@ -1,6 +1,6 @@
---
title: '@urql/exchange-refocus'
-order: 10
+order: 11
---
# Refocus exchange
diff --git a/docs/api/request-policy-exchange.md b/docs/api/request-policy-exchange.md
index a086f32110..5f66637506 100644
--- a/docs/api/request-policy-exchange.md
+++ b/docs/api/request-policy-exchange.md
@@ -1,6 +1,6 @@
---
title: '@urql/exchange-request-policy'
-order: 8
+order: 9
---
# Request Policy Exchange
diff --git a/docs/api/retry-exchange.md b/docs/api/retry-exchange.md
index dc594ee492..82cb5fb0a6 100644
--- a/docs/api/retry-exchange.md
+++ b/docs/api/retry-exchange.md
@@ -1,6 +1,6 @@
---
title: '@urql/exchange-retry'
-order: 4
+order: 5
---
# Retry Exchange
diff --git a/docs/api/svelte.md b/docs/api/svelte.md
new file mode 100644
index 0000000000..029da6eb2f
--- /dev/null
+++ b/docs/api/svelte.md
@@ -0,0 +1,106 @@
+---
+title: '@urql/svelte'
+order: 3
+---
+
+# Svelte API
+
+## operationStore
+
+Accepts three arguments as inputs, where only the first one — `query` — is required.
+
+| Argument | Type | Description |
+| --------- | ------------------------ | ---------------------------------------------------------------------------------- |
+| query | `string \| DocumentNode` | The query to be executed. Accepts as a plain string query or GraphQL DocumentNode. |
+| variables | `?object` | The variables to be used with the GraphQL request. |
+| context | `?object` | Holds the contextual information for the query. |
+
+This is a [Svelte Writable Store](https://svelte.dev/docs#writable) that is used by other utilities
+listed in these docs to read [`Operation` inputs](./core.md#operation) from and write
+[`OperationResult` outputs](./core.md#operationresult) to.
+
+The store has several properties on its value. The **writable properties** of it are inputs that are
+used by either [`query`](#query), [`mutation`](#mutation), or [`subscription`](#subscription) to
+create an [`Operation`](./core.md#operation) to execute. These are `query`, `variables`, and
+`context`; the same properties that the `operationStore` accepts as arguments on creation.
+
+Furthermore the store exposes some **readonly properties** which represent the operation's progress
+and [result](./core.md#operationresult).
+
+| Prop | Type | Description |
+| ----------------------------------------------------------------------------------------- | ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
+| data | `?any` | Data returned by the specified query |
+| error | `?CombinedError` | A [`CombinedError`](./core.md#combinederror) instances that wraps network or `GraphQLError`s (if any) |
+| extensions | `?Record` | Extensions that the GraphQL server may have returned. |
+| stale | `boolean` | A flag that may be set to `true` by exchanges to indicate that the `data` is incomplete or out-of-date, and that the result will be updated soon. |
+| fetching | `boolean` | A flag that indicates whether the operation is currently |
+| in progress, which means that the `data` and `error` is out-of-date for the given inputs. |
+
+All of the writable properties are updatable either via the common Svelte Writable's `set` or
+`update` methods or directly. The `operationStore` exposes setters for the writable properties which
+will automatically update the store and notify reactive subscribers.
+
+In development, trying to update the _readonly_ properties directly or via the `set` or `update`
+method will result in a `TypeError` being thrown.
+
+[Read more about `writable` stores on the Svelte API docs.](https://svelte.dev/docs#writable)
+
+## query
+
+The `query` utility function only accepts an `operationStore` as its only argument. Per
+`operationStore` it should only be called once per component as it lives alongside the component and
+hooks into its `onDestroy` lifecycle method. This means that we must avoid passing a reactive
+variable to it, and instead must pass the raw `operationStore`.
+
+This function will return the `operationStore` itself that has been passed.
+
+[Read more about how to use the `query` API on the "Queries" page.](../basics/queries.md#svelte)
+
+## subscription
+
+The `subscription` utility function accepts an `operationStore` as its first argument, like the
+[`query` function](#query). It should also per `operationStore` be called once per component.
+
+The function also optionally accepts a second argument, a `handler` function. This function has the
+following type signature:
+
+```js
+type SubscriptionHandler = (previousData: R | undefined, data: T) => R;
+```
+
+This function will be called with the previous data (or `undefined`) and the new data that's
+incoming from a subscription event, and may be used to "reduce" the data over time, altering the
+value of `result.data`.
+
+`subscription` itself will return the `operationStore` that has been passed when called.
+
+[Read more about how to use the `subscription` API on the "Subscriptions"
+page.](../advanced/subscriptions.md#svelte)
+
+## mutation
+
+The `mutation` utility function either accepts an `operationStore` as its only argument or an object
+containing `query`, `variables`, and `context` properties. When it receives the latter it will
+create an `operationStore` automatically.
+
+The function will return an `executeMutation` callback, which can be used to trigger the mutation.
+This callback optionally accepts a `variables` argument and a `context` argument of type
+[`Partial`](./core.md#operationcontext). If these arguments are passed, they will
+automatically update the `operationStore` before starting the mutation.
+
+The `executeMutation` callback will return a promise which resolves to the `operationStore` once the
+mutation has been completed.
+
+[Read more about how to use the `mutation` API on the "Mutations"
+page.](../basics/mutations.md#svelte)
+
+## Context API
+
+In Svelte the [`Client`](./core.md#client) is passed around using [Svelte's Context
+API](https://svelte.dev/tutorial/context-api). `@urql/svelte` wraps around Svelte's
+[`setContext`](https://svelte.dev/docs#setContext) and
+[`getContext`](https://svelte.dev/docs#getContext) functions and exposes:
+
+- `setClient`
+- `getClient`
+- `initClient` (a shortcut for `createClient` + `setClient`)
diff --git a/docs/basics/getting-started.md b/docs/basics/getting-started.md
index d3ee1bda67..67342faf3a 100644
--- a/docs/basics/getting-started.md
+++ b/docs/basics/getting-started.md
@@ -95,3 +95,104 @@ const App = () => (
Now every component and element inside and under the `Provider` are able to use GraphQL queries that
will be sent to our API.
+
+[On the next page we'll learn about executing "Queries".](./queries.md#react--preact)
+
+## Svelte
+
+This "Getting Started" guide covers how to install and set up `urql` and provide a `Client` for
+Svelte. The `@urql/svelte` package, which provides bindings for Svelte, doesn't fundamentally
+function differently from `@urql/preact` or `urql` and uses the same [Core Package and
+`Client`](../concepts/core-package.md).
+
+### Installation
+
+Installing `@urql/svelte` is quick and no other packages are immediately necessary.
+
+```sh
+yarn add @urql/svelte graphql
+# or
+npm install --save @urql/svelte graphql
+```
+
+Most libraries related to GraphQL also need the `graphql` package to be installed as a peer
+dependency, so that they can adapt to your specific versioning requirements. That's why we'll need
+to install `graphql` alongside `@urql/svelte`.
+
+Both the `@urql/svelte` and `graphql` packages follow [semantic versioning](https://semver.org) and
+all `@urql/svelte` packages will define a range of compatible versions of `graphql`. Watch out
+for breaking changes in the future however, in which case your package manager may warn you about
+`graphql` being out of the defined peer dependency range.
+
+### Setting up the `Client`
+
+The `@urql/svelte` package exports a method called `createClient` which we can use to create
+the GraphQL client. This central `Client` manages all of our GraphQL requests and results.
+
+```js
+import { createClient } from '@urql/svelte';
+
+const client = createClient({
+ url: 'http://localhost:3000/graphql',
+});
+```
+
+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 be
+passed to `fetch` when a request is sent to the given API `url`. We may pass in an options object or
+a function returning an options object.
+
+In the following example we'll add a token to each `fetch` request that our `Client` sends to our
+GraphQL API.
+
+```js
+const client = createClient({
+ url: 'http://localhost:3000/graphql',
+ fetchOptions: () => {
+ const token = getToken();
+ return {
+ headers: { authorization: token ? `Bearer ${token}` : '' },
+ };
+ },
+});
+```
+
+### Providing the `Client`
+
+To make use of the `Client` in Svelte we will have to provide it via the
+[Context API](https://svelte.dev/tutorial/context-api). From a parent component to its child
+components. This will share one `Client` with the rest of our app, if we for instance provide the
+`Client`
+
+```html
+
+```
+
+The `setClient` method internally calls [Svelte's `setContext`
+function](https://svelte.dev/docs#setContext). The `@urql/svelte` package also exposes a `getClient`
+function that uses [`getContext`](https://svelte.dev/docs#getContext) to retrieve the `Client` in
+child components. This is used throughout `@urql/svelte`'s API.
+
+We can also use a convenience function, `initClient`. This function combines the `createClient` and
+`setClient` calls into one.
+
+```html
+
+```
+
+[On the next page we'll learn about executing "Queries".](./queries.md#svelte)
diff --git a/docs/basics/mutations.md b/docs/basics/mutations.md
index a84de89df0..42f6583253 100644
--- a/docs/basics/mutations.md
+++ b/docs/basics/mutations.md
@@ -100,3 +100,129 @@ it.](../api/urql.md#usemutation)
[On the next page we'll learn about "Document Caching", `urql`'s default caching
mechanism.](./document-caching.md)
+
+## Svelte
+
+This guide covers how to send mutations in Svelte using `@urql/svelte`'s `mutation` utility.
+The `mutation` function isn't dissimilar from the `query` function but is triggered manually and
+can accept a [`GraphQLRequest` object](../api/core.md#graphqlrequest) too while also supporting our
+trusty `operationStore`.
+
+### Sending a mutation
+
+Let's again pick up an example with an imaginary GraphQL API for todo items, and dive into an
+example! We'll set up a mutation that _updates_ a todo item's title.
+
+```html
+
+```
+
+This small call to `mutation` accepts a `query` property (besides the `variables` property) and
+returns an execute function. We've wrapped it in an `updateTodo` function to illustrate its usage.
+
+Unlike the `query` function, the `mutation` function doesn't start our mutation automatically.
+Instead, mutations are started programmatically by calling the function they return. This function
+also returns a promise so that we can use the mutation's result.
+
+### Using the mutation result
+
+When calling `mutateTodo` in our previous example, we start the mutation. To use the mutation's
+result we actually have two options instead of one.
+
+The first option is to use the promise that the `mutation`'s execute function returns. This promise
+will resolve to an `operationStore`, which is what we're used to from sending queries. Using this
+store we can then read the mutation's `data` or `error`.
+
+```html
+
+```
+
+Alternatively, we can pass `mutation` an `operationStore` directly. This allows us to use a
+mutation's result in our component's UI more easily, without storing it ourselves.
+
+```html
+
+
+{#if $updateTodoStore.data} Todo was updated! {/if}
+```
+
+### Handling mutation errors
+
+It's worth noting that the promise we receive when calling the execute function will never
+reject. Instead it will always return a promise that resolves to an `operationStore`, even if the
+mutation has failed.
+
+If you're checking for errors, you should use `operationStore.error` instead, which will be set
+to a `CombinedError` when any kind of errors occurred while executing your mutation.
+[Read more about errors on our "Errors" page.](./errors.md)
+
+```jsx
+mutateTodo({ id, title: newTitle }).then(result => {
+ if (result.error) {
+ console.error('Oh no!', result.error);
+ }
+});
+```
+
+[On the next page we'll learn about "Document Caching", `urql`'s default caching
+mechanism.](./document-caching.md)
diff --git a/docs/basics/queries.md b/docs/basics/queries.md
index aa0cecc525..e23931f788 100644
--- a/docs/basics/queries.md
+++ b/docs/basics/queries.md
@@ -192,4 +192,219 @@ when `pause` is set to `true`, which would usually stop all automatic queries.
There are some more tricks we can use with `useQuery`. [Read more about its API in the API docs for
it.](../api/urql.md#usequery)
-[On the next page we'll learn about "Mutations" rather than Queries.](./mutations.md)
+[On the next page we'll learn about "Mutations" rather than Queries.](./mutations.md#react--preact)
+
+## Svelte
+
+This guide covers how to query data with Svelte with our `Client` now fully set up and provided via
+the Context API. We'll implement queries using the `operationStore` and the `query` function from
+`@urql/svelte`.
+
+The `operationStore` function creates a [Svelte Writable store](https://svelte.dev/docs#writable).
+You can use it to initialise a data container in `urql`. This store holds on to our query inputs,
+like the GraphQL query and variables, which we can change to launch new queries, and also exposes
+the query's eventual result, which we can then observe.
+
+### Run a first query
+
+For the following examples, we'll imagine that we're querying data from a GraphQL API that contains
+todo items. Let's dive right into it!
+
+```html
+
+
+{#if $todos.fetching}
+
Loading...
+{:else if $todos.error}
+
Oh no... {$todos.error.message}
+{:else}
+
+ {#each $todos.data.todos as todo}
+
{todo.title}
+ {/each}
+
+{/if}
+```
+
+Here we have implemented our first GraphQL query to fetch todos. We're first creating an
+`operationStore` which holds on to our `query` and are then passing the store to the `query`
+function, which starts the GraphQL query.
+
+The `todos` store can now be used like any other Svelte store using a
+[reactive auto-subscription](https://svelte.dev/tutorial/auto-subscriptions) in Svelte. This means
+that we prefix `$todos` with a dollar symbol, which automatically subscribes us to its changes.
+
+The `query` function accepts our store and starts using the `Client` to execute our query. It may
+only be called once for a store and lives alongside the component's lifecycle. It will automatically
+read changes on the `operationStore` and will update our query and results accordingly.
+
+### Variables
+
+Typically we'll also need to pass variables to our queries, for instance, if we are dealing with
+pagination. For this purpose the `operationStore` also accepts a `variables` argument, which we can
+use to supply variables to our query.
+
+```html
+
+
+...
+```
+
+As when we're sending GraphQL queries manually using `fetch`, the variables will be attached to the
+`POST` request body that is sent to our GraphQL API.
+
+The `operationStore` also supports being actively changed. This will hook into Svelte's reactivity
+model as well and cause the `query` utility to start a new operation.
+
+```html
+
+
+
+```
+
+The `operationStore` provides getters too so it's also possible for us to pass `todos` around and
+update `todos.variables` or `todos.query` directly. Both, updating `todos.variables` and
+`$todos.variables` in a component for instance, will cause `query` to pick up the update and execute
+our changes.
+
+### Request Policies
+
+The `operationStore` also accepts another argument apart from `query` and `variables`. Optionally
+you may pass a third argument, [the `context` object](../api/core.md#operationcontext). The arguably
+most interesting option the `context` may contain is `requestPolicy`.
+
+The `requestPolicy` option determines how results are retrieved from our `Client`'s cache. By
+default this is set to `cache-first`, which means that we prefer to get results from our cache, but
+are falling back to sending an API request.
+
+In total there are four different policies that we can use:
+
+- `cache-first` (the default) prefers cached results and falls back to sending an API request when
+ no prior result is cached.
+- `cache-and-network` returns cached results but also always sends an API request, which is perfect
+ for displaying data quickly while keeping it up-to-date.
+- `network-only` will always send an API request and will ignore cached results.
+- `cache-only` will always return cached results or `null`.
+
+The `cache-and-network` policy is particularly useful, since it allows us to display data instantly
+if it has been cached, but also refreshes data in our cache in the background. This means though
+that `fetching` will be `false` for cached results although an API request may still be ongoing in
+the background.
+
+For this reason there's another field on results, `result.stale`, which indicates that the cached
+result is either outdated or that another request is being sent in the background.
+
+```html
+
+
+...
+```
+
+As we can see, the `requestPolicy` is easily changed here and we can read our `context` option back
+from `todos.context`, just as we can check `todos.query` and `todos.variables`. Updating
+`operationStore.context` can be very useful to also refetch queries, as we'll see in the next
+section.
+
+[You can learn more about request policies on the API docs.](../api/core.md#requestpolicy)
+
+### Reexecuting Queries
+
+The default caching approach in `@urql/svelte` typically takes care of updating queries on the fly
+quite well and does so automatically. Sometimes it may be necessary though to refetch data and to
+execute a query with a different `context`. Triggering a query programmatically may be useful in a
+couple of cases. It can for instance be used to refresh data that is currently being displayed.
+
+We can trigger a new query update by changing out the `context` of our `operationStore`.
+
+```html
+
+```
+
+Calling `refresh` in the above example will execute the query again forcefully, and will skip the
+cache, since we're passing `requestPolicy: 'network-only'`.
+
+### Reading on
+
+There are some more tricks we can use with `operationStore`.
+[Read more about its API in the API docs for it.](../api/svelte.md#operationStore)
+
+[On the next page we'll learn about "Mutations" rather than Queries.](./mutations.md#svelte)
diff --git a/packages/svelte-urql/package.json b/packages/svelte-urql/package.json
index 828ecf9d25..56ecde0491 100644
--- a/packages/svelte-urql/package.json
+++ b/packages/svelte-urql/package.json
@@ -55,7 +55,7 @@
"svelte": "^3.0.0"
},
"dependencies": {
- "@urql/core": "^1.12.3",
+ "@urql/core": "^1.13.1",
"wonka": "^4.0.14"
},
"devDependencies": {
diff --git a/packages/svelte-urql/src/context.ts b/packages/svelte-urql/src/context.ts
index 96e8da2eb0..f9443b55eb 100644
--- a/packages/svelte-urql/src/context.ts
+++ b/packages/svelte-urql/src/context.ts
@@ -1,12 +1,11 @@
import { setContext, getContext } from 'svelte';
import { Client, ClientOptions } from '@urql/core';
+import { _contextKey } from './internal';
-const CLIENT = '$$_URQL';
-
-export const getClient = (): Client => getContext(CLIENT);
+export const getClient = (): Client => getContext(_contextKey);
export const setClient = (client: Client): void => {
- setContext(CLIENT, client);
+ setContext(_contextKey, client);
};
export const initClient = (args: ClientOptions): Client => {
diff --git a/packages/svelte-urql/src/index.ts b/packages/svelte-urql/src/index.ts
index 662f139578..f8acafa614 100644
--- a/packages/svelte-urql/src/index.ts
+++ b/packages/svelte-urql/src/index.ts
@@ -1,3 +1,4 @@
export * from '@urql/core';
+export * from './operationStore';
export * from './context';
export * from './operations';
diff --git a/packages/svelte-urql/src/internal.ts b/packages/svelte-urql/src/internal.ts
new file mode 100644
index 0000000000..58ab8e1fc5
--- /dev/null
+++ b/packages/svelte-urql/src/internal.ts
@@ -0,0 +1,6 @@
+export const _contextKey = '$$_urql';
+export const _storeUpdate = new Set