├── .changeset
├── README.md
├── config.json
├── heavy-hairs-bow.md
├── nervous-flies-confess.md
├── old-ears-hunt.md
├── serious-chefs-march.md
└── slow-hotels-yawn.md
├── .editorconfig
├── .gitattributes
├── .github
├── CODEOWNERS
├── ISSUE_TEMPLATE
│ ├── RFC.md
│ ├── bug_report.yaml
│ └── config.yml
├── PULL_REQUEST_TEMPLATE.md
├── actions
│ ├── discord-message
│ │ ├── action.mjs
│ │ └── action.yml
│ └── pnpm-run
│ │ ├── action.mjs
│ │ └── action.yml
└── workflows
│ ├── ci.yml
│ └── release.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── docs
├── README.md
├── advanced
│ ├── README.md
│ ├── authentication.md
│ ├── authoring-exchanges.md
│ ├── auto-populate-mutations.md
│ ├── debugging.md
│ ├── persistence-and-uploads.md
│ ├── retry-operations.md
│ ├── server-side-rendering.md
│ ├── subscriptions.md
│ └── testing.md
├── api
│ ├── README.md
│ ├── auth-exchange.md
│ ├── core.md
│ ├── execute-exchange.md
│ ├── graphcache.md
│ ├── preact.md
│ ├── refocus-exchange.md
│ ├── request-policy-exchange.md
│ ├── retry-exchange.md
│ ├── svelte.md
│ ├── urql.md
│ └── vue.md
├── architecture.md
├── assets
│ ├── commutative-layers.png
│ ├── devtools-timeline.png
│ ├── logos
│ │ ├── egghead.png
│ │ ├── gatsby.png
│ │ ├── github.png
│ │ ├── loveholidays.png
│ │ ├── open-social.png
│ │ ├── sturdy.png
│ │ ├── swan.png
│ │ ├── the-atlantic.png
│ │ └── tripadvisor.png
│ ├── next-logo.png
│ ├── partial-results.png
│ ├── query-document-info.png
│ ├── urql-client-architecture.png
│ ├── urql-combined-error.png
│ ├── urql-document-caching.png
│ ├── urql-event-hub.png
│ ├── urql-exchanges.png
│ ├── urql-normalized-cache.png
│ ├── urql-operation-keys.png
│ ├── urql-signals.png
│ └── urql-spoiler.png
├── basics
│ ├── README.md
│ ├── core.md
│ ├── document-caching.md
│ ├── errors.md
│ ├── react-preact.md
│ ├── svelte.md
│ ├── typescript-integration.md
│ ├── ui-patterns.md
│ └── vue.md
├── comparison.md
├── graphcache
│ ├── README.md
│ ├── cache-updates.md
│ ├── errors.md
│ ├── local-directives.md
│ ├── local-resolvers.md
│ ├── normalized-caching.md
│ ├── offline.md
│ └── schema-awareness.md
└── showcase.md
├── examples
├── README.md
├── pnpm-workspace.yaml
├── with-apq
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.jsx
│ │ ├── LocationsList.jsx
│ │ └── index.jsx
│ └── vite.config.js
├── with-defer-stream-directives
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── server
│ │ ├── apollo-server.js
│ │ ├── graphql-yoga.js
│ │ └── schema.js
│ ├── src
│ │ ├── App.jsx
│ │ ├── Songs.jsx
│ │ └── index.jsx
│ └── vite.config.js
├── with-graphcache-pagination
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.jsx
│ │ ├── PaginatedNpmSearch.jsx
│ │ └── index.jsx
│ └── vite.config.js
├── with-graphcache-updates
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.jsx
│ │ ├── client.js
│ │ ├── index.jsx
│ │ └── pages
│ │ │ ├── Links.jsx
│ │ │ └── LoginForm.jsx
│ └── vite.config.js
├── with-infinite-pagination
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.jsx
│ │ ├── SearchResults.jsx
│ │ └── index.jsx
│ └── vite.config.js
├── with-multipart
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.jsx
│ │ ├── FileUpload.jsx
│ │ └── index.jsx
│ └── vite.config.js
├── with-next
│ ├── README.md
│ ├── app
│ │ ├── layout.tsx
│ │ ├── non-rsc
│ │ │ ├── layout.tsx
│ │ │ └── page.tsx
│ │ └── page.tsx
│ ├── next-env.d.ts
│ ├── package.json
│ └── tsconfig.json
├── with-pagination
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.jsx
│ │ ├── PaginatedNpmSearch.jsx
│ │ └── index.jsx
│ └── vite.config.js
├── with-react-native
│ ├── App.js
│ ├── README.md
│ ├── app.json
│ ├── index.js
│ ├── package.json
│ └── src
│ │ └── screens
│ │ └── PokemonList.js
├── with-react
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.jsx
│ │ ├── PokemonList.jsx
│ │ └── index.jsx
│ └── vite.config.js
├── with-refresh-auth
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.jsx
│ │ ├── authStore.js
│ │ ├── client.js
│ │ ├── index.jsx
│ │ └── pages
│ │ │ ├── LoginForm.jsx
│ │ │ └── Profile.jsx
│ └── vite.config.js
├── with-retry
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.jsx
│ │ ├── Color.jsx
│ │ └── index.jsx
│ └── vite.config.js
├── with-subscriptions-via-fetch
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── server
│ │ ├── graphql-yoga.js
│ │ └── schema.js
│ ├── src
│ │ ├── App.jsx
│ │ ├── Songs.jsx
│ │ └── index.jsx
│ └── vite.config.js
├── with-svelte
│ ├── .gitignore
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── src
│ │ ├── App.svelte
│ │ ├── PokemonList.svelte
│ │ └── main.js
│ └── vite.config.mjs
└── with-vue3
│ ├── .gitignore
│ ├── README.md
│ ├── index.html
│ ├── package.json
│ ├── src
│ ├── App.vue
│ ├── PokemonList.vue
│ └── main.js
│ └── vite.config.js
├── exchanges
├── auth
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── authExchange.test.ts
│ │ ├── authExchange.ts
│ │ └── index.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── context
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── context.test.ts
│ │ ├── context.ts
│ │ └── index.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── execute
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── execute.test.ts
│ │ ├── execute.ts
│ │ └── index.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── graphcache
│ ├── .gitignore
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── benchmarks
│ │ ├── 10000Reads.html
│ │ ├── 10000ReadsComplex.html
│ │ ├── 10000Writes.html
│ │ ├── 10000WritesComplex.html
│ │ ├── 1000Reads.html
│ │ ├── 1000ReadsComplex.html
│ │ ├── 1000Writes.html
│ │ ├── 1000WritesComplex.html
│ │ ├── 100Reads.html
│ │ ├── 100ReadsComplex.html
│ │ ├── 100Writes.html
│ │ ├── 100WritesComplex.html
│ │ ├── 50000Reads.html
│ │ ├── 50000Writes.html
│ │ ├── 5000Reads.html
│ │ ├── 5000Writes.html
│ │ ├── 500Reads.html
│ │ ├── 500Writes.html
│ │ ├── addTodo.html
│ │ ├── benchmarks.js
│ │ ├── entities.js
│ │ ├── makeEntries.js
│ │ ├── operations.js
│ │ ├── package.json
│ │ ├── readMe.md
│ │ ├── updateTodo.html
│ │ ├── urqlClient.js
│ │ └── yarn.lock
│ ├── cypress.config.js
│ ├── cypress
│ │ ├── fixtures
│ │ │ └── example.json
│ │ ├── plugins
│ │ │ └── index.js
│ │ └── support
│ │ │ ├── component-index.html
│ │ │ └── component.js
│ ├── e2e-tests
│ │ ├── query.spec.tsx
│ │ └── updates.spec.tsx
│ ├── help.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── ast
│ │ │ ├── graphql.ts
│ │ │ ├── index.ts
│ │ │ ├── node.ts
│ │ │ ├── schema.ts
│ │ │ ├── schemaPredicates.test.ts
│ │ │ ├── schemaPredicates.ts
│ │ │ ├── traversal.test.ts
│ │ │ ├── traversal.ts
│ │ │ ├── variables.test.ts
│ │ │ └── variables.ts
│ │ ├── cacheExchange-types.test.ts
│ │ ├── cacheExchange.test.ts
│ │ ├── cacheExchange.ts
│ │ ├── default-storage
│ │ │ └── index.ts
│ │ ├── extras
│ │ │ ├── index.ts
│ │ │ ├── relayPagination.test.ts
│ │ │ ├── relayPagination.ts
│ │ │ ├── simplePagination.test.ts
│ │ │ └── simplePagination.ts
│ │ ├── helpers
│ │ │ ├── help.ts
│ │ │ └── operation.ts
│ │ ├── index.ts
│ │ ├── offlineExchange.test.ts
│ │ ├── offlineExchange.ts
│ │ ├── operations
│ │ │ ├── invalidate.ts
│ │ │ ├── query.test.ts
│ │ │ ├── query.ts
│ │ │ ├── shared.test.ts
│ │ │ ├── shared.ts
│ │ │ ├── write.test.ts
│ │ │ └── write.ts
│ │ ├── store
│ │ │ ├── __snapshots__
│ │ │ │ └── store.test.ts.snap
│ │ │ ├── data.test.ts
│ │ │ ├── data.ts
│ │ │ ├── keys.ts
│ │ │ ├── store.test.ts
│ │ │ └── store.ts
│ │ ├── test-utils
│ │ │ ├── altered_root_schema.json
│ │ │ ├── examples-1.test.ts
│ │ │ ├── examples-2.test.ts
│ │ │ ├── examples-3.test.ts
│ │ │ ├── relayPagination_schema.json
│ │ │ ├── simple_schema.json
│ │ │ ├── suite.test.ts
│ │ │ └── utils.ts
│ │ └── types.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── persisted
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── index.ts
│ │ ├── persistedExchange.test.ts
│ │ ├── persistedExchange.ts
│ │ ├── sha256.ts
│ │ └── test-utils.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── populate
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── helpers
│ │ │ ├── help.ts
│ │ │ ├── node.ts
│ │ │ └── traverse.ts
│ │ ├── index.ts
│ │ ├── populateExchange.test.ts
│ │ └── populateExchange.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── refocus
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── index.ts
│ │ ├── refocusExchange.test.ts
│ │ └── refocusExchange.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── request-policy
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── index.ts
│ │ ├── requestPolicyExchange.test.ts
│ │ └── requestPolicyExchange.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── retry
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── index.ts
│ │ ├── retryExchange.test.ts
│ │ └── retryExchange.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
└── throw-on-error
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ ├── index.ts
│ ├── throwOnErrorExchange.test.ts
│ └── throwOnErrorExchange.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── package.json
├── packages
├── core
│ ├── .gitignore
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── __snapshots__
│ │ │ └── client.test.ts.snap
│ │ ├── client.test.ts
│ │ ├── client.ts
│ │ ├── exchanges
│ │ │ ├── __snapshots__
│ │ │ │ ├── fetch.test.ts.snap
│ │ │ │ └── subscription.test.ts.snap
│ │ │ ├── cache.test.ts
│ │ │ ├── cache.ts
│ │ │ ├── compose.test.ts
│ │ │ ├── compose.ts
│ │ │ ├── debug.test.ts
│ │ │ ├── debug.ts
│ │ │ ├── fallback.test.ts
│ │ │ ├── fallback.ts
│ │ │ ├── fetch.test.ts
│ │ │ ├── fetch.ts
│ │ │ ├── index.ts
│ │ │ ├── map.test.ts
│ │ │ ├── map.ts
│ │ │ ├── ssr.test.ts
│ │ │ ├── ssr.ts
│ │ │ ├── subscription.test.ts
│ │ │ └── subscription.ts
│ │ ├── gql.test.ts
│ │ ├── gql.ts
│ │ ├── index.ts
│ │ ├── internal
│ │ │ ├── __snapshots__
│ │ │ │ └── fetchSource.test.ts.snap
│ │ │ ├── fetchOptions.test.ts
│ │ │ ├── fetchOptions.ts
│ │ │ ├── fetchSource.test.ts
│ │ │ ├── fetchSource.ts
│ │ │ └── index.ts
│ │ ├── test-utils
│ │ │ ├── index.ts
│ │ │ └── samples.ts
│ │ ├── types.ts
│ │ └── utils
│ │ │ ├── __snapshots__
│ │ │ └── error.test.ts.snap
│ │ │ ├── collectTypenames.test.ts
│ │ │ ├── collectTypenames.ts
│ │ │ ├── error.test.ts
│ │ │ ├── error.ts
│ │ │ ├── formatDocument.test.ts
│ │ │ ├── formatDocument.ts
│ │ │ ├── graphql.ts
│ │ │ ├── hash.test.ts
│ │ │ ├── hash.ts
│ │ │ ├── index.ts
│ │ │ ├── operation.ts
│ │ │ ├── request.test.ts
│ │ │ ├── request.ts
│ │ │ ├── result.test.ts
│ │ │ ├── result.ts
│ │ │ ├── streamUtils.ts
│ │ │ ├── variables.test.ts
│ │ │ └── variables.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── introspection
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── getIntrospectedSchema.ts
│ │ ├── index.ts
│ │ └── minifyIntrospectionQuery.ts
│ └── tsconfig.json
├── next-urql
│ ├── .gitignore
│ ├── CHANGELOG.md
│ ├── LICENSE
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── DataHydrationContext.ts
│ │ ├── Provider.ts
│ │ ├── htmlescape.ts
│ │ ├── index.ts
│ │ ├── rsc.ts
│ │ ├── useQuery.ts
│ │ └── useUrqlValue.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── preact-urql
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── components
│ │ │ ├── Mutation.test.tsx
│ │ │ ├── Mutation.ts
│ │ │ ├── Query.test.tsx
│ │ │ ├── Query.ts
│ │ │ ├── Subscription.test.tsx
│ │ │ ├── Subscription.ts
│ │ │ └── index.ts
│ │ ├── context.ts
│ │ ├── hooks
│ │ │ ├── constants.ts
│ │ │ ├── index.ts
│ │ │ ├── useMutation.test.tsx
│ │ │ ├── useMutation.ts
│ │ │ ├── useQuery.test.tsx
│ │ │ ├── useQuery.ts
│ │ │ ├── useRequest.ts
│ │ │ ├── useSource.ts
│ │ │ ├── useSubscription.test.tsx
│ │ │ └── useSubscription.ts
│ │ └── index.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── react-urql
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── core
│ │ ├── index.d.ts
│ │ ├── index.esm.js
│ │ ├── index.js
│ │ ├── package.json
│ │ └── yarn.lock
│ ├── cypress.config.js
│ ├── cypress
│ │ ├── fixtures
│ │ │ └── example.json
│ │ └── support
│ │ │ ├── component-index.html
│ │ │ └── component.js
│ ├── e2e-tests
│ │ └── useQuery.spec.tsx
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── components
│ │ │ ├── Mutation.test.tsx
│ │ │ ├── Mutation.ts
│ │ │ ├── Query.test.tsx
│ │ │ ├── Query.ts
│ │ │ ├── Subscription.ts
│ │ │ └── index.ts
│ │ ├── context.ts
│ │ ├── hooks
│ │ │ ├── __snapshots__
│ │ │ │ ├── useMutation.test.tsx.snap
│ │ │ │ ├── useQuery.test.tsx.snap
│ │ │ │ └── useSubscription.test.tsx.snap
│ │ │ ├── cache.ts
│ │ │ ├── index.ts
│ │ │ ├── state.ts
│ │ │ ├── useMutation.test.tsx
│ │ │ ├── useMutation.ts
│ │ │ ├── useQuery.spec.ts
│ │ │ ├── useQuery.test.tsx
│ │ │ ├── useQuery.ts
│ │ │ ├── useRequest.test.ts
│ │ │ ├── useRequest.ts
│ │ │ ├── useSubscription.test.tsx
│ │ │ └── useSubscription.ts
│ │ ├── index.ts
│ │ └── test-utils
│ │ │ └── ssr.test.tsx
│ ├── tsconfig.json
│ └── vitest.config.ts
├── site
│ ├── CHANGELOG.md
│ ├── dist-prod
│ │ └── open-source
│ │ │ └── urql
│ ├── package.json
│ ├── plugins
│ │ ├── assets-fix
│ │ │ └── node.api.js
│ │ ├── monorepo-fix
│ │ │ └── node.api.js
│ │ ├── preact
│ │ │ └── node.api.js
│ │ └── react-router
│ │ │ └── browser.api.js
│ ├── public
│ │ ├── browserconfig.xml
│ │ ├── favicon
│ │ │ ├── favicon-16.png
│ │ │ ├── favicon-192.png
│ │ │ ├── favicon-32.png
│ │ │ └── favicon-512.png
│ │ └── site.webmanifest
│ ├── src
│ │ ├── analytics.js
│ │ ├── app.js
│ │ ├── assets
│ │ │ ├── anchor.js
│ │ │ ├── anchor.svg
│ │ │ ├── badge_runpkg.svg
│ │ │ ├── badge_spectacle.svg
│ │ │ ├── badge_victory.svg
│ │ │ ├── burger.svg
│ │ │ ├── chevron.js
│ │ │ ├── chevron.svg
│ │ │ ├── clock-tile.svg
│ │ │ ├── close.svg
│ │ │ ├── eagle-tile.svg
│ │ │ ├── gql-tile.svg
│ │ │ ├── left-triangles.svg
│ │ │ ├── logo-sidebar.svg
│ │ │ ├── logo_formidable_dark.svg
│ │ │ ├── logo_formidable_white.svg
│ │ │ ├── logos
│ │ │ │ ├── logo-formidable-icon.svg
│ │ │ │ └── logo-formidable.svg
│ │ │ ├── react-tile.svg
│ │ │ ├── right-triangles.svg
│ │ │ └── sidebar-badge.svg
│ │ ├── components
│ │ │ ├── body-copy.js
│ │ │ ├── button.js
│ │ │ ├── footer.js
│ │ │ ├── header.js
│ │ │ ├── link.js
│ │ │ ├── loading.js
│ │ │ ├── markdown.js
│ │ │ ├── mdx.js
│ │ │ ├── navigation.js
│ │ │ ├── panel.js
│ │ │ ├── scroll-to-top.js
│ │ │ ├── secondary-title.js
│ │ │ ├── section-title.js
│ │ │ ├── sidebar-search-input.js
│ │ │ ├── sidebar.js
│ │ │ └── wrapper.js
│ │ ├── constants.js
│ │ ├── google-analytics.js
│ │ ├── google-tag-manager.js
│ │ ├── html.js
│ │ ├── index.js
│ │ ├── screens
│ │ │ ├── 404
│ │ │ │ ├── 404.js
│ │ │ │ └── index.js
│ │ │ ├── docs
│ │ │ │ ├── article.js
│ │ │ │ ├── header.js
│ │ │ │ └── index.js
│ │ │ └── home
│ │ │ │ ├── _content.js
│ │ │ │ ├── features.js
│ │ │ │ ├── get-started.js
│ │ │ │ ├── hero.js
│ │ │ │ ├── index.js
│ │ │ │ └── more-oss.js
│ │ └── styles
│ │ │ ├── global.js
│ │ │ └── theme.js
│ ├── static.config.js
│ └── vercel.json
├── solid-urql
│ ├── CHANGELOG.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── context.ts
│ │ ├── createMutation.test.ts
│ │ ├── createMutation.ts
│ │ ├── createQuery.test.tsx
│ │ ├── createQuery.ts
│ │ ├── createSubscription.test.ts
│ │ ├── createSubscription.ts
│ │ ├── index.ts
│ │ ├── suspense.test.tsx
│ │ └── utils.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── storage-rn
│ ├── CHANGELOG.md
│ ├── LICENCE
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── index.ts
│ │ ├── makeAsyncStorage.test.ts
│ │ └── makeAsyncStorage.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── svelte-urql
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ │ ├── common.ts
│ │ ├── context.ts
│ │ ├── index.ts
│ │ ├── mutationStore.test.ts
│ │ ├── mutationStore.ts
│ │ ├── queryStore.test.ts
│ │ ├── queryStore.ts
│ │ ├── subscriptionStore.test.ts
│ │ └── subscriptionStore.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
└── vue-urql
│ ├── CHANGELOG.md
│ ├── README.md
│ ├── jsr.json
│ ├── package.json
│ ├── src
│ ├── index.ts
│ ├── useClient.test.ts
│ ├── useClient.ts
│ ├── useClientHandle.ts
│ ├── useMutation.test.ts
│ ├── useMutation.ts
│ ├── useQuery.test.ts
│ ├── useQuery.ts
│ ├── useSubscription.test.ts
│ ├── useSubscription.ts
│ └── utils.ts
│ ├── tsconfig.json
│ └── vitest.config.ts
├── pnpm-lock.yaml
├── pnpm-workspace.yaml
├── scripts
├── actions
│ ├── build-all.mjs
│ ├── lib
│ │ ├── commands.mjs
│ │ ├── constants.mjs
│ │ ├── github.mjs
│ │ └── packages.mjs
│ └── pack-all.mjs
├── babel
│ ├── transform-debug-target.mjs
│ ├── transform-invariant-warning.mjs
│ └── transform-pipe.mjs
├── changesets
│ ├── changelog.js
│ ├── jsr.mjs
│ └── version.mjs
├── eslint
│ └── preset.js
├── prepare
│ ├── index.js
│ └── postinstall.js
├── rollup
│ ├── cleanup-plugin.mjs
│ ├── config.mjs
│ ├── plugins.mjs
│ └── settings.mjs
└── vitest
│ └── setup.js
├── tsconfig.json
├── vercel.json
└── vitest.config.ts
/.changeset/README.md:
--------------------------------------------------------------------------------
1 | # Changesets
2 |
3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
4 | with multi-package repos, or single-package repos to help you version and publish your code. You can
5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets)
6 |
7 | We have a quick list of common questions to get you started engaging with this project in
8 | [our documentation](https://github.com/changesets/changesets/blob/master/docs/common-questions.md)
9 |
--------------------------------------------------------------------------------
/.changeset/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://unpkg.com/@changesets/config@0.3.0/schema.json",
3 | "changelog": "../scripts/changesets/changelog.js",
4 | "commit": false,
5 | "access": "public",
6 | "baseBranch": "main",
7 | "updateInternalDependencies": "minor",
8 | "snapshot": {
9 | "prereleaseTemplate": "{tag}-{commit}",
10 | "useCalculatedVersion": true
11 | },
12 | "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
13 | "onlyUpdatePeerDependentsWhenOutOfRange": true,
14 | "updateInternalDependents": "out-of-range"
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.changeset/heavy-hairs-bow.md:
--------------------------------------------------------------------------------
1 | ---
2 | "@urql/core": patch
3 | ---
4 |
5 | Correct typo in cacheHit debug message of the `debugExchange`
6 |
--------------------------------------------------------------------------------
/.changeset/nervous-flies-confess.md:
--------------------------------------------------------------------------------
1 | ---
2 | '@urql/core': patch
3 | ---
4 |
5 | Fix `fetchSource` not text-decoding response chunks as streams, which could cause UTF-8 decoding to break.
6 |
--------------------------------------------------------------------------------
/.changeset/old-ears-hunt.md:
--------------------------------------------------------------------------------
1 | ---
2 | '@urql/exchange-graphcache': patch
3 | '@urql/core': patch
4 | ---
5 |
6 | Fix compatibility with Typescript >5.5 (See: https://github.com/0no-co/graphql.web/pull/49)
7 |
--------------------------------------------------------------------------------
/.changeset/serious-chefs-march.md:
--------------------------------------------------------------------------------
1 | ---
2 | '@urql/core': patch
3 | ---
4 |
5 | Change debug log verbosity to `console.debug` rather than `console.log`
6 |
--------------------------------------------------------------------------------
/.changeset/slow-hotels-yawn.md:
--------------------------------------------------------------------------------
1 | ---
2 | "@urql/exchange-retry": patch
3 | ---
4 |
5 | Mark options argument as optional (`retryExchange()`)
6 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_size = 2
7 | end_of_line = lf
8 | indent_style = space
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
12 | [*.md]
13 | max_line_length = 100
14 | trim_trailing_whitespace = false
15 |
16 | [COMMIT_EDITMSG]
17 | max_line_length = 0
18 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
--------------------------------------------------------------------------------
/.github/CODEOWNERS:
--------------------------------------------------------------------------------
1 | /.github/ @urql-graphql/core
2 | /.changeset/config.json @urql-graphql/core
3 | /scripts/actions/* @urql-graphql/core
4 | /scripts/prepare/* @urql-graphql/core
5 | /scripts/rollup/* @urql-graphql/core
6 | /scripts/changesets/* @urql-graphql/core
7 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/RFC.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 'RFC'
3 | about: Propose an enhancement / feature and start a discussion
4 | title: 'RFC: Your Proposal'
5 | labels: "future \U0001F52E"
6 | ---
7 |
8 |
16 |
17 | ## Summary
18 |
19 |
25 |
26 | ## Proposed Solution
27 |
28 |
32 |
33 | ## Requirements
34 |
35 |
43 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: true
2 | contact_links:
3 | - name: Ask a question
4 | url: https://github.com/urql-graphql/urql/discussions
5 | about: Ask questions and discuss with other community members
6 | - name: Join the Discord
7 | url: https://urql.dev/discord
8 | about: Chat with maintainers and other community members
9 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
11 |
12 | ## Summary
13 |
14 |
15 |
16 | ## Set of changes
17 |
18 |
23 |
--------------------------------------------------------------------------------
/.github/actions/discord-message/action.yml:
--------------------------------------------------------------------------------
1 | name: 'Send a discord message'
2 | description: 'Send a discord message as a result of an urql publish.'
3 | inputs:
4 | publishedPackages:
5 | description: >
6 | A JSON array to present the published packages. The format is `[{"name": "@xx/xx", "version": "1.2.0"}, {"name": "@xx/xy", "version": "0.8.9"}]`
7 | runs:
8 | using: 'node20'
9 | main: 'action.mjs'
10 |
--------------------------------------------------------------------------------
/.github/actions/pnpm-run/action.mjs:
--------------------------------------------------------------------------------
1 | import { execa } from 'execa';
2 |
3 | const run = execa('pnpm', ['run', process.env.INPUT_COMMAND], {
4 | cwd: process.cwd(),
5 | });
6 |
7 | run.stdout.pipe(process.stdout);
8 | run.stderr.pipe(process.stderr);
9 |
10 | run
11 | .then(result => process.exit(result.exitCode))
12 | .catch(error => process.exit(error.exitCode || -1));
13 |
--------------------------------------------------------------------------------
/.github/actions/pnpm-run/action.yml:
--------------------------------------------------------------------------------
1 | name: 'Run a pnpm command'
2 | description: 'Locally run a forked pnpm command as an action.'
3 | inputs:
4 | command:
5 | description: 'Command'
6 | default: 'help'
7 | runs:
8 | using: 'node20'
9 | main: 'action.mjs'
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 | /.vscode
3 | **/node_modules
4 | *.log
5 | .rts2_cache*
6 | .husky
7 | dist/
8 | build/
9 | coverage/
10 | package-lock.json
11 | .DS_Store
12 | .next
13 |
14 | packages/*/LICENSE
15 | exchanges/*/LICENSE
16 |
17 | # TODO: Figure out how to remove these:
18 | tmp/
19 | dist/
20 | examples/yarn.lock
21 | examples/pnpm-lock.yaml
22 | examples/package-lock.json
23 | examples/*/public
24 | examples/*/yarn.lock
25 | examples/*/pnpm-lock.yaml
26 | examples/*/package-lock.json
27 | examples/*/ios/
28 | examples/*/android/
29 | examples/*/.watchmanconfig
30 | examples/*/metro.config.js
31 | examples/*/babel.config.js
32 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018–2020 Formidable,
4 | Copyright (c) urql GraphQL Team and other contributors
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/docs/api/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: API
3 | order: 9
4 | ---
5 |
6 | # API
7 |
8 | `urql` is a collection of multiple packages. You'll likely be using one of the framework bindings
9 | package or exchange packages, which are all listed in this section.
10 |
11 | Most of these packages will refer to or use utilities and types from the `@urql/core` package. [Read
12 | more about the core package on the "Core" page.](../basics/core.md)
13 |
14 | > **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
15 | > You can view TSDocs while using these packages in your editor, as long as it supports the
16 | > TypeScript Language Server.
17 | > We're planning to replace these API docs with a separate web app soon.
18 |
19 | - [`@urql/core` API docs](./core.md)
20 | - [`urql` React API docs](./urql.md)
21 | - [`@urql/preact` Preact API docs](./preact.md)
22 | - [`@urql/svelte` Svelte API docs](./svelte.md)
23 | - [`@urql/exchange-graphcache` API docs](./graphcache.md)
24 | - [`@urql/exchange-retry` API docs](./retry-exchange.md)
25 | - [`@urql/exchange-execute` API docs](./execute-exchange.md)
26 | - [`@urql/exchange-request-policy` API docs](./request-policy-exchange.md)
27 | - [`@urql/exchange-auth` API docs](./auth-exchange.md)
28 | - [`@urql/exchange-refocus` API docs](./refocus-exchange.md)
29 |
--------------------------------------------------------------------------------
/docs/api/preact.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '@urql/preact'
3 | order: 2
4 | ---
5 |
6 | # @urql/preact
7 |
8 | > **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
9 | > You can view TSDocs while using these packages in your editor, as long as it supports the
10 | > TypeScript Language Server.
11 | > We're planning to replace these API docs with a separate web app soon.
12 |
13 | The `@urql/preact` API is the same as the React `urql` API.
14 | Please refer to [the "urql" API docs](./urql.md) for details on the Preact API.
15 |
--------------------------------------------------------------------------------
/docs/api/refocus-exchange.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: '@urql/exchange-refocus'
3 | order: 11
4 | ---
5 |
6 | # Refocus Exchange
7 |
8 | > **Note:** These API docs are deprecated as we now keep TSDocs in all published packages.
9 | > You can view TSDocs while using these packages in your editor, as long as it supports the
10 | > TypeScript Language Server.
11 | > We're planning to replace these API docs with a separate web app soon.
12 |
13 | `@urql/exchange-refocus` is an exchange for the `urql` that tracks currently active operations and redispatches them when the
14 | window regains focus
15 |
16 | ## Quick Start Guide
17 |
18 | First install `@urql/exchange-refocus` alongside `urql`:
19 |
20 | ```sh
21 | yarn add @urql/exchange-refocus
22 | # or
23 | npm install --save @urql/exchange-refocus
24 | ```
25 |
26 | Then add it to your `Client`, preferably in front of your `cacheExchange`
27 |
28 | ```js
29 | import { createClient, cacheExchange, fetchExchange } from 'urql';
30 | import { refocusExchange } from '@urql/exchange-refocus';
31 |
32 | const client = createClient({
33 | url: 'http://localhost:3000/graphql',
34 | exchanges: [refocusExchange(), cacheExchange, fetchExchange],
35 | });
36 | ```
37 |
--------------------------------------------------------------------------------
/docs/assets/commutative-layers.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/commutative-layers.png
--------------------------------------------------------------------------------
/docs/assets/devtools-timeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/devtools-timeline.png
--------------------------------------------------------------------------------
/docs/assets/logos/egghead.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/logos/egghead.png
--------------------------------------------------------------------------------
/docs/assets/logos/gatsby.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/logos/gatsby.png
--------------------------------------------------------------------------------
/docs/assets/logos/github.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/logos/github.png
--------------------------------------------------------------------------------
/docs/assets/logos/loveholidays.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/logos/loveholidays.png
--------------------------------------------------------------------------------
/docs/assets/logos/open-social.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/logos/open-social.png
--------------------------------------------------------------------------------
/docs/assets/logos/sturdy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/logos/sturdy.png
--------------------------------------------------------------------------------
/docs/assets/logos/swan.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/logos/swan.png
--------------------------------------------------------------------------------
/docs/assets/logos/the-atlantic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/logos/the-atlantic.png
--------------------------------------------------------------------------------
/docs/assets/logos/tripadvisor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/logos/tripadvisor.png
--------------------------------------------------------------------------------
/docs/assets/next-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/next-logo.png
--------------------------------------------------------------------------------
/docs/assets/partial-results.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/partial-results.png
--------------------------------------------------------------------------------
/docs/assets/query-document-info.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/query-document-info.png
--------------------------------------------------------------------------------
/docs/assets/urql-client-architecture.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/urql-client-architecture.png
--------------------------------------------------------------------------------
/docs/assets/urql-combined-error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/urql-combined-error.png
--------------------------------------------------------------------------------
/docs/assets/urql-document-caching.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/urql-document-caching.png
--------------------------------------------------------------------------------
/docs/assets/urql-event-hub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/urql-event-hub.png
--------------------------------------------------------------------------------
/docs/assets/urql-exchanges.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/urql-exchanges.png
--------------------------------------------------------------------------------
/docs/assets/urql-normalized-cache.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/urql-normalized-cache.png
--------------------------------------------------------------------------------
/docs/assets/urql-operation-keys.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/urql-operation-keys.png
--------------------------------------------------------------------------------
/docs/assets/urql-signals.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/urql-signals.png
--------------------------------------------------------------------------------
/docs/assets/urql-spoiler.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/docs/assets/urql-spoiler.png
--------------------------------------------------------------------------------
/docs/basics/README.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Basics
3 | order: 2
4 | ---
5 |
6 | # Basics
7 |
8 | In this chapter we'll explain the basics of `urql` and how to get started with using it without any
9 | prior knowledge.
10 |
11 | - [**React/Preact**](./react-preact.md) covers how to work with the bindings for React/Preact.
12 | - [**Vue**](./vue.md) covers how to work with the bindings for Vue 3.
13 | - [**Svelte**](./svelte.md) covers how to work with the bindings for Svelte.
14 | - [**Core Package**](./core.md) defines why a shared package exists that contains the main
15 | logic of `urql`, and how we can use it directly in Node.js.
16 |
17 | After reading the page for your bindings and the "Core" page you may want to the next two pages in
18 | this section of the documentation:
19 |
20 | - [**Document Caching**](./document-caching.md) explains the default cache mechanism of `urql`, as opposed to the opt-in
21 | [Normalized Cache](../graphcache/normalized-caching.md).
22 | - [**Errors**](../basics/errors.md) contains information on error handling in `urql`.
23 | - [**UI-Patterns**](../basics/ui-patterns.md) presents some common UI-patterns with `urql`.
24 |
--------------------------------------------------------------------------------
/examples/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - '*'
3 |
--------------------------------------------------------------------------------
/examples/with-apq/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | with-apq
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/examples/with-apq/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-apq",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "vite"
7 | },
8 | "dependencies": {
9 | "@urql/core": "^5.1.1",
10 | "@urql/exchange-persisted": "^4.3.1",
11 | "graphql": "^16.6.0",
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0",
14 | "urql": "^4.2.2"
15 | },
16 | "devDependencies": {
17 | "@vitejs/plugin-react": "^3.1.0",
18 | "vite": "^4.2.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/examples/with-apq/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Client, Provider, fetchExchange } from 'urql';
3 | import { persistedExchange } from '@urql/exchange-persisted';
4 |
5 | import LocationsList from './LocationsList';
6 |
7 | const client = new Client({
8 | url: 'https://trygql.formidable.dev/graphql/apq-weather',
9 | exchanges: [
10 | persistedExchange({
11 | preferGetForPersistedQueries: true,
12 | }),
13 | fetchExchange,
14 | ],
15 | });
16 |
17 | function App() {
18 | return (
19 |
20 |
21 |
22 | );
23 | }
24 |
25 | export default App;
26 |
--------------------------------------------------------------------------------
/examples/with-apq/src/LocationsList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { gql, useQuery } from 'urql';
3 |
4 | const LOCATIONS_QUERY = gql`
5 | query Locations($query: String!) {
6 | locations(query: $query) {
7 | id
8 | name
9 | }
10 | }
11 | `;
12 |
13 | const LocationsList = () => {
14 | const [result] = useQuery({
15 | query: LOCATIONS_QUERY,
16 | variables: { query: 'LON' },
17 | });
18 |
19 | const { data, fetching, error } = result;
20 |
21 | return (
22 |
23 | {fetching &&
Loading...
}
24 |
25 | {error &&
Oh no... {error.message}
}
26 |
27 | {data && (
28 |
29 | {data.locations.map(location => (
30 | - {location.name}
31 | ))}
32 |
33 | )}
34 |
35 | );
36 | };
37 |
38 | export default LocationsList;
39 |
--------------------------------------------------------------------------------
/examples/with-apq/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import App from './App';
5 |
6 | createRoot(document.getElementById('root')).render();
7 |
--------------------------------------------------------------------------------
/examples/with-apq/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/with-defer-stream-directives/README.md:
--------------------------------------------------------------------------------
1 | # With `@defer` / `@stream` Directives
2 |
3 |
4 |
5 |
9 |
10 |
12 |
16 |
17 |
18 |
19 | This example shows `urql` in use [with `@defer` and `@stream`
20 | directives](https://graphql.org/blog/2020-12-08-improving-latency-with-defer-and-stream-directives)
21 | in GraphQL.
22 |
23 | To run this example install dependencies and run the `start` script:
24 |
25 | ```sh
26 | yarn install
27 | yarn run start
28 | # or
29 | npm install
30 | npm run start
31 | ```
32 |
33 | This example contains:
34 |
35 | - The `urql` bindings and a React app with a client set up in [`src/App.jsx`](src/App.jsx)
36 | - A local `graphql-yoga` server set up to test deferred and streamed results in [`server/`](server/).
37 |
--------------------------------------------------------------------------------
/examples/with-defer-stream-directives/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | with-defer-stream-directives
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/examples/with-defer-stream-directives/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-defer-stream-directives",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "server:apollo": "node server/apollo-server.js",
7 | "server:yoga": "node server/graphql-yoga.js",
8 | "client": "vite",
9 | "start": "run-p client server:yoga"
10 | },
11 | "pnpm": {
12 | "peerDependencyRules": {
13 | "allowedVersions": {
14 | "graphql": "17"
15 | }
16 | }
17 | },
18 | "dependencies": {
19 | "@graphql-yoga/plugin-defer-stream": "^1.7.1",
20 | "@urql/core": "^5.1.1",
21 | "@urql/exchange-graphcache": "^7.2.3",
22 | "graphql": "17.0.0-alpha.2",
23 | "react": "^18.2.0",
24 | "react-dom": "^18.2.0",
25 | "urql": "^4.2.2"
26 | },
27 | "devDependencies": {
28 | "@apollo/server": "^4.4.1",
29 | "@vitejs/plugin-react": "^3.1.0",
30 | "graphql-yoga": "^3.7.1",
31 | "npm-run-all": "^4.1.5",
32 | "vite": "^4.2.0"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/examples/with-defer-stream-directives/server/apollo-server.js:
--------------------------------------------------------------------------------
1 | // NOTE: This currently fails because responses for @defer/@stream are not sent
2 | // as multipart responses, but the request fails silently with an empty JSON response payload
3 |
4 | const { ApolloServer } = require('@apollo/server');
5 | const { startStandaloneServer } = require('@apollo/server/standalone');
6 | const { schema } = require('./schema');
7 |
8 | const server = new ApolloServer({ schema });
9 |
10 | startStandaloneServer(server, {
11 | listen: {
12 | port: 3004,
13 | },
14 | });
15 |
--------------------------------------------------------------------------------
/examples/with-defer-stream-directives/server/graphql-yoga.js:
--------------------------------------------------------------------------------
1 | const { createYoga } = require('graphql-yoga');
2 | const { useDeferStream } = require('@graphql-yoga/plugin-defer-stream');
3 | const { createServer } = require('http');
4 | const { schema } = require('./schema');
5 |
6 | const yoga = createYoga({
7 | schema,
8 | plugins: [useDeferStream()],
9 | });
10 |
11 | const server = createServer(yoga);
12 |
13 | server.listen(3004);
14 |
--------------------------------------------------------------------------------
/examples/with-defer-stream-directives/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Client, Provider, fetchExchange } from 'urql';
3 |
4 | import { cacheExchange } from '@urql/exchange-graphcache';
5 |
6 | import Songs from './Songs';
7 |
8 | const cache = cacheExchange({
9 | keys: {
10 | Alphabet: data => data.char,
11 | Song: () => null,
12 | },
13 | });
14 |
15 | const client = new Client({
16 | url: 'http://localhost:3004/graphql',
17 | exchanges: [cache, fetchExchange],
18 | });
19 |
20 | function App() {
21 | return (
22 |
23 |
24 |
25 | );
26 | }
27 |
28 | export default App;
29 |
--------------------------------------------------------------------------------
/examples/with-defer-stream-directives/src/Songs.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { gql, useQuery } from 'urql';
3 |
4 | const SecondVerseFragment = gql`
5 | fragment secondVerseFields on Song {
6 | secondVerse
7 | }
8 | `;
9 |
10 | const SONGS_QUERY = gql`
11 | query App_Query {
12 | song {
13 | firstVerse
14 | ...secondVerseFields @defer
15 | }
16 | alphabet @stream(initialCount: 3) {
17 | char
18 | }
19 | }
20 |
21 | ${SecondVerseFragment}
22 | `;
23 |
24 | const Song = React.memo(function Song({ song }) {
25 | return (
26 |
27 | {song.firstVerse}
28 | {song.secondVerse}
29 |
30 | );
31 | });
32 |
33 | const LocationsList = () => {
34 | const [result] = useQuery({
35 | query: SONGS_QUERY,
36 | });
37 |
38 | const { data } = result;
39 |
40 | return (
41 |
42 | {data && (
43 | <>
44 |
45 | {data.alphabet.map(i => (
46 |
{i.char}
47 | ))}
48 | >
49 | )}
50 |
51 | );
52 | };
53 |
54 | export default LocationsList;
55 |
--------------------------------------------------------------------------------
/examples/with-defer-stream-directives/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import App from './App';
5 |
6 | createRoot(document.getElementById('root')).render();
7 |
--------------------------------------------------------------------------------
/examples/with-defer-stream-directives/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/with-graphcache-pagination/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | with-graphcache-pagination
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/examples/with-graphcache-pagination/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-graphcache-pagination",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "vite"
7 | },
8 | "dependencies": {
9 | "@urql/core": "^5.1.1",
10 | "@urql/exchange-graphcache": "^7.2.3",
11 | "graphql": "^16.6.0",
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0",
14 | "urql": "^4.2.2"
15 | },
16 | "devDependencies": {
17 | "@vitejs/plugin-react": "^3.1.0",
18 | "vite": "^4.2.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/examples/with-graphcache-pagination/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Client, Provider, fetchExchange } from 'urql';
3 | import { cacheExchange } from '@urql/exchange-graphcache';
4 | import { relayPagination } from '@urql/exchange-graphcache/extras';
5 |
6 | import PaginatedNpmSearch from './PaginatedNpmSearch';
7 |
8 | const client = new Client({
9 | url: 'https://trygql.formidable.dev/graphql/relay-npm',
10 | exchanges: [
11 | cacheExchange({
12 | resolvers: {
13 | Query: {
14 | search: relayPagination(),
15 | },
16 | },
17 | }),
18 | fetchExchange,
19 | ],
20 | });
21 |
22 | function App() {
23 | return (
24 |
25 |
26 |
27 | );
28 | }
29 |
30 | export default App;
31 |
--------------------------------------------------------------------------------
/examples/with-graphcache-pagination/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import App from './App';
5 |
6 | createRoot(document.getElementById('root')).render();
7 |
--------------------------------------------------------------------------------
/examples/with-graphcache-pagination/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/with-graphcache-updates/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | with-graphcache-updates
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/examples/with-graphcache-updates/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-graphcache-updates",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "vite"
7 | },
8 | "dependencies": {
9 | "@urql/core": "^5.1.1",
10 | "@urql/exchange-auth": "^2.2.1",
11 | "@urql/exchange-graphcache": "^7.2.3",
12 | "graphql": "^16.6.0",
13 | "react": "^18.2.0",
14 | "react-dom": "^18.2.0",
15 | "urql": "^4.2.2"
16 | },
17 | "devDependencies": {
18 | "@vitejs/plugin-react": "^3.1.0",
19 | "vite": "^4.2.0"
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/examples/with-graphcache-updates/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { Provider } from 'urql';
3 |
4 | import client from './client';
5 | import Links from './pages/Links';
6 | import LoginForm from './pages/LoginForm';
7 |
8 | const Home = () => {
9 | const [isLoggedIn, setIsLoggedIn] = useState(false);
10 |
11 | const onLoginSuccess = auth => {
12 | localStorage.setItem('authToken', auth.token);
13 | setIsLoggedIn(true);
14 | };
15 |
16 | useEffect(() => {
17 | if (localStorage.getItem('authToken')) {
18 | setIsLoggedIn(true);
19 | }
20 | }, []);
21 |
22 | return isLoggedIn ? : ;
23 | };
24 |
25 | function App() {
26 | return (
27 |
28 |
29 |
30 | );
31 | }
32 |
33 | export default App;
34 |
--------------------------------------------------------------------------------
/examples/with-graphcache-updates/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import App from './App';
5 |
6 | createRoot(document.getElementById('root')).render();
7 |
--------------------------------------------------------------------------------
/examples/with-graphcache-updates/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/with-infinite-pagination/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | with-pagination
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/examples/with-infinite-pagination/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-pagination",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "vite"
7 | },
8 | "dependencies": {
9 | "@urql/core": "^5.1.1",
10 | "graphql": "^16.6.0",
11 | "react": "^18.2.0",
12 | "react-dom": "^18.2.0",
13 | "urql": "^4.2.2"
14 | },
15 | "devDependencies": {
16 | "@vitejs/plugin-react": "^3.1.0",
17 | "vite": "^4.2.0"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/with-infinite-pagination/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import App from './App';
5 |
6 | createRoot(document.getElementById('root')).render();
7 |
--------------------------------------------------------------------------------
/examples/with-infinite-pagination/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/with-multipart/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | with-multipart
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/examples/with-multipart/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-multipart",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "vite"
7 | },
8 | "dependencies": {
9 | "@urql/core": "^5.1.1",
10 | "graphql": "^16.6.0",
11 | "react": "^18.2.0",
12 | "react-dom": "^18.2.0",
13 | "urql": "^4.2.2"
14 | },
15 | "devDependencies": {
16 | "@vitejs/plugin-react": "^3.1.0",
17 | "vite": "^4.2.0"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/with-multipart/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Client, Provider, fetchExchange } from 'urql';
3 |
4 | import FileUpload from './FileUpload';
5 |
6 | const client = new Client({
7 | url: 'https://trygql.formidable.dev/graphql/uploads-mock',
8 | exchanges: [fetchExchange],
9 | });
10 |
11 | function App() {
12 | return (
13 |
14 |
15 |
16 | );
17 | }
18 |
19 | export default App;
20 |
--------------------------------------------------------------------------------
/examples/with-multipart/src/FileUpload.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState } from 'react';
2 | import { gql, useMutation } from 'urql';
3 |
4 | const UPLOAD_FILE = gql`
5 | mutation UploadFile($file: Upload!) {
6 | uploadFile(file: $file) {
7 | filename
8 | }
9 | }
10 | `;
11 |
12 | const FileUpload = () => {
13 | const [selectedFile, setSelectedFile] = useState();
14 | const [result, uploadFile] = useMutation(UPLOAD_FILE);
15 |
16 | const { data, fetching, error } = result;
17 |
18 | const handleFileUpload = () => {
19 | uploadFile({ file: selectedFile });
20 | };
21 |
22 | const handleFileChange = event => {
23 | setSelectedFile(event.target.files[0]);
24 | };
25 |
26 | return (
27 |
28 | {fetching &&
Loading...
}
29 |
30 | {error &&
Oh no... {error.message}
}
31 |
32 | {data && data.uploadFile ? (
33 |
File uploaded to {data.uploadFile.filename}
34 | ) : (
35 |
36 |
37 |
38 |
39 |
40 | )}
41 |
42 | );
43 | };
44 |
45 | export default FileUpload;
46 |
--------------------------------------------------------------------------------
/examples/with-multipart/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import App from './App';
5 |
6 | createRoot(document.getElementById('root')).render();
7 |
--------------------------------------------------------------------------------
/examples/with-multipart/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/with-next/README.md:
--------------------------------------------------------------------------------
1 | # With Next.js
2 |
3 |
4 |
5 |
9 |
10 |
11 |
15 |
16 |
17 |
18 | This example shows `next-urql` and `urql` in use with Next.js as explained [in the "Next.js" section
19 | on the "Server-side Rendering" docs
20 | page](https://formidable.com/open-source/urql/docs/advanced/server-side-rendering/#nextjs).
21 |
22 | To run this example install dependencies and run the `start` script:
23 |
24 | ```sh
25 | yarn install
26 | yarn run start
27 | # or
28 | npm install
29 | npm run start
30 | ```
31 |
--------------------------------------------------------------------------------
/examples/with-next/app/layout.tsx:
--------------------------------------------------------------------------------
1 | export const metadata = {
2 | title: 'Create Next App',
3 | description: 'Generated by create next app',
4 | };
5 |
6 | export default function RootLayout({
7 | children,
8 | }: {
9 | children: React.ReactNode;
10 | }) {
11 | return (
12 |
13 | {children}
14 |
15 | );
16 | }
17 |
--------------------------------------------------------------------------------
/examples/with-next/app/non-rsc/layout.tsx:
--------------------------------------------------------------------------------
1 | 'use client';
2 |
3 | import { useMemo } from 'react';
4 | import {
5 | UrqlProvider,
6 | ssrExchange,
7 | cacheExchange,
8 | fetchExchange,
9 | createClient,
10 | } from '@urql/next';
11 |
12 | export default function Layout({ children }: React.PropsWithChildren) {
13 | const [client, ssr] = useMemo(() => {
14 | const ssr = ssrExchange({
15 | isClient: typeof window !== 'undefined',
16 | });
17 | const client = createClient({
18 | url: 'https://graphql-pokeapi.graphcdn.app/',
19 | exchanges: [cacheExchange, ssr, fetchExchange],
20 | suspense: true,
21 | });
22 |
23 | return [client, ssr];
24 | }, []);
25 |
26 | return (
27 |
28 | {children}
29 |
30 | );
31 | }
32 |
--------------------------------------------------------------------------------
/examples/with-next/app/page.tsx:
--------------------------------------------------------------------------------
1 | import Link from 'next/link';
2 | import { cacheExchange, createClient, fetchExchange, gql } from '@urql/core';
3 | import { registerUrql } from '@urql/next/rsc';
4 |
5 | const makeClient = () => {
6 | return createClient({
7 | url: 'https://graphql-pokeapi.graphcdn.app/',
8 | exchanges: [cacheExchange, fetchExchange],
9 | });
10 | };
11 |
12 | const { getClient } = registerUrql(makeClient);
13 |
14 | const PokemonsQuery = gql`
15 | query {
16 | pokemons(limit: 10) {
17 | results {
18 | id
19 | name
20 | }
21 | }
22 | }
23 | `;
24 |
25 | export default async function Home() {
26 | const result = await getClient().query(PokemonsQuery, {});
27 | return (
28 |
29 | This is rendered as part of an RSC
30 |
31 | {result.data
32 | ? result.data.pokemons.results.map((x: any) => (
33 | - {x.name}
34 | ))
35 | : JSON.stringify(result.error)}
36 |
37 | Non RSC
38 |
39 | );
40 | }
41 |
--------------------------------------------------------------------------------
/examples/with-next/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 |
4 | // NOTE: This file should not be edited
5 | // see https://nextjs.org/docs/basic-features/typescript for more information.
6 |
--------------------------------------------------------------------------------
/examples/with-next/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-next",
3 | "version": "0.0.0",
4 | "private": true,
5 | "dependencies": {
6 | "@urql/core": "^5.1.1",
7 | "@urql/next": "^1.1.5",
8 | "graphql": "^16.6.0",
9 | "next": "13.4.2",
10 | "react": "^18.2.0",
11 | "react-dom": "^18.2.0",
12 | "urql": "^4.2.2"
13 | },
14 | "scripts": {
15 | "dev": "next dev",
16 | "start": "next",
17 | "build": "next build"
18 | },
19 | "devDependencies": {
20 | "@types/react": "18.2.6"
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/examples/with-next/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "lib": ["dom", "dom.iterable", "esnext"],
4 | "allowJs": true,
5 | "skipLibCheck": true,
6 | "strict": false,
7 | "forceConsistentCasingInFileNames": true,
8 | "noEmit": true,
9 | "incremental": true,
10 | "esModuleInterop": true,
11 | "module": "esnext",
12 | "moduleResolution": "node",
13 | "resolveJsonModule": true,
14 | "isolatedModules": true,
15 | "jsx": "preserve",
16 | "plugins": [
17 | {
18 | "name": "next"
19 | }
20 | ]
21 | },
22 | "include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx"],
23 | "exclude": ["node_modules"]
24 | }
25 |
--------------------------------------------------------------------------------
/examples/with-pagination/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | with-pagination
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/examples/with-pagination/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-pagination",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "vite"
7 | },
8 | "dependencies": {
9 | "@urql/core": "^5.1.1",
10 | "graphql": "^16.6.0",
11 | "react": "^18.2.0",
12 | "react-dom": "^18.2.0",
13 | "urql": "^4.2.2"
14 | },
15 | "devDependencies": {
16 | "@vitejs/plugin-react": "^3.1.0",
17 | "vite": "^4.2.0"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/with-pagination/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Client, Provider, cacheExchange, fetchExchange } from 'urql';
3 |
4 | import PaginatedNpmSearch from './PaginatedNpmSearch';
5 |
6 | const client = new Client({
7 | url: 'https://trygql.formidable.dev/graphql/relay-npm',
8 | exchanges: [cacheExchange, fetchExchange],
9 | });
10 |
11 | function App() {
12 | return (
13 |
14 |
15 |
16 | );
17 | }
18 |
19 | export default App;
20 |
--------------------------------------------------------------------------------
/examples/with-pagination/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import App from './App';
5 |
6 | createRoot(document.getElementById('root')).render();
7 |
--------------------------------------------------------------------------------
/examples/with-pagination/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/with-react-native/App.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Client, Provider, cacheExchange, fetchExchange } from 'urql';
3 |
4 | import PokemonList from './src/screens/PokemonList';
5 |
6 | const client = new Client({
7 | url: 'https://trygql.formidable.dev/graphql/basic-pokedex',
8 | exchanges: [cacheExchange, fetchExchange],
9 | });
10 |
11 | const App = () => {
12 | return (
13 |
14 |
15 |
16 | );
17 | };
18 |
19 | export default App;
20 |
--------------------------------------------------------------------------------
/examples/with-react-native/README.md:
--------------------------------------------------------------------------------
1 | # With React Native
2 |
3 |
4 |
5 |
9 |
10 |
12 |
16 |
17 |
18 |
19 | This example shows `urql` in use with React Native.
20 |
21 | To run this example install dependencies and run the `start` script:
22 |
23 | ```sh
24 | yarn install
25 | yarn run start
26 | # or
27 | npm install
28 | npm run start
29 | ```
30 |
31 | This example contains:
32 |
33 | - The `urql` bindings and a React Native app with a client set up in [`App.js`](./App.js)
34 | - A query for pokémon in [`src/screens/PokemonList.js`](src/screens/PokemonList.js)
35 |
--------------------------------------------------------------------------------
/examples/with-react-native/app.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "withReactNative",
3 | "displayName": "withReactNative"
4 | }
5 |
--------------------------------------------------------------------------------
/examples/with-react-native/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * @format
3 | */
4 |
5 | import { AppRegistry } from 'react-native';
6 | import App from './App';
7 | import { name as appName } from './app.json';
8 |
9 | AppRegistry.registerComponent(appName, () => App);
10 |
--------------------------------------------------------------------------------
/examples/with-react-native/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-react-native",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "android": "react-native run-android",
7 | "ios": "react-native run-ios",
8 | "start": "react-native start"
9 | },
10 | "dependencies": {
11 | "@urql/core": "^5.1.1",
12 | "graphql": "^16.6.0",
13 | "react": "18.2.0",
14 | "react-native": "0.71.4",
15 | "urql": "^4.2.2"
16 | },
17 | "devDependencies": {
18 | "@babel/core": "^7.12.9",
19 | "@babel/preset-env": "^7.20.2",
20 | "@babel/runtime": "^7.12.5",
21 | "metro-react-native-babel-preset": "^0.76.0"
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/examples/with-react/README.md:
--------------------------------------------------------------------------------
1 | # With React
2 |
3 |
4 |
5 |
9 |
10 |
11 |
15 |
16 |
17 |
18 | This example shows `urql` in use with React, as explained on the ["React/Preact" page of the "Basics"
19 | documentation.](https://formidable.com/open-source/urql/docs/basics/react-preact/)
20 |
21 | To run this example install dependencies and run the `start` script:
22 |
23 | ```sh
24 | yarn install
25 | yarn run start
26 | # or
27 | npm install
28 | npm run start
29 | ```
30 |
31 | This example contains:
32 |
33 | - The `urql` bindings and a React app with a client set up in [`src/App.jsx`](src/App.jsx)
34 | - A query for pokémon in [`src/PokemonList.jsx`](src/PokemonList.jsx)
35 |
--------------------------------------------------------------------------------
/examples/with-react/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | with-react
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/examples/with-react/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-react",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "vite"
7 | },
8 | "dependencies": {
9 | "@urql/core": "^5.1.1",
10 | "graphql": "^16.6.0",
11 | "react": "^18.2.0",
12 | "react-dom": "^18.2.0",
13 | "urql": "^4.2.2"
14 | },
15 | "devDependencies": {
16 | "@vitejs/plugin-react": "^3.1.0",
17 | "vite": "^4.2.0"
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/examples/with-react/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Client, Provider, cacheExchange, fetchExchange } from 'urql';
3 |
4 | import PokemonList from './PokemonList';
5 |
6 | const client = new Client({
7 | url: 'https://trygql.formidable.dev/graphql/basic-pokedex',
8 | exchanges: [cacheExchange, fetchExchange],
9 | });
10 |
11 | function App() {
12 | return (
13 |
14 |
15 |
16 | );
17 | }
18 |
19 | export default App;
20 |
--------------------------------------------------------------------------------
/examples/with-react/src/PokemonList.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { gql, useQuery } from 'urql';
3 |
4 | const POKEMONS_QUERY = gql`
5 | query Pokemons {
6 | pokemons(limit: 10) {
7 | id
8 | name
9 | }
10 | }
11 | `;
12 |
13 | const PokemonList = () => {
14 | const [result] = useQuery({ query: POKEMONS_QUERY });
15 |
16 | const { data, fetching, error } = result;
17 |
18 | return (
19 |
20 | {fetching &&
Loading...
}
21 |
22 | {error &&
Oh no... {error.message}
}
23 |
24 | {data && (
25 |
26 | {data.pokemons.map(pokemon => (
27 | - {pokemon.name}
28 | ))}
29 |
30 | )}
31 |
32 | );
33 | };
34 |
35 | export default PokemonList;
36 |
--------------------------------------------------------------------------------
/examples/with-react/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import App from './App';
5 |
6 | createRoot(document.getElementById('root')).render();
7 |
--------------------------------------------------------------------------------
/examples/with-react/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/with-refresh-auth/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | with-refresh-auth
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/examples/with-refresh-auth/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-refresh-auth",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "vite"
7 | },
8 | "dependencies": {
9 | "@urql/core": "^5.1.1",
10 | "@urql/exchange-auth": "^2.2.1",
11 | "graphql": "^16.6.0",
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0",
14 | "urql": "^4.2.2"
15 | },
16 | "devDependencies": {
17 | "@vitejs/plugin-react": "^3.1.0",
18 | "vite": "^4.2.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/examples/with-refresh-auth/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from 'react';
2 | import { Provider } from 'urql';
3 |
4 | import client from './client';
5 |
6 | import { getToken, saveAuthData } from './authStore';
7 | import Profile from './pages/Profile';
8 | import LoginForm from './pages/LoginForm';
9 |
10 | const Home = () => {
11 | const [isLoggedIn, setIsLoggedIn] = useState(false);
12 |
13 | const onLoginSuccess = auth => {
14 | saveAuthData(auth);
15 | setIsLoggedIn(true);
16 | };
17 |
18 | useEffect(() => {
19 | if (getToken()) {
20 | setIsLoggedIn(true);
21 | }
22 | }, []);
23 |
24 | return isLoggedIn ? (
25 |
26 | ) : (
27 |
28 | );
29 | };
30 |
31 | function App() {
32 | return (
33 |
34 |
35 |
36 | );
37 | }
38 |
39 | export default App;
40 |
--------------------------------------------------------------------------------
/examples/with-refresh-auth/src/authStore.js:
--------------------------------------------------------------------------------
1 | const TOKEN_KEY = 'token';
2 | const REFRESH_TOKEN_KEY = 'refresh_token';
3 |
4 | export const saveAuthData = ({ token, refreshToken }) => {
5 | localStorage.setItem(TOKEN_KEY, token);
6 | localStorage.setItem(REFRESH_TOKEN_KEY, refreshToken);
7 | };
8 |
9 | export const getToken = () => {
10 | return localStorage.getItem(TOKEN_KEY);
11 | };
12 |
13 | export const getRefreshToken = () => {
14 | return localStorage.getItem(REFRESH_TOKEN_KEY);
15 | };
16 |
17 | export const clearStorage = () => {
18 | localStorage.clear();
19 | };
20 |
--------------------------------------------------------------------------------
/examples/with-refresh-auth/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import App from './App';
5 |
6 | createRoot(document.getElementById('root')).render();
7 |
--------------------------------------------------------------------------------
/examples/with-refresh-auth/src/pages/Profile.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { gql, useQuery } from 'urql';
3 |
4 | const PROFILE_QUERY = gql`
5 | query Profile {
6 | me {
7 | id
8 | username
9 | createdAt
10 | }
11 | }
12 | `;
13 |
14 | const Profile = () => {
15 | const [result] = useQuery({ query: PROFILE_QUERY });
16 |
17 | const { data, fetching, error } = result;
18 |
19 | return (
20 |
21 | {fetching &&
Loading...
}
22 |
23 | {error &&
Oh no... {error.message}
}
24 |
25 | {data?.me && (
26 | <>
27 |
profile data
28 |
id: {data.me.id}
29 |
username: {data.me.username}
30 | >
31 | )}
32 |
33 | );
34 | };
35 |
36 | export default Profile;
37 |
--------------------------------------------------------------------------------
/examples/with-refresh-auth/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/with-retry/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | with-retry
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/examples/with-retry/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-retry",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "vite"
7 | },
8 | "dependencies": {
9 | "@urql/core": "^5.1.1",
10 | "@urql/exchange-retry": "^1.3.1",
11 | "graphql": "^16.6.0",
12 | "react": "^18.2.0",
13 | "react-dom": "^18.2.0",
14 | "urql": "^4.2.2"
15 | },
16 | "devDependencies": {
17 | "@vitejs/plugin-react": "^3.1.0",
18 | "vite": "^4.2.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/examples/with-retry/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Client, fetchExchange, Provider } from 'urql';
3 | import { retryExchange } from '@urql/exchange-retry';
4 |
5 | import Color from './Color';
6 |
7 | const client = new Client({
8 | url: 'https://trygql.formidable.dev/graphql/intermittent-colors',
9 | exchanges: [
10 | retryExchange({
11 | maxNumberAttempts: 10,
12 | maxDelayMs: 500,
13 | retryIf: error => {
14 | // NOTE: With this deemo schema we have a specific random error to look out for:
15 | return (
16 | error.graphQLErrors.some(x => x.extensions?.code === 'NO_SOUP') ||
17 | !!error.networkError
18 | );
19 | },
20 | }),
21 | fetchExchange,
22 | ],
23 | });
24 |
25 | function App() {
26 | return (
27 |
28 |
29 |
30 | );
31 | }
32 |
33 | export default App;
34 |
--------------------------------------------------------------------------------
/examples/with-retry/src/Color.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { gql, useQuery } from 'urql';
3 |
4 | const RANDOM_COLOR_QUERY = gql`
5 | query RandomColor {
6 | randomColor {
7 | name
8 | hex
9 | }
10 | }
11 | `;
12 |
13 | const RandomColorDisplay = () => {
14 | const [result] = useQuery({ query: RANDOM_COLOR_QUERY });
15 |
16 | const { data, fetching, error } = result;
17 |
18 | return (
19 |
20 | {fetching &&
Loading...
}
21 |
22 | {error &&
Oh no... {error.message}
}
23 |
24 | {data && (
25 |
26 | {data.randomColor.name}
27 |
28 | )}
29 |
30 | {result.operation && (
31 |
32 | To get a result, the retry exchange retried:{' '}
33 | {result.operation.context.retryCount || 0} times.
34 |
35 | )}
36 |
37 | );
38 | };
39 |
40 | export default RandomColorDisplay;
41 |
--------------------------------------------------------------------------------
/examples/with-retry/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import App from './App';
5 |
6 | createRoot(document.getElementById('root')).render();
7 |
--------------------------------------------------------------------------------
/examples/with-retry/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/with-subscriptions-via-fetch/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | with-defer-stream-directives
7 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/examples/with-subscriptions-via-fetch/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-subscriptions-via-fetch",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "server": "node server/graphql-yoga.js",
7 | "client": "vite",
8 | "start": "run-p client server"
9 | },
10 | "dependencies": {
11 | "@urql/core": "^5.1.1",
12 | "@urql/exchange-graphcache": "^7.2.3",
13 | "graphql": "^16.6.0",
14 | "react": "^18.2.0",
15 | "react-dom": "^18.2.0",
16 | "urql": "^4.2.2"
17 | },
18 | "devDependencies": {
19 | "@vitejs/plugin-react": "^3.1.0",
20 | "graphql-yoga": "^3.7.1",
21 | "npm-run-all": "^4.1.5",
22 | "vite": "^4.2.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/examples/with-subscriptions-via-fetch/server/graphql-yoga.js:
--------------------------------------------------------------------------------
1 | const { createYoga } = require('graphql-yoga');
2 | const { createServer } = require('http');
3 | const { schema } = require('./schema');
4 |
5 | const yoga = createYoga({ schema });
6 | const server = createServer(yoga);
7 | server.listen(3004);
8 |
--------------------------------------------------------------------------------
/examples/with-subscriptions-via-fetch/server/schema.js:
--------------------------------------------------------------------------------
1 | const {
2 | GraphQLList,
3 | GraphQLObjectType,
4 | GraphQLSchema,
5 | GraphQLString,
6 | } = require('graphql');
7 |
8 | const Alphabet = new GraphQLObjectType({
9 | name: 'Alphabet',
10 | fields: {
11 | char: {
12 | type: GraphQLString,
13 | },
14 | },
15 | });
16 |
17 | const schema = new GraphQLSchema({
18 | query: new GraphQLObjectType({
19 | name: 'Query',
20 | fields: () => ({
21 | list: {
22 | type: new GraphQLList(Alphabet),
23 | resolve() {
24 | return [{ char: 'Where are my letters?' }];
25 | },
26 | },
27 | }),
28 | }),
29 | subscription: new GraphQLObjectType({
30 | name: 'Subscription',
31 | fields: () => ({
32 | alphabet: {
33 | type: Alphabet,
34 | resolve(root) {
35 | return root;
36 | },
37 | subscribe: async function* () {
38 | for (let letter = 65; letter <= 90; letter++) {
39 | await new Promise(resolve => setTimeout(resolve, 500));
40 | yield { char: String.fromCharCode(letter) };
41 | }
42 | },
43 | },
44 | }),
45 | }),
46 | });
47 |
48 | module.exports = { schema };
49 |
--------------------------------------------------------------------------------
/examples/with-subscriptions-via-fetch/src/App.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { Client, Provider, fetchExchange } from 'urql';
3 |
4 | import { cacheExchange } from '@urql/exchange-graphcache';
5 |
6 | import Songs from './Songs';
7 |
8 | const cache = cacheExchange({
9 | keys: {
10 | Alphabet: data => data.char,
11 | },
12 | updates: {
13 | Subscription: {
14 | alphabet(parent, _args, cache) {
15 | const list = cache.resolve('Query', 'list') || [];
16 | list.push(parent.alphabet);
17 | cache.link('Query', 'list', list);
18 | },
19 | },
20 | },
21 | });
22 |
23 | const client = new Client({
24 | url: 'http://localhost:3004/graphql',
25 | fetchSubscriptions: true,
26 | exchanges: [cache, fetchExchange],
27 | });
28 |
29 | function App() {
30 | return (
31 |
32 |
33 |
34 | );
35 | }
36 |
37 | export default App;
38 |
--------------------------------------------------------------------------------
/examples/with-subscriptions-via-fetch/src/Songs.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { gql, useQuery, useSubscription } from 'urql';
3 |
4 | const LIST_QUERY = gql`
5 | query List_Query {
6 | list {
7 | char
8 | }
9 | }
10 | `;
11 |
12 | const SONG_SUBSCRIPTION = gql`
13 | subscription App_Subscription {
14 | alphabet {
15 | char
16 | }
17 | }
18 | `;
19 |
20 | const ListQuery = () => {
21 | const [listResult] = useQuery({
22 | query: LIST_QUERY,
23 | });
24 | return (
25 |
26 |
List
27 | {listResult?.data?.list.map(i => (
28 |
{i.char}
29 | ))}
30 |
31 | );
32 | };
33 |
34 | const SongSubscription = () => {
35 | const [songsResult] = useSubscription(
36 | { query: SONG_SUBSCRIPTION },
37 | (prev = [], data) => [...prev, data.alphabet]
38 | );
39 |
40 | return (
41 |
42 |
Song
43 | {songsResult?.data?.map(i => (
44 |
{i.char}
45 | ))}
46 |
47 | );
48 | };
49 |
50 | const LocationsList = () => {
51 | return (
52 | <>
53 |
54 |
55 | >
56 | );
57 | };
58 |
59 | export default LocationsList;
60 |
--------------------------------------------------------------------------------
/examples/with-subscriptions-via-fetch/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { createRoot } from 'react-dom/client';
3 |
4 | import App from './App';
5 |
6 | createRoot(document.getElementById('root')).render();
7 |
--------------------------------------------------------------------------------
/examples/with-subscriptions-via-fetch/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import react from '@vitejs/plugin-react';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/with-svelte/.gitignore:
--------------------------------------------------------------------------------
1 | /node_modules/
2 | /public/build/
3 |
4 | .DS_Store
5 |
--------------------------------------------------------------------------------
/examples/with-svelte/README.md:
--------------------------------------------------------------------------------
1 | # With Svelte
2 |
3 |
4 |
5 |
9 |
10 |
11 |
15 |
16 |
17 |
18 | This example shows `@urql/svelte` in use with Svelte, as explained on the ["Svelte" page of the "Basics"
19 | documentation.](https://formidable.com/open-source/urql/docs/basics/svelte/)
20 |
21 | To run this example install dependencies and run the `start` script:
22 |
23 | ```sh
24 | yarn install
25 | yarn run start
26 | # or
27 | npm install
28 | npm run start
29 | ```
30 |
31 | This example contains:
32 |
33 | - The `@urql/svelte` bindings with a client set up in [`src/App.svelte`](src/App.svelte)
34 | - A query for pokémon in [`src/PokemonList.svelte`](src/pages/PokemonList.svelte)
35 |
--------------------------------------------------------------------------------
/examples/with-svelte/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | with-svelte
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/with-svelte/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-svelte",
3 | "private": true,
4 | "version": "0.0.0",
5 | "scripts": {
6 | "start": "vite",
7 | "build": "vite build",
8 | "serve": "vite preview"
9 | },
10 | "dependencies": {
11 | "@urql/core": "^5.1.1",
12 | "@urql/svelte": "^4.2.3",
13 | "graphql": "^16.6.0",
14 | "svelte": "^4.0.5"
15 | },
16 | "devDependencies": {
17 | "@sveltejs/vite-plugin-svelte": "^2.4.2",
18 | "vite": "^4.2.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/examples/with-svelte/src/App.svelte:
--------------------------------------------------------------------------------
1 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/examples/with-svelte/src/PokemonList.svelte:
--------------------------------------------------------------------------------
1 |
27 |
28 |
29 | {#if $pokemons.fetching}
30 | Loading...
31 | {:else if $pokemons.error}
32 | Oh no... {$pokemons.error.message}
33 | {:else}
34 |
35 | {#each $pokemons.data.pokemons as pokemon}
36 | - {pokemon.name}
37 | {/each}
38 |
39 | {/if}
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/examples/with-svelte/src/main.js:
--------------------------------------------------------------------------------
1 | import App from './App.svelte';
2 |
3 | var app = new App({
4 | target: document.body,
5 | });
6 |
7 | export default app;
8 |
--------------------------------------------------------------------------------
/examples/with-svelte/vite.config.mjs:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import { svelte } from '@sveltejs/vite-plugin-svelte';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [svelte()],
7 | });
8 |
--------------------------------------------------------------------------------
/examples/with-vue3/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .DS_Store
3 | dist
4 | *.local
--------------------------------------------------------------------------------
/examples/with-vue3/README.md:
--------------------------------------------------------------------------------
1 | # With Vue 3
2 |
3 |
4 |
5 |
9 |
10 |
11 |
15 |
16 |
17 |
18 | This example shows `@urql/vue` in use with Vue 3, as explained on the ["Vue" page of the "Basics"
19 | documentation.](https://formidable.com/open-source/urql/docs/basics/vue/)
20 |
21 | To run this example install dependencies and run the `start` script:
22 |
23 | ```sh
24 | yarn install
25 | yarn run start
26 | # or
27 | npm install
28 | npm run start
29 | ```
30 |
31 | This example contains:
32 |
33 | - The `@urql/vue` bindings with a client set up in [`src/App.vue`](src/App.vue)
34 | - A suspense loading boundary in the `App` component in [`src/App.vue`](src/App.vue)
35 | - A query for pokémon in [`src/PokemonList.vue`](src/pages/PokemonList.vue)
36 |
--------------------------------------------------------------------------------
/examples/with-vue3/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Vite App
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/examples/with-vue3/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "with-vue3",
3 | "version": "0.0.0",
4 | "private": true,
5 | "scripts": {
6 | "start": "vite",
7 | "build": "vite build",
8 | "serve": "vite preview"
9 | },
10 | "dependencies": {
11 | "@urql/core": "^5.1.1",
12 | "@urql/vue": "^1.4.3",
13 | "graphql": "^16.6.0",
14 | "vue": "^3.2.47"
15 | },
16 | "devDependencies": {
17 | "@vitejs/plugin-vue": "^4.1.0",
18 | "vite": "^4.2.0"
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/examples/with-vue3/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Loading...
8 |
9 |
10 |
11 |
12 |
29 |
--------------------------------------------------------------------------------
/examples/with-vue3/src/PokemonList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | -
5 | {{ pokemon.name }}
6 |
7 |
8 |
9 |
10 |
11 |
12 |
42 |
--------------------------------------------------------------------------------
/examples/with-vue3/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from 'vue';
2 | import App from './App.vue';
3 |
4 | createApp(App).mount('#app');
5 |
--------------------------------------------------------------------------------
/examples/with-vue3/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite';
2 | import vue from '@vitejs/plugin-vue';
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [vue()],
7 | });
8 |
--------------------------------------------------------------------------------
/exchanges/auth/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/exchange-auth",
3 | "version": "2.2.1",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/exchanges/auth/src/index.ts:
--------------------------------------------------------------------------------
1 | export { authExchange } from './authExchange';
2 | export type { AuthUtilities, AuthConfig } from './authExchange';
3 |
--------------------------------------------------------------------------------
/exchanges/auth/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/exchanges/auth/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/exchanges/context/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/exchange-context",
3 | "version": "0.3.1",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/exchanges/context/src/index.ts:
--------------------------------------------------------------------------------
1 | export { contextExchange } from './context';
2 | export type { ContextExchangeArgs } from './context';
3 |
--------------------------------------------------------------------------------
/exchanges/context/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/exchanges/context/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/exchanges/execute/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/exchange-execute",
3 | "version": "2.3.1",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/exchanges/execute/src/index.ts:
--------------------------------------------------------------------------------
1 | export { executeExchange } from './execute';
2 | export type { ExecuteExchangeArgs } from './execute';
3 |
--------------------------------------------------------------------------------
/exchanges/execute/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/exchanges/execute/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/exchanges/graphcache/.gitignore:
--------------------------------------------------------------------------------
1 | /extras
2 | /default-storage
3 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/10000Reads.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 10000 Reads
7 |
10 |
11 |
12 |
13 |
14 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/10000ReadsComplex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 10000 Reads Complex
7 |
10 |
11 |
12 |
13 |
14 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/10000Writes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 10000 Writes
7 |
10 |
11 |
12 |
13 |
14 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/10000WritesComplex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 10000 Writes Complex
7 |
10 |
11 |
12 |
13 |
14 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/1000Reads.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 1000 Reads
7 |
10 |
11 |
12 |
13 |
14 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/1000ReadsComplex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 1000 Reads Complex
7 |
10 |
11 |
12 |
13 |
14 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/1000Writes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 1000 Writes
7 |
10 |
11 |
12 |
13 |
14 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/1000WritesComplex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 1000 Writes Complex
7 |
10 |
11 |
12 |
13 |
14 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/100Reads.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 100 Reads
7 |
10 |
11 |
12 |
13 |
14 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/100ReadsComplex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 100 Reads Complex
7 |
10 |
11 |
12 |
13 |
14 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/100Writes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 100 Writes
7 |
10 |
11 |
12 |
13 |
14 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/100WritesComplex.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 100 Writes Complex
7 |
10 |
11 |
12 |
13 |
14 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/addTodo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Add Todo
7 |
10 |
11 |
12 |
13 |
14 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/makeEntries.js:
--------------------------------------------------------------------------------
1 | // create a function that will take in a number of times to be run and a function that will produce an entry/entity
2 | export const makeEntries = (amount, makeEntry) => {
3 | // create array of entries to be outputted
4 | const entries = [];
5 | // iterate from 0 up to the amount inputted
6 | for (let i = 0; i < amount; i += 1) {
7 | // each iteration, create an entry and pass it the current index & push it into output array
8 | const entry = makeEntry(i);
9 | entries.push(entry);
10 | }
11 | // return array of entries
12 | return entries;
13 | };
14 |
--------------------------------------------------------------------------------
/exchanges/graphcache/benchmarks/updateTodo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Update Todo
7 |
10 |
11 |
12 |
13 |
14 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/exchanges/graphcache/cypress.config.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line
2 | const { defineConfig } = require('cypress');
3 | // eslint-disable-next-line
4 | const tsconfigPaths = require('vite-tsconfig-paths').default;
5 |
6 | module.exports = defineConfig({
7 | video: false,
8 |
9 | e2e: {
10 | setupNodeEvents(_on, _config) {
11 | /*noop*/
12 | },
13 | supportFile: false,
14 | },
15 | component: {
16 | specPattern: './**/e2e-tests/*spec.tsx',
17 | devServer: {
18 | framework: 'react',
19 | bundler: 'vite',
20 | viteConfig: {
21 | plugins: [tsconfigPaths()],
22 | server: {
23 | fs: {
24 | allow: ['../..'],
25 | },
26 | },
27 | },
28 | },
29 | },
30 | });
31 |
--------------------------------------------------------------------------------
/exchanges/graphcache/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
6 |
--------------------------------------------------------------------------------
/exchanges/graphcache/cypress/plugins/index.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line
2 | const { startDevServer } = require('@cypress/vite-dev-server');
3 | // eslint-disable-next-line
4 | const path = require('path');
5 |
6 | /**
7 | * @type {Cypress.PluginConfig}
8 | */
9 | module.exports = (on, _config) => {
10 | on('dev-server:start', options =>
11 | startDevServer({
12 | options,
13 | })
14 | );
15 | };
16 |
--------------------------------------------------------------------------------
/exchanges/graphcache/cypress/support/component-index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Components App
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/exchanges/graphcache/cypress/support/component.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/component.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | import { mount } from 'cypress/react';
17 |
18 | Cypress.Commands.add('mount', mount);
19 |
20 | // Example use:
21 | // cy.mount()
22 |
--------------------------------------------------------------------------------
/exchanges/graphcache/help.md:
--------------------------------------------------------------------------------
1 | This file (`exchanges/graphcache/help.md`) has been moved to `docs/graphcache/errors.md`
2 |
3 | If you are looking at this in a browser
4 |
5 | - ...and your URL looks like this: `github.com/urql-graphql/urql/blob/main/exchanges/graphcache/help.md#15`
6 | - ...in the URL, replace `exchanges/graphcache/help.md` with `docs/graphcache/errors.md`
7 | - ...and keep the `#15`
8 | - ...and then you will get help with your error!
9 |
--------------------------------------------------------------------------------
/exchanges/graphcache/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/exchange-graphcache",
3 | "version": "7.2.3",
4 | "exports": {
5 | ".": "./src/index.ts",
6 | "./extras": "./src/extras/index.ts",
7 | "./default-storage": "./src/default-storage/index.ts"
8 | },
9 | "exclude": [
10 | "node_modules",
11 | "cypress",
12 | "**/*.test.*",
13 | "**/*.spec.*",
14 | "**/*.test.*.snap",
15 | "**/*.spec.*.snap"
16 | ]
17 | }
--------------------------------------------------------------------------------
/exchanges/graphcache/src/ast/index.ts:
--------------------------------------------------------------------------------
1 | export * from './variables';
2 | export * from './traversal';
3 | export * from './schema';
4 | export * from './schemaPredicates';
5 | export * from './node';
6 |
--------------------------------------------------------------------------------
/exchanges/graphcache/src/extras/index.ts:
--------------------------------------------------------------------------------
1 | export { relayPagination } from './relayPagination';
2 | export { simplePagination } from './simplePagination';
3 |
--------------------------------------------------------------------------------
/exchanges/graphcache/src/helpers/operation.ts:
--------------------------------------------------------------------------------
1 | import type { Operation, RequestPolicy, OperationDebugMeta } from '@urql/core';
2 | import { makeOperation } from '@urql/core';
3 |
4 | // Returns the given operation result with added cacheOutcome meta field
5 | export const addMetadata = (
6 | operation: Operation,
7 | meta: OperationDebugMeta
8 | ): Operation =>
9 | makeOperation(operation.kind, operation, {
10 | ...operation.context,
11 | meta: {
12 | ...operation.context.meta,
13 | ...meta,
14 | },
15 | });
16 |
17 | // Copy an operation and change the requestPolicy to skip the cache
18 | export const toRequestPolicy = (
19 | operation: Operation,
20 | requestPolicy: RequestPolicy
21 | ): Operation => {
22 | return makeOperation(operation.kind, operation, {
23 | ...operation.context,
24 | requestPolicy,
25 | });
26 | };
27 |
--------------------------------------------------------------------------------
/exchanges/graphcache/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './types';
2 | export { Store } from './store/store';
3 | export { cacheExchange } from './cacheExchange';
4 | export { offlineExchange } from './offlineExchange';
5 |
--------------------------------------------------------------------------------
/exchanges/graphcache/src/operations/invalidate.ts:
--------------------------------------------------------------------------------
1 | import * as InMemoryData from '../store/data';
2 | import { keyOfField } from '../store/keys';
3 | import type { FieldArgs } from '../types';
4 |
5 | interface PartialFieldInfo {
6 | fieldKey: string;
7 | }
8 |
9 | export const invalidateEntity = (
10 | entityKey: string,
11 | field?: string,
12 | args?: FieldArgs
13 | ) => {
14 | const fields: PartialFieldInfo[] = field
15 | ? [{ fieldKey: keyOfField(field, args) }]
16 | : InMemoryData.inspectFields(entityKey);
17 |
18 | for (let i = 0, l = fields.length; i < l; i++) {
19 | const { fieldKey } = fields[i];
20 | if (InMemoryData.readLink(entityKey, fieldKey) !== undefined) {
21 | InMemoryData.writeLink(entityKey, fieldKey, undefined);
22 | } else {
23 | InMemoryData.writeRecord(entityKey, fieldKey, undefined);
24 | }
25 | }
26 | };
27 |
28 | export const invalidateType = (
29 | typename: string,
30 | excludedEntities: string[]
31 | ) => {
32 | const types = InMemoryData.getEntitiesForType(typename);
33 | for (const entity of types) {
34 | if (excludedEntities.includes(entity)) continue;
35 | invalidateEntity(entity);
36 | }
37 | };
38 |
--------------------------------------------------------------------------------
/exchanges/graphcache/src/store/__snapshots__/store.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`Store with storage > should be able to persist embedded data 1`] = `
4 | {
5 | "Query%2eappointment({"id":"1"}).__typename": ""Appointment"",
6 | "Query%2eappointment({"id":"1"}).info": ""urql meeting"",
7 | "Query.appointment({"id":"1"})": ":"Query.appointment({\\"id\\":\\"1\\"})"",
8 | }
9 | `;
10 |
11 | exports[`Store with storage > should be able to store and rehydrate data 1`] = `
12 | {
13 | "Appointment:1.__typename": ""Appointment"",
14 | "Appointment:1.id": ""1"",
15 | "Appointment:1.info": ""urql meeting"",
16 | "Query.appointment({"id":"1"})": ":"Appointment:1"",
17 | }
18 | `;
19 |
--------------------------------------------------------------------------------
/exchanges/graphcache/src/store/keys.ts:
--------------------------------------------------------------------------------
1 | import { stringifyVariables } from '@urql/core';
2 | import type { FieldArgs, FieldInfo, KeyInfo } from '../types';
3 |
4 | export const keyOfField = (fieldName: string, args?: FieldArgs) =>
5 | args ? `${fieldName}(${stringifyVariables(args)})` : fieldName;
6 |
7 | export const joinKeys = (parentKey: string, key: string) =>
8 | `${parentKey}.${key}`;
9 |
10 | export const fieldInfoOfKey = (fieldKey: string): FieldInfo => {
11 | const parenIndex = fieldKey.indexOf('(');
12 | if (parenIndex > -1) {
13 | return {
14 | fieldKey,
15 | fieldName: fieldKey.slice(0, parenIndex),
16 | arguments: JSON.parse(fieldKey.slice(parenIndex + 1, -1)),
17 | };
18 | } else {
19 | return {
20 | fieldKey,
21 | fieldName: fieldKey,
22 | arguments: null,
23 | };
24 | }
25 | };
26 |
27 | export const serializeKeys = (entityKey: string, fieldKey: string) =>
28 | `${entityKey.replace(/\./g, '%2e')}.${fieldKey}`;
29 |
30 | export const deserializeKeyInfo = (key: string): KeyInfo => {
31 | const dotIndex = key.indexOf('.');
32 | const entityKey = key.slice(0, dotIndex).replace(/%2e/g, '.');
33 | const fieldKey = key.slice(dotIndex + 1);
34 | return { entityKey, fieldKey };
35 | };
36 |
--------------------------------------------------------------------------------
/exchanges/graphcache/src/test-utils/examples-3.test.ts:
--------------------------------------------------------------------------------
1 | import { gql } from '@urql/core';
2 | import { it, afterEach, expect } from 'vitest';
3 | import { __initAnd_query as query } from '../operations/query';
4 | import { __initAnd_write as write } from '../operations/write';
5 | import { Store } from '../store/store';
6 |
7 | afterEach(() => {
8 | expect(console.warn).not.toHaveBeenCalled();
9 | });
10 |
11 | it('allows viewer fields to overwrite the root Query data', () => {
12 | const store = new Store();
13 | const get = gql`
14 | {
15 | int
16 | }
17 | `;
18 | const set = gql`
19 | mutation {
20 | mutate {
21 | viewer {
22 | int
23 | }
24 | }
25 | }
26 | `;
27 |
28 | write(
29 | store,
30 | { query: get },
31 | {
32 | __typename: 'Query',
33 | int: 42,
34 | }
35 | );
36 |
37 | write(
38 | store,
39 | { query: set },
40 | {
41 | __typename: 'Mutation',
42 | mutate: {
43 | __typename: 'MutateResult',
44 | viewer: {
45 | __typename: 'Query',
46 | int: 43,
47 | },
48 | },
49 | }
50 | );
51 |
52 | const res = query(store, { query: get });
53 |
54 | expect(res.partial).toBe(false);
55 | expect(res.data).toEqual({
56 | int: 43,
57 | });
58 | });
59 |
--------------------------------------------------------------------------------
/exchanges/graphcache/src/test-utils/utils.ts:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line
2 | export const noop = () => {};
3 |
--------------------------------------------------------------------------------
/exchanges/graphcache/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/exchanges/graphcache/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/exchanges/persisted/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/exchange-persisted",
3 | "version": "4.3.1",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/exchanges/persisted/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './persistedExchange';
2 |
--------------------------------------------------------------------------------
/exchanges/persisted/src/test-utils.ts:
--------------------------------------------------------------------------------
1 | import type { GraphQLRequest, OperationContext, Operation } from '@urql/core';
2 | import { gql, makeOperation } from '@urql/core';
3 |
4 | const context: OperationContext = {
5 | fetchOptions: {
6 | method: 'POST',
7 | },
8 | requestPolicy: 'cache-first',
9 | url: 'http://localhost:3000/graphql',
10 | };
11 |
12 | const queryGql: GraphQLRequest = {
13 | key: 2,
14 | query: gql`
15 | query getUser($name: String) {
16 | user(name: $name) {
17 | id
18 | firstName
19 | lastName
20 | }
21 | }
22 | `,
23 | variables: {
24 | name: 'Clara',
25 | },
26 | };
27 |
28 | export const mutationGql: GraphQLRequest = {
29 | key: 2,
30 | query: gql`
31 | mutation AddUser($name: String) {
32 | addUser(name: $name) {
33 | name
34 | }
35 | }
36 | `,
37 | variables: {
38 | name: 'Clara',
39 | },
40 | };
41 |
42 | export const queryOperation: Operation = makeOperation(
43 | 'query',
44 | queryGql,
45 | context
46 | );
47 |
48 | export const mutationOperation: Operation = makeOperation(
49 | 'mutation',
50 | mutationGql,
51 | context
52 | );
53 |
--------------------------------------------------------------------------------
/exchanges/persisted/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/exchanges/persisted/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/exchanges/populate/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/exchange-populate",
3 | "version": "1.2.1",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/exchanges/populate/src/helpers/help.ts:
--------------------------------------------------------------------------------
1 | // These are guards that are used throughout the codebase to warn or error on
2 | // unexpected behaviour or conditions.
3 | // Every warning and error comes with a number that uniquely identifies them.
4 | // You can read more about the messages themselves in `docs/graphcache/errors.md`
5 | export type ErrorCode =
6 | | 1
7 | | 2
8 | | 3
9 | | 4
10 | | 5
11 | | 6
12 | | 7
13 | | 8
14 | | 9
15 | | 10
16 | | 11
17 | | 12
18 | | 13
19 | | 15
20 | | 16
21 | | 17
22 | | 18
23 | | 19;
24 |
25 | // URL unfurls to https://formidable.com/open-source/urql/docs/graphcache/errors/
26 | const helpUrl = '\nhttps://bit.ly/2XbVrpR#';
27 | const cache = new Set();
28 |
29 | export function warn(message: string, code: ErrorCode) {
30 | if (!cache.has(message)) {
31 | console.warn(message + helpUrl + code);
32 | cache.add(message);
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/exchanges/populate/src/helpers/node.ts:
--------------------------------------------------------------------------------
1 | import type { NameNode, GraphQLOutputType, GraphQLWrappingType } from 'graphql';
2 | import { isWrappingType, Kind } from 'graphql';
3 |
4 | export type GraphQLFlatType = Exclude;
5 |
6 | /** Returns the name of a given node */
7 | export const getName = (node: { name: NameNode }): string => node.name.value;
8 |
9 | export const unwrapType = (
10 | type: null | undefined | GraphQLOutputType
11 | ): GraphQLFlatType | null => {
12 | if (isWrappingType(type)) {
13 | return unwrapType(type.ofType);
14 | }
15 |
16 | return type || null;
17 | };
18 |
19 | export function createNameNode(value: string): NameNode {
20 | return {
21 | kind: Kind.NAME,
22 | value,
23 | };
24 | }
25 |
--------------------------------------------------------------------------------
/exchanges/populate/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './populateExchange';
2 |
--------------------------------------------------------------------------------
/exchanges/populate/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/exchanges/populate/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/exchanges/refocus/README.md:
--------------------------------------------------------------------------------
1 | # @urql/exchange-refocus
2 |
3 | `@urql/exchange-refocus` is an exchange for the [`urql`](../../README.md) GraphQL client that tracks currently active operations and redispatches them when the
4 | window regains focus
5 |
6 | ## Quick Start Guide
7 |
8 | First install `@urql/exchange-refocus` alongside `urql`:
9 |
10 | ```sh
11 | yarn add @urql/exchange-refocus
12 | # or
13 | npm install --save @urql/exchange-refocus
14 | ```
15 |
16 | Then add it to your `Client`, preferably before the `cacheExchange` and in front of any asynchronous
17 | exchanges, like the `fetchExchange`:
18 |
19 | ```js
20 | import { createClient, cacheExchange, fetchExchange } from 'urql';
21 | import { refocusExchange } from '@urql/exchange-refocus';
22 |
23 | const client = createClient({
24 | url: 'http://localhost:3000/graphql',
25 | exchanges: [refocusExchange(), cacheExchange, fetchExchange],
26 | });
27 | ```
28 |
--------------------------------------------------------------------------------
/exchanges/refocus/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/exchange-refocus",
3 | "version": "1.1.1",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/exchanges/refocus/src/index.ts:
--------------------------------------------------------------------------------
1 | export { refocusExchange } from './refocusExchange';
2 |
--------------------------------------------------------------------------------
/exchanges/refocus/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/exchanges/refocus/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/exchanges/request-policy/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/exchange-request-policy",
3 | "version": "1.2.1",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/exchanges/request-policy/src/index.ts:
--------------------------------------------------------------------------------
1 | export { requestPolicyExchange } from './requestPolicyExchange';
2 |
--------------------------------------------------------------------------------
/exchanges/request-policy/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/exchanges/request-policy/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/exchanges/retry/README.md:
--------------------------------------------------------------------------------
1 | # @urql/exchange-retry (Exchange factory)
2 |
3 | `@urql/exchange-retry` is an exchange for the [`urql`](../../README.md) GraphQL client that allows operations (queries, mutations, subscriptions) to be retried based on an `options` parameter.
4 |
5 | ## Quick Start Guide
6 |
7 | First install `@urql/exchange-retry` alongside `urql`:
8 |
9 | ```sh
10 | yarn add @urql/exchange-retry
11 | # or
12 | npm install --save @urql/exchange-retry
13 | ```
14 |
15 | Read more about the [retry exchange](https://formidable.com/open-source/urql/docs/advanced/retry-operations).
16 |
--------------------------------------------------------------------------------
/exchanges/retry/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/exchange-retry",
3 | "version": "1.3.1",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/exchanges/retry/src/index.ts:
--------------------------------------------------------------------------------
1 | export { retryExchange } from './retryExchange';
2 | export type { RetryExchangeOptions } from './retryExchange';
3 |
--------------------------------------------------------------------------------
/exchanges/retry/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/exchanges/retry/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/exchanges/throw-on-error/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # @urql/exchange-throw-on-error
2 |
3 | ## 0.1.2
4 |
5 | ### Patch Changes
6 |
7 | - Update `graphql-toe` and add more detail to README
8 | Submitted by [@benjie](https://github.com/benjie) (See [#3765](https://github.com/urql-graphql/urql/pull/3765))
9 |
10 | ## 0.1.1
11 |
12 | ### Patch Changes
13 |
14 | - Omit minified files and sourcemaps' `sourcesContent` in published packages
15 | Submitted by [@kitten](https://github.com/kitten) (See [#3755](https://github.com/urql-graphql/urql/pull/3755))
16 | - Updated dependencies (See [#3755](https://github.com/urql-graphql/urql/pull/3755))
17 | - @urql/core@5.1.1
18 |
19 | ## 0.1.0
20 |
21 | ### Minor Changes
22 |
23 | - Initial release
24 | Submitted by [@XiNiHa](https://github.com/XiNiHa) (See [#3677](https://github.com/urql-graphql/urql/pull/3677))
25 |
--------------------------------------------------------------------------------
/exchanges/throw-on-error/README.md:
--------------------------------------------------------------------------------
1 | # @urql/exchange-throw-on-error (Exchange factory)
2 |
3 | `@urql/exchange-throw-on-error` is an exchange for the [`urql`](https://github.com/urql-graphql/urql) GraphQL client that throws on field access to errored fields.
4 |
5 | It is built on top of the [`graphql-toe`](https://github.com/graphile/graphql-toe) package - please see that package for more information.
6 |
7 | ## Quick Start Guide
8 |
9 | First install `@urql/exchange-throw-on-error` alongside `urql`:
10 |
11 | ```sh
12 | yarn add @urql/exchange-throw-on-error
13 | # or
14 | npm install --save @urql/exchange-throw-on-error
15 | ```
16 |
17 | Then add the `throwOnErrorExchange`, to your client:
18 |
19 | ```js
20 | import { createClient, cacheExchange, fetchExchange } from 'urql';
21 | import { throwOnErrorExchange } from '@urql/exchange-throw-on-error';
22 |
23 | const client = createClient({
24 | url: '/graphql',
25 | exchanges: [cacheExchange, throwOnErrorExchange(), fetchExchange],
26 | });
27 | ```
28 |
--------------------------------------------------------------------------------
/exchanges/throw-on-error/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/exchange-throw-on-error",
3 | "version": "0.1.2",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/exchanges/throw-on-error/src/index.ts:
--------------------------------------------------------------------------------
1 | export { throwOnErrorExchange } from './throwOnErrorExchange';
2 |
--------------------------------------------------------------------------------
/exchanges/throw-on-error/src/throwOnErrorExchange.ts:
--------------------------------------------------------------------------------
1 | import type { Exchange } from '@urql/core';
2 | import { mapExchange } from '@urql/core';
3 | import { toe } from 'graphql-toe';
4 |
5 | /** Exchange factory that maps the fields of the data to throw an error on access if the field was errored.
6 | *
7 | * @returns the created throw-on-error {@link Exchange}.
8 | */
9 | export const throwOnErrorExchange = (): Exchange => {
10 | return mapExchange({
11 | onResult(result) {
12 | if (result.data) {
13 | const errors = result.error && result.error.graphQLErrors;
14 | result.data = toe({ data: result.data, errors });
15 | }
16 | return result;
17 | },
18 | });
19 | };
20 |
--------------------------------------------------------------------------------
/exchanges/throw-on-error/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/exchanges/throw-on-error/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/packages/core/.gitignore:
--------------------------------------------------------------------------------
1 | /internal
2 |
--------------------------------------------------------------------------------
/packages/core/README.md:
--------------------------------------------------------------------------------
1 | # @urql/core
2 |
3 | > The shared core for the highly customizable and versatile GraphQL client, urql
4 |
5 | More documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).
6 |
--------------------------------------------------------------------------------
/packages/core/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/core",
3 | "version": "5.1.1",
4 | "exports": {
5 | ".": "./src/index.ts",
6 | "./internal": "./src/internal/index.ts"
7 | },
8 | "exclude": [
9 | "node_modules",
10 | "cypress",
11 | "**/*.test.*",
12 | "**/*.spec.*",
13 | "**/*.test.*.snap",
14 | "**/*.spec.*.snap"
15 | ]
16 | }
--------------------------------------------------------------------------------
/packages/core/src/__snapshots__/client.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`createClient / Client > passes snapshot 1`] = `
4 | Client2 {
5 | "createRequestOperation": [Function],
6 | "executeMutation": [Function],
7 | "executeQuery": [Function],
8 | "executeRequestOperation": [Function],
9 | "executeSubscription": [Function],
10 | "mutation": [Function],
11 | "operations$": [Function],
12 | "query": [Function],
13 | "readQuery": [Function],
14 | "reexecuteOperation": [Function],
15 | "subscribeToDebugTarget": [Function],
16 | "subscription": [Function],
17 | "suspense": false,
18 | }
19 | `;
20 |
--------------------------------------------------------------------------------
/packages/core/src/exchanges/debug.ts:
--------------------------------------------------------------------------------
1 | import { pipe, tap } from 'wonka';
2 | import type { Exchange } from '../types';
3 |
4 | /** Simple log debugger exchange.
5 | *
6 | * @remarks
7 | * An exchange that logs incoming {@link Operation | Operations} and
8 | * {@link OperationResult | OperationResults} in development.
9 | *
10 | * This exchange is a no-op in production and often used in issue reporting
11 | * to understand certain usage patterns of `urql` without having access to
12 | * the original source code.
13 | *
14 | * Hint: When you report an issue you’re having with `urql`, adding
15 | * this as your first exchange and posting its output can speed up
16 | * issue triaging a lot!
17 | */
18 | export const debugExchange: Exchange = ({ forward }) => {
19 | if (process.env.NODE_ENV === 'production') {
20 | return ops$ => forward(ops$);
21 | } else {
22 | return ops$ =>
23 | pipe(
24 | ops$,
25 | // eslint-disable-next-line no-console
26 | tap(op => console.debug('[Exchange debug]: Incoming operation: ', op)),
27 | forward,
28 | tap(result =>
29 | // eslint-disable-next-line no-console
30 | console.debug('[Exchange debug]: Completed operation: ', result)
31 | )
32 | );
33 | }
34 | };
35 |
--------------------------------------------------------------------------------
/packages/core/src/exchanges/fallback.test.ts:
--------------------------------------------------------------------------------
1 | import { forEach, fromValue, pipe } from 'wonka';
2 | import { vi, expect, it, beforeEach, afterAll } from 'vitest';
3 |
4 | import { queryOperation, teardownOperation } from '../test-utils';
5 | import { fallbackExchange } from './fallback';
6 |
7 | const consoleWarn = console.warn;
8 |
9 | const dispatchDebug = vi.fn();
10 |
11 | beforeEach(() => {
12 | console.warn = vi.fn();
13 | });
14 |
15 | afterAll(() => {
16 | console.warn = consoleWarn;
17 | });
18 |
19 | it('filters all results and warns about input', () => {
20 | const res: any[] = [];
21 |
22 | pipe(
23 | fallbackExchange({ dispatchDebug })(fromValue(queryOperation)),
24 | forEach(x => res.push(x))
25 | );
26 |
27 | expect(res.length).toBe(0);
28 | expect(console.warn).toHaveBeenCalled();
29 | });
30 |
31 | it('filters all results and does not warn about teardown operations', () => {
32 | const res: any[] = [];
33 |
34 | pipe(
35 | fallbackExchange({ dispatchDebug })(fromValue(teardownOperation)),
36 | forEach(x => res.push(x))
37 | );
38 |
39 | expect(res.length).toBe(0);
40 | expect(console.warn).not.toHaveBeenCalled();
41 | });
42 |
--------------------------------------------------------------------------------
/packages/core/src/exchanges/index.ts:
--------------------------------------------------------------------------------
1 | export { ssrExchange } from './ssr';
2 | export { cacheExchange } from './cache';
3 | export { subscriptionExchange } from './subscription';
4 | export { debugExchange } from './debug';
5 | export { fetchExchange } from './fetch';
6 | export { composeExchanges } from './compose';
7 |
8 | export type {
9 | SerializedResult,
10 | SSRExchangeParams,
11 | SSRExchange,
12 | SSRData,
13 | } from './ssr';
14 |
15 | export type {
16 | SubscriptionOperation,
17 | SubscriptionForwarder,
18 | SubscriptionExchangeOpts,
19 | } from './subscription';
20 |
21 | export { mapExchange, mapExchange as errorExchange } from './map';
22 | export type { MapExchangeOpts } from './map';
23 |
--------------------------------------------------------------------------------
/packages/core/src/index.ts:
--------------------------------------------------------------------------------
1 | export { gql } from './gql';
2 |
3 | export * from './client';
4 | export * from './exchanges';
5 | export * from './types';
6 |
7 | export {
8 | CombinedError,
9 | stringifyVariables,
10 | stringifyDocument,
11 | createRequest,
12 | makeResult,
13 | makeErrorResult,
14 | mergeResultPatch,
15 | formatDocument,
16 | makeOperation,
17 | } from './utils';
18 |
--------------------------------------------------------------------------------
/packages/core/src/internal/index.ts:
--------------------------------------------------------------------------------
1 | export * from './fetchOptions';
2 | export * from './fetchSource';
3 |
--------------------------------------------------------------------------------
/packages/core/src/test-utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './samples';
2 |
--------------------------------------------------------------------------------
/packages/core/src/utils/__snapshots__/error.test.ts.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`CombinedError > behaves like a normal Error 1`] = `"[Network] test"`;
4 |
--------------------------------------------------------------------------------
/packages/core/src/utils/collectTypenames.ts:
--------------------------------------------------------------------------------
1 | interface EntityLike {
2 | [key: string]: EntityLike | EntityLike[] | any;
3 | __typename: string | null | void;
4 | }
5 |
6 | const collectTypes = (obj: EntityLike | EntityLike[], types: Set) => {
7 | if (Array.isArray(obj)) {
8 | for (let i = 0, l = obj.length; i < l; i++) {
9 | collectTypes(obj[i], types);
10 | }
11 | } else if (typeof obj === 'object' && obj !== null) {
12 | for (const key in obj) {
13 | if (key === '__typename' && typeof obj[key] === 'string') {
14 | types.add(obj[key] as string);
15 | } else {
16 | collectTypes(obj[key], types);
17 | }
18 | }
19 | }
20 |
21 | return types;
22 | };
23 |
24 | /** Finds and returns a list of `__typename` fields found in response data.
25 | *
26 | * @privateRemarks
27 | * This is used by `@urql/core`’s document `cacheExchange` to find typenames
28 | * in a given GraphQL response’s data.
29 | */
30 | export const collectTypenames = (response: object): string[] => [
31 | ...collectTypes(response as EntityLike, new Set()),
32 | ];
33 |
--------------------------------------------------------------------------------
/packages/core/src/utils/graphql.ts:
--------------------------------------------------------------------------------
1 | import type * as GraphQLWeb from '@0no-co/graphql.web';
2 | import type * as GraphQL from 'graphql';
3 |
4 | type OrNever = void extends T ? never : T;
5 |
6 | export type GraphQLError =
7 | | GraphQLWeb.GraphQLError
8 | | OrNever;
9 |
10 | export type DocumentNode =
11 | | GraphQLWeb.DocumentNode
12 | | OrNever;
13 |
14 | export type DefinitionNode =
15 | | GraphQLWeb.DefinitionNode
16 | | OrNever;
17 |
--------------------------------------------------------------------------------
/packages/core/src/utils/hash.test.ts:
--------------------------------------------------------------------------------
1 | import { HashValue, phash } from './hash';
2 | import { expect, it } from 'vitest';
3 |
4 | it('hashes given strings', () => {
5 | expect(phash('hello')).toMatchInlineSnapshot('261238937');
6 | });
7 |
8 | it('hashes given strings and seeds', () => {
9 | let hash: HashValue;
10 | expect((hash = phash('hello'))).toMatchInlineSnapshot('261238937');
11 | expect((hash = phash('world', hash))).toMatchInlineSnapshot('-152191');
12 | expect((hash = phash('!', hash))).toMatchInlineSnapshot('-5022270');
13 | expect(typeof hash).toBe('number');
14 | });
15 |
--------------------------------------------------------------------------------
/packages/core/src/utils/hash.ts:
--------------------------------------------------------------------------------
1 | /** A hash value as computed by {@link phash}.
2 | *
3 | * @remarks
4 | * Typically `HashValue`s are used as hashes and keys of GraphQL documents,
5 | * variables, and combined, for GraphQL requests.
6 | */
7 | export type HashValue = number & {
8 | /** Marker to indicate that a `HashValue` may not be created by a user.
9 | *
10 | * @remarks
11 | * `HashValue`s are created by {@link phash} and are marked as such to not mix them
12 | * up with other numbers and prevent them from being created or used outside of this
13 | * hashing function.
14 | *
15 | * @internal
16 | */
17 | readonly _opaque: unique symbol;
18 | };
19 |
20 | /** Computes a djb2 hash of the given string.
21 | *
22 | * @param x - the string to be hashed
23 | * @param seed - optionally a prior hash for progressive hashing
24 | * @returns a hash value, i.e. a number
25 | *
26 | * @remark
27 | * This is the hashing function used throughout `urql`, primarily to compute
28 | * {@link Operation.key}.
29 | *
30 | * @see {@link http://www.cse.yorku.ca/~oz/hash.html#djb2} for a further description of djb2.
31 | */
32 | export const phash = (x: string, seed?: HashValue): HashValue => {
33 | let h = (seed || 5381) | 0;
34 | for (let i = 0, l = x.length | 0; i < l; i++)
35 | h = (h << 5) + h + x.charCodeAt(i);
36 | return h as HashValue;
37 | };
38 |
--------------------------------------------------------------------------------
/packages/core/src/utils/index.ts:
--------------------------------------------------------------------------------
1 | export * from './error';
2 | export * from './request';
3 | export * from './result';
4 | export * from './variables';
5 | export * from './collectTypenames';
6 | export * from './formatDocument';
7 | export * from './streamUtils';
8 | export * from './operation';
9 |
10 | export const noop = () => {
11 | /* noop */
12 | };
13 |
--------------------------------------------------------------------------------
/packages/core/src/utils/streamUtils.ts:
--------------------------------------------------------------------------------
1 | import type { Sink, Source } from 'wonka';
2 | import { subscribe, take, filter, toPromise, pipe } from 'wonka';
3 | import type { OperationResult, OperationResultSource } from '../types';
4 |
5 | /** Patches a `toPromise` method onto the `Source` passed to it.
6 | * @param source$ - the Wonka {@link Source} to patch.
7 | * @returns The passed `source$` with a patched `toPromise` method as a {@link PromisifiedSource}.
8 | * @internal
9 | */
10 | export function withPromise(
11 | _source$: Source
12 | ): OperationResultSource {
13 | const source$ = ((sink: Sink) =>
14 | _source$(sink)) as OperationResultSource;
15 | source$.toPromise = () =>
16 | pipe(
17 | source$,
18 | filter(result => !result.stale && !result.hasNext),
19 | take(1),
20 | toPromise
21 | );
22 | source$.then = (onResolve, onReject) =>
23 | source$.toPromise().then(onResolve, onReject);
24 | source$.subscribe = onResult => subscribe(onResult)(source$);
25 | return source$;
26 | }
27 |
--------------------------------------------------------------------------------
/packages/core/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/core/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/packages/introspection/README.md:
--------------------------------------------------------------------------------
1 | @urql/introspection
2 |
3 | Utilities for dealing with Introspection Queries and Client Schemas
4 |
--------------------------------------------------------------------------------
/packages/introspection/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/introspection",
3 | "version": "1.2.1",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/packages/introspection/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './getIntrospectedSchema';
2 | export * from './minifyIntrospectionQuery';
3 |
--------------------------------------------------------------------------------
/packages/introspection/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/next-urql/.gitignore:
--------------------------------------------------------------------------------
1 | /rsc
2 |
--------------------------------------------------------------------------------
/packages/next-urql/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018–2020 Formidable,
4 | Copyright (c) urql GraphQL Team and other contributors
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy
7 | of this software and associated documentation files (the "Software"), to deal
8 | in the Software without restriction, including without limitation the rights
9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 | copies of the Software, and to permit persons to whom the Software is
11 | furnished to do so, subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 | SOFTWARE.
23 |
--------------------------------------------------------------------------------
/packages/next-urql/README.md:
--------------------------------------------------------------------------------
1 | ## `next-urql`
2 |
3 | A set of convenience utilities for using `urql` with Next.js.
4 |
5 | More documentation is available at https://urql.dev/goto/docs/advanced/server-side-rendering/#nextjs
6 | Examples can be found at https://github.com/urql-graphql/urql/tree/main/examples/with-next
7 |
--------------------------------------------------------------------------------
/packages/next-urql/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/next",
3 | "version": "1.1.5",
4 | "exports": {
5 | ".": "./src/index.ts",
6 | "./rsc": "./src/rsc.ts"
7 | },
8 | "exclude": [
9 | "node_modules",
10 | "cypress",
11 | "**/*.test.*",
12 | "**/*.spec.*",
13 | "**/*.test.*.snap",
14 | "**/*.spec.*.snap"
15 | ]
16 | }
--------------------------------------------------------------------------------
/packages/next-urql/src/htmlescape.ts:
--------------------------------------------------------------------------------
1 | // See: https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/src/server/htmlescape.ts
2 | // License: https://github.com/vercel/next.js/blob/6bc07792a4462a4bf921a72ab30dc4ab2c4e1bda/packages/next/license.md
3 |
4 | // This utility is based on https://github.com/zertosh/htmlescape
5 | // License: https://github.com/zertosh/htmlescape/blob/0527ca7156a524d256101bb310a9f970f63078ad/LICENSE
6 |
7 | const ESCAPE_LOOKUP: { [match: string]: string } = {
8 | '&': '\\u0026',
9 | '>': '\\u003e',
10 | '<': '\\u003c',
11 | '\u2028': '\\u2028',
12 | '\u2029': '\\u2029',
13 | };
14 |
15 | export const ESCAPE_REGEX = /[&><\u2028\u2029]/g;
16 |
17 | export function htmlEscapeJsonString(str: string): string {
18 | return str.replace(ESCAPE_REGEX, match => ESCAPE_LOOKUP[match]);
19 | }
20 |
--------------------------------------------------------------------------------
/packages/next-urql/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from 'urql';
2 | export { useQuery } from './useQuery';
3 | export { UrqlProvider, SSRContext } from './Provider';
4 |
--------------------------------------------------------------------------------
/packages/next-urql/src/rsc.ts:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import type { Client } from '@urql/core';
3 |
4 | /** Function to cache an urql-client across React Server Components.
5 | *
6 | * @param makeClient - A function that creates an urql-client.
7 | * @returns an object containing a getClient method.
8 | *
9 | * @example
10 | * ```ts
11 | * import { cacheExchange, createClient, fetchExchange, gql } from '@urql/core';
12 | * import { registerUrql } from '@urql/next/rsc';
13 | * const makeClient = () => {
14 | * return createClient({
15 | * url: 'https://trygql.formidable.dev/graphql/basic-pokedex',
16 | * exchanges: [cacheExchange, fetchExchange],
17 | * });
18 | * };
19 | *
20 | * const { getClient } = registerUrql(makeClient);
21 | * ```
22 | */
23 | export function registerUrql(makeClient: () => Client): {
24 | getClient: () => Client;
25 | } {
26 | // @ts-ignore you exist don't worry
27 | const getClient = React.cache(makeClient);
28 | return {
29 | getClient,
30 | };
31 | }
32 |
--------------------------------------------------------------------------------
/packages/next-urql/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/next-urql/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/packages/preact-urql/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/preact",
3 | "version": "4.1.2",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/packages/preact-urql/src/components/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Mutation';
2 | export * from './Query';
3 | export * from './Subscription';
4 |
--------------------------------------------------------------------------------
/packages/preact-urql/src/hooks/constants.ts:
--------------------------------------------------------------------------------
1 | export const initialState = {
2 | fetching: false,
3 | stale: false,
4 | hasNext: false,
5 | error: undefined,
6 | data: undefined,
7 | extensions: undefined,
8 | operation: undefined,
9 | };
10 |
--------------------------------------------------------------------------------
/packages/preact-urql/src/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './useQuery';
2 | export * from './useMutation';
3 | export * from './useSubscription';
4 |
--------------------------------------------------------------------------------
/packages/preact-urql/src/hooks/useRequest.ts:
--------------------------------------------------------------------------------
1 | import type { DocumentNode } from 'graphql';
2 | import { useRef, useMemo } from 'preact/hooks';
3 | import type {
4 | AnyVariables,
5 | TypedDocumentNode,
6 | GraphQLRequest,
7 | } from '@urql/core';
8 | import { createRequest } from '@urql/core';
9 |
10 | /** Creates a request from a query and variables but preserves reference equality if the key isn't changing
11 | * @internal
12 | */
13 | export function useRequest<
14 | Data = any,
15 | Variables extends AnyVariables = AnyVariables,
16 | >(
17 | query: string | DocumentNode | TypedDocumentNode,
18 | variables: Variables
19 | ): GraphQLRequest {
20 | const prev = useRef>(undefined);
21 | return useMemo(() => {
22 | const request = createRequest(query, variables);
23 | // We manually ensure reference equality if the key hasn't changed
24 | if (prev.current !== undefined && prev.current.key === request.key) {
25 | return prev.current;
26 | } else {
27 | prev.current = request;
28 | return request;
29 | }
30 | }, [query, variables]);
31 | }
32 |
--------------------------------------------------------------------------------
/packages/preact-urql/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from '@urql/core';
2 | export * from './hooks';
3 | export * from './components';
4 | export * from './context';
5 |
--------------------------------------------------------------------------------
/packages/preact-urql/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/preact-urql/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/packages/react-urql/README.md:
--------------------------------------------------------------------------------
1 | # urql
2 |
3 | > A highly customizable and versatile GraphQL client **for React**
4 |
5 | More documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).
6 |
--------------------------------------------------------------------------------
/packages/react-urql/core/index.d.ts:
--------------------------------------------------------------------------------
1 | export * from '@urql/core';
2 |
--------------------------------------------------------------------------------
/packages/react-urql/core/index.esm.js:
--------------------------------------------------------------------------------
1 | export * from '@urql/core';
2 |
--------------------------------------------------------------------------------
/packages/react-urql/core/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require('@urql/core');
2 |
--------------------------------------------------------------------------------
/packages/react-urql/core/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "urql-core",
3 | "private": true,
4 | "main": "index.js",
5 | "module": "index.esm.js",
6 | "types": "index.d.ts",
7 | "dependencies": {
8 | "@urql/core": "^1.7.0"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/packages/react-urql/core/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@urql/core@^1.7.0":
6 | version "1.9.2"
7 | resolved "https://registry.yarnpkg.com/@urql/core/-/core-1.9.2.tgz#bc2880a279dd5ada26527063c7a173fda26abb58"
8 | integrity sha512-0eitjW/HlUAkMTwiWFQyQkcmwAlnWlscH3/AKU1Y5MJUzzehAkOffHFQ9eD5st/0TlKSvehbz/eUAHDq/CnX8w==
9 | dependencies:
10 | wonka "^4.0.7"
11 |
12 | wonka@^4.0.7:
13 | version "4.0.7"
14 | resolved "https://registry.yarnpkg.com/wonka/-/wonka-4.0.7.tgz#b4934685bd2449367bd72ce7770bfe3e6cc8a68b"
15 | integrity sha512-Uhyl2cgWCUksYtU0Jt8MSzKUqK4BVUrewWxnn1YlKL3Zco4sDcCUDkbgH0i762HJs1rtsq03cfzsCWxJKaDgVg==
16 |
--------------------------------------------------------------------------------
/packages/react-urql/cypress.config.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line
2 | const { defineConfig } = require('cypress');
3 | // eslint-disable-next-line
4 | const tsconfigPaths = require('vite-tsconfig-paths').default;
5 |
6 | module.exports = defineConfig({
7 | video: false,
8 |
9 | e2e: {
10 | setupNodeEvents(_on, _config) {
11 | /*noop*/
12 | },
13 | supportFile: false,
14 | },
15 | component: {
16 | specPattern: './**/e2e-tests/*spec.tsx',
17 | devServer: {
18 | framework: 'react',
19 | bundler: 'vite',
20 | viteConfig: {
21 | plugins: [tsconfigPaths()],
22 | server: {
23 | fs: {
24 | allow: ['..'],
25 | },
26 | },
27 | },
28 | },
29 | },
30 | });
31 |
--------------------------------------------------------------------------------
/packages/react-urql/cypress/fixtures/example.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Using fixtures to represent data",
3 | "email": "hello@cypress.io",
4 | "body": "Fixtures are a great way to mock data for responses to routes"
5 | }
6 |
--------------------------------------------------------------------------------
/packages/react-urql/cypress/support/component-index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Components App
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/packages/react-urql/cypress/support/component.js:
--------------------------------------------------------------------------------
1 | // ***********************************************************
2 | // This example support/component.js is processed and
3 | // loaded automatically before your test files.
4 | //
5 | // This is a great place to put global configuration and
6 | // behavior that modifies Cypress.
7 | //
8 | // You can change the location of this file or turn off
9 | // automatically serving support files with the
10 | // 'supportFile' configuration option.
11 | //
12 | // You can read more here:
13 | // https://on.cypress.io/configuration
14 | // ***********************************************************
15 |
16 | import { mount } from 'cypress/react';
17 |
18 | Cypress.Commands.add('mount', mount);
19 |
--------------------------------------------------------------------------------
/packages/react-urql/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "urql",
3 | "version": "4.2.2",
4 | "exports": "src/index.ts",
5 | "exclude": [
6 | "node_modules",
7 | "cypress",
8 | "**/*.test.*",
9 | "**/*.spec.*",
10 | "**/*.test.*.snap",
11 | "**/*.spec.*.snap"
12 | ]
13 | }
--------------------------------------------------------------------------------
/packages/react-urql/src/components/index.ts:
--------------------------------------------------------------------------------
1 | export * from './Mutation';
2 | export * from './Query';
3 | export * from './Subscription';
4 |
--------------------------------------------------------------------------------
/packages/react-urql/src/hooks/__snapshots__/useMutation.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`on initial useEffect > initialises default state 1`] = `
4 | {
5 | "data": undefined,
6 | "error": undefined,
7 | "extensions": undefined,
8 | "fetching": false,
9 | "hasNext": false,
10 | "operation": undefined,
11 | "stale": false,
12 | }
13 | `;
14 |
--------------------------------------------------------------------------------
/packages/react-urql/src/hooks/__snapshots__/useQuery.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`on initial useEffect > initialises default state 1`] = `
4 | {
5 | "data": undefined,
6 | "error": undefined,
7 | "extensions": undefined,
8 | "fetching": true,
9 | "hasNext": false,
10 | "operation": undefined,
11 | "stale": false,
12 | }
13 | `;
14 |
--------------------------------------------------------------------------------
/packages/react-urql/src/hooks/__snapshots__/useSubscription.test.tsx.snap:
--------------------------------------------------------------------------------
1 | // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
2 |
3 | exports[`on initial useEffect > initialises default state 1`] = `
4 | {
5 | "data": undefined,
6 | "error": undefined,
7 | "extensions": undefined,
8 | "fetching": true,
9 | "hasNext": false,
10 | "operation": undefined,
11 | "stale": false,
12 | }
13 | `;
14 |
--------------------------------------------------------------------------------
/packages/react-urql/src/hooks/index.ts:
--------------------------------------------------------------------------------
1 | export * from './useMutation';
2 | export * from './useQuery';
3 | export * from './useSubscription';
4 |
--------------------------------------------------------------------------------
/packages/react-urql/src/hooks/useRequest.test.ts:
--------------------------------------------------------------------------------
1 | // @vitest-environment jsdom
2 | import { gql } from '@urql/core';
3 | import { renderHook } from '@testing-library/react';
4 | import { it, expect } from 'vitest';
5 | import { useRequest } from './useRequest';
6 |
7 | it('preserves instance of request when key has not changed', () => {
8 | const query = gql`
9 | query getUser($name: String) {
10 | user(name: $name) {
11 | id
12 | firstName
13 | lastName
14 | }
15 | }
16 | `;
17 |
18 | let variables = {
19 | name: 'Clara',
20 | };
21 |
22 | const { result, rerender } = renderHook(
23 | ({ query, variables }) => useRequest(query, variables),
24 | { initialProps: { query, variables } }
25 | );
26 |
27 | const resultA = result.current;
28 | expect(resultA).toEqual({
29 | key: expect.any(Number),
30 | query: expect.anything(),
31 | variables: variables,
32 | });
33 |
34 | variables = { ...variables }; // Change reference
35 | rerender({ query, variables });
36 |
37 | const resultB = result.current;
38 | expect(resultA).toBe(resultB);
39 |
40 | variables = { ...variables, test: true } as any; // Change values
41 | rerender({ query, variables });
42 |
43 | const resultC = result.current;
44 | expect(resultA).not.toBe(resultC);
45 | });
46 |
--------------------------------------------------------------------------------
/packages/react-urql/src/hooks/useRequest.ts:
--------------------------------------------------------------------------------
1 | import * as React from 'react';
2 | import type { AnyVariables, DocumentInput, GraphQLRequest } from '@urql/core';
3 | import { createRequest } from '@urql/core';
4 |
5 | /** Creates a request from a query and variables but preserves reference equality if the key isn't changing
6 | * @internal
7 | */
8 | export function useRequest<
9 | Data = any,
10 | Variables extends AnyVariables = AnyVariables,
11 | >(
12 | query: DocumentInput,
13 | variables: Variables
14 | ): GraphQLRequest {
15 | const prev = React.useRef>(
16 | undefined
17 | );
18 |
19 | return React.useMemo(() => {
20 | const request = createRequest(query, variables);
21 | // We manually ensure reference equality if the key hasn't changed
22 | if (prev.current !== undefined && prev.current.key === request.key) {
23 | return prev.current;
24 | } else {
25 | prev.current = request;
26 | return request;
27 | }
28 | }, [query, variables]);
29 | }
30 |
--------------------------------------------------------------------------------
/packages/react-urql/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from '@urql/core';
2 | export * from './context';
3 | export * from './components';
4 | export * from './hooks';
5 |
--------------------------------------------------------------------------------
/packages/react-urql/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/react-urql/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {
5 | test: {
6 | environment: 'jsdom',
7 | },
8 | });
9 |
--------------------------------------------------------------------------------
/packages/site/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # urql-docs
2 |
3 | ## 1.0.0
4 |
5 | ### Major Changes
6 |
7 | - **Goodbye IE11!** 👋 This major release removes support for IE11. All code that is shipped will be transpiled much less and will _not_ be ES5-compatible anymore, by [@kitten](https://github.com/kitten) (See [#2504](https://github.com/urql-graphql/urql/pull/2504))
8 |
--------------------------------------------------------------------------------
/packages/site/dist-prod/open-source/urql:
--------------------------------------------------------------------------------
1 | ../../dist
--------------------------------------------------------------------------------
/packages/site/plugins/assets-fix/node.api.js:
--------------------------------------------------------------------------------
1 | export default () => ({
2 | webpack(config) {
3 | const rules = config.module.rules[0].oneOf;
4 | for (let i = 0; i < rules.length; i++) {
5 | const rule = rules[i];
6 | if (rule.loader === 'url-loader') {
7 | delete rule.options;
8 | rule.query = {
9 | limit: 10000,
10 | name: 'static/[name].[hash:8].[ext]',
11 | };
12 | }
13 | }
14 |
15 | return config;
16 | },
17 | });
18 |
--------------------------------------------------------------------------------
/packages/site/plugins/monorepo-fix/node.api.js:
--------------------------------------------------------------------------------
1 | import { silent as resolveFrom } from 'resolve-from';
2 |
3 | const NODE_MODULES_JS_RE = /node_modules[/\\].*\.js$/;
4 | const REACT_STATIC_RE = /node_modules[/\\]react-static/;
5 |
6 | export default () => ({
7 | webpack: (config, { stage }) => {
8 | if (stage === 'node') {
9 | config.externals = [
10 | ...config.externals,
11 | (context, request, callback) => {
12 | if (/^[./]/.test(request)) {
13 | return callback();
14 | }
15 |
16 | const res = resolveFrom(`${context}/`, request);
17 | if (
18 | res &&
19 | NODE_MODULES_JS_RE.test(res) &&
20 | !REACT_STATIC_RE.test(res)
21 | ) {
22 | return callback(null, `commonjs ${request}`);
23 | } else {
24 | return callback();
25 | }
26 | },
27 | ];
28 | }
29 |
30 | return config;
31 | },
32 | });
33 |
--------------------------------------------------------------------------------
/packages/site/plugins/preact/node.api.js:
--------------------------------------------------------------------------------
1 | export default () => ({
2 | webpack: config => {
3 | config.resolve.alias = {
4 | ...(config.resolve.alias || {}),
5 | react: 'preact/compat',
6 | 'react-dom': 'preact/compat',
7 | };
8 |
9 | return config;
10 | },
11 | });
12 |
--------------------------------------------------------------------------------
/packages/site/public/browserconfig.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | #fff
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/packages/site/public/favicon/favicon-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/packages/site/public/favicon/favicon-16.png
--------------------------------------------------------------------------------
/packages/site/public/favicon/favicon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/packages/site/public/favicon/favicon-192.png
--------------------------------------------------------------------------------
/packages/site/public/favicon/favicon-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/packages/site/public/favicon/favicon-32.png
--------------------------------------------------------------------------------
/packages/site/public/favicon/favicon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/urql-graphql/urql/92a101a5497040641306a783b56d5fc3ee0917b1/packages/site/public/favicon/favicon-512.png
--------------------------------------------------------------------------------
/packages/site/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "urql Documentation",
3 | "short_name": "urql",
4 | "icons": [
5 | {
6 | "src": "./favicon/favicon-32.png",
7 | "sizes": "16x16",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "./favicon/favicon-32.png",
12 | "sizes": "32x32",
13 | "type": "image/png"
14 | },
15 | {
16 | "src": "./favicon/favicon-192.png",
17 | "sizes": "192x192",
18 | "type": "image/png"
19 | },
20 | {
21 | "src": "./favicon/favicon-32.png",
22 | "sizes": "512x512",
23 | "type": "image/png"
24 | }
25 | ],
26 | "theme_color": "#ffffff",
27 | "background_color": "#ffffff",
28 | "display": "standalone"
29 | }
30 |
--------------------------------------------------------------------------------
/packages/site/src/analytics.js:
--------------------------------------------------------------------------------
1 | import React, { Fragment } from 'react';
2 | import PropTypes from 'prop-types';
3 |
4 | let GoogleAnalytics = null;
5 | if (typeof window !== 'undefined') {
6 | GoogleAnalytics = require('react-router-ga');
7 | if (GoogleAnalytics.default) GoogleAnalytics = GoogleAnalytics.default;
8 | }
9 |
10 | export const Analytics = props =>
11 | !GoogleAnalytics ? (
12 |
13 | ) : (
14 | {props.children}
15 | );
16 |
17 | Analytics.propTypes = {
18 | children: PropTypes.element,
19 | };
20 |
--------------------------------------------------------------------------------
/packages/site/src/app.js:
--------------------------------------------------------------------------------
1 | // eslint-disable-next-line react/no-multi-comp
2 |
3 | import React, { useEffect } from 'react';
4 | import { Root, Routes } from 'react-static';
5 | import { ThemeProvider } from 'styled-components';
6 |
7 | import constants from './constants';
8 | import { GlobalStyle } from './styles/global';
9 | import * as theme from './styles/theme';
10 | import Analytics from './google-analytics';
11 | import { initGoogleTagManager } from './google-tag-manager';
12 | import { Loading } from './components/loading';
13 |
14 | const App = () => {
15 | useEffect(() => {
16 | initGoogleTagManager();
17 | }, []);
18 |
19 | return (
20 |
21 |
22 |
23 | }>
24 |
25 |
26 |
27 |
28 |
29 |
30 | );
31 | };
32 |
33 | export default App;
34 |
--------------------------------------------------------------------------------
/packages/site/src/assets/anchor.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const SvgAnchor = props => (
4 |
11 | );
12 |
13 | export default SvgAnchor;
14 |
--------------------------------------------------------------------------------
/packages/site/src/assets/anchor.svg:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
--------------------------------------------------------------------------------
/packages/site/src/assets/burger.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/packages/site/src/assets/chevron.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const SvgChevron = props => (
4 |
11 | );
12 |
13 | export default SvgChevron;
14 |
--------------------------------------------------------------------------------
/packages/site/src/assets/chevron.svg:
--------------------------------------------------------------------------------
1 |
2 |
9 |
--------------------------------------------------------------------------------
/packages/site/src/assets/close.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/site/src/assets/right-triangles.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/packages/site/src/components/body-copy.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const BodyCopy = styled.p`
4 | font-size: 1.4rem;
5 | line-height: 2.2rem;
6 | width: 100%;
7 | text-align: center;
8 | ${p => p.noMargin && 'margin: 0'};
9 | @media (min-width: 768px) {
10 | font-size: 1.5rem;
11 | line-height: 2.4rem;
12 | text-align: left;
13 | }
14 | `;
15 |
--------------------------------------------------------------------------------
/packages/site/src/components/button.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styled, { css } from 'styled-components';
3 |
4 | export const buttonLinkStyling = css`
5 | background: white;
6 | color: #383838;
7 | font-weight: normal;
8 | font-size: 1.4rem;
9 | font-style: normal;
10 | font-stretch: normal;
11 | height: 4rem;
12 | line-height: 4rem;
13 | padding: 0 2rem;
14 | letter-spacing: 0.01rem;
15 | text-align: center;
16 | text-transform: uppercase;
17 | transition: opacity 0.4s ease-out;
18 |
19 | &:hover {
20 | opacity: 0.8;
21 | }
22 | &:active {
23 | opacity: 0.6;
24 | }
25 | `;
26 |
27 | const ButtonNoBorder = styled.button`
28 | border: none;
29 | `;
30 |
31 | export const Button = styled(props => (
32 | {props.children}
33 | ))`
34 | ${buttonLinkStyling}
35 | `;
36 |
--------------------------------------------------------------------------------
/packages/site/src/components/link.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styled from 'styled-components';
3 | import { Link as ReactRouterLink } from 'react-router-dom';
4 |
5 | import { buttonLinkStyling } from './button';
6 |
7 | export const Link = styled(({ isExternal, ...rest }) =>
8 | isExternal ? (
9 |
10 | {rest.children}
11 |
12 | ) : (
13 |
14 | )
15 | )`
16 | ${buttonLinkStyling}
17 | `;
18 |
--------------------------------------------------------------------------------
/packages/site/src/components/panel.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styled, { css } from 'styled-components';
3 | import constants from '../constants';
4 |
5 | const dark = css`
6 | background-color: #0d1129;
7 | `;
8 |
9 | const light = css`
10 | background: ${constants.color};
11 | border-bottom: 1rem solid rgba(0, 0, 0, 0.4);
12 | box-shadow: inset 0 -1rem 0 rgba(0, 0, 0, 0.2);
13 | `;
14 | export const FullWidthContainer = styled.div`
15 | color: #e3eef8;
16 | display: flex;
17 | justify-content: center;
18 | ${p => (p.isLight ? light : dark)};
19 | ${p => p.background && `background: ${p.background}`}
20 | `;
21 |
22 | export const SectionWrapper = styled.div`
23 | flex-direction: column;
24 | align-items: center;
25 | display: flex;
26 | padding: 8rem 4rem;
27 | width: 100%;
28 | @media (min-width: 768px) {
29 | flex-direction: column;
30 | margin: 0 8rem;
31 | padding: 8rem 8rem;
32 | }
33 | `;
34 |
35 | export const PanelSectionWrapper = ({
36 | children,
37 | isLight,
38 | background,
39 | ...rest
40 | }) => (
41 |
42 | {children}
43 |
44 | );
45 |
--------------------------------------------------------------------------------
/packages/site/src/components/scroll-to-top.js:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useRef } from 'react';
2 | import { useLocation } from 'react-router-dom';
3 | import { useMarkdownPage } from 'react-static-plugin-md-pages';
4 |
5 | const parsePathname = pathname => {
6 | const match = pathname && pathname.match(/#[a-z|-]+/);
7 | return match && match[0];
8 | };
9 |
10 | export const ScrollToTop = () => {
11 | const inputRef = useRef(null);
12 | const location = useLocation();
13 | const md = useMarkdownPage();
14 |
15 | const hash = location.hash || parsePathname(location.pathname);
16 |
17 | useEffect(() => {
18 | if (hash && md) {
19 | inputRef.current.click();
20 | } else {
21 | window.scrollTo(0, 0);
22 | }
23 | }, [hash, md]);
24 |
25 | return ;
26 | };
27 |
--------------------------------------------------------------------------------
/packages/site/src/components/secondary-title.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const SecondaryTitle = styled.h3`
4 | color: white;
5 | font-size: 2rem;
6 | line-height: 2.4rem;
7 | margin: 2rem auto 1rem;
8 | text-align: center;
9 | @media (min-width: 768px) {
10 | font-size: 2.2rem;
11 | line-height: 2.6rem;
12 | }
13 | `;
14 |
--------------------------------------------------------------------------------
/packages/site/src/components/section-title.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const SectionTitle = styled.h2`
4 | color: #fff;
5 | font-size: 3.5rem;
6 | flex: auto;
7 | line-height: 1.3;
8 | margin: 0 0 3rem;
9 | width: 100%;
10 | text-align: center;
11 | @media (min-width: 768px) {
12 | font-size: 4.5rem;
13 | margin: 0 0 6rem;
14 | }
15 | `;
16 |
--------------------------------------------------------------------------------
/packages/site/src/components/sidebar-search-input.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import styled from 'styled-components';
4 |
5 | const StyledInput = styled.input`
6 | background-color: rgba(255, 255, 255, 0.8);
7 | border: none;
8 | border-radius: 0.5rem;
9 | color: ${p => p.theme.colors.text};
10 | font-family: ${p => p.theme.fonts.body};
11 | font-size: 1.6rem;
12 | line-height: 2.3rem;
13 | letter-spacing: -0.6px;
14 | margin: ${p =>
15 | `${p.theme.spacing.sm} 0 ${p.theme.spacing.sm} calc(${p.theme.spacing.xs} * -1.5)`};
16 | padding: ${p =>
17 | `${p.theme.spacing.xs} calc(${p.theme.spacing.xs} * 1.5) ${p.theme.spacing.xs}`};
18 | width: calc(100% + 1.8rem);
19 | background-color: ${p => p.theme.colors.passiveBg};
20 |
21 | @media ${p => p.theme.media.sm} {
22 | background-color: ${p => p.theme.colors.bg};
23 | }
24 | `;
25 |
26 | const SidebarSearchInput = ({ value, onHandleInputChange }) => (
27 |
33 | );
34 |
35 | SidebarSearchInput.propTypes = {
36 | value: PropTypes.string,
37 | onHandleInputChange: PropTypes.func,
38 | };
39 |
40 | export default SidebarSearchInput;
41 |
--------------------------------------------------------------------------------
/packages/site/src/components/wrapper.js:
--------------------------------------------------------------------------------
1 | import styled from 'styled-components';
2 |
3 | export const Wrapper = styled.div`
4 | display: flex;
5 | flex-direction: column;
6 | flex-wrap: wrap;
7 | justify-content: space-between;
8 | margin: 0;
9 | padding: ${props => (props.noPadding ? '0 4rem' : '4rem')};
10 | text-align: center;
11 | width: 100%;
12 |
13 | @media (min-width: 768px) {
14 | flex-direction: row;
15 | max-width: 116rem;
16 | padding: ${props => (props.noPadding ? '0 4rem' : '4rem 8rem')};
17 | }
18 |
19 | @media (max-width: 768px) {
20 | padding: ${props => (props.noPadding ? '0 4rem' : '0 8rem')};
21 | text-align: center;
22 | img {
23 | max-width: 240px;
24 | }
25 | }
26 | `;
27 |
--------------------------------------------------------------------------------
/packages/site/src/constants.js:
--------------------------------------------------------------------------------
1 | const constants = {
2 | docsTitle: 'URQL',
3 | githubIssues: 'https://www.github.com/urql-graphql/urql/issues',
4 | github: 'https://www.github.com/urql-graphql/urql',
5 | readme: 'https://github.com/urql-graphql/urql/blob/main/README.md',
6 | color: '#6B78B8',
7 | googleAnalyticsId: 'UA-43290258-1',
8 | };
9 |
10 | export default constants;
11 |
--------------------------------------------------------------------------------
/packages/site/src/google-analytics.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { useBasepath } from 'react-static';
3 | import PropTypes from 'prop-types';
4 |
5 | let Analytics = {};
6 |
7 | if (typeof document !== 'undefined') {
8 | Analytics = require('react-router-ga').default;
9 | } else {
10 | Analytics = React.Fragment;
11 | }
12 |
13 | const GoogleAnalytics = ({ children, ...rest }) => {
14 | const basename = `/${useBasepath() || ''}`;
15 | if (typeof document !== 'undefined') {
16 | // fragment doesn't like it when you try to give it attributes
17 | return (
18 |
19 | {children}
20 |
21 | );
22 | }
23 | return {children};
24 | };
25 |
26 | GoogleAnalytics.propTypes = {
27 | children: PropTypes.element,
28 | };
29 |
30 | export default GoogleAnalytics;
31 |
--------------------------------------------------------------------------------
/packages/site/src/google-tag-manager.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Google Tag Manager
3 | */
4 | const TagManager = require('react-gtm-module');
5 |
6 | export const initGoogleTagManager = () => {
7 | if (typeof document === 'undefined') {
8 | return {};
9 | } else {
10 | return TagManager.initialize({ gtmId: 'GTM-MD32945' });
11 | }
12 | };
13 |
--------------------------------------------------------------------------------
/packages/site/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import { render, hydrate } from 'react-dom';
3 | import { AppContainer } from 'react-hot-loader';
4 |
5 | import App from './app';
6 |
7 | export default App;
8 |
9 | // Render your app
10 | if (typeof document !== 'undefined') {
11 | const renderMethod = module.hot ? render : hydrate;
12 | const mount = Comp => {
13 | renderMethod(
14 |
15 |
16 | ,
17 | document.getElementById('root')
18 | );
19 | };
20 |
21 | mount(App);
22 | if (module.hot) {
23 | module.hot.accept('./app', () => mount(require('./app').default));
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/packages/site/src/screens/404/404.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const NotFound = () => {
4 | return 404! That page does not exist :(
;
5 | };
6 |
7 | export default NotFound;
8 |
--------------------------------------------------------------------------------
/packages/site/src/screens/404/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import Docs from '../docs';
3 | import NotFoundPage from './404';
4 |
5 | const NotFound = () => {
6 | return (
7 |
8 |
9 |
10 | );
11 | };
12 |
13 | export default NotFound;
14 |
--------------------------------------------------------------------------------
/packages/site/src/screens/home/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import styled from 'styled-components';
3 | import { usePrefetch } from 'react-static';
4 | import { useMarkdownTree } from 'react-static-plugin-md-pages';
5 |
6 | import Features from './features';
7 | import GetStarted from './get-started';
8 | import MoreOSS from './more-oss';
9 | import content from './_content';
10 | import { Header } from '../../components/header';
11 | import { Footer } from '../../components/footer';
12 |
13 | const Container = styled.div`
14 | width: 100%;
15 | `;
16 |
17 | const Home = () => {
18 | const ref = usePrefetch('docs');
19 | useMarkdownTree();
20 |
21 | return (
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | );
30 | };
31 |
32 | export default Home;
33 |
--------------------------------------------------------------------------------
/packages/site/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "github": {
3 | "silent": true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/packages/solid-urql/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # @urql/solid
2 |
3 | ## 0.1.2
4 |
5 | ### Patch Changes
6 |
7 | - Omit minified files and sourcemaps' `sourcesContent` in published packages
8 | Submitted by [@kitten](https://github.com/kitten) (See [#3755](https://github.com/urql-graphql/urql/pull/3755))
9 | - Updated dependencies (See [#3755](https://github.com/urql-graphql/urql/pull/3755))
10 | - @urql/core@5.1.1
11 |
12 | ## 0.1.1
13 |
14 | ### Patch Changes
15 |
16 | - Add type for `hasNext` to the query and mutation results
17 | Submitted by [@JoviDeCroock](https://github.com/JoviDeCroock) (See [#3703](https://github.com/urql-graphql/urql/pull/3703))
18 |
19 | ## 0.1.0
20 |
21 | ### Minor Changes
22 |
23 | - Initial release
24 | Submitted by [@stefanmaric](https://github.com/stefanmaric) (See [#3607](https://github.com/urql-graphql/urql/pull/3607))
25 |
26 | ### Patch Changes
27 |
28 | - Export Provider from the entry
29 | Submitted by [@XiNiHa](https://github.com/XiNiHa) (See [#3670](https://github.com/urql-graphql/urql/pull/3670))
30 | - Correctly track query data reads with suspense
31 | Submitted by [@XiNiHa](https://github.com/XiNiHa) (See [#3672](https://github.com/urql-graphql/urql/pull/3672))
32 | - feat(solid): reconcile data updates
33 | Submitted by [@XiNiHa](https://github.com/XiNiHa) (See [#3674](https://github.com/urql-graphql/urql/pull/3674))
34 |
--------------------------------------------------------------------------------
/packages/solid-urql/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/solid",
3 | "version": "0.1.2",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/packages/solid-urql/src/context.ts:
--------------------------------------------------------------------------------
1 | import type { Client } from '@urql/core';
2 | import { createContext, useContext } from 'solid-js';
3 |
4 | export const Context = createContext();
5 | export const Provider = Context.Provider;
6 |
7 | export type UseClient = () => Client;
8 | export const useClient: UseClient = () => {
9 | const client = useContext(Context);
10 |
11 | if (process.env.NODE_ENV !== 'production' && client === undefined) {
12 | const error =
13 | "No client has been specified using urql's Provider. please create a client and add a Provider.";
14 |
15 | console.error(error);
16 | throw new Error(error);
17 | }
18 |
19 | return client!;
20 | };
21 |
--------------------------------------------------------------------------------
/packages/solid-urql/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from '@urql/core';
2 |
3 | export { type UseClient } from './context';
4 | export { useClient, Provider } from './context';
5 |
6 | export {
7 | type CreateMutationState,
8 | type CreateMutationExecute,
9 | type CreateMutationResult,
10 | } from './createMutation';
11 | export { createMutation } from './createMutation';
12 |
13 | export {
14 | type CreateQueryArgs,
15 | type CreateQueryState,
16 | type CreateQueryExecute,
17 | type CreateQueryResult,
18 | } from './createQuery';
19 | export { createQuery } from './createQuery';
20 |
21 | export {
22 | type CreateSubscriptionArgs,
23 | type CreateSubscriptionState,
24 | type CreateSubscriptionExecute,
25 | type CreateSubscriptionResult,
26 | type SubscriptionHandler,
27 | } from './createSubscription';
28 |
29 | export { createSubscription } from './createSubscription';
30 |
--------------------------------------------------------------------------------
/packages/solid-urql/src/utils.ts:
--------------------------------------------------------------------------------
1 | import type { Accessor } from 'solid-js';
2 |
3 | export type MaybeAccessor = T | Accessor;
4 |
5 | export type MaybeAccessorValue> =
6 | T extends () => any ? ReturnType : T;
7 |
8 | export const asAccessor = >(
9 | v: A
10 | ): Accessor> =>
11 | typeof v === 'function' ? (v as any) : () => v;
12 |
--------------------------------------------------------------------------------
/packages/solid-urql/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"],
4 | "compilerOptions": {
5 | "jsx": "preserve",
6 | "jsxImportSource": "solid-js"
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/packages/solid-urql/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import solidPlugin from 'vite-plugin-solid';
3 | import baseConfig from '../../vitest.config';
4 |
5 | export default mergeConfig(baseConfig, {
6 | plugins: [solidPlugin({ hot: false })],
7 | });
8 |
--------------------------------------------------------------------------------
/packages/storage-rn/LICENCE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018–2020 Formidable
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/packages/storage-rn/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/storage-rn",
3 | "version": "1.1.1",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/packages/storage-rn/src/index.ts:
--------------------------------------------------------------------------------
1 | export { makeAsyncStorage } from './makeAsyncStorage';
2 |
--------------------------------------------------------------------------------
/packages/storage-rn/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/storage-rn/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/packages/svelte-urql/README.md:
--------------------------------------------------------------------------------
1 | # @urql/svelte
2 |
3 | > A highly customizable and versatile GraphQL client **for Svelte**
4 |
5 | More documentation is available at [formidable.com/open-source/urql](https://formidable.com/open-source/urql/).
6 |
--------------------------------------------------------------------------------
/packages/svelte-urql/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/svelte",
3 | "version": "4.2.3",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/packages/svelte-urql/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from '@urql/core';
2 |
3 | export type {
4 | Pausable,
5 | OperationResultStore,
6 | OperationResultState,
7 | } from './common';
8 |
9 | export * from './queryStore';
10 | export * from './mutationStore';
11 | export * from './subscriptionStore';
12 | export * from './context';
13 |
--------------------------------------------------------------------------------
/packages/svelte-urql/src/mutationStore.test.ts:
--------------------------------------------------------------------------------
1 | import { print } from 'graphql';
2 | import { createClient } from '@urql/core';
3 | import { get } from 'svelte/store';
4 | import { vi, expect, it, describe } from 'vitest';
5 |
6 | import { mutationStore } from './mutationStore';
7 |
8 | describe('mutationStore', () => {
9 | const client = createClient({
10 | url: 'noop',
11 | exchanges: [],
12 | });
13 |
14 | const variables = {};
15 | const context = {};
16 |
17 | const query =
18 | 'mutation ($input: Example!) { doExample(input: $input) { id } }';
19 | const store = mutationStore({
20 | client,
21 | query,
22 | variables,
23 | context,
24 | });
25 |
26 | it('creates a svelte store', () => {
27 | const subscriber = vi.fn();
28 | store.subscribe(subscriber);
29 | expect(subscriber).toHaveBeenCalledTimes(1);
30 | });
31 |
32 | it('fills the store with correct values', () => {
33 | expect(get(store).operation.kind).toBe('mutation');
34 | expect(get(store).operation.context.url).toBe('noop');
35 | expect(get(store).operation.variables).toBe(variables);
36 |
37 | expect(print(get(store).operation.query)).toMatchInlineSnapshot(`
38 | "mutation ($input: Example!) {
39 | doExample(input: $input) {
40 | id
41 | }
42 | }"
43 | `);
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/packages/svelte-urql/src/queryStore.test.ts:
--------------------------------------------------------------------------------
1 | import { createClient } from '@urql/core';
2 | import { vi, expect, it, describe } from 'vitest';
3 | import { get } from 'svelte/store';
4 |
5 | import { queryStore } from './queryStore';
6 |
7 | describe('queryStore', () => {
8 | const client = createClient({
9 | url: 'https://example.com',
10 | exchanges: [],
11 | });
12 |
13 | const variables = {};
14 | const context = {};
15 | const query = '{ test }';
16 | const store = queryStore({ client, query, variables, context });
17 |
18 | it('creates a svelte store', () => {
19 | const subscriber = vi.fn();
20 | store.subscribe(subscriber);
21 | expect(subscriber).toHaveBeenCalledTimes(1);
22 | });
23 |
24 | it('fills the store with correct values', () => {
25 | expect(get(store).operation.kind).toBe('query');
26 | expect(get(store).operation.context.url).toBe('https://example.com');
27 | expect(get(store).operation.variables).toBe(variables);
28 |
29 | expect(get(store).operation.query.loc?.source.body).toMatchInlineSnapshot(`
30 | "{
31 | test
32 | }"
33 | `);
34 | });
35 |
36 | it('adds pause handles', () => {
37 | expect(get(store.isPaused$)).toBe(false);
38 |
39 | store.pause();
40 | expect(get(store.isPaused$)).toBe(true);
41 |
42 | store.resume();
43 | expect(get(store.isPaused$)).toBe(false);
44 | });
45 | });
46 |
--------------------------------------------------------------------------------
/packages/svelte-urql/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/svelte-urql/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/packages/vue-urql/README.md:
--------------------------------------------------------------------------------
1 |
16 |
17 | ## Installation
18 |
19 | ```sh
20 | yarn add @urql/vue graphql
21 | # or
22 | npm install --save @urql/vue graphql
23 | ```
24 |
25 | > **Note:** `@urql/vue` has a peer dependency on `vue@^3.0.0` (Not v2) and doesn't currently plan to
26 | > be backwards compatible to Vue 2.
27 |
--------------------------------------------------------------------------------
/packages/vue-urql/jsr.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@urql/vue",
3 | "version": "1.4.3",
4 | "exports": {
5 | ".": "./src/index.ts"
6 | },
7 | "exclude": [
8 | "node_modules",
9 | "cypress",
10 | "**/*.test.*",
11 | "**/*.spec.*",
12 | "**/*.test.*.snap",
13 | "**/*.spec.*.snap"
14 | ]
15 | }
--------------------------------------------------------------------------------
/packages/vue-urql/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from '@urql/core';
2 |
3 | export * from './useClientHandle';
4 | export { install, provideClient } from './useClient';
5 |
6 | export { useQuery } from './useQuery';
7 |
8 | export type { UseQueryArgs, UseQueryResponse, UseQueryState } from './useQuery';
9 |
10 | export { useSubscription } from './useSubscription';
11 |
12 | export type {
13 | UseSubscriptionArgs,
14 | UseSubscriptionResponse,
15 | SubscriptionHandlerArg,
16 | SubscriptionHandler,
17 | } from './useSubscription';
18 |
19 | export { useMutation } from './useMutation';
20 |
21 | export type { UseMutationResponse } from './useMutation';
22 |
23 | import { install } from './useClient';
24 |
25 | export default install;
26 |
--------------------------------------------------------------------------------
/packages/vue-urql/src/useClient.test.ts:
--------------------------------------------------------------------------------
1 | // @vitest-environment jsdom
2 |
3 | import { expect, it, describe } from 'vitest';
4 | import { defineComponent } from 'vue';
5 | import { mount } from '@vue/test-utils';
6 | import { Client } from '@urql/core';
7 | import { useClient, provideClient } from './useClient';
8 |
9 | describe('provideClient', () => {
10 | it('provides client to current component instance', async () => {
11 | const TestComponent = defineComponent({
12 | setup() {
13 | provideClient(
14 | new Client({
15 | url: 'test',
16 | exchanges: [],
17 | })
18 | );
19 |
20 | const client = useClient();
21 | expect(client).toBeDefined();
22 | return null;
23 | },
24 | });
25 |
26 | mount(TestComponent);
27 | });
28 | });
29 |
--------------------------------------------------------------------------------
/packages/vue-urql/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../../tsconfig.json",
3 | "include": ["src"]
4 | }
5 |
--------------------------------------------------------------------------------
/packages/vue-urql/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { mergeConfig } from 'vitest/config';
2 | import baseConfig from '../../vitest.config';
3 |
4 | export default mergeConfig(baseConfig, {});
5 |
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - 'packages/*'
3 | - 'exchanges/*'
4 | - '!examples/*'
5 |
--------------------------------------------------------------------------------
/scripts/actions/build-all.mjs:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | import { listPackages } from './lib/packages.mjs';
4 | import { buildPackage } from './lib/commands.mjs';
5 |
6 | (async () => {
7 | try {
8 | const packages = await listPackages();
9 | const builds = packages.map(buildPackage);
10 | await Promise.all(builds);
11 | } catch (e) {
12 | console.error(e.message);
13 | process.exit(1);
14 | }
15 | })();
16 |
--------------------------------------------------------------------------------
/scripts/actions/lib/constants.mjs:
--------------------------------------------------------------------------------
1 | import * as url from 'url';
2 | import * as path from 'path';
3 | import { createRequire } from 'node:module';
4 |
5 | const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
6 | export const workspaceRoot = path.resolve(__dirname, '../../../');
7 |
8 | export const workspaces = ['packages/*', 'exchanges/*'];
9 |
10 | export const require = createRequire(import.meta.url);
11 |
--------------------------------------------------------------------------------
/scripts/actions/lib/github.mjs:
--------------------------------------------------------------------------------
1 | import * as path from 'path';
2 | import { getPackageManifest, getPackageArtifact } from './packages.mjs';
3 | import { DefaultArtifactClient } from '@actions/artifact';
4 |
5 | export const uploadArtifact = async cwd => {
6 | const manifest = getPackageManifest(cwd);
7 | const artifact = getPackageArtifact(cwd);
8 | console.log('> Uploading', manifest.name);
9 |
10 | try {
11 | const client = new DefaultArtifactClient();
12 | await client.uploadArtifact(artifact, [path.resolve(cwd, artifact)], cwd, {
13 | continueOnError: false,
14 | });
15 | } catch (error) {
16 | console.error('> Uploading failed', manifest.name);
17 | throw error;
18 | }
19 | };
20 |
--------------------------------------------------------------------------------
/scripts/actions/pack-all.mjs:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | import { listPackages } from './lib/packages.mjs';
4 | import { preparePackage, packPackage } from './lib/commands.mjs';
5 | import { uploadArtifact } from './lib/github.mjs';
6 |
7 | (async () => {
8 | try {
9 | const isPR = process.env.GITHUB_EVENT_NAME === 'pull_request';
10 | const packages = await listPackages();
11 | const packs = packages.map(async cwd => {
12 | await preparePackage(cwd);
13 | await packPackage(cwd);
14 | if (isPR) {
15 | await uploadArtifact(cwd);
16 | }
17 | });
18 |
19 | await Promise.all(packs);
20 | } catch (e) {
21 | console.error(e.message);
22 | process.exit(1);
23 | }
24 | })();
25 |
--------------------------------------------------------------------------------
/scripts/changesets/jsr.mjs:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | import fs from 'node:fs';
4 | import path from 'node:path';
5 |
6 | import { getPackageManifest, listPackages } from '../actions/lib/packages.mjs';
7 |
8 | const getExports = exports => {
9 | const exportNames = Object.keys(exports);
10 | const eventualExports = {};
11 | for (const exportName of exportNames) {
12 | if (exportName.includes('package.json')) continue;
13 | const exp = exports[exportName];
14 | eventualExports[exportName] = exp.source;
15 | }
16 | return eventualExports;
17 | };
18 |
19 | export const updateJsr = async () => {
20 | (await listPackages()).forEach(dir => {
21 | const manifest = getPackageManifest(dir);
22 | const jsrManifest = {
23 | name: manifest.name,
24 | version: manifest.version,
25 | exports: manifest.exports
26 | ? getExports(manifest.exports)
27 | : manifest.source,
28 | exclude: [
29 | 'node_modules',
30 | 'cypress',
31 | '**/*.test.*',
32 | '**/*.spec.*',
33 | '**/*.test.*.snap',
34 | '**/*.spec.*.snap',
35 | ],
36 | };
37 |
38 | fs.writeFileSync(
39 | path.resolve(dir, 'jsr.json'),
40 | JSON.stringify(jsrManifest, undefined, 2)
41 | );
42 | });
43 | };
44 |
--------------------------------------------------------------------------------
/scripts/prepare/postinstall.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const fs = require('fs');
3 |
4 | const hookSource = path.resolve(
5 | __dirname,
6 | '../../node_modules/husky-v4/sh/husky.sh'
7 | );
8 | const hook = path.resolve(__dirname, '../../.git/hooks/husky.sh');
9 | const localHook = path.resolve(__dirname, '../../.git/hooks/husky.local.sh');
10 | const gitConfig = path.resolve(__dirname, '../../.git/config');
11 |
12 | let script = fs.readFileSync(hookSource, { encoding: 'utf-8' });
13 | script = script.replace(`$(basename "$0")`, `$(basename "$0" .sh)`);
14 |
15 | let config = fs.readFileSync(gitConfig, { encoding: 'utf-8' });
16 | config = config.replace(/\s*hooksPath\s*=\s*\.husky\n?/g, '\n');
17 |
18 | fs.writeFileSync(hook, script);
19 | fs.writeFileSync(gitConfig, config);
20 |
21 | fs.writeFileSync(localHook, 'packageManager=yarn\n' + 'cd "."\n');
22 |
--------------------------------------------------------------------------------
/scripts/rollup/cleanup-plugin.mjs:
--------------------------------------------------------------------------------
1 | import { createFilter } from '@rollup/pluginutils';
2 |
3 | function cleanup() {
4 | const emptyImportRe = /import\s+(?:'[^']+'|"[^"]+")\s*;?/g;
5 | const gqlImportRe = /(import\s+(?:[*\s{}\w\d]+)\s*from\s*'graphql';?)/g;
6 | const dtsFilter = createFilter(/\.d\.ts(\.map)?$/, null, { resolve: false });
7 |
8 | return {
9 | name: 'cleanup',
10 |
11 | renderChunk(input, chunk) {
12 | if (dtsFilter(chunk.fileName)) {
13 | return input
14 | .replace(emptyImportRe, '')
15 | .replace(gqlImportRe, x => '/*@ts-ignore*/\n' + x);
16 | }
17 | },
18 | };
19 | }
20 |
21 | export default cleanup;
22 |
--------------------------------------------------------------------------------
/scripts/vitest/setup.js:
--------------------------------------------------------------------------------
1 | // This script is run before each `.test.ts` file.
2 | globalThis.AbortController = undefined;
3 | globalThis.fetch = vi.fn();
4 |
5 | process.on('unhandledRejection', error => {
6 | throw error;
7 | });
8 |
9 | const originalConsole = console;
10 | globalThis.console = {
11 | ...originalConsole,
12 | warn: (vi.SpyInstance = () => {
13 | /* noop */
14 | }),
15 | error: (vi.SpyInstance = message => {
16 | throw new Error(message);
17 | }),
18 | };
19 |
20 | vi.spyOn(console, 'log');
21 | vi.spyOn(console, 'warn');
22 | vi.spyOn(console, 'error');
23 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "baseUrl": "./",
4 | "paths": {
5 | "urql": ["node_modules/urql/src", "packages/react-urql/src"],
6 | "*-urql": ["node_modules/*-urql/src", "packages/*-urql/src"],
7 | "@urql/exchange-*": [
8 | "node_modules/@urql/exchange-*/src",
9 | "exchanges/*/src"
10 | ],
11 | "@urql/core/*": ["node_modules/@urql/core/src/*", "packages/core/src/*"],
12 | "@urql/devtools": ["node_modules/@urql/devtools"],
13 | "@urql/*": [
14 | "node_modules/@urql/*/src",
15 | "packages/*-urql/src",
16 | "packages/*/src"
17 | ]
18 | },
19 | "esModuleInterop": true,
20 | "isolatedModules": true,
21 | "forceConsistentCasingInFileNames": true,
22 | "noUnusedLocals": true,
23 | "noEmit": true,
24 | "lib": ["dom", "esnext"],
25 | "jsx": "react",
26 | "module": "es2015",
27 | "moduleResolution": "node",
28 | "target": "esnext",
29 | "strict": true,
30 | "noImplicitAny": false,
31 | "noUnusedParameters": true,
32 | "skipLibCheck": true
33 | },
34 | "include": ["packages", "exchanges"],
35 | "exclude": [
36 | "**/e2e-tests",
37 | "**/examples",
38 | "**/dist",
39 | "**/node_modules",
40 | "node_modules",
41 | "scripts"
42 | ]
43 | }
44 |
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "github": {
3 | "silent": true
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import { resolve } from 'path';
2 | import { defineConfig } from 'vitest/config';
3 | import tsconfigPaths from 'vite-tsconfig-paths';
4 |
5 | export default defineConfig({
6 | resolve: {
7 | alias: {
8 | 'preact/hooks':
9 | __dirname +
10 | '/packages/preact-urql/node_modules/preact/hooks/dist/hooks.js',
11 | preact:
12 | __dirname + '/packages/preact-urql/node_modules/preact/dist/preact.js',
13 | },
14 | },
15 | plugins: [tsconfigPaths()],
16 | test: {
17 | globals: true,
18 | setupFiles: [resolve(__dirname, 'scripts/vitest/setup.js')],
19 | clearMocks: true,
20 | exclude: [
21 | 'packages/solid-urql/**',
22 | '**/node_modules/**',
23 | '**/dist/**',
24 | '**/cypress/**',
25 | '**/e2e-tests/**',
26 | '**/.{idea,git,cache,output,temp}/**',
27 | '**/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress}.config.*',
28 | ],
29 | },
30 | });
31 |
--------------------------------------------------------------------------------