{"owner":"urql-graphql","repo":"urql","hasSkills":true,"totalSkillsCount":11,"totalTokensCount":8632,"categories":["project-spec","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":["docs/architecture.md","packages/core/README.md","packages/introspection/README.md","packages/next-urql/README.md","packages/preact-urql/README.md","packages/react-urql/README.md","packages/solid-start-urql/README.md","packages/solid-urql/README.md","packages/storage-rn/README.md","packages/svelte-urql/README.md","packages/vue-urql/README.md"],"skills":{"docs/architecture.md":"---\ntitle: Architecture\norder: 3\n---\n\n# Architecture\n\n`urql` is a highly customizable and flexible GraphQL client.\nAs you use it in your app, it's split into three parts:\n\n- Bindings — such as for React, Preact, Vue, or Svelte — which interact with `@urql/core`'s\n  `Client`.\n- The Client — as created [with the core `@urql/core` package](./basics/core.md), which interacts with \"exchanges\" to execute GraphQL\n  operations, and which you can also use directly.\n- Exchanges, which provide functionality like fetching or caching to the `Client`.\n\nBy default, `urql` aims to provide the minimal amount of features that allow us to build an app\nquickly. However, `urql` has also been designed to be a GraphQL Client\nthat grows with our usage and demands. As we go from building our smallest or first GraphQL apps to\nutilising its full functionality, we have tools at our disposal to extend and customize `urql` to\nour liking.\n\n## Using GraphQL Clients\n\nYou may have worked with a GraphQL API previously and noticed that using GraphQL in your app can be\nas straightforward as sending a plain HTTP request with your query to fetch some data.\n\nGraphQL also provides an opportunity to abstract away a lot of the manual work that goes with\nsending these queries and managing the data. Ultimately, this lets you focus on building\nyour app without having to handle the technical details of state management in detail.\n\nSpecifically, `urql` simplifies three common aspects of using GraphQL:\n\n- Sending queries and mutations and receiving results _declaratively_\n- Abstracting _caching_ and state management internally\n- Providing a central point of _extensibility_ and integration with your API\n\nIn the following sections we'll talk about the way that `urql` solves these three problems and how the logic is abstracted away internally.\n\n## Requests and Operations on the Client\n\nIf `urql` was a train it would take several stops to arrive at its terminus, our API. It starts with us\ndefining queries or mutations by writing in GraphQL's query language.\n\nAny GraphQL request can be abstracted into its query documents and its variables.\n\n```js\nimport { gql } from '@urql/core';\n\nconst query = gql`\n  query ($name: String!) {\n    helloWorld(name: $name)\n  }\n`;\n\nconst request = createRequest(query, {\n  name: 'Urkel',\n});\n```\n\nIn `urql`, these GraphQL requests are treated as unique objects and each GraphQL request will have\na `key` generated for them. This `key` is a hash of the query document and the variables you provide\nand are set on the `key` property of a [`GraphQLRequest`](./api/core.md#graphqlrequest).\n\nWhenever we decide to send our GraphQL requests to a GraphQL API we start by using `urql`'s\n[`Client`](./api/core.md#client).\nThe `Client` accepts several options to configure its behaviour and the behaviour of exchanges,\nlike the `fetchExchange`. For instance, we can pass it a `url` which the `fetchExchange` will\nuse to make a `fetch` call to our GraphQL API.\n\n```js\nimport { Client, cacheExchange, fetchExchange } from '@urql/core';\n\nconst client = new Client({\n  url: 'http://localhost:3000/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n```\n\nAbove, we're defining a `Client` that is ready to accept our requests. It will apply basic\ndocument caching and will send uncached requests to the `url` we pass it.\nThe bindings that we've seen in [the \"Basics\" section](./basics/README.md), like `useQuery` for\nReact for example, interact with [the `Client`](./api/core.md#client) directly and are a thin\nabstraction.\n\nSome methods can be called on it directly however, as seen [on the \"Core Usage\"\npage](./basics/core.md#one-off-queries-and-mutations).\n\n```js\n// Given our request and client defined above, we can call\nconst subscription = client.executeQuery(request).subscribe(result => {\n  console.log(result.data);\n});\n```\n\nAs we've seen, `urql` defines our query documents and variables as\n[`GraphQLRequest`s](./api/core.md#graphqlrequest). However, since we have more metadata that is\nneeded, like our `url` option on the `Client`, `urql` internally creates [`Operation`s](./api/core.md#operation)\neach time a request is executed. The operations are then forwarded to the exchanges, like the\n`cacheExchange` and `fetchExchange`.\n\nAn \"Operation\" is an extension of `GraphQLRequest`s. Not only do they carry the `query`, `variables`,\nand a `key` property, they will also identify the `kind` of operation that is executed, like\n`\"query\"` or `\"mutation\"`, and they contain the `Client`'s options on `operation.context`.\n\n![Operations and Results](./assets/urql-event-hub.png)\n\nThis means, once we hand over a GraphQL request to the `Client`, it will create an `Operation`,\nand then hand it over to the exchanges until a result comes back.\n\nAs shown in the diagram, each operation is like an event or signal for a GraphQL request to start,\nand the exchanges will eventually send back a corresponding result.\nHowever, because the cache can send updates to us whenever it detects a change, or you could cancel\na GraphQL request before it finishes, a special \"teardown\" `Operation` also exists, which cancels\nongoing requests.\n\n## The Client and Exchanges\n\nTo reiterate, when we use `urql`'s bindings for our framework of choice, methods are called on the\n`Client`, but we never see the operations that are created in the background from our bindings. We\ncall a method like `client.executeQuery` (or it's called for us in the bindings), an operation is\nissued internally when we subscribe with a callback, and later, we're given results.\n\n![Operations stream and results stream](./assets/urql-client-architecture.png)\n\nWhile we know that, for us, we're only interested in a single [`Operation`](./api/core.md#operation)\nand its [`OperationResult`s](./api/core.md#operationresult) at a time, the `Client` treats these as\none big stream. The `Client` sees an incoming flow of all of our operations.\n\nAs we've learned before, each operation carries a `key` and each result we receive carries the\noriginal `operation`. Because an `OperationResult` also carries an `operation` property the `Client`\nwill always know which results correspond to an individual operation.\nHowever, internally, all of our operations are processed at the same time concurrently. However, from\nour perspective:\n\n- We subscribe to a \"stream\" and expect to get results on a callback\n- The `Client` issues the operation, and we'll receive some results back eventually as either the\n  cache responds (synchronously), or the request gets sent to our API.\n- We eventually unsubscribe, and the `Client` issues a \"teardown\" operation with the same `key` as\n  the original operation, which concludes our flow.\n\nThe `Client` itself doesn't actually know what to do with operations. Instead, it sends them through\n\"exchanges\". Exchanges are akin to [middleware in Redux](https://redux.js.org/advanced/middleware)\nand have access to all operations and all results. Multiple exchanges are chained to process our\noperations and to execute logic on them, one of them being the `fetchExchange`, which as the name\nimplies sends our requests to our API.\n\n### How operations get to exchanges\n\nWe now know how we get to operations and to the `Client`:\n\n- Any bindings or calls to the `Client` create an **operation**\n- This operation identifies itself as either a `\"query\"`, `\"mutation\"` or `\"subscription\"` and has a\n  unique `key`.\n- This operation is sent into the **exchanges** and eventually ends up at the `fetchExchange`\n  (or a similar exchange)\n- The operation is sent to the API and a **result** comes back, which is wrapped in an `OperationResult`\n- The `Client` filters the `OperationResult` by the `operation.key` and — via a callback — gives us\n  a **stream of results**.\n\nTo come back to our train analogy from earlier, an operation, like a train, travels from one end\nof the track to the terminus — our API. The results then come back on the same path as they're just\ntravelling the same line in reverse.\n\n### The Exchanges\n\nBy default, the `Client` doesn't do anything with GraphQL requests. It contains only the logic to\nmanage and differentiate between active and inactive requests and converts them to operations.\nTo actually do something with our GraphQL requests, it needs _exchanges_, which are like plugins\nthat you can pass to create a pipeline of how GraphQL operations are executed.\n\nBy default, you may want to add the `cacheExchange` and the `fetchExchange` from `@urql/core`:\n\n- `cacheExchange`: Caches GraphQL results with [\"Document Caching\"](./basics/document-caching.md)\n- `fetchExchange`: Executes GraphQL requests with a `fetch` HTTP call\n\n```js\nimport { Client, cacheExchange, fetchExchange } from '@urql/core';\n\nconst client = new Client({\n  url: 'http://localhost:3000/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n```\n\nAs we can tell, exchanges define not only how GraphQL requests are executed and handled, but also\nget control over caching. Exchanges can be used to change almost any behaviour in the `Client`,\nalthough internally they only handle incoming & outgoing requests and incoming & outgoing results.\n\nSome more exchanges that we can use with our `Client` are:\n\n- [`mapExchange`](./api/core.md#mapexchange): Allows changing and reacting to operations, results, and errors\n- [`ssrExchange`](./advanced/server-side-rendering.md): Allows for a server-side renderer to\n  collect results for client-side rehydration.\n- [`retryExchange`](./advanced/retry-operations.md): Allows operations to be retried on errors\n- [`persistedExchange`](./advanced/persistence-and-uploads.md#automatic-persisted-queries): Provides support for Automatic\n  Persisted Queries\n- [`authExchange`](./advanced/authentication.md): Allows refresh authentication to be implemented easily.\n- [`requestPolicyExchange`](./api/request-policy-exchange.md): Automatically refreshes results given a TTL.\n- `devtoolsExchange`: Provides the ability to use the [urql-devtools](https://github.com/urql-graphql/urql-devtools)\n\nWe can even swap out our [document cache](./basics/document-caching.md), which is implemented by\n`@urql/core`'s `cacheExchange`, with `urql`'s [normalized cache,\nGraphcache](./graphcache/README.md).\n\n[Read more about exchanges and how to write them from scratch on the \"Authoring Exchanges\"\npage.](./advanced/authoring-exchanges.md)\n\n## Stream Patterns in `urql`\n\nIn the previous sections we've learned a lot about how the `Client` works, but we've always learned\nit in vague terms — for instance, we've learned that we get a \"stream of results\" or `urql` sees all\noperations as \"one stream of operations\" that it sends to the exchanges.\nBut, **what are streams?**\n\nGenerally we refer to _streams_ as abstractions that allow us to program with asynchronous events\nover time. Within the context of JavaScript we're specifically thinking in terms of\n[Observables](https://github.com/tc39/proposal-observable)\nand [Reactive Programming with Observables.](http://reactivex.io/documentation/observable.html)\nThese concepts may sound intimidating, but from a high-level view what we're talking about can be\nthought of as a combination of promises and iterables (e.g. arrays). We're dealing with multiple\nevents, but our callback is called over time. It's like calling `forEach` on an array but expecting\nthe results to come in asynchronously.\n\nAs a user, if we're using the one framework bindings that we've seen in [the \"Basics\"\nsection](./basics/README.md), we may never see these streams in action or may never use them even,\nsince the bindings internally use them for us. But if we [use the `Client`\ndirectly](./basics/core.md#one-off-queries-and-mutations) or write exchanges then we'll see streams\nand will have to deal with their API.\n\n### Stream patterns with the client\n\nWhen we call methods on the `Client` like [`client.executeQuery`](./api/core.md#clientexecutequery)\nor [`client.query`](./api/core.md#clientquery) then these will return a \"stream\" of results.\n\nIt's normal for GraphQL subscriptions to deliver multiple results, however, even GraphQL queries can\ngive you multiple results in `urql`. This is because operations influence one another. When a cache\ninvalidates a query, this query may refetch, and a new result is delivered to your application.\n\nMultiple results mean that once you subscribe to a GraphQL query via the `Client`, you may receive\nnew results in the future.\n\n```js\nimport { gql } from '@urql/core';\n\nconst QUERY = gql`\n  query Test($id: ID!) {\n    getUser(id: $id) {\n      id\n      name\n    }\n  }\n`;\n\nclient.query(QUERY, { id: 'test' }).subscribe(result => {\n  console.log(result); // { data: ... }\n});\n```\n\nRead more about the available APIs on the `Client` in the [Core API docs](./api/core.md).\n\nInternally, these streams and all exchanges are written using a library called\n[`wonka`](https://wonka.kitten.sh/basics/background), which is a tiny Observable-like\nlibrary. It is used to write exchanges and when we interact with the `Client` it is used internally\nas well.\n","packages/core/README.md":"# @urql/core\n\n> The shared core for the highly customizable and versatile GraphQL client, urql\n\nMore documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).\n","packages/introspection/README.md":"<h2 align=\"center\">@urql/introspection</h2>\n\n<p align=\"center\"><strong>Utilities for dealing with Introspection Queries and Client Schemas</strong></p>\n","packages/next-urql/README.md":"## `next-urql`\n\nA set of convenience utilities for using `urql` with Next.js.\n\nMore documentation is available at https://urql.dev/goto/docs/advanced/server-side-rendering/#nextjs\nExamples can be found at https://github.com/urql-graphql/urql/tree/main/examples/with-next\n","packages/preact-urql/README.md":"<div align=\"center\">\n  <br />\n  <br />\n  <a href=\"https://www.npmjs.com/package/@urql/preact\">\n    <img alt=\"Npm version\" src=\"https://badgen.net/npm/v/@urql/preact\" />\n  </a>\n  <a href=\"https://bundlephobia.com/result?p=@urql/preact\">\n    <img alt=\"Minified gzip size\" src=\"https://img.shields.io/bundlephobia/minzip/@urql/preact.svg?label=gzip%20size\" />\n  </a>\n  <a href=\"https://github.com/urql-graphql/urql/discussions\">\n    <img alt=\"GitHub Discussions: Chat With Us\" src=\"https://badgen.net/badge/discussions/chat%20with%20us/purple\" />\n  </a>\n  <br />\n  <br />\n</div>\n\n## Installation\n\n```sh\nyarn add @urql/preact urql graphql\n# or\nnpm install --save @urql/preact urql graphql\n```\n\n## Usage\n\nThe usage is a 1:1 mapping of the React usage found [here](https://formidable.com/open-source/urql/docs)\n\nsmall example:\n\n```jsx\nimport { createClient, cacheExchange, fetchExchange, Provider, useQuery } from '@urql/preact';\n\nconst client = createClient({\n  url: 'https://myHost/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n\nconst App = () => (\n  <Provider value={client}>\n    <Dogs />\n  </Provider>\n);\n\nconst Dogs = () => {\n  const [result] = useQuery({\n    query: `{ dogs { id name } }`,\n  });\n\n  if (result.fetching) return <p>Loading...</p>;\n  if (result.error) return <p>Oh no...</p>;\n\n  return result.data.dogs.map(dog => <p>{dog.name} is a good boy!</p>);\n};\n```\n","packages/react-urql/README.md":"# urql\n\n> A highly customizable and versatile GraphQL client **for React**\n\nMore documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).\n","packages/solid-start-urql/README.md":"# @urql/solid-start\n\n`@urql/solid-start` provides URQL integration for [SolidStart](https://start.solidjs.com/), built with SolidStart's native primitives like `query`, `action`, and `createAsync`.\n\n> **Note:** This package is specifically designed for SolidStart applications with SSR. If you're building a client-side only SolidJS app, use [`@urql/solid`](https://github.com/urql-graphql/urql/tree/main/packages/solid-urql) instead. See [SolidJS vs SolidStart](#solidjs-vs-solidstart) for key differences.\n\n## Features\n\n- 🎯 **SolidStart Native** - Built with `query`, `action`, `createAsync`, and `useAction`\n- 🚀 **Automatic SSR** - Works seamlessly with SolidStart's server-side rendering\n- 🔄 **Reactive Variables** - Query variables can be signals that automatically trigger re-execution\n- 📡 **Real-time Subscriptions** - Full GraphQL subscription support\n- 🎨 **Type Safe** - Complete TypeScript support with GraphQL types\n- 🪶 **Lightweight** - Minimal wrapper over URQL core\n\n## Installation\n\n```bash\nnpm install @urql/solid-start @urql/solid @urql/core graphql\n# or\npnpm add @urql/solid-start @urql/solid @urql/core graphql\n# or\nyarn add @urql/solid-start @urql/solid @urql/core graphql\n```\n\n> **Note:** `@urql/solid` is a peer dependency required for subscriptions.\n\n## Quick Start\n\n### 1. Set up the Provider\n\nWrap your app with the `Provider` to make the URQL client and router primitives available:\n\n```tsx\n// src/app.tsx\nimport { Router, action, query } from '@solidjs/router';\nimport { FileRoutes } from '@solidjs/start/router';\nimport { Provider } from '@urql/solid-start';\nimport { createClient, cacheExchange, fetchExchange } from '@urql/core';\n\nconst client = createClient({\n  url: 'https://api.example.com/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n\nexport default function App() {\n  return (\n    <Router root={props => <Provider value={{ client, query, action }}>{props.children}</Provider>}>\n      <FileRoutes />\n    </Router>\n  );\n}\n```\n\n> **Note:** The Provider accepts `client`, `query`, and `action` so `createQuery` and `createMutation` can use SolidStart APIs via context.\n\n### 2. Use Queries\n\n```tsx\n// src/routes/todos.tsx\nimport { createQuery } from '@urql/solid-start';\nimport { createAsync } from '@solidjs/router';\nimport { gql } from '@urql/core';\nimport { For, Show, Suspense } from 'solid-js';\n\nconst TodosQuery = gql`\n  query {\n    todos {\n      id\n      title\n      completed\n    }\n  }\n`;\n\nexport default function TodosPage() {\n  const queryTodos = createQuery(TodosQuery, 'todos-list');\n  const todos = createAsync(() => queryTodos());\n\n  return (\n    <div>\n      <h1>Todos</h1>\n      <Suspense fallback={<div>Loading...</div>}>\n        <Show when={todos()?.data}>\n          <ul>\n            <For each={todos()!.data.todos}>\n              {todo => (\n                <li>\n                  <input type=\"checkbox\" checked={todo.completed} />\n                  {todo.title}\n                </li>\n              )}\n            </For>\n          </ul>\n        </Show>\n        <Show when={todos()?.error}>\n          <p>Error: {todos()!.error.message}</p>\n        </Show>\n      </Suspense>\n    </div>\n  );\n}\n```\n\n### 3. Use Mutations\n\n```tsx\n// src/components/AddTodoForm.tsx\nimport { createMutation } from '@urql/solid-start';\nimport { useAction, useSubmission } from '@solidjs/router';\nimport { gql } from '@urql/core';\nimport { Show } from 'solid-js';\n\nconst AddTodoMutation = gql`\n  mutation AddTodo($title: String!) {\n    addTodo(title: $title) {\n      id\n      title\n    }\n  }\n`;\n\nexport function AddTodoForm() {\n  const addTodoAction = createMutation(AddTodoMutation, 'add-todo');\n  const addTodo = useAction(addTodoAction);\n  const submission = useSubmission(addTodoAction);\n\n  let inputRef: HTMLInputElement | undefined;\n\n  const handleSubmit = async (e: Event) => {\n    e.preventDefault();\n    if (!inputRef?.value) return;\n\n    const result = await addTodo({ title: inputRef.value });\n    if (result.data) {\n      inputRef.value = '';\n    }\n  };\n\n  return (\n    <form onSubmit={handleSubmit}>\n      <input ref={inputRef} type=\"text\" placeholder=\"New todo\" />\n      <button type=\"submit\" disabled={submission.pending}>\n        Add Todo\n      </button>\n      <Show when={submission.result?.error}>\n        <p>Error: {submission.result!.error.message}</p>\n      </Show>\n    </form>\n  );\n}\n```\n\n### 4. Use Subscriptions\n\n```tsx\n// src/components/LiveMessages.tsx\nimport { createSubscription } from '@urql/solid-start';\nimport { gql } from '@urql/core';\nimport { For } from 'solid-js';\n\nconst MessagesSubscription = gql`\n  subscription {\n    messageAdded {\n      id\n      text\n      createdAt\n    }\n  }\n`;\n\nexport function LiveMessages() {\n  const [messages] = createSubscription(\n    { query: MessagesSubscription },\n    // Optional handler to accumulate messages\n    (prev = [], data) => [...prev, data.messageAdded]\n  );\n\n  return (\n    <div>\n      <h2>Live Messages</h2>\n      <For each={messages.data}>{msg => <div>{msg.text}</div>}</For>\n    </div>\n  );\n}\n```\n\n## API Reference\n\n### `createQuery(queryDocument, key, options?)`\n\nCreates a GraphQL query using SolidStart's `query` and `createAsync` primitives. The `query` function is automatically retrieved from context.\n\n**Parameters:**\n\n- `queryDocument: DocumentInput` - GraphQL query document\n- `key: string` - Cache key for SolidStart's router\n- `options?: object` - Optional configuration\n  - `variables?: Variables` - Query variables\n  - `requestPolicy?: RequestPolicy` - Cache policy\n  - `context?: Partial<OperationContext>` - Additional context\n\n**Returns:** A query function that can be used with `createAsync`\n\n**Basic Example:**\n\n```tsx\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\n\nexport default function TodosPage() {\n  const queryTodos = createQuery(TodosQuery, 'todos-list');\n  const todos = createAsync(() => queryTodos());\n\n  return <div>{/* ... */}</div>;\n}\n```\n\n**Example with variables:**\n\n```tsx\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\n\nexport default function UserPage() {\n  const queryUser = createQuery(UserQuery, 'user-details', {\n    variables: { id: 1 },\n  });\n  const user = createAsync(() => queryUser());\n\n  return <div>{/* ... */}</div>;\n}\n```\n\n**Example with custom client:**\n\n```tsx\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\nimport { createClient } from '@urql/core';\n\nconst customClient = createClient({ url: 'https://api.example.com/graphql' });\n\nexport default function CustomPage() {\n  const queryTodos = createQuery(TodosQuery, 'todos-list');\n  const todos = createAsync(() => queryTodos(customClient));\n\n  return <div>{/* ... */}</div>;\n}\n```\n\n> **Note:** `createQuery` must be called inside a component where it has access to the URQL context. The query function from `@solidjs/router` is automatically retrieved from the Provider.\n\n### `createMutation(mutation, key)`\n\nCreates a GraphQL mutation action using SolidStart's `action` primitive.\n\n**Args:**\n\n- `mutation: DocumentInput` - GraphQL mutation document\n- `key: string` - Cache key for SolidStart's router\n\n**Returns:** `Action` - A SolidStart action that can be used with `useAction()` and `useSubmission()`\n\n**Example:**\n\n```tsx\nimport { createMutation } from '@urql/solid-start';\nimport { useAction, useSubmission } from '@solidjs/router';\n\nconst updateUserAction = createMutation(UpdateUserMutation, 'update-user');\nconst updateUser = useAction(updateUserAction);\nconst submission = useSubmission(updateUserAction);\n\n// Call the mutation\nconst result = await updateUser({ id: 1, name: 'Alice' });\n\n// Access submission state\nconsole.log(submission.pending); // boolean\nconsole.log(submission.result); // OperationResult\n```\n\n### `createSubscription(args, handler?)`\n\nCreates a GraphQL subscription for real-time updates.\n\n**Args:**\n\n```ts\n{\n  query: DocumentInput;\n  variables?: MaybeAccessor<Variables>;\n  context?: MaybeAccessor<Partial<OperationContext>>;\n  pause?: MaybeAccessor<boolean>;\n}\n```\n\n**Handler:** Optional function to accumulate/transform subscription data\n\n```ts\n(previousData: Data | undefined, newData: Data) => Data;\n```\n\n**Returns:** `[State, ExecuteFunction]`\n\n**Example with handler:**\n\n```tsx\nconst [messages] = createSubscription({ query: MessagesSubscription }, (prev = [], data) => [\n  ...prev,\n  data.messageAdded,\n]);\n```\n\n### `Provider`\n\nContext provider for the URQL client and SolidStart router primitives.\n\n**Props:**\n\n- `value: { client: Client; query: typeof query; action: typeof action }` - Object containing the URQL client and SolidStart router primitives\n\n**Example:**\n\n```tsx\nimport { action, query } from '@solidjs/router';\nimport { Provider } from '@urql/solid-start';\n\n<Provider value={{ client, query, action }}>\n  <App />\n</Provider>;\n```\n\n### `useClient()`\n\nHook to access the URQL client from context.\n\n**Returns:** `Client`\n\n## Request Policies\n\nControl caching behavior with `requestPolicy`:\n\n- `cache-first` (default) - Use cache if available, otherwise fetch\n- `cache-only` - Only use cached data, never fetch\n- `network-only` - Always fetch, ignore cache\n- `cache-and-network` - Return cache immediately, then fetch in background\n\n```tsx\nconst todos = createQuery({\n  query: TodosQuery,\n  requestPolicy: 'cache-and-network',\n});\n```\n\n## Dynamic Queries\n\nFor dynamic queries that change based on reactive values, you can pass variables to the query function:\n\n```tsx\nimport { createSignal } from 'solid-js';\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\n\nexport default function UserPage() {\n  const [userId, setUserId] = createSignal(1);\n\n  // Create the query function\n  const queryUser = createQuery(UserQuery, 'user-details', {\n    variables: { id: userId() },\n  });\n\n  // Wrap with createAsync to get reactive data\n  const user = createAsync(() => queryUser());\n\n  return (\n    <div>\n      <button onClick={() => setUserId(userId() + 1)}>Next User</button>\n      <Show when={user()?.data}>\n        <h1>{user()!.data.user.name}</h1>\n      </Show>\n    </div>\n  );\n}\n```\n\nNote: For fully reactive variables that trigger re-fetches, you may need to create the query function inside a `createEffect` or recreate it when dependencies change.\n\n## Cache Keys\n\nCache keys are required for both queries and mutations to enable SolidStart's caching and revalidation features:\n\n```tsx\n// Query with cache key\nconst queryTodos = createQuery(TodosQuery, 'todos-list', query);\n\n// Mutation with cache key\nconst [state, addTodo] = createMutation(AddTodoMutation, 'add-todo');\n```\n\nChoose descriptive cache keys that:\n\n- Are unique within your application\n- Describe the data being cached (e.g., 'user-profile', 'todos-list')\n- Make debugging easier by being human-readable\n\n## Advanced: Custom Exchanges\n\nAdd custom exchanges for authentication, error handling, etc:\n\n```tsx\nimport { createClient, cacheExchange, fetchExchange } from '@urql/core';\nimport { authExchange } from '@urql/exchange-auth';\n\nconst client = createClient({\n  url: 'https://api.example.com/graphql',\n  exchanges: [\n    cacheExchange,\n    authExchange(async utils => {\n      return {\n        addAuthToOperation(operation) {\n          const token = localStorage.getItem('token');\n          if (!token) return operation;\n          return utils.appendHeaders(operation, {\n            Authorization: `Bearer ${token}`,\n          });\n        },\n        didAuthError(error) {\n          return error.graphQLErrors.some(e => e.extensions?.code === 'UNAUTHENTICATED');\n        },\n        async refreshAuth() {\n          // Refresh token logic\n        },\n      };\n    }),\n    fetchExchange,\n  ],\n});\n```\n\n## TypeScript\n\nFull type safety with GraphQL types:\n\n```tsx\nimport { createQuery } from '@urql/solid-start';\nimport { gql, type TypedDocumentNode } from '@urql/core';\n\ninterface Todo {\n  id: string;\n  title: string;\n  completed: boolean;\n}\n\ninterface TodosData {\n  todos: Todo[];\n}\n\nconst TodosQuery: TypedDocumentNode<TodosData> = gql`\n  query {\n    todos {\n      id\n      title\n      completed\n    }\n  }\n`;\n\n// Fully typed!\nconst todos = createQuery({ query: TodosQuery });\n//    ^? Accessor<OperationResult<TodosData> | undefined>\n```\n\n## How It Works\n\n`@urql/solid-start` integrates URQL with SolidStart's primitives:\n\n- **`createQuery`** wraps SolidStart's `query()` function to execute URQL queries with automatic SSR and caching. The `query` function is automatically retrieved from the URQL context, eliminating the need for manual injection.\n- **`createMutation`** creates SolidStart `action()` primitives that integrate with `useAction()` and `useSubmission()` for form handling and progressive enhancement\n- **`createSubscription`** uses `@urql/solid-start` context so it works with the same Provider as queries and mutations\n\nThis means you get:\n\n- ✅ Automatic server-side rendering\n- ✅ Request deduplication via SolidStart's query caching\n- ✅ Streaming responses\n- ✅ Progressive enhancement with actions\n- ✅ Full fine-grained reactivity\n\n## SolidJS vs SolidStart\n\n### When to Use Each Package\n\n| Use Case           | Package             | Why                                                              |\n| ------------------ | ------------------- | ---------------------------------------------------------------- |\n| Client-side SPA    | `@urql/solid`       | Optimized for client-only apps, uses SolidJS reactivity patterns |\n| SolidStart SSR App | `@urql/solid-start` | Integrates with SolidStart's routing, SSR, and action system     |\n\n### Key Differences\n\n#### Queries\n\n**@urql/solid** (Client-side):\n\n```tsx\nimport { createQuery } from '@urql/solid';\n\nconst [result] = createQuery({ query: TodosQuery });\n// Returns: [Accessor<OperationResult>, Accessor<ReExecute>]\n```\n\n**@urql/solid-start** (SSR):\n\n```tsx\nimport { createQuery } from '@urql/solid-start';\nimport { createAsync } from '@solidjs/router';\n\nconst queryTodos = createQuery(TodosQuery, 'todos');\nconst todos = createAsync(() => queryTodos());\n// Returns: Accessor<OperationResult | undefined>\n// Works with SSR and SolidStart's caching\n```\n\n#### Mutations\n\n**@urql/solid** (Client-side):\n\n```tsx\nimport { createMutation } from '@urql/solid';\n\nconst [result, executeMutation] = createMutation(AddTodoMutation);\nawait executeMutation({ title: 'New Todo' });\n// Returns: [Accessor<OperationResult>, ExecuteMutation]\n```\n\n**@urql/solid-start** (SSR with Actions):\n\n```tsx\nimport { createMutation } from '@urql/solid-start';\nimport { useAction, useSubmission } from '@solidjs/router';\n\nconst addTodoAction = createMutation(AddTodoMutation, 'add-todo');\nconst addTodo = useAction(addTodoAction);\nconst submission = useSubmission(addTodoAction);\nawait addTodo({ title: 'New Todo' });\n// Integrates with SolidStart's action system for progressive enhancement\n```\n\n### Why Different APIs?\n\n- **SSR Support**: SolidStart queries run on the server and stream to the client\n- **Router Integration**: Automatic caching and invalidation with SolidStart's router\n- **Progressive Enhancement**: Actions work without JavaScript enabled\n- **Suspense**: Native support for SolidJS Suspense boundaries\n\n### Migration\n\nIf you're moving from a SolidJS SPA to SolidStart:\n\n1. Change imports from `@urql/solid` to `@urql/solid-start`\n2. Wrap queries with `createAsync()`\n3. Update mutations to use the action pattern with `useAction()` and `useSubmission()`\n\n## Resources\n\n- [SolidStart Documentation](https://start.solidjs.com/)\n- [URQL Documentation](https://formidable.com/open-source/urql/docs/)\n- [Solid Primitives](https://primitives.solidjs.community/)\n\n## License\n\nMIT\n","packages/solid-urql/README.md":"# @urql/solid\n\nA highly customizable and versatile GraphQL client for SolidJS.\n\n> **Note:** This package is for client-side SolidJS applications. If you're building a SolidStart application with SSR, use [`@urql/solid-start`](../solid-start-urql) instead. See the [comparison section](../solid-start-urql#solidjs-vs-solidstart) in the SolidStart package for key differences.\n\n## Installation\n\n```bash\nnpm install @urql/solid @urql/core graphql\n# or\npnpm add @urql/solid @urql/core graphql\n# or\nyarn add @urql/solid @urql/core graphql\n```\n\n## Documentation\n\nFull documentation is available at [formidable.com/open-source/urql/docs/](https://formidable.com/open-source/urql/docs/).\n\n## Quick Start\n\n```tsx\nimport { createClient, Provider, createQuery } from '@urql/solid';\nimport { cacheExchange, fetchExchange } from '@urql/core';\nimport { gql } from '@urql/core';\n\nconst client = createClient({\n  url: 'https://api.example.com/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n\nconst TodosQuery = gql`\n  query {\n    todos {\n      id\n      title\n    }\n  }\n`;\n\nfunction App() {\n  return (\n    <Provider value={client}>\n      <TodoList />\n    </Provider>\n  );\n}\n\nfunction TodoList() {\n  const [result] = createQuery({ query: TodosQuery });\n\n  return (\n    <div>\n      {result().data?.todos.map(todo => (\n        <div>{todo.title}</div>\n      ))}\n    </div>\n  );\n}\n```\n\n## When to Use @urql/solid vs @urql/solid-start\n\n| Use Case | Package |\n|----------|---------|\n| Client-side SPA | `@urql/solid` |\n| SolidStart with SSR | `@urql/solid-start` |\n\nFor a detailed comparison of the APIs and when to use each package, see the [SolidJS vs SolidStart comparison](../solid-start-urql#solidjs-vs-solidstart) in the `@urql/solid-start` documentation.\n\n## License\n\nMIT\n","packages/storage-rn/README.md":"# @urql/storage-rn\n\n`@urql/storage-rn` is a Graphcache offline storage for React Native.\n\nIt is compatible for both plain React Native and Expo apps (including managed workflow), but it has a two peer dependencies - [Async Storage](https://react-native-async-storage.github.io/async-storage/) and [NetInfo](https://github.com/react-native-netinfo/react-native-netinfo) - which must be installed separately. AsyncStorage will be used to persist the data, and NetInfo will be used to determine when the app is online and offline.\n\n## Quick Start Guide\n\nInstall NetInfo ([RN](https://github.com/react-native-netinfo/react-native-netinfo) | [Expo](https://docs.expo.dev/versions/latest/sdk/netinfo/)) and AsyncStorage ([RN](https://react-native-async-storage.github.io/async-storage/docs/install) | [Expo](https://docs.expo.dev/versions/v42.0.0/sdk/async-storage/)).\n\nInstall `@urql/storage-rn` alongside `urql` and `@urql/exchange-graphcache`:\n\n```sh\nyarn add @urql/storage-rn\n# or\nnpm install --save @urql/storage-rn\n```\n\nThen add it to the offline exchange:\n\n```js\nimport { createClient, fetchExchange } from 'urql';\nimport { offlineExchange } from '@urql/exchange-graphcache';\nimport { makeAsyncStorage } from '@urql/storage-rn';\n\nconst storage = makeAsyncStorage({\n  dataKey: 'graphcache-data', // The AsyncStorage key used for the data (defaults to graphcache-data)\n  metadataKey: 'graphcache-metadata', // The AsyncStorage key used for the metadata (defaults to graphcache-metadata)\n  maxAge: 7, // How long to persist the data in storage (defaults to 7 days)\n});\n\nconst cache = offlineExchange({\n  schema,\n  storage,\n  updates: {\n    /* ... */\n  },\n  optimistic: {\n    /* ... */\n  },\n});\n\nconst client = createClient({\n  url: 'http://localhost:3000/graphql',\n  exchanges: [cache, fetchExchange],\n});\n```\n","packages/svelte-urql/README.md":"# @urql/svelte\n\n> A highly customizable and versatile GraphQL client **for Svelte**\n\nMore documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).\n","packages/vue-urql/README.md":"<div align=\"center\">\n  <br />\n  <br />\n  <a href=\"https://www.npmjs.com/package/@urql/vue\">\n    <img alt=\"Npm version\" src=\"https://badgen.net/npm/v/@urql/vue\" />\n  </a>\n  <a href=\"https://bundlephobia.com/result?p=@urql/vue\">\n    <img alt=\"Minified gzip size\" src=\"https://img.shields.io/bundlephobia/minzip/@urql/vue.svg?label=gzip%20size\" />\n  </a>\n  <a href=\"https://github.com/urql-graphql/urql/discussions\">\n    <img alt=\"GitHub Discussions: Chat With Us\" src=\"https://badgen.net/badge/discussions/chat%20with%20us/purple\" />\n  </a>\n  <br />\n  <br />\n</div>\n\n## Installation\n\n```sh\nyarn add @urql/vue graphql\n# or\nnpm install --save @urql/vue graphql\n```\n\n> **Note:** `@urql/vue` has a peer dependency on `vue@^3.0.0` (Not v2) and doesn't currently plan to\n> be backwards compatible to Vue 2.\n"},"files":{"docs/architecture.md":"---\ntitle: Architecture\norder: 3\n---\n\n# Architecture\n\n`urql` is a highly customizable and flexible GraphQL client.\nAs you use it in your app, it's split into three parts:\n\n- Bindings — such as for React, Preact, Vue, or Svelte — which interact with `@urql/core`'s\n  `Client`.\n- The Client — as created [with the core `@urql/core` package](./basics/core.md), which interacts with \"exchanges\" to execute GraphQL\n  operations, and which you can also use directly.\n- Exchanges, which provide functionality like fetching or caching to the `Client`.\n\nBy default, `urql` aims to provide the minimal amount of features that allow us to build an app\nquickly. However, `urql` has also been designed to be a GraphQL Client\nthat grows with our usage and demands. As we go from building our smallest or first GraphQL apps to\nutilising its full functionality, we have tools at our disposal to extend and customize `urql` to\nour liking.\n\n## Using GraphQL Clients\n\nYou may have worked with a GraphQL API previously and noticed that using GraphQL in your app can be\nas straightforward as sending a plain HTTP request with your query to fetch some data.\n\nGraphQL also provides an opportunity to abstract away a lot of the manual work that goes with\nsending these queries and managing the data. Ultimately, this lets you focus on building\nyour app without having to handle the technical details of state management in detail.\n\nSpecifically, `urql` simplifies three common aspects of using GraphQL:\n\n- Sending queries and mutations and receiving results _declaratively_\n- Abstracting _caching_ and state management internally\n- Providing a central point of _extensibility_ and integration with your API\n\nIn the following sections we'll talk about the way that `urql` solves these three problems and how the logic is abstracted away internally.\n\n## Requests and Operations on the Client\n\nIf `urql` was a train it would take several stops to arrive at its terminus, our API. It starts with us\ndefining queries or mutations by writing in GraphQL's query language.\n\nAny GraphQL request can be abstracted into its query documents and its variables.\n\n```js\nimport { gql } from '@urql/core';\n\nconst query = gql`\n  query ($name: String!) {\n    helloWorld(name: $name)\n  }\n`;\n\nconst request = createRequest(query, {\n  name: 'Urkel',\n});\n```\n\nIn `urql`, these GraphQL requests are treated as unique objects and each GraphQL request will have\na `key` generated for them. This `key` is a hash of the query document and the variables you provide\nand are set on the `key` property of a [`GraphQLRequest`](./api/core.md#graphqlrequest).\n\nWhenever we decide to send our GraphQL requests to a GraphQL API we start by using `urql`'s\n[`Client`](./api/core.md#client).\nThe `Client` accepts several options to configure its behaviour and the behaviour of exchanges,\nlike the `fetchExchange`. For instance, we can pass it a `url` which the `fetchExchange` will\nuse to make a `fetch` call to our GraphQL API.\n\n```js\nimport { Client, cacheExchange, fetchExchange } from '@urql/core';\n\nconst client = new Client({\n  url: 'http://localhost:3000/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n```\n\nAbove, we're defining a `Client` that is ready to accept our requests. It will apply basic\ndocument caching and will send uncached requests to the `url` we pass it.\nThe bindings that we've seen in [the \"Basics\" section](./basics/README.md), like `useQuery` for\nReact for example, interact with [the `Client`](./api/core.md#client) directly and are a thin\nabstraction.\n\nSome methods can be called on it directly however, as seen [on the \"Core Usage\"\npage](./basics/core.md#one-off-queries-and-mutations).\n\n```js\n// Given our request and client defined above, we can call\nconst subscription = client.executeQuery(request).subscribe(result => {\n  console.log(result.data);\n});\n```\n\nAs we've seen, `urql` defines our query documents and variables as\n[`GraphQLRequest`s](./api/core.md#graphqlrequest). However, since we have more metadata that is\nneeded, like our `url` option on the `Client`, `urql` internally creates [`Operation`s](./api/core.md#operation)\neach time a request is executed. The operations are then forwarded to the exchanges, like the\n`cacheExchange` and `fetchExchange`.\n\nAn \"Operation\" is an extension of `GraphQLRequest`s. Not only do they carry the `query`, `variables`,\nand a `key` property, they will also identify the `kind` of operation that is executed, like\n`\"query\"` or `\"mutation\"`, and they contain the `Client`'s options on `operation.context`.\n\n![Operations and Results](./assets/urql-event-hub.png)\n\nThis means, once we hand over a GraphQL request to the `Client`, it will create an `Operation`,\nand then hand it over to the exchanges until a result comes back.\n\nAs shown in the diagram, each operation is like an event or signal for a GraphQL request to start,\nand the exchanges will eventually send back a corresponding result.\nHowever, because the cache can send updates to us whenever it detects a change, or you could cancel\na GraphQL request before it finishes, a special \"teardown\" `Operation` also exists, which cancels\nongoing requests.\n\n## The Client and Exchanges\n\nTo reiterate, when we use `urql`'s bindings for our framework of choice, methods are called on the\n`Client`, but we never see the operations that are created in the background from our bindings. We\ncall a method like `client.executeQuery` (or it's called for us in the bindings), an operation is\nissued internally when we subscribe with a callback, and later, we're given results.\n\n![Operations stream and results stream](./assets/urql-client-architecture.png)\n\nWhile we know that, for us, we're only interested in a single [`Operation`](./api/core.md#operation)\nand its [`OperationResult`s](./api/core.md#operationresult) at a time, the `Client` treats these as\none big stream. The `Client` sees an incoming flow of all of our operations.\n\nAs we've learned before, each operation carries a `key` and each result we receive carries the\noriginal `operation`. Because an `OperationResult` also carries an `operation` property the `Client`\nwill always know which results correspond to an individual operation.\nHowever, internally, all of our operations are processed at the same time concurrently. However, from\nour perspective:\n\n- We subscribe to a \"stream\" and expect to get results on a callback\n- The `Client` issues the operation, and we'll receive some results back eventually as either the\n  cache responds (synchronously), or the request gets sent to our API.\n- We eventually unsubscribe, and the `Client` issues a \"teardown\" operation with the same `key` as\n  the original operation, which concludes our flow.\n\nThe `Client` itself doesn't actually know what to do with operations. Instead, it sends them through\n\"exchanges\". Exchanges are akin to [middleware in Redux](https://redux.js.org/advanced/middleware)\nand have access to all operations and all results. Multiple exchanges are chained to process our\noperations and to execute logic on them, one of them being the `fetchExchange`, which as the name\nimplies sends our requests to our API.\n\n### How operations get to exchanges\n\nWe now know how we get to operations and to the `Client`:\n\n- Any bindings or calls to the `Client` create an **operation**\n- This operation identifies itself as either a `\"query\"`, `\"mutation\"` or `\"subscription\"` and has a\n  unique `key`.\n- This operation is sent into the **exchanges** and eventually ends up at the `fetchExchange`\n  (or a similar exchange)\n- The operation is sent to the API and a **result** comes back, which is wrapped in an `OperationResult`\n- The `Client` filters the `OperationResult` by the `operation.key` and — via a callback — gives us\n  a **stream of results**.\n\nTo come back to our train analogy from earlier, an operation, like a train, travels from one end\nof the track to the terminus — our API. The results then come back on the same path as they're just\ntravelling the same line in reverse.\n\n### The Exchanges\n\nBy default, the `Client` doesn't do anything with GraphQL requests. It contains only the logic to\nmanage and differentiate between active and inactive requests and converts them to operations.\nTo actually do something with our GraphQL requests, it needs _exchanges_, which are like plugins\nthat you can pass to create a pipeline of how GraphQL operations are executed.\n\nBy default, you may want to add the `cacheExchange` and the `fetchExchange` from `@urql/core`:\n\n- `cacheExchange`: Caches GraphQL results with [\"Document Caching\"](./basics/document-caching.md)\n- `fetchExchange`: Executes GraphQL requests with a `fetch` HTTP call\n\n```js\nimport { Client, cacheExchange, fetchExchange } from '@urql/core';\n\nconst client = new Client({\n  url: 'http://localhost:3000/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n```\n\nAs we can tell, exchanges define not only how GraphQL requests are executed and handled, but also\nget control over caching. Exchanges can be used to change almost any behaviour in the `Client`,\nalthough internally they only handle incoming & outgoing requests and incoming & outgoing results.\n\nSome more exchanges that we can use with our `Client` are:\n\n- [`mapExchange`](./api/core.md#mapexchange): Allows changing and reacting to operations, results, and errors\n- [`ssrExchange`](./advanced/server-side-rendering.md): Allows for a server-side renderer to\n  collect results for client-side rehydration.\n- [`retryExchange`](./advanced/retry-operations.md): Allows operations to be retried on errors\n- [`persistedExchange`](./advanced/persistence-and-uploads.md#automatic-persisted-queries): Provides support for Automatic\n  Persisted Queries\n- [`authExchange`](./advanced/authentication.md): Allows refresh authentication to be implemented easily.\n- [`requestPolicyExchange`](./api/request-policy-exchange.md): Automatically refreshes results given a TTL.\n- `devtoolsExchange`: Provides the ability to use the [urql-devtools](https://github.com/urql-graphql/urql-devtools)\n\nWe can even swap out our [document cache](./basics/document-caching.md), which is implemented by\n`@urql/core`'s `cacheExchange`, with `urql`'s [normalized cache,\nGraphcache](./graphcache/README.md).\n\n[Read more about exchanges and how to write them from scratch on the \"Authoring Exchanges\"\npage.](./advanced/authoring-exchanges.md)\n\n## Stream Patterns in `urql`\n\nIn the previous sections we've learned a lot about how the `Client` works, but we've always learned\nit in vague terms — for instance, we've learned that we get a \"stream of results\" or `urql` sees all\noperations as \"one stream of operations\" that it sends to the exchanges.\nBut, **what are streams?**\n\nGenerally we refer to _streams_ as abstractions that allow us to program with asynchronous events\nover time. Within the context of JavaScript we're specifically thinking in terms of\n[Observables](https://github.com/tc39/proposal-observable)\nand [Reactive Programming with Observables.](http://reactivex.io/documentation/observable.html)\nThese concepts may sound intimidating, but from a high-level view what we're talking about can be\nthought of as a combination of promises and iterables (e.g. arrays). We're dealing with multiple\nevents, but our callback is called over time. It's like calling `forEach` on an array but expecting\nthe results to come in asynchronously.\n\nAs a user, if we're using the one framework bindings that we've seen in [the \"Basics\"\nsection](./basics/README.md), we may never see these streams in action or may never use them even,\nsince the bindings internally use them for us. But if we [use the `Client`\ndirectly](./basics/core.md#one-off-queries-and-mutations) or write exchanges then we'll see streams\nand will have to deal with their API.\n\n### Stream patterns with the client\n\nWhen we call methods on the `Client` like [`client.executeQuery`](./api/core.md#clientexecutequery)\nor [`client.query`](./api/core.md#clientquery) then these will return a \"stream\" of results.\n\nIt's normal for GraphQL subscriptions to deliver multiple results, however, even GraphQL queries can\ngive you multiple results in `urql`. This is because operations influence one another. When a cache\ninvalidates a query, this query may refetch, and a new result is delivered to your application.\n\nMultiple results mean that once you subscribe to a GraphQL query via the `Client`, you may receive\nnew results in the future.\n\n```js\nimport { gql } from '@urql/core';\n\nconst QUERY = gql`\n  query Test($id: ID!) {\n    getUser(id: $id) {\n      id\n      name\n    }\n  }\n`;\n\nclient.query(QUERY, { id: 'test' }).subscribe(result => {\n  console.log(result); // { data: ... }\n});\n```\n\nRead more about the available APIs on the `Client` in the [Core API docs](./api/core.md).\n\nInternally, these streams and all exchanges are written using a library called\n[`wonka`](https://wonka.kitten.sh/basics/background), which is a tiny Observable-like\nlibrary. It is used to write exchanges and when we interact with the `Client` it is used internally\nas well.\n","packages/core/README.md":"# @urql/core\n\n> The shared core for the highly customizable and versatile GraphQL client, urql\n\nMore documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).\n","packages/introspection/README.md":"<h2 align=\"center\">@urql/introspection</h2>\n\n<p align=\"center\"><strong>Utilities for dealing with Introspection Queries and Client Schemas</strong></p>\n","packages/next-urql/README.md":"## `next-urql`\n\nA set of convenience utilities for using `urql` with Next.js.\n\nMore documentation is available at https://urql.dev/goto/docs/advanced/server-side-rendering/#nextjs\nExamples can be found at https://github.com/urql-graphql/urql/tree/main/examples/with-next\n","packages/preact-urql/README.md":"<div align=\"center\">\n  <br />\n  <br />\n  <a href=\"https://www.npmjs.com/package/@urql/preact\">\n    <img alt=\"Npm version\" src=\"https://badgen.net/npm/v/@urql/preact\" />\n  </a>\n  <a href=\"https://bundlephobia.com/result?p=@urql/preact\">\n    <img alt=\"Minified gzip size\" src=\"https://img.shields.io/bundlephobia/minzip/@urql/preact.svg?label=gzip%20size\" />\n  </a>\n  <a href=\"https://github.com/urql-graphql/urql/discussions\">\n    <img alt=\"GitHub Discussions: Chat With Us\" src=\"https://badgen.net/badge/discussions/chat%20with%20us/purple\" />\n  </a>\n  <br />\n  <br />\n</div>\n\n## Installation\n\n```sh\nyarn add @urql/preact urql graphql\n# or\nnpm install --save @urql/preact urql graphql\n```\n\n## Usage\n\nThe usage is a 1:1 mapping of the React usage found [here](https://formidable.com/open-source/urql/docs)\n\nsmall example:\n\n```jsx\nimport { createClient, cacheExchange, fetchExchange, Provider, useQuery } from '@urql/preact';\n\nconst client = createClient({\n  url: 'https://myHost/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n\nconst App = () => (\n  <Provider value={client}>\n    <Dogs />\n  </Provider>\n);\n\nconst Dogs = () => {\n  const [result] = useQuery({\n    query: `{ dogs { id name } }`,\n  });\n\n  if (result.fetching) return <p>Loading...</p>;\n  if (result.error) return <p>Oh no...</p>;\n\n  return result.data.dogs.map(dog => <p>{dog.name} is a good boy!</p>);\n};\n```\n","packages/react-urql/README.md":"# urql\n\n> A highly customizable and versatile GraphQL client **for React**\n\nMore documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).\n","packages/solid-start-urql/README.md":"# @urql/solid-start\n\n`@urql/solid-start` provides URQL integration for [SolidStart](https://start.solidjs.com/), built with SolidStart's native primitives like `query`, `action`, and `createAsync`.\n\n> **Note:** This package is specifically designed for SolidStart applications with SSR. If you're building a client-side only SolidJS app, use [`@urql/solid`](https://github.com/urql-graphql/urql/tree/main/packages/solid-urql) instead. See [SolidJS vs SolidStart](#solidjs-vs-solidstart) for key differences.\n\n## Features\n\n- 🎯 **SolidStart Native** - Built with `query`, `action`, `createAsync`, and `useAction`\n- 🚀 **Automatic SSR** - Works seamlessly with SolidStart's server-side rendering\n- 🔄 **Reactive Variables** - Query variables can be signals that automatically trigger re-execution\n- 📡 **Real-time Subscriptions** - Full GraphQL subscription support\n- 🎨 **Type Safe** - Complete TypeScript support with GraphQL types\n- 🪶 **Lightweight** - Minimal wrapper over URQL core\n\n## Installation\n\n```bash\nnpm install @urql/solid-start @urql/solid @urql/core graphql\n# or\npnpm add @urql/solid-start @urql/solid @urql/core graphql\n# or\nyarn add @urql/solid-start @urql/solid @urql/core graphql\n```\n\n> **Note:** `@urql/solid` is a peer dependency required for subscriptions.\n\n## Quick Start\n\n### 1. Set up the Provider\n\nWrap your app with the `Provider` to make the URQL client and router primitives available:\n\n```tsx\n// src/app.tsx\nimport { Router, action, query } from '@solidjs/router';\nimport { FileRoutes } from '@solidjs/start/router';\nimport { Provider } from '@urql/solid-start';\nimport { createClient, cacheExchange, fetchExchange } from '@urql/core';\n\nconst client = createClient({\n  url: 'https://api.example.com/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n\nexport default function App() {\n  return (\n    <Router root={props => <Provider value={{ client, query, action }}>{props.children}</Provider>}>\n      <FileRoutes />\n    </Router>\n  );\n}\n```\n\n> **Note:** The Provider accepts `client`, `query`, and `action` so `createQuery` and `createMutation` can use SolidStart APIs via context.\n\n### 2. Use Queries\n\n```tsx\n// src/routes/todos.tsx\nimport { createQuery } from '@urql/solid-start';\nimport { createAsync } from '@solidjs/router';\nimport { gql } from '@urql/core';\nimport { For, Show, Suspense } from 'solid-js';\n\nconst TodosQuery = gql`\n  query {\n    todos {\n      id\n      title\n      completed\n    }\n  }\n`;\n\nexport default function TodosPage() {\n  const queryTodos = createQuery(TodosQuery, 'todos-list');\n  const todos = createAsync(() => queryTodos());\n\n  return (\n    <div>\n      <h1>Todos</h1>\n      <Suspense fallback={<div>Loading...</div>}>\n        <Show when={todos()?.data}>\n          <ul>\n            <For each={todos()!.data.todos}>\n              {todo => (\n                <li>\n                  <input type=\"checkbox\" checked={todo.completed} />\n                  {todo.title}\n                </li>\n              )}\n            </For>\n          </ul>\n        </Show>\n        <Show when={todos()?.error}>\n          <p>Error: {todos()!.error.message}</p>\n        </Show>\n      </Suspense>\n    </div>\n  );\n}\n```\n\n### 3. Use Mutations\n\n```tsx\n// src/components/AddTodoForm.tsx\nimport { createMutation } from '@urql/solid-start';\nimport { useAction, useSubmission } from '@solidjs/router';\nimport { gql } from '@urql/core';\nimport { Show } from 'solid-js';\n\nconst AddTodoMutation = gql`\n  mutation AddTodo($title: String!) {\n    addTodo(title: $title) {\n      id\n      title\n    }\n  }\n`;\n\nexport function AddTodoForm() {\n  const addTodoAction = createMutation(AddTodoMutation, 'add-todo');\n  const addTodo = useAction(addTodoAction);\n  const submission = useSubmission(addTodoAction);\n\n  let inputRef: HTMLInputElement | undefined;\n\n  const handleSubmit = async (e: Event) => {\n    e.preventDefault();\n    if (!inputRef?.value) return;\n\n    const result = await addTodo({ title: inputRef.value });\n    if (result.data) {\n      inputRef.value = '';\n    }\n  };\n\n  return (\n    <form onSubmit={handleSubmit}>\n      <input ref={inputRef} type=\"text\" placeholder=\"New todo\" />\n      <button type=\"submit\" disabled={submission.pending}>\n        Add Todo\n      </button>\n      <Show when={submission.result?.error}>\n        <p>Error: {submission.result!.error.message}</p>\n      </Show>\n    </form>\n  );\n}\n```\n\n### 4. Use Subscriptions\n\n```tsx\n// src/components/LiveMessages.tsx\nimport { createSubscription } from '@urql/solid-start';\nimport { gql } from '@urql/core';\nimport { For } from 'solid-js';\n\nconst MessagesSubscription = gql`\n  subscription {\n    messageAdded {\n      id\n      text\n      createdAt\n    }\n  }\n`;\n\nexport function LiveMessages() {\n  const [messages] = createSubscription(\n    { query: MessagesSubscription },\n    // Optional handler to accumulate messages\n    (prev = [], data) => [...prev, data.messageAdded]\n  );\n\n  return (\n    <div>\n      <h2>Live Messages</h2>\n      <For each={messages.data}>{msg => <div>{msg.text}</div>}</For>\n    </div>\n  );\n}\n```\n\n## API Reference\n\n### `createQuery(queryDocument, key, options?)`\n\nCreates a GraphQL query using SolidStart's `query` and `createAsync` primitives. The `query` function is automatically retrieved from context.\n\n**Parameters:**\n\n- `queryDocument: DocumentInput` - GraphQL query document\n- `key: string` - Cache key for SolidStart's router\n- `options?: object` - Optional configuration\n  - `variables?: Variables` - Query variables\n  - `requestPolicy?: RequestPolicy` - Cache policy\n  - `context?: Partial<OperationContext>` - Additional context\n\n**Returns:** A query function that can be used with `createAsync`\n\n**Basic Example:**\n\n```tsx\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\n\nexport default function TodosPage() {\n  const queryTodos = createQuery(TodosQuery, 'todos-list');\n  const todos = createAsync(() => queryTodos());\n\n  return <div>{/* ... */}</div>;\n}\n```\n\n**Example with variables:**\n\n```tsx\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\n\nexport default function UserPage() {\n  const queryUser = createQuery(UserQuery, 'user-details', {\n    variables: { id: 1 },\n  });\n  const user = createAsync(() => queryUser());\n\n  return <div>{/* ... */}</div>;\n}\n```\n\n**Example with custom client:**\n\n```tsx\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\nimport { createClient } from '@urql/core';\n\nconst customClient = createClient({ url: 'https://api.example.com/graphql' });\n\nexport default function CustomPage() {\n  const queryTodos = createQuery(TodosQuery, 'todos-list');\n  const todos = createAsync(() => queryTodos(customClient));\n\n  return <div>{/* ... */}</div>;\n}\n```\n\n> **Note:** `createQuery` must be called inside a component where it has access to the URQL context. The query function from `@solidjs/router` is automatically retrieved from the Provider.\n\n### `createMutation(mutation, key)`\n\nCreates a GraphQL mutation action using SolidStart's `action` primitive.\n\n**Args:**\n\n- `mutation: DocumentInput` - GraphQL mutation document\n- `key: string` - Cache key for SolidStart's router\n\n**Returns:** `Action` - A SolidStart action that can be used with `useAction()` and `useSubmission()`\n\n**Example:**\n\n```tsx\nimport { createMutation } from '@urql/solid-start';\nimport { useAction, useSubmission } from '@solidjs/router';\n\nconst updateUserAction = createMutation(UpdateUserMutation, 'update-user');\nconst updateUser = useAction(updateUserAction);\nconst submission = useSubmission(updateUserAction);\n\n// Call the mutation\nconst result = await updateUser({ id: 1, name: 'Alice' });\n\n// Access submission state\nconsole.log(submission.pending); // boolean\nconsole.log(submission.result); // OperationResult\n```\n\n### `createSubscription(args, handler?)`\n\nCreates a GraphQL subscription for real-time updates.\n\n**Args:**\n\n```ts\n{\n  query: DocumentInput;\n  variables?: MaybeAccessor<Variables>;\n  context?: MaybeAccessor<Partial<OperationContext>>;\n  pause?: MaybeAccessor<boolean>;\n}\n```\n\n**Handler:** Optional function to accumulate/transform subscription data\n\n```ts\n(previousData: Data | undefined, newData: Data) => Data;\n```\n\n**Returns:** `[State, ExecuteFunction]`\n\n**Example with handler:**\n\n```tsx\nconst [messages] = createSubscription({ query: MessagesSubscription }, (prev = [], data) => [\n  ...prev,\n  data.messageAdded,\n]);\n```\n\n### `Provider`\n\nContext provider for the URQL client and SolidStart router primitives.\n\n**Props:**\n\n- `value: { client: Client; query: typeof query; action: typeof action }` - Object containing the URQL client and SolidStart router primitives\n\n**Example:**\n\n```tsx\nimport { action, query } from '@solidjs/router';\nimport { Provider } from '@urql/solid-start';\n\n<Provider value={{ client, query, action }}>\n  <App />\n</Provider>;\n```\n\n### `useClient()`\n\nHook to access the URQL client from context.\n\n**Returns:** `Client`\n\n## Request Policies\n\nControl caching behavior with `requestPolicy`:\n\n- `cache-first` (default) - Use cache if available, otherwise fetch\n- `cache-only` - Only use cached data, never fetch\n- `network-only` - Always fetch, ignore cache\n- `cache-and-network` - Return cache immediately, then fetch in background\n\n```tsx\nconst todos = createQuery({\n  query: TodosQuery,\n  requestPolicy: 'cache-and-network',\n});\n```\n\n## Dynamic Queries\n\nFor dynamic queries that change based on reactive values, you can pass variables to the query function:\n\n```tsx\nimport { createSignal } from 'solid-js';\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\n\nexport default function UserPage() {\n  const [userId, setUserId] = createSignal(1);\n\n  // Create the query function\n  const queryUser = createQuery(UserQuery, 'user-details', {\n    variables: { id: userId() },\n  });\n\n  // Wrap with createAsync to get reactive data\n  const user = createAsync(() => queryUser());\n\n  return (\n    <div>\n      <button onClick={() => setUserId(userId() + 1)}>Next User</button>\n      <Show when={user()?.data}>\n        <h1>{user()!.data.user.name}</h1>\n      </Show>\n    </div>\n  );\n}\n```\n\nNote: For fully reactive variables that trigger re-fetches, you may need to create the query function inside a `createEffect` or recreate it when dependencies change.\n\n## Cache Keys\n\nCache keys are required for both queries and mutations to enable SolidStart's caching and revalidation features:\n\n```tsx\n// Query with cache key\nconst queryTodos = createQuery(TodosQuery, 'todos-list', query);\n\n// Mutation with cache key\nconst [state, addTodo] = createMutation(AddTodoMutation, 'add-todo');\n```\n\nChoose descriptive cache keys that:\n\n- Are unique within your application\n- Describe the data being cached (e.g., 'user-profile', 'todos-list')\n- Make debugging easier by being human-readable\n\n## Advanced: Custom Exchanges\n\nAdd custom exchanges for authentication, error handling, etc:\n\n```tsx\nimport { createClient, cacheExchange, fetchExchange } from '@urql/core';\nimport { authExchange } from '@urql/exchange-auth';\n\nconst client = createClient({\n  url: 'https://api.example.com/graphql',\n  exchanges: [\n    cacheExchange,\n    authExchange(async utils => {\n      return {\n        addAuthToOperation(operation) {\n          const token = localStorage.getItem('token');\n          if (!token) return operation;\n          return utils.appendHeaders(operation, {\n            Authorization: `Bearer ${token}`,\n          });\n        },\n        didAuthError(error) {\n          return error.graphQLErrors.some(e => e.extensions?.code === 'UNAUTHENTICATED');\n        },\n        async refreshAuth() {\n          // Refresh token logic\n        },\n      };\n    }),\n    fetchExchange,\n  ],\n});\n```\n\n## TypeScript\n\nFull type safety with GraphQL types:\n\n```tsx\nimport { createQuery } from '@urql/solid-start';\nimport { gql, type TypedDocumentNode } from '@urql/core';\n\ninterface Todo {\n  id: string;\n  title: string;\n  completed: boolean;\n}\n\ninterface TodosData {\n  todos: Todo[];\n}\n\nconst TodosQuery: TypedDocumentNode<TodosData> = gql`\n  query {\n    todos {\n      id\n      title\n      completed\n    }\n  }\n`;\n\n// Fully typed!\nconst todos = createQuery({ query: TodosQuery });\n//    ^? Accessor<OperationResult<TodosData> | undefined>\n```\n\n## How It Works\n\n`@urql/solid-start` integrates URQL with SolidStart's primitives:\n\n- **`createQuery`** wraps SolidStart's `query()` function to execute URQL queries with automatic SSR and caching. The `query` function is automatically retrieved from the URQL context, eliminating the need for manual injection.\n- **`createMutation`** creates SolidStart `action()` primitives that integrate with `useAction()` and `useSubmission()` for form handling and progressive enhancement\n- **`createSubscription`** uses `@urql/solid-start` context so it works with the same Provider as queries and mutations\n\nThis means you get:\n\n- ✅ Automatic server-side rendering\n- ✅ Request deduplication via SolidStart's query caching\n- ✅ Streaming responses\n- ✅ Progressive enhancement with actions\n- ✅ Full fine-grained reactivity\n\n## SolidJS vs SolidStart\n\n### When to Use Each Package\n\n| Use Case           | Package             | Why                                                              |\n| ------------------ | ------------------- | ---------------------------------------------------------------- |\n| Client-side SPA    | `@urql/solid`       | Optimized for client-only apps, uses SolidJS reactivity patterns |\n| SolidStart SSR App | `@urql/solid-start` | Integrates with SolidStart's routing, SSR, and action system     |\n\n### Key Differences\n\n#### Queries\n\n**@urql/solid** (Client-side):\n\n```tsx\nimport { createQuery } from '@urql/solid';\n\nconst [result] = createQuery({ query: TodosQuery });\n// Returns: [Accessor<OperationResult>, Accessor<ReExecute>]\n```\n\n**@urql/solid-start** (SSR):\n\n```tsx\nimport { createQuery } from '@urql/solid-start';\nimport { createAsync } from '@solidjs/router';\n\nconst queryTodos = createQuery(TodosQuery, 'todos');\nconst todos = createAsync(() => queryTodos());\n// Returns: Accessor<OperationResult | undefined>\n// Works with SSR and SolidStart's caching\n```\n\n#### Mutations\n\n**@urql/solid** (Client-side):\n\n```tsx\nimport { createMutation } from '@urql/solid';\n\nconst [result, executeMutation] = createMutation(AddTodoMutation);\nawait executeMutation({ title: 'New Todo' });\n// Returns: [Accessor<OperationResult>, ExecuteMutation]\n```\n\n**@urql/solid-start** (SSR with Actions):\n\n```tsx\nimport { createMutation } from '@urql/solid-start';\nimport { useAction, useSubmission } from '@solidjs/router';\n\nconst addTodoAction = createMutation(AddTodoMutation, 'add-todo');\nconst addTodo = useAction(addTodoAction);\nconst submission = useSubmission(addTodoAction);\nawait addTodo({ title: 'New Todo' });\n// Integrates with SolidStart's action system for progressive enhancement\n```\n\n### Why Different APIs?\n\n- **SSR Support**: SolidStart queries run on the server and stream to the client\n- **Router Integration**: Automatic caching and invalidation with SolidStart's router\n- **Progressive Enhancement**: Actions work without JavaScript enabled\n- **Suspense**: Native support for SolidJS Suspense boundaries\n\n### Migration\n\nIf you're moving from a SolidJS SPA to SolidStart:\n\n1. Change imports from `@urql/solid` to `@urql/solid-start`\n2. Wrap queries with `createAsync()`\n3. Update mutations to use the action pattern with `useAction()` and `useSubmission()`\n\n## Resources\n\n- [SolidStart Documentation](https://start.solidjs.com/)\n- [URQL Documentation](https://formidable.com/open-source/urql/docs/)\n- [Solid Primitives](https://primitives.solidjs.community/)\n\n## License\n\nMIT\n","packages/solid-urql/README.md":"# @urql/solid\n\nA highly customizable and versatile GraphQL client for SolidJS.\n\n> **Note:** This package is for client-side SolidJS applications. If you're building a SolidStart application with SSR, use [`@urql/solid-start`](../solid-start-urql) instead. See the [comparison section](../solid-start-urql#solidjs-vs-solidstart) in the SolidStart package for key differences.\n\n## Installation\n\n```bash\nnpm install @urql/solid @urql/core graphql\n# or\npnpm add @urql/solid @urql/core graphql\n# or\nyarn add @urql/solid @urql/core graphql\n```\n\n## Documentation\n\nFull documentation is available at [formidable.com/open-source/urql/docs/](https://formidable.com/open-source/urql/docs/).\n\n## Quick Start\n\n```tsx\nimport { createClient, Provider, createQuery } from '@urql/solid';\nimport { cacheExchange, fetchExchange } from '@urql/core';\nimport { gql } from '@urql/core';\n\nconst client = createClient({\n  url: 'https://api.example.com/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n\nconst TodosQuery = gql`\n  query {\n    todos {\n      id\n      title\n    }\n  }\n`;\n\nfunction App() {\n  return (\n    <Provider value={client}>\n      <TodoList />\n    </Provider>\n  );\n}\n\nfunction TodoList() {\n  const [result] = createQuery({ query: TodosQuery });\n\n  return (\n    <div>\n      {result().data?.todos.map(todo => (\n        <div>{todo.title}</div>\n      ))}\n    </div>\n  );\n}\n```\n\n## When to Use @urql/solid vs @urql/solid-start\n\n| Use Case | Package |\n|----------|---------|\n| Client-side SPA | `@urql/solid` |\n| SolidStart with SSR | `@urql/solid-start` |\n\nFor a detailed comparison of the APIs and when to use each package, see the [SolidJS vs SolidStart comparison](../solid-start-urql#solidjs-vs-solidstart) in the `@urql/solid-start` documentation.\n\n## License\n\nMIT\n","packages/storage-rn/README.md":"# @urql/storage-rn\n\n`@urql/storage-rn` is a Graphcache offline storage for React Native.\n\nIt is compatible for both plain React Native and Expo apps (including managed workflow), but it has a two peer dependencies - [Async Storage](https://react-native-async-storage.github.io/async-storage/) and [NetInfo](https://github.com/react-native-netinfo/react-native-netinfo) - which must be installed separately. AsyncStorage will be used to persist the data, and NetInfo will be used to determine when the app is online and offline.\n\n## Quick Start Guide\n\nInstall NetInfo ([RN](https://github.com/react-native-netinfo/react-native-netinfo) | [Expo](https://docs.expo.dev/versions/latest/sdk/netinfo/)) and AsyncStorage ([RN](https://react-native-async-storage.github.io/async-storage/docs/install) | [Expo](https://docs.expo.dev/versions/v42.0.0/sdk/async-storage/)).\n\nInstall `@urql/storage-rn` alongside `urql` and `@urql/exchange-graphcache`:\n\n```sh\nyarn add @urql/storage-rn\n# or\nnpm install --save @urql/storage-rn\n```\n\nThen add it to the offline exchange:\n\n```js\nimport { createClient, fetchExchange } from 'urql';\nimport { offlineExchange } from '@urql/exchange-graphcache';\nimport { makeAsyncStorage } from '@urql/storage-rn';\n\nconst storage = makeAsyncStorage({\n  dataKey: 'graphcache-data', // The AsyncStorage key used for the data (defaults to graphcache-data)\n  metadataKey: 'graphcache-metadata', // The AsyncStorage key used for the metadata (defaults to graphcache-metadata)\n  maxAge: 7, // How long to persist the data in storage (defaults to 7 days)\n});\n\nconst cache = offlineExchange({\n  schema,\n  storage,\n  updates: {\n    /* ... */\n  },\n  optimistic: {\n    /* ... */\n  },\n});\n\nconst client = createClient({\n  url: 'http://localhost:3000/graphql',\n  exchanges: [cache, fetchExchange],\n});\n```\n","packages/svelte-urql/README.md":"# @urql/svelte\n\n> A highly customizable and versatile GraphQL client **for Svelte**\n\nMore documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).\n","packages/vue-urql/README.md":"<div align=\"center\">\n  <br />\n  <br />\n  <a href=\"https://www.npmjs.com/package/@urql/vue\">\n    <img alt=\"Npm version\" src=\"https://badgen.net/npm/v/@urql/vue\" />\n  </a>\n  <a href=\"https://bundlephobia.com/result?p=@urql/vue\">\n    <img alt=\"Minified gzip size\" src=\"https://img.shields.io/bundlephobia/minzip/@urql/vue.svg?label=gzip%20size\" />\n  </a>\n  <a href=\"https://github.com/urql-graphql/urql/discussions\">\n    <img alt=\"GitHub Discussions: Chat With Us\" src=\"https://badgen.net/badge/discussions/chat%20with%20us/purple\" />\n  </a>\n  <br />\n  <br />\n</div>\n\n## Installation\n\n```sh\nyarn add @urql/vue graphql\n# or\nnpm install --save @urql/vue graphql\n```\n\n> **Note:** `@urql/vue` has a peer dependency on `vue@^3.0.0` (Not v2) and doesn't currently plan to\n> be backwards compatible to Vue 2.\n"},"items":[{"name":"architecture.md","path":"docs/architecture.md","rawUrl":"https://raw.githubusercontent.com/urql-graphql/urql/HEAD/docs/architecture.md","title":"docs - System Architecture & Module Boundaries","category":"project-spec","format":"markdown","content":"---\ntitle: Architecture\norder: 3\n---\n\n# Architecture\n\n`urql` is a highly customizable and flexible GraphQL client.\nAs you use it in your app, it's split into three parts:\n\n- Bindings — such as for React, Preact, Vue, or Svelte — which interact with `@urql/core`'s\n  `Client`.\n- The Client — as created [with the core `@urql/core` package](./basics/core.md), which interacts with \"exchanges\" to execute GraphQL\n  operations, and which you can also use directly.\n- Exchanges, which provide functionality like fetching or caching to the `Client`.\n\nBy default, `urql` aims to provide the minimal amount of features that allow us to build an app\nquickly. However, `urql` has also been designed to be a GraphQL Client\nthat grows with our usage and demands. As we go from building our smallest or first GraphQL apps to\nutilising its full functionality, we have tools at our disposal to extend and customize `urql` to\nour liking.\n\n## Using GraphQL Clients\n\nYou may have worked with a GraphQL API previously and noticed that using GraphQL in your app can be\nas straightforward as sending a plain HTTP request with your query to fetch some data.\n\nGraphQL also provides an opportunity to abstract away a lot of the manual work that goes with\nsending these queries and managing the data. Ultimately, this lets you focus on building\nyour app without having to handle the technical details of state management in detail.\n\nSpecifically, `urql` simplifies three common aspects of using GraphQL:\n\n- Sending queries and mutations and receiving results _declaratively_\n- Abstracting _caching_ and state management internally\n- Providing a central point of _extensibility_ and integration with your API\n\nIn the following sections we'll talk about the way that `urql` solves these three problems and how the logic is abstracted away internally.\n\n## Requests and Operations on the Client\n\nIf `urql` was a train it would take several stops to arrive at its terminus, our API. It starts with us\ndefining queries or mutations by writing in GraphQL's query language.\n\nAny GraphQL request can be abstracted into its query documents and its variables.\n\n```js\nimport { gql } from '@urql/core';\n\nconst query = gql`\n  query ($name: String!) {\n    helloWorld(name: $name)\n  }\n`;\n\nconst request = createRequest(query, {\n  name: 'Urkel',\n});\n```\n\nIn `urql`, these GraphQL requests are treated as unique objects and each GraphQL request will have\na `key` generated for them. This `key` is a hash of the query document and the variables you provide\nand are set on the `key` property of a [`GraphQLRequest`](./api/core.md#graphqlrequest).\n\nWhenever we decide to send our GraphQL requests to a GraphQL API we start by using `urql`'s\n[`Client`](./api/core.md#client).\nThe `Client` accepts several options to configure its behaviour and the behaviour of exchanges,\nlike the `fetchExchange`. For instance, we can pass it a `url` which the `fetchExchange` will\nuse to make a `fetch` call to our GraphQL API.\n\n```js\nimport { Client, cacheExchange, fetchExchange } from '@urql/core';\n\nconst client = new Client({\n  url: 'http://localhost:3000/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n```\n\nAbove, we're defining a `Client` that is ready to accept our requests. It will apply basic\ndocument caching and will send uncached requests to the `url` we pass it.\nThe bindings that we've seen in [the \"Basics\" section](./basics/README.md), like `useQuery` for\nReact for example, interact with [the `Client`](./api/core.md#client) directly and are a thin\nabstraction.\n\nSome methods can be called on it directly however, as seen [on the \"Core Usage\"\npage](./basics/core.md#one-off-queries-and-mutations).\n\n```js\n// Given our request and client defined above, we can call\nconst subscription = client.executeQuery(request).subscribe(result => {\n  console.log(result.data);\n});\n```\n\nAs we've seen, `urql` defines our query documents and variables as\n[`GraphQLRequest`s](./api/core.md#graphqlrequest). However, since we have more metadata that is\nneeded, like our `url` option on the `Client`, `urql` internally creates [`Operation`s](./api/core.md#operation)\neach time a request is executed. The operations are then forwarded to the exchanges, like the\n`cacheExchange` and `fetchExchange`.\n\nAn \"Operation\" is an extension of `GraphQLRequest`s. Not only do they carry the `query`, `variables`,\nand a `key` property, they will also identify the `kind` of operation that is executed, like\n`\"query\"` or `\"mutation\"`, and they contain the `Client`'s options on `operation.context`.\n\n![Operations and Results](./assets/urql-event-hub.png)\n\nThis means, once we hand over a GraphQL request to the `Client`, it will create an `Operation`,\nand then hand it over to the exchanges until a result comes back.\n\nAs shown in the diagram, each operation is like an event or signal for a GraphQL request to start,\nand the exchanges will eventually send back a corresponding result.\nHowever, because the cache can send updates to us whenever it detects a change, or you could cancel\na GraphQL request before it finishes, a special \"teardown\" `Operation` also exists, which cancels\nongoing requests.\n\n## The Client and Exchanges\n\nTo reiterate, when we use `urql`'s bindings for our framework of choice, methods are called on the\n`Client`, but we never see the operations that are created in the background from our bindings. We\ncall a method like `client.executeQuery` (or it's called for us in the bindings), an operation is\nissued internally when we subscribe with a callback, and later, we're given results.\n\n![Operations stream and results stream](./assets/urql-client-architecture.png)\n\nWhile we know that, for us, we're only interested in a single [`Operation`](./api/core.md#operation)\nand its [`OperationResult`s](./api/core.md#operationresult) at a time, the `Client` treats these as\none big stream. The `Client` sees an incoming flow of all of our operations.\n\nAs we've learned before, each operation carries a `key` and each result we receive carries the\noriginal `operation`. Because an `OperationResult` also carries an `operation` property the `Client`\nwill always know which results correspond to an individual operation.\nHowever, internally, all of our operations are processed at the same time concurrently. However, from\nour perspective:\n\n- We subscribe to a \"stream\" and expect to get results on a callback\n- The `Client` issues the operation, and we'll receive some results back eventually as either the\n  cache responds (synchronously), or the request gets sent to our API.\n- We eventually unsubscribe, and the `Client` issues a \"teardown\" operation with the same `key` as\n  the original operation, which concludes our flow.\n\nThe `Client` itself doesn't actually know what to do with operations. Instead, it sends them through\n\"exchanges\". Exchanges are akin to [middleware in Redux](https://redux.js.org/advanced/middleware)\nand have access to all operations and all results. Multiple exchanges are chained to process our\noperations and to execute logic on them, one of them being the `fetchExchange`, which as the name\nimplies sends our requests to our API.\n\n### How operations get to exchanges\n\nWe now know how we get to operations and to the `Client`:\n\n- Any bindings or calls to the `Client` create an **operation**\n- This operation identifies itself as either a `\"query\"`, `\"mutation\"` or `\"subscription\"` and has a\n  unique `key`.\n- This operation is sent into the **exchanges** and eventually ends up at the `fetchExchange`\n  (or a similar exchange)\n- The operation is sent to the API and a **result** comes back, which is wrapped in an `OperationResult`\n- The `Client` filters the `OperationResult` by the `operation.key` and — via a callback — gives us\n  a **stream of results**.\n\nTo come back to our train analogy from earlier, an operation, like a train, travels from one end\nof the track to the terminus — our API. The results then come back on the same path as they're just\ntravelling the same line in reverse.\n\n### The Exchanges\n\nBy default, the `Client` doesn't do anything with GraphQL requests. It contains only the logic to\nmanage and differentiate between active and inactive requests and converts them to operations.\nTo actually do something with our GraphQL requests, it needs _exchanges_, which are like plugins\nthat you can pass to create a pipeline of how GraphQL operations are executed.\n\nBy default, you may want to add the `cacheExchange` and the `fetchExchange` from `@urql/core`:\n\n- `cacheExchange`: Caches GraphQL results with [\"Document Caching\"](./basics/document-caching.md)\n- `fetchExchange`: Executes GraphQL requests with a `fetch` HTTP call\n\n```js\nimport { Client, cacheExchange, fetchExchange } from '@urql/core';\n\nconst client = new Client({\n  url: 'http://localhost:3000/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n```\n\nAs we can tell, exchanges define not only how GraphQL requests are executed and handled, but also\nget control over caching. Exchanges can be used to change almost any behaviour in the `Client`,\nalthough internally they only handle incoming & outgoing requests and incoming & outgoing results.\n\nSome more exchanges that we can use with our `Client` are:\n\n- [`mapExchange`](./api/core.md#mapexchange): Allows changing and reacting to operations, results, and errors\n- [`ssrExchange`](./advanced/server-side-rendering.md): Allows for a server-side renderer to\n  collect results for client-side rehydration.\n- [`retryExchange`](./advanced/retry-operations.md): Allows operations to be retried on errors\n- [`persistedExchange`](./advanced/persistence-and-uploads.md#automatic-persisted-queries): Provides support for Automatic\n  Persisted Queries\n- [`authExchange`](./advanced/authentication.md): Allows refresh authentication to be implemented easily.\n- [`requestPolicyExchange`](./api/request-policy-exchange.md): Automatically refreshes results given a TTL.\n- `devtoolsExchange`: Provides the ability to use the [urql-devtools](https://github.com/urql-graphql/urql-devtools)\n\nWe can even swap out our [document cache](./basics/document-caching.md), which is implemented by\n`@urql/core`'s `cacheExchange`, with `urql`'s [normalized cache,\nGraphcache](./graphcache/README.md).\n\n[Read more about exchanges and how to write them from scratch on the \"Authoring Exchanges\"\npage.](./advanced/authoring-exchanges.md)\n\n## Stream Patterns in `urql`\n\nIn the previous sections we've learned a lot about how the `Client` works, but we've always learned\nit in vague terms — for instance, we've learned that we get a \"stream of results\" or `urql` sees all\noperations as \"one stream of operations\" that it sends to the exchanges.\nBut, **what are streams?**\n\nGenerally we refer to _streams_ as abstractions that allow us to program with asynchronous events\nover time. Within the context of JavaScript we're specifically thinking in terms of\n[Observables](https://github.com/tc39/proposal-observable)\nand [Reactive Programming with Observables.](http://reactivex.io/documentation/observable.html)\nThese concepts may sound intimidating, but from a high-level view what we're talking about can be\nthought of as a combination of promises and iterables (e.g. arrays). We're dealing with multiple\nevents, but our callback is called over time. It's like calling `forEach` on an array but expecting\nthe results to come in asynchronously.\n\nAs a user, if we're using the one framework bindings that we've seen in [the \"Basics\"\nsection](./basics/README.md), we may never see these streams in action or may never use them even,\nsince the bindings internally use them for us. But if we [use the `Client`\ndirectly](./basics/core.md#one-off-queries-and-mutations) or write exchanges then we'll see streams\nand will have to deal with their API.\n\n### Stream patterns with the client\n\nWhen we call methods on the `Client` like [`client.executeQuery`](./api/core.md#clientexecutequery)\nor [`client.query`](./api/core.md#clientquery) then these will return a \"stream\" of results.\n\nIt's normal for GraphQL subscriptions to deliver multiple results, however, even GraphQL queries can\ngive you multiple results in `urql`. This is because operations influence one another. When a cache\ninvalidates a query, this query may refetch, and a new result is delivered to your application.\n\nMultiple results mean that once you subscribe to a GraphQL query via the `Client`, you may receive\nnew results in the future.\n\n```js\nimport { gql } from '@urql/core';\n\nconst QUERY = gql`\n  query Test($id: ID!) {\n    getUser(id: $id) {\n      id\n      name\n    }\n  }\n`;\n\nclient.query(QUERY, { id: 'test' }).subscribe(result => {\n  console.log(result); // { data: ... }\n});\n```\n\nRead more about the available APIs on the `Client` in the [Core API docs](./api/core.md).\n\nInternally, these streams and all exchanges are written using a library called\n[`wonka`](https://wonka.kitten.sh/basics/background), which is a tiny Observable-like\nlibrary. It is used to write exchanges and when we interact with the `Client` it is used internally\nas well.\n","frontmatter":{"title":"Architecture","order":3},"isInternal":false,"tokens":3005,"sizeBytes":13032},{"name":"README.md","path":"packages/core/README.md","rawUrl":"https://raw.githubusercontent.com/urql-graphql/urql/HEAD/packages/core/README.md","title":"core Documentation","category":"plugin-manifest","format":"markdown","content":"# @urql/core\n\n> The shared core for the highly customizable and versatile GraphQL client, urql\n\nMore documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).\n","isInternal":false,"tokens":49,"sizeBytes":208},{"name":"README.md","path":"packages/introspection/README.md","rawUrl":"https://raw.githubusercontent.com/urql-graphql/urql/HEAD/packages/introspection/README.md","title":"introspection Documentation","category":"plugin-manifest","format":"markdown","content":"<h2 align=\"center\">@urql/introspection</h2>\n\n<p align=\"center\"><strong>Utilities for dealing with Introspection Queries and Client Schemas</strong></p>\n","isInternal":false,"tokens":39,"sizeBytes":152},{"name":"README.md","path":"packages/next-urql/README.md","rawUrl":"https://raw.githubusercontent.com/urql-graphql/urql/HEAD/packages/next-urql/README.md","title":"next-urql Documentation","category":"plugin-manifest","format":"markdown","content":"## `next-urql`\n\nA set of convenience utilities for using `urql` with Next.js.\n\nMore documentation is available at https://urql.dev/goto/docs/advanced/server-side-rendering/#nextjs\nExamples can be found at https://github.com/urql-graphql/urql/tree/main/examples/with-next\n","isInternal":false,"tokens":68,"sizeBytes":271},{"name":"README.md","path":"packages/preact-urql/README.md","rawUrl":"https://raw.githubusercontent.com/urql-graphql/urql/HEAD/packages/preact-urql/README.md","title":"preact-urql Documentation","category":"plugin-manifest","format":"markdown","content":"<div align=\"center\">\n  <br />\n  <br />\n  <a href=\"https://www.npmjs.com/package/@urql/preact\">\n    <img alt=\"Npm version\" src=\"https://badgen.net/npm/v/@urql/preact\" />\n  </a>\n  <a href=\"https://bundlephobia.com/result?p=@urql/preact\">\n    <img alt=\"Minified gzip size\" src=\"https://img.shields.io/bundlephobia/minzip/@urql/preact.svg?label=gzip%20size\" />\n  </a>\n  <a href=\"https://github.com/urql-graphql/urql/discussions\">\n    <img alt=\"GitHub Discussions: Chat With Us\" src=\"https://badgen.net/badge/discussions/chat%20with%20us/purple\" />\n  </a>\n  <br />\n  <br />\n</div>\n\n## Installation\n\n```sh\nyarn add @urql/preact urql graphql\n# or\nnpm install --save @urql/preact urql graphql\n```\n\n## Usage\n\nThe usage is a 1:1 mapping of the React usage found [here](https://formidable.com/open-source/urql/docs)\n\nsmall example:\n\n```jsx\nimport { createClient, cacheExchange, fetchExchange, Provider, useQuery } from '@urql/preact';\n\nconst client = createClient({\n  url: 'https://myHost/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n\nconst App = () => (\n  <Provider value={client}>\n    <Dogs />\n  </Provider>\n);\n\nconst Dogs = () => {\n  const [result] = useQuery({\n    query: `{ dogs { id name } }`,\n  });\n\n  if (result.fetching) return <p>Loading...</p>;\n  if (result.error) return <p>Oh no...</p>;\n\n  return result.data.dogs.map(dog => <p>{dog.name} is a good boy!</p>);\n};\n```\n","isInternal":false,"tokens":422,"sizeBytes":1383},{"name":"README.md","path":"packages/react-urql/README.md","rawUrl":"https://raw.githubusercontent.com/urql-graphql/urql/HEAD/packages/react-urql/README.md","title":"react-urql Documentation","category":"plugin-manifest","format":"markdown","content":"# urql\n\n> A highly customizable and versatile GraphQL client **for React**\n\nMore documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).\n","isInternal":false,"tokens":43,"sizeBytes":188},{"name":"README.md","path":"packages/solid-start-urql/README.md","rawUrl":"https://raw.githubusercontent.com/urql-graphql/urql/HEAD/packages/solid-start-urql/README.md","title":"solid-start-urql Documentation","category":"plugin-manifest","format":"markdown","content":"# @urql/solid-start\n\n`@urql/solid-start` provides URQL integration for [SolidStart](https://start.solidjs.com/), built with SolidStart's native primitives like `query`, `action`, and `createAsync`.\n\n> **Note:** This package is specifically designed for SolidStart applications with SSR. If you're building a client-side only SolidJS app, use [`@urql/solid`](https://github.com/urql-graphql/urql/tree/main/packages/solid-urql) instead. See [SolidJS vs SolidStart](#solidjs-vs-solidstart) for key differences.\n\n## Features\n\n- 🎯 **SolidStart Native** - Built with `query`, `action`, `createAsync`, and `useAction`\n- 🚀 **Automatic SSR** - Works seamlessly with SolidStart's server-side rendering\n- 🔄 **Reactive Variables** - Query variables can be signals that automatically trigger re-execution\n- 📡 **Real-time Subscriptions** - Full GraphQL subscription support\n- 🎨 **Type Safe** - Complete TypeScript support with GraphQL types\n- 🪶 **Lightweight** - Minimal wrapper over URQL core\n\n## Installation\n\n```bash\nnpm install @urql/solid-start @urql/solid @urql/core graphql\n# or\npnpm add @urql/solid-start @urql/solid @urql/core graphql\n# or\nyarn add @urql/solid-start @urql/solid @urql/core graphql\n```\n\n> **Note:** `@urql/solid` is a peer dependency required for subscriptions.\n\n## Quick Start\n\n### 1. Set up the Provider\n\nWrap your app with the `Provider` to make the URQL client and router primitives available:\n\n```tsx\n// src/app.tsx\nimport { Router, action, query } from '@solidjs/router';\nimport { FileRoutes } from '@solidjs/start/router';\nimport { Provider } from '@urql/solid-start';\nimport { createClient, cacheExchange, fetchExchange } from '@urql/core';\n\nconst client = createClient({\n  url: 'https://api.example.com/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n\nexport default function App() {\n  return (\n    <Router root={props => <Provider value={{ client, query, action }}>{props.children}</Provider>}>\n      <FileRoutes />\n    </Router>\n  );\n}\n```\n\n> **Note:** The Provider accepts `client`, `query`, and `action` so `createQuery` and `createMutation` can use SolidStart APIs via context.\n\n### 2. Use Queries\n\n```tsx\n// src/routes/todos.tsx\nimport { createQuery } from '@urql/solid-start';\nimport { createAsync } from '@solidjs/router';\nimport { gql } from '@urql/core';\nimport { For, Show, Suspense } from 'solid-js';\n\nconst TodosQuery = gql`\n  query {\n    todos {\n      id\n      title\n      completed\n    }\n  }\n`;\n\nexport default function TodosPage() {\n  const queryTodos = createQuery(TodosQuery, 'todos-list');\n  const todos = createAsync(() => queryTodos());\n\n  return (\n    <div>\n      <h1>Todos</h1>\n      <Suspense fallback={<div>Loading...</div>}>\n        <Show when={todos()?.data}>\n          <ul>\n            <For each={todos()!.data.todos}>\n              {todo => (\n                <li>\n                  <input type=\"checkbox\" checked={todo.completed} />\n                  {todo.title}\n                </li>\n              )}\n            </For>\n          </ul>\n        </Show>\n        <Show when={todos()?.error}>\n          <p>Error: {todos()!.error.message}</p>\n        </Show>\n      </Suspense>\n    </div>\n  );\n}\n```\n\n### 3. Use Mutations\n\n```tsx\n// src/components/AddTodoForm.tsx\nimport { createMutation } from '@urql/solid-start';\nimport { useAction, useSubmission } from '@solidjs/router';\nimport { gql } from '@urql/core';\nimport { Show } from 'solid-js';\n\nconst AddTodoMutation = gql`\n  mutation AddTodo($title: String!) {\n    addTodo(title: $title) {\n      id\n      title\n    }\n  }\n`;\n\nexport function AddTodoForm() {\n  const addTodoAction = createMutation(AddTodoMutation, 'add-todo');\n  const addTodo = useAction(addTodoAction);\n  const submission = useSubmission(addTodoAction);\n\n  let inputRef: HTMLInputElement | undefined;\n\n  const handleSubmit = async (e: Event) => {\n    e.preventDefault();\n    if (!inputRef?.value) return;\n\n    const result = await addTodo({ title: inputRef.value });\n    if (result.data) {\n      inputRef.value = '';\n    }\n  };\n\n  return (\n    <form onSubmit={handleSubmit}>\n      <input ref={inputRef} type=\"text\" placeholder=\"New todo\" />\n      <button type=\"submit\" disabled={submission.pending}>\n        Add Todo\n      </button>\n      <Show when={submission.result?.error}>\n        <p>Error: {submission.result!.error.message}</p>\n      </Show>\n    </form>\n  );\n}\n```\n\n### 4. Use Subscriptions\n\n```tsx\n// src/components/LiveMessages.tsx\nimport { createSubscription } from '@urql/solid-start';\nimport { gql } from '@urql/core';\nimport { For } from 'solid-js';\n\nconst MessagesSubscription = gql`\n  subscription {\n    messageAdded {\n      id\n      text\n      createdAt\n    }\n  }\n`;\n\nexport function LiveMessages() {\n  const [messages] = createSubscription(\n    { query: MessagesSubscription },\n    // Optional handler to accumulate messages\n    (prev = [], data) => [...prev, data.messageAdded]\n  );\n\n  return (\n    <div>\n      <h2>Live Messages</h2>\n      <For each={messages.data}>{msg => <div>{msg.text}</div>}</For>\n    </div>\n  );\n}\n```\n\n## API Reference\n\n### `createQuery(queryDocument, key, options?)`\n\nCreates a GraphQL query using SolidStart's `query` and `createAsync` primitives. The `query` function is automatically retrieved from context.\n\n**Parameters:**\n\n- `queryDocument: DocumentInput` - GraphQL query document\n- `key: string` - Cache key for SolidStart's router\n- `options?: object` - Optional configuration\n  - `variables?: Variables` - Query variables\n  - `requestPolicy?: RequestPolicy` - Cache policy\n  - `context?: Partial<OperationContext>` - Additional context\n\n**Returns:** A query function that can be used with `createAsync`\n\n**Basic Example:**\n\n```tsx\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\n\nexport default function TodosPage() {\n  const queryTodos = createQuery(TodosQuery, 'todos-list');\n  const todos = createAsync(() => queryTodos());\n\n  return <div>{/* ... */}</div>;\n}\n```\n\n**Example with variables:**\n\n```tsx\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\n\nexport default function UserPage() {\n  const queryUser = createQuery(UserQuery, 'user-details', {\n    variables: { id: 1 },\n  });\n  const user = createAsync(() => queryUser());\n\n  return <div>{/* ... */}</div>;\n}\n```\n\n**Example with custom client:**\n\n```tsx\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\nimport { createClient } from '@urql/core';\n\nconst customClient = createClient({ url: 'https://api.example.com/graphql' });\n\nexport default function CustomPage() {\n  const queryTodos = createQuery(TodosQuery, 'todos-list');\n  const todos = createAsync(() => queryTodos(customClient));\n\n  return <div>{/* ... */}</div>;\n}\n```\n\n> **Note:** `createQuery` must be called inside a component where it has access to the URQL context. The query function from `@solidjs/router` is automatically retrieved from the Provider.\n\n### `createMutation(mutation, key)`\n\nCreates a GraphQL mutation action using SolidStart's `action` primitive.\n\n**Args:**\n\n- `mutation: DocumentInput` - GraphQL mutation document\n- `key: string` - Cache key for SolidStart's router\n\n**Returns:** `Action` - A SolidStart action that can be used with `useAction()` and `useSubmission()`\n\n**Example:**\n\n```tsx\nimport { createMutation } from '@urql/solid-start';\nimport { useAction, useSubmission } from '@solidjs/router';\n\nconst updateUserAction = createMutation(UpdateUserMutation, 'update-user');\nconst updateUser = useAction(updateUserAction);\nconst submission = useSubmission(updateUserAction);\n\n// Call the mutation\nconst result = await updateUser({ id: 1, name: 'Alice' });\n\n// Access submission state\nconsole.log(submission.pending); // boolean\nconsole.log(submission.result); // OperationResult\n```\n\n### `createSubscription(args, handler?)`\n\nCreates a GraphQL subscription for real-time updates.\n\n**Args:**\n\n```ts\n{\n  query: DocumentInput;\n  variables?: MaybeAccessor<Variables>;\n  context?: MaybeAccessor<Partial<OperationContext>>;\n  pause?: MaybeAccessor<boolean>;\n}\n```\n\n**Handler:** Optional function to accumulate/transform subscription data\n\n```ts\n(previousData: Data | undefined, newData: Data) => Data;\n```\n\n**Returns:** `[State, ExecuteFunction]`\n\n**Example with handler:**\n\n```tsx\nconst [messages] = createSubscription({ query: MessagesSubscription }, (prev = [], data) => [\n  ...prev,\n  data.messageAdded,\n]);\n```\n\n### `Provider`\n\nContext provider for the URQL client and SolidStart router primitives.\n\n**Props:**\n\n- `value: { client: Client; query: typeof query; action: typeof action }` - Object containing the URQL client and SolidStart router primitives\n\n**Example:**\n\n```tsx\nimport { action, query } from '@solidjs/router';\nimport { Provider } from '@urql/solid-start';\n\n<Provider value={{ client, query, action }}>\n  <App />\n</Provider>;\n```\n\n### `useClient()`\n\nHook to access the URQL client from context.\n\n**Returns:** `Client`\n\n## Request Policies\n\nControl caching behavior with `requestPolicy`:\n\n- `cache-first` (default) - Use cache if available, otherwise fetch\n- `cache-only` - Only use cached data, never fetch\n- `network-only` - Always fetch, ignore cache\n- `cache-and-network` - Return cache immediately, then fetch in background\n\n```tsx\nconst todos = createQuery({\n  query: TodosQuery,\n  requestPolicy: 'cache-and-network',\n});\n```\n\n## Dynamic Queries\n\nFor dynamic queries that change based on reactive values, you can pass variables to the query function:\n\n```tsx\nimport { createSignal } from 'solid-js';\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\n\nexport default function UserPage() {\n  const [userId, setUserId] = createSignal(1);\n\n  // Create the query function\n  const queryUser = createQuery(UserQuery, 'user-details', {\n    variables: { id: userId() },\n  });\n\n  // Wrap with createAsync to get reactive data\n  const user = createAsync(() => queryUser());\n\n  return (\n    <div>\n      <button onClick={() => setUserId(userId() + 1)}>Next User</button>\n      <Show when={user()?.data}>\n        <h1>{user()!.data.user.name}</h1>\n      </Show>\n    </div>\n  );\n}\n```\n\nNote: For fully reactive variables that trigger re-fetches, you may need to create the query function inside a `createEffect` or recreate it when dependencies change.\n\n## Cache Keys\n\nCache keys are required for both queries and mutations to enable SolidStart's caching and revalidation features:\n\n```tsx\n// Query with cache key\nconst queryTodos = createQuery(TodosQuery, 'todos-list', query);\n\n// Mutation with cache key\nconst [state, addTodo] = createMutation(AddTodoMutation, 'add-todo');\n```\n\nChoose descriptive cache keys that:\n\n- Are unique within your application\n- Describe the data being cached (e.g., 'user-profile', 'todos-list')\n- Make debugging easier by being human-readable\n\n## Advanced: Custom Exchanges\n\nAdd custom exchanges for authentication, error handling, etc:\n\n```tsx\nimport { createClient, cacheExchange, fetchExchange } from '@urql/core';\nimport { authExchange } from '@urql/exchange-auth';\n\nconst client = createClient({\n  url: 'https://api.example.com/graphql',\n  exchanges: [\n    cacheExchange,\n    authExchange(async utils => {\n      return {\n        addAuthToOperation(operation) {\n          const token = localStorage.getItem('token');\n          if (!token) return operation;\n          return utils.appendHeaders(operation, {\n            Authorization: `Bearer ${token}`,\n          });\n        },\n        didAuthError(error) {\n          return error.graphQLErrors.some(e => e.extensions?.code === 'UNAUTHENTICATED');\n        },\n        async refreshAuth() {\n          // Refresh token logic\n        },\n      };\n    }),\n    fetchExchange,\n  ],\n});\n```\n\n## TypeScript\n\nFull type safety with GraphQL types:\n\n```tsx\nimport { createQuery } from '@urql/solid-start';\nimport { gql, type TypedDocumentNode } from '@urql/core';\n\ninterface Todo {\n  id: string;\n  title: string;\n  completed: boolean;\n}\n\ninterface TodosData {\n  todos: Todo[];\n}\n\nconst TodosQuery: TypedDocumentNode<TodosData> = gql`\n  query {\n    todos {\n      id\n      title\n      completed\n    }\n  }\n`;\n\n// Fully typed!\nconst todos = createQuery({ query: TodosQuery });\n//    ^? Accessor<OperationResult<TodosData> | undefined>\n```\n\n## How It Works\n\n`@urql/solid-start` integrates URQL with SolidStart's primitives:\n\n- **`createQuery`** wraps SolidStart's `query()` function to execute URQL queries with automatic SSR and caching. The `query` function is automatically retrieved from the URQL context, eliminating the need for manual injection.\n- **`createMutation`** creates SolidStart `action()` primitives that integrate with `useAction()` and `useSubmission()` for form handling and progressive enhancement\n- **`createSubscription`** uses `@urql/solid-start` context so it works with the same Provider as queries and mutations\n\nThis means you get:\n\n- ✅ Automatic server-side rendering\n- ✅ Request deduplication via SolidStart's query caching\n- ✅ Streaming responses\n- ✅ Progressive enhancement with actions\n- ✅ Full fine-grained reactivity\n\n## SolidJS vs SolidStart\n\n### When to Use Each Package\n\n| Use Case           | Package             | Why                                                              |\n| ------------------ | ------------------- | ---------------------------------------------------------------- |\n| Client-side SPA    | `@urql/solid`       | Optimized for client-only apps, uses SolidJS reactivity patterns |\n| SolidStart SSR App | `@urql/solid-start` | Integrates with SolidStart's routing, SSR, and action system     |\n\n### Key Differences\n\n#### Queries\n\n**@urql/solid** (Client-side):\n\n```tsx\nimport { createQuery } from '@urql/solid';\n\nconst [result] = createQuery({ query: TodosQuery });\n// Returns: [Accessor<OperationResult>, Accessor<ReExecute>]\n```\n\n**@urql/solid-start** (SSR):\n\n```tsx\nimport { createQuery } from '@urql/solid-start';\nimport { createAsync } from '@solidjs/router';\n\nconst queryTodos = createQuery(TodosQuery, 'todos');\nconst todos = createAsync(() => queryTodos());\n// Returns: Accessor<OperationResult | undefined>\n// Works with SSR and SolidStart's caching\n```\n\n#### Mutations\n\n**@urql/solid** (Client-side):\n\n```tsx\nimport { createMutation } from '@urql/solid';\n\nconst [result, executeMutation] = createMutation(AddTodoMutation);\nawait executeMutation({ title: 'New Todo' });\n// Returns: [Accessor<OperationResult>, ExecuteMutation]\n```\n\n**@urql/solid-start** (SSR with Actions):\n\n```tsx\nimport { createMutation } from '@urql/solid-start';\nimport { useAction, useSubmission } from '@solidjs/router';\n\nconst addTodoAction = createMutation(AddTodoMutation, 'add-todo');\nconst addTodo = useAction(addTodoAction);\nconst submission = useSubmission(addTodoAction);\nawait addTodo({ title: 'New Todo' });\n// Integrates with SolidStart's action system for progressive enhancement\n```\n\n### Why Different APIs?\n\n- **SSR Support**: SolidStart queries run on the server and stream to the client\n- **Router Integration**: Automatic caching and invalidation with SolidStart's router\n- **Progressive Enhancement**: Actions work without JavaScript enabled\n- **Suspense**: Native support for SolidJS Suspense boundaries\n\n### Migration\n\nIf you're moving from a SolidJS SPA to SolidStart:\n\n1. Change imports from `@urql/solid` to `@urql/solid-start`\n2. Wrap queries with `createAsync()`\n3. Update mutations to use the action pattern with `useAction()` and `useSubmission()`\n\n## Resources\n\n- [SolidStart Documentation](https://start.solidjs.com/)\n- [URQL Documentation](https://formidable.com/open-source/urql/docs/)\n- [Solid Primitives](https://primitives.solidjs.community/)\n\n## License\n\nMIT\n","isInternal":false,"tokens":3772,"sizeBytes":15694},{"name":"README.md","path":"packages/solid-urql/README.md","rawUrl":"https://raw.githubusercontent.com/urql-graphql/urql/HEAD/packages/solid-urql/README.md","title":"solid-urql Documentation","category":"plugin-manifest","format":"markdown","content":"# @urql/solid\n\nA highly customizable and versatile GraphQL client for SolidJS.\n\n> **Note:** This package is for client-side SolidJS applications. If you're building a SolidStart application with SSR, use [`@urql/solid-start`](../solid-start-urql) instead. See the [comparison section](../solid-start-urql#solidjs-vs-solidstart) in the SolidStart package for key differences.\n\n## Installation\n\n```bash\nnpm install @urql/solid @urql/core graphql\n# or\npnpm add @urql/solid @urql/core graphql\n# or\nyarn add @urql/solid @urql/core graphql\n```\n\n## Documentation\n\nFull documentation is available at [formidable.com/open-source/urql/docs/](https://formidable.com/open-source/urql/docs/).\n\n## Quick Start\n\n```tsx\nimport { createClient, Provider, createQuery } from '@urql/solid';\nimport { cacheExchange, fetchExchange } from '@urql/core';\nimport { gql } from '@urql/core';\n\nconst client = createClient({\n  url: 'https://api.example.com/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n\nconst TodosQuery = gql`\n  query {\n    todos {\n      id\n      title\n    }\n  }\n`;\n\nfunction App() {\n  return (\n    <Provider value={client}>\n      <TodoList />\n    </Provider>\n  );\n}\n\nfunction TodoList() {\n  const [result] = createQuery({ query: TodosQuery });\n\n  return (\n    <div>\n      {result().data?.todos.map(todo => (\n        <div>{todo.title}</div>\n      ))}\n    </div>\n  );\n}\n```\n\n## When to Use @urql/solid vs @urql/solid-start\n\n| Use Case | Package |\n|----------|---------|\n| Client-side SPA | `@urql/solid` |\n| SolidStart with SSR | `@urql/solid-start` |\n\nFor a detailed comparison of the APIs and when to use each package, see the [SolidJS vs SolidStart comparison](../solid-start-urql#solidjs-vs-solidstart) in the `@urql/solid-start` documentation.\n\n## License\n\nMIT\n","isInternal":false,"tokens":469,"sizeBytes":1766},{"name":"README.md","path":"packages/storage-rn/README.md","rawUrl":"https://raw.githubusercontent.com/urql-graphql/urql/HEAD/packages/storage-rn/README.md","title":"storage-rn Documentation","category":"plugin-manifest","format":"markdown","content":"# @urql/storage-rn\n\n`@urql/storage-rn` is a Graphcache offline storage for React Native.\n\nIt is compatible for both plain React Native and Expo apps (including managed workflow), but it has a two peer dependencies - [Async Storage](https://react-native-async-storage.github.io/async-storage/) and [NetInfo](https://github.com/react-native-netinfo/react-native-netinfo) - which must be installed separately. AsyncStorage will be used to persist the data, and NetInfo will be used to determine when the app is online and offline.\n\n## Quick Start Guide\n\nInstall NetInfo ([RN](https://github.com/react-native-netinfo/react-native-netinfo) | [Expo](https://docs.expo.dev/versions/latest/sdk/netinfo/)) and AsyncStorage ([RN](https://react-native-async-storage.github.io/async-storage/docs/install) | [Expo](https://docs.expo.dev/versions/v42.0.0/sdk/async-storage/)).\n\nInstall `@urql/storage-rn` alongside `urql` and `@urql/exchange-graphcache`:\n\n```sh\nyarn add @urql/storage-rn\n# or\nnpm install --save @urql/storage-rn\n```\n\nThen add it to the offline exchange:\n\n```js\nimport { createClient, fetchExchange } from 'urql';\nimport { offlineExchange } from '@urql/exchange-graphcache';\nimport { makeAsyncStorage } from '@urql/storage-rn';\n\nconst storage = makeAsyncStorage({\n  dataKey: 'graphcache-data', // The AsyncStorage key used for the data (defaults to graphcache-data)\n  metadataKey: 'graphcache-metadata', // The AsyncStorage key used for the metadata (defaults to graphcache-metadata)\n  maxAge: 7, // How long to persist the data in storage (defaults to 7 days)\n});\n\nconst cache = offlineExchange({\n  schema,\n  storage,\n  updates: {\n    /* ... */\n  },\n  optimistic: {\n    /* ... */\n  },\n});\n\nconst client = createClient({\n  url: 'http://localhost:3000/graphql',\n  exchanges: [cache, fetchExchange],\n});\n```\n","isInternal":false,"tokens":454,"sizeBytes":1808},{"name":"README.md","path":"packages/svelte-urql/README.md","rawUrl":"https://raw.githubusercontent.com/urql-graphql/urql/HEAD/packages/svelte-urql/README.md","title":"svelte-urql Documentation","category":"plugin-manifest","format":"markdown","content":"# @urql/svelte\n\n> A highly customizable and versatile GraphQL client **for Svelte**\n\nMore documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).\n","isInternal":false,"tokens":47,"sizeBytes":197},{"name":"README.md","path":"packages/vue-urql/README.md","rawUrl":"https://raw.githubusercontent.com/urql-graphql/urql/HEAD/packages/vue-urql/README.md","title":"vue-urql Documentation","category":"plugin-manifest","format":"markdown","content":"<div align=\"center\">\n  <br />\n  <br />\n  <a href=\"https://www.npmjs.com/package/@urql/vue\">\n    <img alt=\"Npm version\" src=\"https://badgen.net/npm/v/@urql/vue\" />\n  </a>\n  <a href=\"https://bundlephobia.com/result?p=@urql/vue\">\n    <img alt=\"Minified gzip size\" src=\"https://img.shields.io/bundlephobia/minzip/@urql/vue.svg?label=gzip%20size\" />\n  </a>\n  <a href=\"https://github.com/urql-graphql/urql/discussions\">\n    <img alt=\"GitHub Discussions: Chat With Us\" src=\"https://badgen.net/badge/discussions/chat%20with%20us/purple\" />\n  </a>\n  <br />\n  <br />\n</div>\n\n## Installation\n\n```sh\nyarn add @urql/vue graphql\n# or\nnpm install --save @urql/vue graphql\n```\n\n> **Note:** `@urql/vue` has a peer dependency on `vue@^3.0.0` (Not v2) and doesn't currently plan to\n> be backwards compatible to Vue 2.\n","isInternal":false,"tokens":264,"sizeBytes":799}],"systemPromptSnippet":"<yakaai_skills repo=\"urql-graphql/urql\">\n<!-- File: docs/architecture.md (Tokens: ~3005 | Category: project-spec) -->\n---\ntitle: Architecture\norder: 3\n---\n\n# Architecture\n\n`urql` is a highly customizable and flexible GraphQL client.\nAs you use it in your app, it's split into three parts:\n\n- Bindings — such as for React, Preact, Vue, or Svelte — which interact with `@urql/core`'s\n  `Client`.\n- The Client — as created [with the core `@urql/core` package](./basics/core.md), which interacts with \"exchanges\" to execute GraphQL\n  operations, and which you can also use directly.\n- Exchanges, which provide functionality like fetching or caching to the `Client`.\n\nBy default, `urql` aims to provide the minimal amount of features that allow us to build an app\nquickly. However, `urql` has also been designed to be a GraphQL Client\nthat grows with our usage and demands. As we go from building our smallest or first GraphQL apps to\nutilising its full functionality, we have tools at our disposal to extend and customize `urql` to\nour liking.\n\n## Using GraphQL Clients\n\nYou may have worked with a GraphQL API previously and noticed that using GraphQL in your app can be\nas straightforward as sending a plain HTTP request with your query to fetch some data.\n\nGraphQL also provides an opportunity to abstract away a lot of the manual work that goes with\nsending these queries and managing the data. Ultimately, this lets you focus on building\nyour app without having to handle the technical details of state management in detail.\n\nSpecifically, `urql` simplifies three common aspects of using GraphQL:\n\n- Sending queries and mutations and receiving results _declaratively_\n- Abstracting _caching_ and state management internally\n- Providing a central point of _extensibility_ and integration with your API\n\nIn the following sections we'll talk about the way that `urql` solves these three problems and how the logic is abstracted away internally.\n\n## Requests and Operations on the Client\n\nIf `urql` was a train it would take several stops to arrive at its terminus, our API. It starts with us\ndefining queries or mutations by writing in GraphQL's query language.\n\nAny GraphQL request can be abstracted into its query documents and its variables.\n\n```js\nimport { gql } from '@urql/core';\n\nconst query = gql`\n  query ($name: String!) {\n    helloWorld(name: $name)\n  }\n`;\n\nconst request = createRequest(query, {\n  name: 'Urkel',\n});\n```\n\nIn `urql`, these GraphQL requests are treated as unique objects and each GraphQL request will have\na `key` generated for them. This `key` is a hash of the query document and the variables you provide\nand are set on the `key` property of a [`GraphQLRequest`](./api/core.md#graphqlrequest).\n\nWhenever we decide to send our GraphQL requests to a GraphQL API we start by using `urql`'s\n[`Client`](./api/core.md#client).\nThe `Client` accepts several options to configure its behaviour and the behaviour of exchanges,\nlike the `fetchExchange`. For instance, we can pass it a `url` which the `fetchExchange` will\nuse to make a `fetch` call to our GraphQL API.\n\n```js\nimport { Client, cacheExchange, fetchExchange } from '@urql/core';\n\nconst client = new Client({\n  url: 'http://localhost:3000/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n```\n\nAbove, we're defining a `Client` that is ready to accept our requests. It will apply basic\ndocument caching and will send uncached requests to the `url` we pass it.\nThe bindings that we've seen in [the \"Basics\" section](./basics/README.md), like `useQuery` for\nReact for example, interact with [the `Client`](./api/core.md#client) directly and are a thin\nabstraction.\n\nSome methods can be called on it directly however, as seen [on the \"Core Usage\"\npage](./basics/core.md#one-off-queries-and-mutations).\n\n```js\n// Given our request and client defined above, we can call\nconst subscription = client.executeQuery(request).subscribe(result => {\n  console.log(result.data);\n});\n```\n\nAs we've seen, `urql` defines our query documents and variables as\n[`GraphQLRequest`s](./api/core.md#graphqlrequest). However, since we have more metadata that is\nneeded, like our `url` option on the `Client`, `urql` internally creates [`Operation`s](./api/core.md#operation)\neach time a request is executed. The operations are then forwarded to the exchanges, like the\n`cacheExchange` and `fetchExchange`.\n\nAn \"Operation\" is an extension of `GraphQLRequest`s. Not only do they carry the `query`, `variables`,\nand a `key` property, they will also identify the `kind` of operation that is executed, like\n`\"query\"` or `\"mutation\"`, and they contain the `Client`'s options on `operation.context`.\n\n![Operations and Results](./assets/urql-event-hub.png)\n\nThis means, once we hand over a GraphQL request to the `Client`, it will create an `Operation`,\nand then hand it over to the exchanges until a result comes back.\n\nAs shown in the diagram, each operation is like an event or signal for a GraphQL request to start,\nand the exchanges will eventually send back a corresponding result.\nHowever, because the cache can send updates to us whenever it detects a change, or you could cancel\na GraphQL request before it finishes, a special \"teardown\" `Operation` also exists, which cancels\nongoing requests.\n\n## The Client and Exchanges\n\nTo reiterate, when we use `urql`'s bindings for our framework of choice, methods are called on the\n`Client`, but we never see the operations that are created in the background from our bindings. We\ncall a method like `client.executeQuery` (or it's called for us in the bindings), an operation is\nissued internally when we subscribe with a callback, and later, we're given results.\n\n![Operations stream and results stream](./assets/urql-client-architecture.png)\n\nWhile we know that, for us, we're only interested in a single [`Operation`](./api/core.md#operation)\nand its [`OperationResult`s](./api/core.md#operationresult) at a time, the `Client` treats these as\none big stream. The `Client` sees an incoming flow of all of our operations.\n\nAs we've learned before, each operation carries a `key` and each result we receive carries the\noriginal `operation`. Because an `OperationResult` also carries an `operation` property the `Client`\nwill always know which results correspond to an individual operation.\nHowever, internally, all of our operations are processed at the same time concurrently. However, from\nour perspective:\n\n- We subscribe to a \"stream\" and expect to get results on a callback\n- The `Client` issues the operation, and we'll receive some results back eventually as either the\n  cache responds (synchronously), or the request gets sent to our API.\n- We eventually unsubscribe, and the `Client` issues a \"teardown\" operation with the same `key` as\n  the original operation, which concludes our flow.\n\nThe `Client` itself doesn't actually know what to do with operations. Instead, it sends them through\n\"exchanges\". Exchanges are akin to [middleware in Redux](https://redux.js.org/advanced/middleware)\nand have access to all operations and all results. Multiple exchanges are chained to process our\noperations and to execute logic on them, one of them being the `fetchExchange`, which as the name\nimplies sends our requests to our API.\n\n### How operations get to exchanges\n\nWe now know how we get to operations and to the `Client`:\n\n- Any bindings or calls to the `Client` create an **operation**\n- This operation identifies itself as either a `\"query\"`, `\"mutation\"` or `\"subscription\"` and has a\n  unique `key`.\n- This operation is sent into the **exchanges** and eventually ends up at the `fetchExchange`\n  (or a similar exchange)\n- The operation is sent to the API and a **result** comes back, which is wrapped in an `OperationResult`\n- The `Client` filters the `OperationResult` by the `operation.key` and — via a callback — gives us\n  a **stream of results**.\n\nTo come back to our train analogy from earlier, an operation, like a train, travels from one end\nof the track to the terminus — our API. The results then come back on the same path as they're just\ntravelling the same line in reverse.\n\n### The Exchanges\n\nBy default, the `Client` doesn't do anything with GraphQL requests. It contains only the logic to\nmanage and differentiate between active and inactive requests and converts them to operations.\nTo actually do something with our GraphQL requests, it needs _exchanges_, which are like plugins\nthat you can pass to create a pipeline of how GraphQL operations are executed.\n\nBy default, you may want to add the `cacheExchange` and the `fetchExchange` from `@urql/core`:\n\n- `cacheExchange`: Caches GraphQL results with [\"Document Caching\"](./basics/document-caching.md)\n- `fetchExchange`: Executes GraphQL requests with a `fetch` HTTP call\n\n```js\nimport { Client, cacheExchange, fetchExchange } from '@urql/core';\n\nconst client = new Client({\n  url: 'http://localhost:3000/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n```\n\nAs we can tell, exchanges define not only how GraphQL requests are executed and handled, but also\nget control over caching. Exchanges can be used to change almost any behaviour in the `Client`,\nalthough internally they only handle incoming & outgoing requests and incoming & outgoing results.\n\nSome more exchanges that we can use with our `Client` are:\n\n- [`mapExchange`](./api/core.md#mapexchange): Allows changing and reacting to operations, results, and errors\n- [`ssrExchange`](./advanced/server-side-rendering.md): Allows for a server-side renderer to\n  collect results for client-side rehydration.\n- [`retryExchange`](./advanced/retry-operations.md): Allows operations to be retried on errors\n- [`persistedExchange`](./advanced/persistence-and-uploads.md#automatic-persisted-queries): Provides support for Automatic\n  Persisted Queries\n- [`authExchange`](./advanced/authentication.md): Allows refresh authentication to be implemented easily.\n- [`requestPolicyExchange`](./api/request-policy-exchange.md): Automatically refreshes results given a TTL.\n- `devtoolsExchange`: Provides the ability to use the [urql-devtools](https://github.com/urql-graphql/urql-devtools)\n\nWe can even swap out our [document cache](./basics/document-caching.md), which is implemented by\n`@urql/core`'s `cacheExchange`, with `urql`'s [normalized cache,\nGraphcache](./graphcache/README.md).\n\n[Read more about exchanges and how to write them from scratch on the \"Authoring Exchanges\"\npage.](./advanced/authoring-exchanges.md)\n\n## Stream Patterns in `urql`\n\nIn the previous sections we've learned a lot about how the `Client` works, but we've always learned\nit in vague terms — for instance, we've learned that we get a \"stream of results\" or `urql` sees all\noperations as \"one stream of operations\" that it sends to the exchanges.\nBut, **what are streams?**\n\nGenerally we refer to _streams_ as abstractions that allow us to program with asynchronous events\nover time. Within the context of JavaScript we're specifically thinking in terms of\n[Observables](https://github.com/tc39/proposal-observable)\nand [Reactive Programming with Observables.](http://reactivex.io/documentation/observable.html)\nThese concepts may sound intimidating, but from a high-level view what we're talking about can be\nthought of as a combination of promises and iterables (e.g. arrays). We're dealing with multiple\nevents, but our callback is called over time. It's like calling `forEach` on an array but expecting\nthe results to come in asynchronously.\n\nAs a user, if we're using the one framework bindings that we've seen in [the \"Basics\"\nsection](./basics/README.md), we may never see these streams in action or may never use them even,\nsince the bindings internally use them for us. But if we [use the `Client`\ndirectly](./basics/core.md#one-off-queries-and-mutations) or write exchanges then we'll see streams\nand will have to deal with their API.\n\n### Stream patterns with the client\n\nWhen we call methods on the `Client` like [`client.executeQuery`](./api/core.md#clientexecutequery)\nor [`client.query`](./api/core.md#clientquery) then these will return a \"stream\" of results.\n\nIt's normal for GraphQL subscriptions to deliver multiple results, however, even GraphQL queries can\ngive you multiple results in `urql`. This is because operations influence one another. When a cache\ninvalidates a query, this query may refetch, and a new result is delivered to your application.\n\nMultiple results mean that once you subscribe to a GraphQL query via the `Client`, you may receive\nnew results in the future.\n\n```js\nimport { gql } from '@urql/core';\n\nconst QUERY = gql`\n  query Test($id: ID!) {\n    getUser(id: $id) {\n      id\n      name\n    }\n  }\n`;\n\nclient.query(QUERY, { id: 'test' }).subscribe(result => {\n  console.log(result); // { data: ... }\n});\n```\n\nRead more about the available APIs on the `Client` in the [Core API docs](./api/core.md).\n\nInternally, these streams and all exchanges are written using a library called\n[`wonka`](https://wonka.kitten.sh/basics/background), which is a tiny Observable-like\nlibrary. It is used to write exchanges and when we interact with the `Client` it is used internally\nas well.\n\n<!-- File: packages/core/README.md (Tokens: ~49 | Category: plugin-manifest) -->\n# @urql/core\n\n> The shared core for the highly customizable and versatile GraphQL client, urql\n\nMore documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).\n\n<!-- File: packages/introspection/README.md (Tokens: ~39 | Category: plugin-manifest) -->\n<h2 align=\"center\">@urql/introspection</h2>\n\n<p align=\"center\"><strong>Utilities for dealing with Introspection Queries and Client Schemas</strong></p>\n\n<!-- File: packages/next-urql/README.md (Tokens: ~68 | Category: plugin-manifest) -->\n## `next-urql`\n\nA set of convenience utilities for using `urql` with Next.js.\n\nMore documentation is available at https://urql.dev/goto/docs/advanced/server-side-rendering/#nextjs\nExamples can be found at https://github.com/urql-graphql/urql/tree/main/examples/with-next\n\n<!-- File: packages/preact-urql/README.md (Tokens: ~422 | Category: plugin-manifest) -->\n<div align=\"center\">\n  <br />\n  <br />\n  <a href=\"https://www.npmjs.com/package/@urql/preact\">\n    <img alt=\"Npm version\" src=\"https://badgen.net/npm/v/@urql/preact\" />\n  </a>\n  <a href=\"https://bundlephobia.com/result?p=@urql/preact\">\n    <img alt=\"Minified gzip size\" src=\"https://img.shields.io/bundlephobia/minzip/@urql/preact.svg?label=gzip%20size\" />\n  </a>\n  <a href=\"https://github.com/urql-graphql/urql/discussions\">\n    <img alt=\"GitHub Discussions: Chat With Us\" src=\"https://badgen.net/badge/discussions/chat%20with%20us/purple\" />\n  </a>\n  <br />\n  <br />\n</div>\n\n## Installation\n\n```sh\nyarn add @urql/preact urql graphql\n# or\nnpm install --save @urql/preact urql graphql\n```\n\n## Usage\n\nThe usage is a 1:1 mapping of the React usage found [here](https://formidable.com/open-source/urql/docs)\n\nsmall example:\n\n```jsx\nimport { createClient, cacheExchange, fetchExchange, Provider, useQuery } from '@urql/preact';\n\nconst client = createClient({\n  url: 'https://myHost/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n\nconst App = () => (\n  <Provider value={client}>\n    <Dogs />\n  </Provider>\n);\n\nconst Dogs = () => {\n  const [result] = useQuery({\n    query: `{ dogs { id name } }`,\n  });\n\n  if (result.fetching) return <p>Loading...</p>;\n  if (result.error) return <p>Oh no...</p>;\n\n  return result.data.dogs.map(dog => <p>{dog.name} is a good boy!</p>);\n};\n```\n\n<!-- File: packages/react-urql/README.md (Tokens: ~43 | Category: plugin-manifest) -->\n# urql\n\n> A highly customizable and versatile GraphQL client **for React**\n\nMore documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).\n\n<!-- File: packages/solid-start-urql/README.md (Tokens: ~3772 | Category: plugin-manifest) -->\n# @urql/solid-start\n\n`@urql/solid-start` provides URQL integration for [SolidStart](https://start.solidjs.com/), built with SolidStart's native primitives like `query`, `action`, and `createAsync`.\n\n> **Note:** This package is specifically designed for SolidStart applications with SSR. If you're building a client-side only SolidJS app, use [`@urql/solid`](https://github.com/urql-graphql/urql/tree/main/packages/solid-urql) instead. See [SolidJS vs SolidStart](#solidjs-vs-solidstart) for key differences.\n\n## Features\n\n- 🎯 **SolidStart Native** - Built with `query`, `action`, `createAsync`, and `useAction`\n- 🚀 **Automatic SSR** - Works seamlessly with SolidStart's server-side rendering\n- 🔄 **Reactive Variables** - Query variables can be signals that automatically trigger re-execution\n- 📡 **Real-time Subscriptions** - Full GraphQL subscription support\n- 🎨 **Type Safe** - Complete TypeScript support with GraphQL types\n- 🪶 **Lightweight** - Minimal wrapper over URQL core\n\n## Installation\n\n```bash\nnpm install @urql/solid-start @urql/solid @urql/core graphql\n# or\npnpm add @urql/solid-start @urql/solid @urql/core graphql\n# or\nyarn add @urql/solid-start @urql/solid @urql/core graphql\n```\n\n> **Note:** `@urql/solid` is a peer dependency required for subscriptions.\n\n## Quick Start\n\n### 1. Set up the Provider\n\nWrap your app with the `Provider` to make the URQL client and router primitives available:\n\n```tsx\n// src/app.tsx\nimport { Router, action, query } from '@solidjs/router';\nimport { FileRoutes } from '@solidjs/start/router';\nimport { Provider } from '@urql/solid-start';\nimport { createClient, cacheExchange, fetchExchange } from '@urql/core';\n\nconst client = createClient({\n  url: 'https://api.example.com/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n\nexport default function App() {\n  return (\n    <Router root={props => <Provider value={{ client, query, action }}>{props.children}</Provider>}>\n      <FileRoutes />\n    </Router>\n  );\n}\n```\n\n> **Note:** The Provider accepts `client`, `query`, and `action` so `createQuery` and `createMutation` can use SolidStart APIs via context.\n\n### 2. Use Queries\n\n```tsx\n// src/routes/todos.tsx\nimport { createQuery } from '@urql/solid-start';\nimport { createAsync } from '@solidjs/router';\nimport { gql } from '@urql/core';\nimport { For, Show, Suspense } from 'solid-js';\n\nconst TodosQuery = gql`\n  query {\n    todos {\n      id\n      title\n      completed\n    }\n  }\n`;\n\nexport default function TodosPage() {\n  const queryTodos = createQuery(TodosQuery, 'todos-list');\n  const todos = createAsync(() => queryTodos());\n\n  return (\n    <div>\n      <h1>Todos</h1>\n      <Suspense fallback={<div>Loading...</div>}>\n        <Show when={todos()?.data}>\n          <ul>\n            <For each={todos()!.data.todos}>\n              {todo => (\n                <li>\n                  <input type=\"checkbox\" checked={todo.completed} />\n                  {todo.title}\n                </li>\n              )}\n            </For>\n          </ul>\n        </Show>\n        <Show when={todos()?.error}>\n          <p>Error: {todos()!.error.message}</p>\n        </Show>\n      </Suspense>\n    </div>\n  );\n}\n```\n\n### 3. Use Mutations\n\n```tsx\n// src/components/AddTodoForm.tsx\nimport { createMutation } from '@urql/solid-start';\nimport { useAction, useSubmission } from '@solidjs/router';\nimport { gql } from '@urql/core';\nimport { Show } from 'solid-js';\n\nconst AddTodoMutation = gql`\n  mutation AddTodo($title: String!) {\n    addTodo(title: $title) {\n      id\n      title\n    }\n  }\n`;\n\nexport function AddTodoForm() {\n  const addTodoAction = createMutation(AddTodoMutation, 'add-todo');\n  const addTodo = useAction(addTodoAction);\n  const submission = useSubmission(addTodoAction);\n\n  let inputRef: HTMLInputElement | undefined;\n\n  const handleSubmit = async (e: Event) => {\n    e.preventDefault();\n    if (!inputRef?.value) return;\n\n    const result = await addTodo({ title: inputRef.value });\n    if (result.data) {\n      inputRef.value = '';\n    }\n  };\n\n  return (\n    <form onSubmit={handleSubmit}>\n      <input ref={inputRef} type=\"text\" placeholder=\"New todo\" />\n      <button type=\"submit\" disabled={submission.pending}>\n        Add Todo\n      </button>\n      <Show when={submission.result?.error}>\n        <p>Error: {submission.result!.error.message}</p>\n      </Show>\n    </form>\n  );\n}\n```\n\n### 4. Use Subscriptions\n\n```tsx\n// src/components/LiveMessages.tsx\nimport { createSubscription } from '@urql/solid-start';\nimport { gql } from '@urql/core';\nimport { For } from 'solid-js';\n\nconst MessagesSubscription = gql`\n  subscription {\n    messageAdded {\n      id\n      text\n      createdAt\n    }\n  }\n`;\n\nexport function LiveMessages() {\n  const [messages] = createSubscription(\n    { query: MessagesSubscription },\n    // Optional handler to accumulate messages\n    (prev = [], data) => [...prev, data.messageAdded]\n  );\n\n  return (\n    <div>\n      <h2>Live Messages</h2>\n      <For each={messages.data}>{msg => <div>{msg.text}</div>}</For>\n    </div>\n  );\n}\n```\n\n## API Reference\n\n### `createQuery(queryDocument, key, options?)`\n\nCreates a GraphQL query using SolidStart's `query` and `createAsync` primitives. The `query` function is automatically retrieved from context.\n\n**Parameters:**\n\n- `queryDocument: DocumentInput` - GraphQL query document\n- `key: string` - Cache key for SolidStart's router\n- `options?: object` - Optional configuration\n  - `variables?: Variables` - Query variables\n  - `requestPolicy?: RequestPolicy` - Cache policy\n  - `context?: Partial<OperationContext>` - Additional context\n\n**Returns:** A query function that can be used with `createAsync`\n\n**Basic Example:**\n\n```tsx\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\n\nexport default function TodosPage() {\n  const queryTodos = createQuery(TodosQuery, 'todos-list');\n  const todos = createAsync(() => queryTodos());\n\n  return <div>{/* ... */}</div>;\n}\n```\n\n**Example with variables:**\n\n```tsx\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\n\nexport default function UserPage() {\n  const queryUser = createQuery(UserQuery, 'user-details', {\n    variables: { id: 1 },\n  });\n  const user = createAsync(() => queryUser());\n\n  return <div>{/* ... */}</div>;\n}\n```\n\n**Example with custom client:**\n\n```tsx\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\nimport { createClient } from '@urql/core';\n\nconst customClient = createClient({ url: 'https://api.example.com/graphql' });\n\nexport default function CustomPage() {\n  const queryTodos = createQuery(TodosQuery, 'todos-list');\n  const todos = createAsync(() => queryTodos(customClient));\n\n  return <div>{/* ... */}</div>;\n}\n```\n\n> **Note:** `createQuery` must be called inside a component where it has access to the URQL context. The query function from `@solidjs/router` is automatically retrieved from the Provider.\n\n### `createMutation(mutation, key)`\n\nCreates a GraphQL mutation action using SolidStart's `action` primitive.\n\n**Args:**\n\n- `mutation: DocumentInput` - GraphQL mutation document\n- `key: string` - Cache key for SolidStart's router\n\n**Returns:** `Action` - A SolidStart action that can be used with `useAction()` and `useSubmission()`\n\n**Example:**\n\n```tsx\nimport { createMutation } from '@urql/solid-start';\nimport { useAction, useSubmission } from '@solidjs/router';\n\nconst updateUserAction = createMutation(UpdateUserMutation, 'update-user');\nconst updateUser = useAction(updateUserAction);\nconst submission = useSubmission(updateUserAction);\n\n// Call the mutation\nconst result = await updateUser({ id: 1, name: 'Alice' });\n\n// Access submission state\nconsole.log(submission.pending); // boolean\nconsole.log(submission.result); // OperationResult\n```\n\n### `createSubscription(args, handler?)`\n\nCreates a GraphQL subscription for real-time updates.\n\n**Args:**\n\n```ts\n{\n  query: DocumentInput;\n  variables?: MaybeAccessor<Variables>;\n  context?: MaybeAccessor<Partial<OperationContext>>;\n  pause?: MaybeAccessor<boolean>;\n}\n```\n\n**Handler:** Optional function to accumulate/transform subscription data\n\n```ts\n(previousData: Data | undefined, newData: Data) => Data;\n```\n\n**Returns:** `[State, ExecuteFunction]`\n\n**Example with handler:**\n\n```tsx\nconst [messages] = createSubscription({ query: MessagesSubscription }, (prev = [], data) => [\n  ...prev,\n  data.messageAdded,\n]);\n```\n\n### `Provider`\n\nContext provider for the URQL client and SolidStart router primitives.\n\n**Props:**\n\n- `value: { client: Client; query: typeof query; action: typeof action }` - Object containing the URQL client and SolidStart router primitives\n\n**Example:**\n\n```tsx\nimport { action, query } from '@solidjs/router';\nimport { Provider } from '@urql/solid-start';\n\n<Provider value={{ client, query, action }}>\n  <App />\n</Provider>;\n```\n\n### `useClient()`\n\nHook to access the URQL client from context.\n\n**Returns:** `Client`\n\n## Request Policies\n\nControl caching behavior with `requestPolicy`:\n\n- `cache-first` (default) - Use cache if available, otherwise fetch\n- `cache-only` - Only use cached data, never fetch\n- `network-only` - Always fetch, ignore cache\n- `cache-and-network` - Return cache immediately, then fetch in background\n\n```tsx\nconst todos = createQuery({\n  query: TodosQuery,\n  requestPolicy: 'cache-and-network',\n});\n```\n\n## Dynamic Queries\n\nFor dynamic queries that change based on reactive values, you can pass variables to the query function:\n\n```tsx\nimport { createSignal } from 'solid-js';\nimport { createAsync } from '@solidjs/router';\nimport { createQuery } from '@urql/solid-start';\n\nexport default function UserPage() {\n  const [userId, setUserId] = createSignal(1);\n\n  // Create the query function\n  const queryUser = createQuery(UserQuery, 'user-details', {\n    variables: { id: userId() },\n  });\n\n  // Wrap with createAsync to get reactive data\n  const user = createAsync(() => queryUser());\n\n  return (\n    <div>\n      <button onClick={() => setUserId(userId() + 1)}>Next User</button>\n      <Show when={user()?.data}>\n        <h1>{user()!.data.user.name}</h1>\n      </Show>\n    </div>\n  );\n}\n```\n\nNote: For fully reactive variables that trigger re-fetches, you may need to create the query function inside a `createEffect` or recreate it when dependencies change.\n\n## Cache Keys\n\nCache keys are required for both queries and mutations to enable SolidStart's caching and revalidation features:\n\n```tsx\n// Query with cache key\nconst queryTodos = createQuery(TodosQuery, 'todos-list', query);\n\n// Mutation with cache key\nconst [state, addTodo] = createMutation(AddTodoMutation, 'add-todo');\n```\n\nChoose descriptive cache keys that:\n\n- Are unique within your application\n- Describe the data being cached (e.g., 'user-profile', 'todos-list')\n- Make debugging easier by being human-readable\n\n## Advanced: Custom Exchanges\n\nAdd custom exchanges for authentication, error handling, etc:\n\n```tsx\nimport { createClient, cacheExchange, fetchExchange } from '@urql/core';\nimport { authExchange } from '@urql/exchange-auth';\n\nconst client = createClient({\n  url: 'https://api.example.com/graphql',\n  exchanges: [\n    cacheExchange,\n    authExchange(async utils => {\n      return {\n        addAuthToOperation(operation) {\n          const token = localStorage.getItem('token');\n          if (!token) return operation;\n          return utils.appendHeaders(operation, {\n            Authorization: `Bearer ${token}`,\n          });\n        },\n        didAuthError(error) {\n          return error.graphQLErrors.some(e => e.extensions?.code === 'UNAUTHENTICATED');\n        },\n        async refreshAuth() {\n          // Refresh token logic\n        },\n      };\n    }),\n    fetchExchange,\n  ],\n});\n```\n\n## TypeScript\n\nFull type safety with GraphQL types:\n\n```tsx\nimport { createQuery } from '@urql/solid-start';\nimport { gql, type TypedDocumentNode } from '@urql/core';\n\ninterface Todo {\n  id: string;\n  title: string;\n  completed: boolean;\n}\n\ninterface TodosData {\n  todos: Todo[];\n}\n\nconst TodosQuery: TypedDocumentNode<TodosData> = gql`\n  query {\n    todos {\n      id\n      title\n      completed\n    }\n  }\n`;\n\n// Fully typed!\nconst todos = createQuery({ query: TodosQuery });\n//    ^? Accessor<OperationResult<TodosData> | undefined>\n```\n\n## How It Works\n\n`@urql/solid-start` integrates URQL with SolidStart's primitives:\n\n- **`createQuery`** wraps SolidStart's `query()` function to execute URQL queries with automatic SSR and caching. The `query` function is automatically retrieved from the URQL context, eliminating the need for manual injection.\n- **`createMutation`** creates SolidStart `action()` primitives that integrate with `useAction()` and `useSubmission()` for form handling and progressive enhancement\n- **`createSubscription`** uses `@urql/solid-start` context so it works with the same Provider as queries and mutations\n\nThis means you get:\n\n- ✅ Automatic server-side rendering\n- ✅ Request deduplication via SolidStart's query caching\n- ✅ Streaming responses\n- ✅ Progressive enhancement with actions\n- ✅ Full fine-grained reactivity\n\n## SolidJS vs SolidStart\n\n### When to Use Each Package\n\n| Use Case           | Package             | Why                                                              |\n| ------------------ | ------------------- | ---------------------------------------------------------------- |\n| Client-side SPA    | `@urql/solid`       | Optimized for client-only apps, uses SolidJS reactivity patterns |\n| SolidStart SSR App | `@urql/solid-start` | Integrates with SolidStart's routing, SSR, and action system     |\n\n### Key Differences\n\n#### Queries\n\n**@urql/solid** (Client-side):\n\n```tsx\nimport { createQuery } from '@urql/solid';\n\nconst [result] = createQuery({ query: TodosQuery });\n// Returns: [Accessor<OperationResult>, Accessor<ReExecute>]\n```\n\n**@urql/solid-start** (SSR):\n\n```tsx\nimport { createQuery } from '@urql/solid-start';\nimport { createAsync } from '@solidjs/router';\n\nconst queryTodos = createQuery(TodosQuery, 'todos');\nconst todos = createAsync(() => queryTodos());\n// Returns: Accessor<OperationResult | undefined>\n// Works with SSR and SolidStart's caching\n```\n\n#### Mutations\n\n**@urql/solid** (Client-side):\n\n```tsx\nimport { createMutation } from '@urql/solid';\n\nconst [result, executeMutation] = createMutation(AddTodoMutation);\nawait executeMutation({ title: 'New Todo' });\n// Returns: [Accessor<OperationResult>, ExecuteMutation]\n```\n\n**@urql/solid-start** (SSR with Actions):\n\n```tsx\nimport { createMutation } from '@urql/solid-start';\nimport { useAction, useSubmission } from '@solidjs/router';\n\nconst addTodoAction = createMutation(AddTodoMutation, 'add-todo');\nconst addTodo = useAction(addTodoAction);\nconst submission = useSubmission(addTodoAction);\nawait addTodo({ title: 'New Todo' });\n// Integrates with SolidStart's action system for progressive enhancement\n```\n\n### Why Different APIs?\n\n- **SSR Support**: SolidStart queries run on the server and stream to the client\n- **Router Integration**: Automatic caching and invalidation with SolidStart's router\n- **Progressive Enhancement**: Actions work without JavaScript enabled\n- **Suspense**: Native support for SolidJS Suspense boundaries\n\n### Migration\n\nIf you're moving from a SolidJS SPA to SolidStart:\n\n1. Change imports from `@urql/solid` to `@urql/solid-start`\n2. Wrap queries with `createAsync()`\n3. Update mutations to use the action pattern with `useAction()` and `useSubmission()`\n\n## Resources\n\n- [SolidStart Documentation](https://start.solidjs.com/)\n- [URQL Documentation](https://formidable.com/open-source/urql/docs/)\n- [Solid Primitives](https://primitives.solidjs.community/)\n\n## License\n\nMIT\n\n<!-- File: packages/solid-urql/README.md (Tokens: ~469 | Category: plugin-manifest) -->\n# @urql/solid\n\nA highly customizable and versatile GraphQL client for SolidJS.\n\n> **Note:** This package is for client-side SolidJS applications. If you're building a SolidStart application with SSR, use [`@urql/solid-start`](../solid-start-urql) instead. See the [comparison section](../solid-start-urql#solidjs-vs-solidstart) in the SolidStart package for key differences.\n\n## Installation\n\n```bash\nnpm install @urql/solid @urql/core graphql\n# or\npnpm add @urql/solid @urql/core graphql\n# or\nyarn add @urql/solid @urql/core graphql\n```\n\n## Documentation\n\nFull documentation is available at [formidable.com/open-source/urql/docs/](https://formidable.com/open-source/urql/docs/).\n\n## Quick Start\n\n```tsx\nimport { createClient, Provider, createQuery } from '@urql/solid';\nimport { cacheExchange, fetchExchange } from '@urql/core';\nimport { gql } from '@urql/core';\n\nconst client = createClient({\n  url: 'https://api.example.com/graphql',\n  exchanges: [cacheExchange, fetchExchange],\n});\n\nconst TodosQuery = gql`\n  query {\n    todos {\n      id\n      title\n    }\n  }\n`;\n\nfunction App() {\n  return (\n    <Provider value={client}>\n      <TodoList />\n    </Provider>\n  );\n}\n\nfunction TodoList() {\n  const [result] = createQuery({ query: TodosQuery });\n\n  return (\n    <div>\n      {result().data?.todos.map(todo => (\n        <div>{todo.title}</div>\n      ))}\n    </div>\n  );\n}\n```\n\n## When to Use @urql/solid vs @urql/solid-start\n\n| Use Case | Package |\n|----------|---------|\n| Client-side SPA | `@urql/solid` |\n| SolidStart with SSR | `@urql/solid-start` |\n\nFor a detailed comparison of the APIs and when to use each package, see the [SolidJS vs SolidStart comparison](../solid-start-urql#solidjs-vs-solidstart) in the `@urql/solid-start` documentation.\n\n## License\n\nMIT\n\n<!-- File: packages/storage-rn/README.md (Tokens: ~454 | Category: plugin-manifest) -->\n# @urql/storage-rn\n\n`@urql/storage-rn` is a Graphcache offline storage for React Native.\n\nIt is compatible for both plain React Native and Expo apps (including managed workflow), but it has a two peer dependencies - [Async Storage](https://react-native-async-storage.github.io/async-storage/) and [NetInfo](https://github.com/react-native-netinfo/react-native-netinfo) - which must be installed separately. AsyncStorage will be used to persist the data, and NetInfo will be used to determine when the app is online and offline.\n\n## Quick Start Guide\n\nInstall NetInfo ([RN](https://github.com/react-native-netinfo/react-native-netinfo) | [Expo](https://docs.expo.dev/versions/latest/sdk/netinfo/)) and AsyncStorage ([RN](https://react-native-async-storage.github.io/async-storage/docs/install) | [Expo](https://docs.expo.dev/versions/v42.0.0/sdk/async-storage/)).\n\nInstall `@urql/storage-rn` alongside `urql` and `@urql/exchange-graphcache`:\n\n```sh\nyarn add @urql/storage-rn\n# or\nnpm install --save @urql/storage-rn\n```\n\nThen add it to the offline exchange:\n\n```js\nimport { createClient, fetchExchange } from 'urql';\nimport { offlineExchange } from '@urql/exchange-graphcache';\nimport { makeAsyncStorage } from '@urql/storage-rn';\n\nconst storage = makeAsyncStorage({\n  dataKey: 'graphcache-data', // The AsyncStorage key used for the data (defaults to graphcache-data)\n  metadataKey: 'graphcache-metadata', // The AsyncStorage key used for the metadata (defaults to graphcache-metadata)\n  maxAge: 7, // How long to persist the data in storage (defaults to 7 days)\n});\n\nconst cache = offlineExchange({\n  schema,\n  storage,\n  updates: {\n    /* ... */\n  },\n  optimistic: {\n    /* ... */\n  },\n});\n\nconst client = createClient({\n  url: 'http://localhost:3000/graphql',\n  exchanges: [cache, fetchExchange],\n});\n```\n\n<!-- File: packages/svelte-urql/README.md (Tokens: ~47 | Category: plugin-manifest) -->\n# @urql/svelte\n\n> A highly customizable and versatile GraphQL client **for Svelte**\n\nMore documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).\n\n<!-- File: packages/vue-urql/README.md (Tokens: ~264 | Category: plugin-manifest) -->\n<div align=\"center\">\n  <br />\n  <br />\n  <a href=\"https://www.npmjs.com/package/@urql/vue\">\n    <img alt=\"Npm version\" src=\"https://badgen.net/npm/v/@urql/vue\" />\n  </a>\n  <a href=\"https://bundlephobia.com/result?p=@urql/vue\">\n    <img alt=\"Minified gzip size\" src=\"https://img.shields.io/bundlephobia/minzip/@urql/vue.svg?label=gzip%20size\" />\n  </a>\n  <a href=\"https://github.com/urql-graphql/urql/discussions\">\n    <img alt=\"GitHub Discussions: Chat With Us\" src=\"https://badgen.net/badge/discussions/chat%20with%20us/purple\" />\n  </a>\n  <br />\n  <br />\n</div>\n\n## Installation\n\n```sh\nyarn add @urql/vue graphql\n# or\nnpm install --save @urql/vue graphql\n```\n\n> **Note:** `@urql/vue` has a peer dependency on `vue@^3.0.0` (Not v2) and doesn't currently plan to\n> be backwards compatible to Vue 2.\n</yakaai_skills>"}