NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #3808 most downloaded on npm
The shared core for the highly customizable and versatile GraphQL client
Last release 3 months ago
22 Jun 2026
Release timing varies
gaps range from 2 weeks to 10 months
Nearly every release is documented
notes for 56 of the last 60 stable releases
4 versions withdrawn
withdrawn after publishing
7 years old
283 releases · first in 2020
One column per quarter.
Nothing published for this version
Nothing published for this version
Add type for hasNext to the query and mutation results Submitted by @JoviDeCroock (See #3703)
hasNext to the query and mutation results
Submitted by @JoviDeCroock (See #3703)cacheExchange crashing on cache-only request policies with cache misses due to undefined results
Submitted by @JoviDeCroock (See #3459)Nothing published for this version
add support for Svelte 5 in the peerDependencies Submitted by @itssumitrai (See #3634)
peerDependencies
Submitted by @itssumitrai (See #3634)Nothing published for this version
Nothing published for this version
Mark @urql/core as a peer dependency as well as a regular dependency Submitted by @kitten (See #3579)
text/plain content-type as JSON before bailing out with an error
Submitted by @JoviDeCroock (See #3430)Nothing published for this version
Implement new @defer / @stream transport protocol spec changes Submitted by @JoviDeCroock (See #3389)
@defer / @stream transport protocol spec changes
Submitted by @JoviDeCroock (See #3389)errors but as an object. Adding
a check whether we are really dealing with an Array of errors enables this
Submitted by @JoviDeCroock (See #3395)preferGetMethod: 'force' | 'within-url-limit' not being applied correctly by the Client
Submitted by @Burbenog (See #3403)Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
⚠️ Fix missing teardown operation handling in the ssrExchange. This could lead to duplicate network operations being executed Submitted by @kitten (Se
Nothing published for this version
Omit minified files and sourcemaps' sourcesContent in published packages Submitted by @kitten (See #3755)
Nothing published for this version
Nothing published for this version
Add type for hasNext to the query and mutation results Submitted by @JoviDeCroock (See #3703)
hasNext to the query and mutation results
Submitted by @JoviDeCroock (See #3703)persistedExchange() sees a persisted-miss error for a result that's already seen a persisted-miss error (i.e. two misses). This shouldn't happen unless something is caching persisted errors and we should warn about this appropriately
Submitted by @kitten (See #3442)subscriptionExchange to handle GraphQLError[] received in the error observer callback.
Note: This doesn't strictly check for the GraphQLError shape and only checks for arrays and receiving errors in the ExecutionResult on the next observer callback is preferred and recommended for transports
Submitted by @kitten (See #3346)Nothing published for this version
Mark @urql/core as a peer dependency as well as a regular dependency Submitted by @kitten (See #3579)
persistedExchange if the passed generateHash function resolves to a nullish value. This allows (A)PQ to be selectively disabled for individual operations
Submitted by @kitten (See #3324)formatDocument to output FormattedNode type mapping. The formatter will now annotate added __typename fields with _generated: true, place selection nodes' directives onto a _directives dictionary, and will filter directives to not include "_" underscore prefixed directives in the final query. This prepares us for a feature that allows enhanced client-side directives in Graphcache
Submitted by @kitten (See #3317)Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Add deprecation notice for maskTypename option. Masking typenames in a result is no longer recommended. It’s only useful when multiple pre-conditions…
maskTypename to apply masking earlier in the chain
Submitted by @kitten (See #3298)ssrExchange not formatting query documents using formatDocument. Without this call we'd run the risk of not having __typename available on the client-side when rehydrating
Submitted by @kitten (See #3288)maskTypename option.
Masking typenames in a result is no longer recommended. It’s only
useful when multiple pre-conditions are applied and inferior to
mapping to an input object manually
Submitted by @kitten (See #3299)Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Add missing fetchSubscriptions entry to OperationContext. The Client’s fetchSubscriptions now works properly and can be used to execute subscriptions
fetchSubscriptions entry to OperationContext. The Client’s fetchSubscriptions now works properly and can be used to execute subscriptions as multipart/event-stream requests
Submitted by @kitten (See #3244)fetchSource not working for subscriptions since hasNext isn’t necessarily set
Submitted by @kitten (See #3244)Return AbortController invocation to previous behaviour where it used to be more forceful. It will now properly abort outside of when our generator yi
AbortController invocation to previous behaviour where it used to be more forceful. It will now properly abort outside of when our generator yields results, and hence now also cancels requests again that have already delivered headers but are currently awaiting a response body
Submitted by @kitten (See #3239)Respect additionalTypenames on subscriptions and re-execute queries for them as well, as one would intuitively expect Submitted by @kitten (See #3230)
additionalTypenames on subscriptions and re-execute queries for them as well, as one would intuitively expect
Submitted by @kitten (See #3230)isSubscriptionOperation option in subscriptionExchange to include teardown operations, to avoid confusion
Submitted by @kitten (See #3206)Publish with npm provenance Submitted by @kitten (See #3180)
Handle multipart/mixed variations starting with boundary rather than CRLF and a boundary Submitted by @kitten (See #3172)
Updated dependencies (See #3520, #3553, and #3520)
File and Blob objects with null in variables if multipart request will be started
Submitted by @kitten (See #3169)cache-and-network and network-only operations, while a non-stale response is being waited for
Submitted by @kitten (See #3157)multipart/mixed streams when it randomly occurs in response payloads
Submitted by @kitten (See #3155)reexecuteOperation
Submitted by @kitten (See #3159)Prioritise context.suspense and fallback to checking client.suspense Submitted by @JoviDeCroock (See #3427)
context.suspense and fallback to checking client.suspense
Submitted by @JoviDeCroock (See #3427)queryStore and subscriptionStore not subscribing when writable calls its StartStopNotifier. This caused both stores to be inactive and become unresponsive when they’ve been unsubscribed from once, as they wouldn’t be able to restart their subscriptions to the Client
Submitted by @kitten (See #3331)Updated peer dependency range to include support for Svelte ^4.0.0 Submitted by @ategen3rt (See #3302)
^4.0.0
Submitted by @ategen3rt (See #3302)Update build process to generate correct source maps Submitted by @kitten (See #3201)
⚠️ Fix persistedExchange ignoring teardowns in its initial operation mapping. Since the hash function is promisified, which defers any persisted opera
Update the preferGetForPersistedQueries option to include the 'force' and 'within-url-limit' values from the Client's preferGetMethod option. The defa
preferGetForPersistedQueries option to include the 'force' and 'within-url-limit' values from the Client's preferGetMethod option. The default value of true no longer sets OperationContext's preferGetMethod setting to 'force'. Instead, the value of preferGetForPersistedQueries carries through to the OperationContext's preferGetMethod setting for persisted queries
Submitted by @NWRichmond (See #3192)OperationResult.hasNext and OperationResult.stale to be required fields. If you have a custom exchange creating results, you'll have to add these fields or use the makeResult, mergeResultPatch, or makeErrorResult helpers
Submitted by @kitten (See #3061)handler, which combines subscription events, from mutationStore to subscriptionStore. It’s accidentally been defined and implemented on the wrong store and was meant to be on subscriptionStore
Submitted by @kitten (See #3078)hasNext: true is set, which indicates deferred or streamed results
Submitted by @kitten (See #3103)sourcesContent, including additional source files, and had incorrect paths in some of them
Submitted by @kitten (See #3053)wonka@^6.3.0
Submitted by @kitten (See #3104)urql bindings packages
Submitted by @kitten (See #3079)Client from Context. Previously, urql kept a legacy default client in its context, with default exchanges and calling an API at /graphql. This has now been removed and you will have to create your own Client if you were relying on this behaviour
Submitted by @JoviDeCroock (See #3033)hasNext: true is set, which indicates deferred or streamed results
Submitted by @kitten (See #3103)sourcesContent, including additional source files, and had incorrect paths in some of them
Submitted by @kitten (See #3053)wonka@^6.3.0
Submitted by @kitten (See #3104)urql bindings packages
Submitted by @kitten (See #3079)Remove defaultExchanges from @urql/core and make exchanges a required property on Client construction.
In doing so we make the urql package more tree-shakeable as the three default exchanges are in no code paths
meaning they can be removed if not used.
A migration would look as follows if you are currently creating a client without exchanges
import { createClient, cacheExchange, fetchExchange } from '@urql/core';
const client = createClient({
url: '',
exchanges: [cacheExchange, fetchExchange],
});
Submitted by @JoviDeCroock (See #3033)
Update subscriptionExchange to receive FetchBody instead. In the usual usage of subscriptionExchange (for instance with graphql-ws) you can expect no breaking changes. However, the key and extensions field has been removed and instead the forwardSubscription function receives the full Operation as a second argument
Submitted by @kitten (See #3054)
Remove dependence on graphql package and replace it with @0no-co/graphql.web, which reduces the default bundlesize impact of urql packages to a minimum. All types should remain compatible, even if you use graphql elsewhere in your app, and if other dependencies are using graphql you may alias it to graphql-web-lite
Submitted by @kitten (See #3097)
Update OperationResult.hasNext and OperationResult.stale to be required fields. If you have a custom exchange creating results, you'll have to add these fields or use the makeResult, mergeResultPatch, or makeErrorResult helpers
Submitted by @kitten (See #3061)
Remove getOperationName export from @urql/core
Submitted by @kitten (See #3062)
OperationResultSource from all Client methods (which replaces PromisifiedSource on shortcut methods). This allows not only toPromise() to be called, but it can also be used as an awaitable PromiseLike and has a .subscribe(onResult) method aliasing the subscribe utility from wonka
Submitted by @kitten (See #3060)subscriptionExchange to support incremental results out of the box. If a subscription proactively completes, results are also now updated with hasNext: false
Submitted by @kitten (See #3055)text/event-stream response support. This generally adheres to the GraphQL SSE protocol and GraphQL Yoga push responses, and is an alternative to multipart/mixed
Submitted by @kitten (See #3050)@urql/core. This adds the File/Blob upload support to @urql/core, which effectively deprecates @urql/exchange-multipart-fetch
Submitted by @kitten (See #3051)GraphQLRequest.extensions as spec-extensions input to GraphQL requests
Submitted by @kitten (See #3054)fetchExchange when fetchSubscriptions is turned on
Submitted by @kitten (See #3106)dedupExchange. The functionality of deduplicating queries and subscriptions has now been moved into and absorbed by the Client.
Previously, the Client already started doing some work to share results between
queries, and to avoid dispatching operations as needed. It now only dispatches operations
strictly when the dedupExchange would allow so as well, moving its logic into the
Client
Submitted by @kitten (See #3058)dedupExchange did; by filtering out duplicate operations until either the original operation has been cancelled (teardown) or a first result (without hasNext: true) has come in
Submitted by @kitten (See #3101)sourcesContent, including additional source files, and had incorrect paths in some of them
Submitted by @kitten (See #3053)makeOperation to be called with a partial OperationContext when it’s called to copy an operation. When it receives an Operation as a second argument now, the third argument, the context, will be spread into the prior operation.context
Submitted by @kitten (See #3081)multipart/mixed to end of Accept header to avoid cauing Yoga to unnecessarily use it
Submitted by @JoviDeCroock (See #3039)wonka@^6.3.0
Submitted by @kitten (See #3104)Exchange contract and composeExchanges utility to remove the need to manually call share on either incoming Source<Operation> or forward()’s Source<OperationResult>. This is now taken care of internally in composeExchanges and should make it easier for you to create custom exchanges and for us to explain them
Submitted by @kitten (See #3082)graphql’s built-in TypedQueryDocumentNode typings for type inference
Submitted by @kitten (See #3085)SerializedResult, SSRExchangeParams, SSRExchange, and SSRData) to @urql/core's type exports
Submitted by @kitten (See #3079)GraphQLError shape to rehydrate without passing through a GraphQLError constructor in CombinedError
Submitted by @kitten (See #3087)hasNext and stale passthroughs on caching exchanges
Submitted by @kitten (See #3059)errors from subsequent non-incremental results
Submitted by @kitten (See #3055)request.extensions.persistedQuery to @urql/core to omit sending query as needed
Submitted by @kitten (See #3057)fromAsyncIterable.
This also further hardens our support for the "Incremental Delivery" specification and
refactors its implementation and covers more edge cases
Submitted by @kitten (See #3043)CombinedErrors, while downstream errors are re-thrown
Submitted by @kitten (See #3063)Client result source construction code and allow multiple mutation
results, if result.hasNext on a mutation result is set to true, indicating
deferred or streamed results
Submitted by @kitten (See #3102)import { visit } from 'graphql'; with smaller but functionally equivalent alternative
Submitted by @kitten (See #3097)⚠️ Fix generated empty Variables type as passed to generics, that outputs a type of { [var: string]: never; }. A legacy/unsupported version of typescr
Variables type as passed to generics, that outputs a type of { [var: string]: never; }.
A legacy/unsupported version of typescript-urql, which wraps urql's React hooks, generates
empty variables types as the following code snippet, which is not detected:type Exact<T extends { [key: string]: unknown }> = { [K in keyof T]: T[K] };
type Variables = Exact<{ [key: string]: never }>;
Submitted by @kitten (See #3029)Bump to @urql/core@3.2.1 due to invalid 3.2.0 release Submitted by @kitten (See `a84268db`)
Nothing published for this version
Correctly mark cache-hits from the ssr-exchange, by @JoviDeCroock (See #2872)
@urql/core's stringifyDocument that caused some formatted documents to not be reprinted, by @JoviDeCroock (See #2871)Implement mapExchange, which replaces errorExchange, allowing onOperation and onResult to be called to either react to or replace operations and resul
mapExchange, which replaces errorExchange, allowing onOperation and onResult to be called to either react to or replace operations and results. For backwards compatibility, this exchange is also exported as errorExchange and supports onError, by @kitten (See #2846)Variables generics over from object default to Variables extends AnyVariables = AnyVariables. This has been introduced previously in #2607 but some missing ports have been missed due to TypeScript not catching them previously. Depending on your TypeScript version the object default is incompatible with AnyVariables, by @kitten (See #2843)stringifyDocument in place of repeated print. This will mean that we now prevent calling print repeatedly for identical operations and are instead only reusing the result once.
This change has a subtle consequence of our internals. Operation keys will change due to this
refactor and we will no longer sanitise strip newlines from queries that @urql/core has printed, by @kitten (See #2847)wonka@^6.1.2 to fix memory leak in fetch caused in Node.js by a lack of clean up after initiating a request, by @kitten (See #2850)Update typings of the client to encompass the changes of , by @c-schwan (See #2758)
compose.ts with the latest found exchange, in this case fetchExchange, by @JoviDeCroock (See #2762)⚠️ Fix type utilities turning the variables properties optional when a type from TypedDocumentNode has no Variables or all optional Variables. Previou
variables properties optional when a type from TypedDocumentNode has no Variables or all optional Variables. Previously this would break for wrappers, e.g. in code generators, or when the type didn't quite match what we'd expect
Submitted by @kitten (See #3022)ssrExchange bug which prevented staleWhileRevalidate from sending off requests as network-only requests, and caused unrelated network-only operations to be dropped, by @kitten (See #2691)preferGetMethod: 'force' rather than the default true or 'within-url-limit' value, by @kitten (See #2692)@urql/core only, this change also affects the offlineExchange in @urql/exchange-graphcache due to it relying on the identity being previously an object rather than an integer, by @kitten (See #2732)⚠️ Fix type utilities turning the variables properties optional when a type from TypedDocumentNode has no Variables or all optional Variables. Previou
variables properties optional when a type from TypedDocumentNode has no Variables or all optional Variables. Previously this would break for wrappers, e.g. in code generators, or when the type didn't quite match what we'd expect
Submitted by @kitten (See #3022)Move remaining Variables generics over from object default to Variables extends AnyVariables = AnyVariables. This has been introduced previously in #2
Variables generics over from object default to Variables extends AnyVariables = AnyVariables. This has been introduced previously in #2607 but some missing ports have been missed due to TypeScript not catching them previously. Depending on your TypeScript version the object default is incompatible with AnyVariables, by @kitten (See #2843)Publish with npm provenance Submitted by @kitten (See #3180)
context.requestPolicy: undefined
from our bindings which makes a spread override the client-set default, by @JoviDeCroock (See #2634)Remove persistedFetchExchange and instead implement persistedExchange. This exchange must be placed in front of a terminating exchange (such as the de
persistedFetchExchange and instead implement persistedExchange. This exchange must be placed in front of a terminating exchange (such as the default fetchExchange or a subscriptionExchange that supports persisted queries), and only modifies incoming operations to contain extensions.persistedQuery, which is sent on via the API. If the API expects Automatic Persisted Queries, requests are retried by this exchange internally
Submitted by @kitten (See #3057)@urql/exchange-persisted-fetch to @urql/exchange-persisted
Submitted by @kitten (See #3057)share calls, since @urql/core’s composeExchanges utility now automatically does so for us
Submitted by @kitten (See #3082)wonka@^6.3.0
Submitted by @kitten (See #3104)wonka@^6.0.0), which has no breaking changes but is built to target ES2015 and comes with other minor improvements.
The library has fully been migrated to TypeScript which will hopefully help with making contributions easier!, by @kitten (See #2504)Client and Client.createOperationContext. We've noticed that there's no real need for createOperationContext or the options on the Client and that it actually encourages modifying properties on the Client that are really meant to be modified dynamically via exchanges, by @kitten (See #2619)wonka@^6.0.0), which has no breaking changes but is built to target ES2015 and comes with other minor improvements.
The library has fully been migrated to TypeScript which will hopefully help with making contributions easier!, by @kitten (See #2504)babel-plugin-modular-graphql helper, this because the graphql package hasn't converted to ESM yet which gives issues in node environments, by @JoviDeCroock (See #2551)We urgently recommend all users of the React bindings to upgrade to this patch!
We urgently recommend all users of the React bindings to upgrade to this patch!
Please don't forget to deduplicate your installed version of @urql/core after you upgrade.
setState) may recursively schedule a mount, which then disabled other setState updates from being processed. Previously we assumed that React used a trampoline scheduler for updates, however it appears that setState can recursively start more React work, by @kitten (See #2556)Your coding agent can read these notes before it upgrades. Set up the MCP server →