Releases: apollographql/apollo-client
@apollo/[email protected]
Major Changes
-
#12644
fe2f005
Thanks @jerelmiller! - Replace theresult
property onServerError
withbodyText
.bodyText
is set to the raw string body.HttpLink
andBatchHttpLink
no longer try and parse the response body as JSON when aServerError
is thrown. -
#12644
fe2f005
Thanks @jerelmiller! - More strictly adhere to the GraphQL over HTTP spec. This change adds support for theapplication/graphql-response+json
media type and modifies the behavior of theapplication/json
media type.- The client will parse the response as a well-formed GraphQL response when the server encodes
content-type
usingapplication/graphql-response+json
with a non-200 status code. - The client will now throw a
ServerError
when the server encodescontent-type
usingapplication/json
and returns a non-200 status code. - The client will now throw a
ServerError
when the server encodes using any othercontent-type
and returns a non-200 status code.
NOTE: If you use a testing utility to mock requests in your test, you may experience different behavior than production if your testing utility responds as
application/json
but your production server responds asapplication/graphql-response+json
. If acontent-type
header is not set, the client interprets the response asapplication/json
. - The client will parse the response as a well-formed GraphQL response when the server encodes
-
#12644
fe2f005
Thanks @jerelmiller! - Change the defaultAccept
header toapplication/graphql-response+json,application/json;q=0.9
. -
#12644
fe2f005
Thanks @jerelmiller! -HttpLink
andBatchHttpLink
no longer emit anext
notification with the JSON-parsed response body when a well-formed GraphQL response is returned and aServerError
is thrown.
@apollo/[email protected]
Major Changes
-
#12617
ea633a1
Thanks @jerelmiller! - Introduce a new GraphQL Codegen plugin aimed at creating resolver types forLocalState
. This plugin is similar to@graphql-codegen/typescript-resolvers
but tailored to provide types that work withLocalState
.To use the plugin, install
@apollo/client-graphql-codegen
and add the following to your codegen config:// codegen.ts const config: CodegenConfig = { // ... generates: { "./path/to/local/resolvers.ts": { schema: ["./path/to/localSchema.graphql"], plugins: ["typescript", "@apollo/client-graphql-codegen/local-state"], // ... }, }, };
This will generate a
Resolvers
type in the generated file that can be used to provide type information toLocalState
.import type { Resolvers } from "./path/to/resolvers-types.ts"; const localState = new LocalState<Resolvers>({ // ... });
It is also recommended to add the following config:
// codegen.ts import type { LocalStatePluginConfig } from "@apollo/client-graphql-codegen/local-state"; const config: CodegenConfig = { // ... generates: { "./path/to/local/resolvers.ts": { config: { // Ensures you return a `__typename` for any `@client` fields that // return object or array types nonOptionalTypename: true, // Required if your localSchema extends existing schema types. baseTypesPath: "./relative/path/to/base/schema/types", // If you provide a `context` function to customize the context value, // provide the path or type here. contextType: "./path/to/contextValue#ContextValue", } satisfies LocalStatePluginConfig, }, }, };
NOTE: It is recommended that the schema file passed to the
schema
option is your local schema, not your entire app schema in order to only generate resolver types for your local fields, otherwise the plugin will generate resolver types for your entire remote schema as well.
v4.0.0-alpha.15
Major Changes
-
#12639
1bdf489
Thanks @jerelmiller! - Move internal testing utilities in@apollo/client/testing
to@apollo/client/testing/internal
and remove deprecated testing utilities. Some of the testing utilities exported from the@apollo/client/testing
endpoint were not considered stable. As a result of this change, testing utilities or types exported from@apollo/client/testing
are now considered stable and will not undergo breaking changes.The following APIs were removed. To migrate, update usages of the following APIs as such:
createMockClient
- const client = createMockClient(data, query, variables); + const client = new ApolloClient({ + cache: new InMemoryCache(), + link: new MockLink([ + { + request: { query, variables }, + result: { data }, + } + ]), + });
mockObservableLink
- const link = mockObservableLink(); + const link = new MockSubscriptionLink();
mockSingleLink
- const link = mockSingleLink({ - request: { query, variables }, - result: { data }, - }); + const link = new MockLink([ + { + request: { query, variables }, + result: { data }, + } + ]);
-
#12637
d2a60d4
Thanks @phryneas! -useQuery
: only advancepreviousData
ifdata
actually changed -
#12631
b147cac
Thanks @phryneas! -ObservableQuery
will now return aloading: false
state forfetchPolicy
standby
, even before subscription -
#12639
1bdf489
Thanks @jerelmiller! - Remove the@apollo/client/testing/core
entrypoint in favor of@apollo/client/testing
.
Minor Changes
-
#12639
1bdf489
Thanks @jerelmiller! - MoveMockLink
types toMockLink
namespace. This affects theMockedResponse
,MockLinkOptions
, andResultFunction
types. These types are still exported but are deprecated in favor of the namespace. To migrate, use the types on theMockLink
namespace instead.import { - MockedResponse, - MockLinkOptions, - ResultFunction, + MockLink } from "@apollo/client/testing"; - const mocks: MockedResponse = []; + const mocks: MockLink.MockedResponse = []; - const result: ResultFunction = () => {/* ... */ } + const result: MockLink.ResultFunction = () => {/* ... */ } - const options: MockLinkOptions = {} + const options: MockLink.Options = {}
Patch Changes
v4.0.0-alpha.14
Major Changes
-
#12614
d2851e2
Thanks @jerelmiller! - ThegetCacheKey
function is no longer available fromoperation.getContext()
in the link chain. Useoperation.client.cache.identify(obj)
in the link chain instead. -
#12556
c3fceda
Thanks @phryneas! -ObservableQuery
will now keep previousdata
around when emitting aloading
state, unlessquery
orvariables
changed.
Note that@exports
variables are not taken into account for this, sodata
will stay around even if they change. -
#12556
c3fceda
Thanks @phryneas! - RemovedgetLastResult
,getLastError
andresetLastResults
fromObservableQuery
-
#12614
d2851e2
Thanks @jerelmiller! - Removes theresolvers
option fromApolloClient
. Local resolvers have instead been moved to the newLocalState
instance which is assigned to thelocalState
option inApolloClient
. To migrate, move theresolvers
values into aLocalState
instance and assign that instance tolocalState
.new ApolloClient({ - resolvers: { /* ... */ } + localState: new LocalState({ + resolvers: { /* ... */ } + }), });
-
#12614
d2851e2
Thanks @jerelmiller! - Remove local resolvers APIs fromApolloClient
in favor oflocalState
. Methods removed are:addResolvers
getResolvers
setResolvers
setLocalStateFragmentMatcher
-
#12614
d2851e2
Thanks @jerelmiller! - Third-party caches must now implement thefragmentMatches
API. AdditionallyfragmentMatches
must be able to handle bothInlineFragmentNode
andFragmentDefinitionNode
nodes.class MyCache extends ApolloCache { // This is now required public fragmentMatches( fragment: InlineFragmentNode | FragmentDefinitionNode, typename: string ): boolean { return; // ... logic to determine if typename matches fragment } }
-
#12556
c3fceda
Thanks @phryneas! - Reworked the logic for then a loading state is triggered. If the link chain responds synchronously, a loading state will be omitted, otherwise it will be triggered.
If local resolvers are used, the time window for "sync vs async" starts as soon as@exports
variables are resolved. -
#12556
c3fceda
Thanks @phryneas! - Dropped thesaveAsLastResult
argument fromObservableQuery.getCurrentResult
-
#12614
d2851e2
Thanks @jerelmiller! - The resolver function'scontext
argument (the 3rd argument) has changed to provide additional information without the possibility of name clashes. Previously thecontext
argument would spread request context and override theclient
andcache
properties to give access to both inside of a resolver. Thecontext
argument takes now takes the following shape:{ // the request context. By default `TContextValue` is of type `DefaultContext`, // but can be changed if a `context` function is provided. requestContext: TContextValue, // The client instance making the request client: ApolloClient, // Whether the resolver is run as a result of gathering exported variables // or resolving the value as part of the result phase: "exports" | "resolve" }
To migrate, pull any request context from
requestContext
and thecache
from theclient
property:new LocalState({ resolvers: { Query: { - myResolver: (parent, args, { someValue, cache }) => { + myResolver: (parent, args, { requestContext, client }) => { + const someValue = requestContext.someValue; + const cache = client.cache; } } } });
-
#12614
d2851e2
Thanks @jerelmiller! - Apollo Client no longer ships with support for@client
fields out-of-the-box and now must be opt-in. To opt in to use@client
fields, pass an instantiatedLocalState
instance to thelocalState
option. If a query contains@client
and local state hasn't been configured, an error will be thrown.import { LocalState } from "@apollo/client/local-state"; new ApolloClient({ localState: new LocalState(), });
-
#12614
d2851e2
Thanks @jerelmiller! - Remove thefragmentMatcher
option fromApolloClient
. Custom fragment matchers used with local state are no longer supported. Fragment matching is now performed by the configuredcache
via thecache.fragmentMatches
API. -
#12556
c3fceda
Thanks @phryneas! - A call toObservableQuery.setVariables
with different variables or aObservableQuery.refetch
call will always now guarantee that a value will be emitted from the observable, even if it is deep equal to the previous value.
Minor Changes
-
#12614
d2851e2
Thanks @jerelmiller! - Revamp local resolvers and fix several issues from the existingresolvers
option.- Throwing errors in a resolver will set the field value as
null
and add an error to the response'serrors
array. - Remote results are dealiased before they are passed as the parent object to a resolver so that you can access fields by their field name.
- You can now specify a
context
function that you can use to customize therequestContext
given to resolvers. - The
LocalState
class accepts aResolvers
generic that provides autocompletion and type checking against your resolver types to ensure your resolvers are type-safe. data: null
is now handled correctly and does not call your local resolvers when the server does not provide a result.- Additional warnings have been added to provide hints when resolvers behave unexpectedly.
import { LocalState } from "@apollo/client/local-state"; import { Resolvers } from "./path/to/local-resolvers-types.ts"; // LocalState now accepts a `Resolvers` generic. const localState = new LocalState<Resolvers>({ // The return value of this funciton context: (options) => ({ // ... }), resolvers: { // ... }, }); // You may also pass a `ContextValue` generic used to ensure the `context` // function returns the correct type. This type is inferred from your resolvers // if not provided. new LocalState<Resolvers, ContextValue>({ // ... });
- Throwing errors in a resolver will set the field value as
v4.0.0-alpha.13
Major Changes
-
#12600
34ff6aa
Thanks @jerelmiller! - Move most of the utilities in@apollo/client/utilities
to@apollo/client/utilities/internal
. Many of the utilities exported from the@apollo/client/utilities
endpoint were not considered stable.As a result of this change, utilities or types exported from
@apollo/client/utilities
are now documented and considered stable and will not undergo breaking changes. -
#12595
60bb49c
Thanks @jerelmiller! - Remove the@apollo/client/testing/experimental
test utilities. Use GraphQL Testing Library instead.
Patch Changes
- #12618
e4a3ecf
Thanks @jerelmiller! - Remove code that strips@client
fields inHttpLink
andBatchHttpLink
. This was unused code since core handles removing@client
fields and should have no observable change.
v4.0.0-alpha.12
Major Changes
-
#12586
605db8e
Thanks @jerelmiller! - Remove thetypeDefs
option fromApolloClient
. -
#12588
eed825a
Thanks @jerelmiller! - RemoveTContext
generic argument from all types that use it.TContext
is replaced withDefaultContext
which can be modified using declaration merging. -
#12590
a005e82
Thanks @jerelmiller! - Dropgraphql
v15 as a valid peer dependency. -
#12591
a7e7383
Thanks @jerelmiller! - Rename the@apollo/client/link/core
entrypoint to@apollo/client/link
. -
#12589
15f5a1c
Thanks @jerelmiller! - Require thelink
option when instantiatingApolloClient
. This removes theuri
,credentials
andheaders
options fromApolloClient
in favor of passing an instantiatedHttpLink
directly. To migrate:If using
uri
,credentials
, orheaders
optionsnew ApolloClient({ // ... - uri, - credentials, - headers, + link: new HttpLink({ uri, credentials, headers }), // or if you prefer the function call approach: + link: createHttpLink({ uri, credentials, headers }), });
If creating a client without the
link
optionnew ApolloClient({ // ... + link: ApolloLink.empty() });
v4.0.0-alpha.11
Major Changes
-
#12576
a92ff78
Thanks @jerelmiller! - Thecache
andforceFetch
properties are no longer available on context when callingoperation.getContext()
.cache
can be accessed through theoperation
withoperation.client.cache
instead.forceFetch
has been replaced withqueryDeduplication
which specifies whetherqueryDeduplication
was enabled for the request or not. -
#12576
a92ff78
Thanks @jerelmiller! -ApolloLink.execute
now requires a third argument which provides theclient
that initiated the request to the link chain. If you useexecute
directly, add a third argument with aclient
property:ApolloLink.execute(link, operation, { client }); // or if you import the `execute` function directly: execute(link, operation, { client });
-
#12566
ce4b488
Thanks @jerelmiller! - Don'tbroadcastQueries
when a query is torn down.
Minor Changes
-
#12576
a92ff78
Thanks @jerelmiller! - Provide an extension to define types forcontext
passed to the link chain. To define your own types, use declaration merging to add properties to theDefaultContext
type.// @apollo-client.d.ts // This import is necessary to ensure all Apollo Client imports // are still available to the rest of the application. import "@apollo/client"; declare module "@apollo/client" { interface DefaultContext extends Record<string, any> { myProperty: string; } }
Links that provide context options can be used with this type to add those context types to
DefaultContext
. For example, to add context options fromHttpLink
, add the following code:import { HttpLink } from "@apollo/client"; declare module "@apollo/client" { interface DefaultContext extends HttpLink.ContextOptions { myProperty: string; } }
At this time, the following built-in links support context options:
HttpLink.ContextOptions
BatchHttpLink.ContextOptions
-
#12576
a92ff78
Thanks @jerelmiller! - Add aclient
property to theoperation
passed to the link chain. Thisclient
is set as theclient
making the request to the link chain.
Patch Changes
-
#12574
0098ec9
Thanks @jerelmiller! - Exportgql
from the@apollo/client/react
entrypoint. -
#12572
3dc50e6
Thanks @jerelmiller! - AdjustuseMutation
types to better handle required variables. When required variables are missing, TypeScript will now complain if they are not provided either to the hook or the returnedmutate
function. Providing required variables touseMutation
will make them optional in the returnedmutate
function.
v4.0.0-alpha.10
Major Changes
-
#12559
49ace0e
Thanks @jerelmiller! -ObservableQuery.variables
can now be reset back to empty when callingreobserve
withvariables: undefined
. Previously thevariables
key would be ignored sovariables
would remain unchanged. -
#12559
49ace0e
Thanks @jerelmiller! -never
is no longer supported as a validTVariables
generic argument for APIs that requirevariables
as part of its type. UseRecord<string, never>
instead. -
#12559
49ace0e
Thanks @jerelmiller! - When passing avariables
key with the valueundefined
, the value will be replaced by the default value in the query, if it is provided, rather than leave it asundefined
.// given this query const query = gql` query PaginatedQuery($limit: Int! = 10, $offset: Int) { list(limit: $limit, offset: $offset) { id } } `; const observable = client.query({ query, variables: { limit: 5, offset: 0 }, }); console.log(observable.variables); // => { limit: 5, offset: 0 } observable.reobserve({ variables: { limit: undefined, offset: 10 } }); // limit is now `10`. This would previously be `undefined` console.log(observable.variables); // => { limit: 10, offset: 10 }
-
#12562
90bf0e6
Thanks @jerelmiller! -client.query
no longer supports afetchPolicy
ofstandby
.standby
does not fetch and did not returndata
.standby
is meant for watched queries where fetching should be on hold.
Minor Changes
-
#12557
51d26ae
Thanks @jerelmiller! - Add ability to specify message formatter forCombinedGraphQLErrors
andCombinedProtocolErrors
. To provide your own message formatter, override the staticformatMessage
property on these classes.CombinedGraphQLErrors.formatMessage = ( errors, { result, defaultFormatMessage } ) => { return "Some formatted message"; }; CombinedProtocolErrors.formatMessage = (errors, { defaultFormatMessage }) => { return "Some formatted message"; };
-
#12546
5dffbbe
Thanks @jerelmiller! - Add a staticis
method to error types defined by Apollo Client.is
makes it simpler to determine whether an error is a specific type, which can be helpful in cases where you'd like to narrow the error type in order to use specific properties from that error.This change applies to the following error types:
CombinedGraphQLErrors
CombinedProtocolErrors
ServerError
ServerParseError
UnconventionalError
Example
import { CombinedGraphQLErrors } from "@apollo/client"; if (CombinedGraphQLErrors.is(error)) { console.log(error.message); error.errors.forEach((graphQLError) => console.log(graphQLError.message)); }
-
#12561
99d72bf
Thanks @jerelmiller! - Add the ability to detect if an error was an error was emitted from the link chain. This is useful if your application throws custom errors in other areas of the application and you'd like to differentiate them from errors emitted by the link chain itself.To detect if an error was emitted from the link chain, use
LinkError.is
.import { LinkError } from "@apollo/client"; client.query({ query }).catch((error) => { if (LinkError.is(error)) { // This error originated from the link chain } });
Patch Changes
-
#12559
49ace0e
Thanks @jerelmiller! - Thevariables
option used with various APIs are now enforced more consistently across the client whenTVariables
contains required variables. If requiredvariables
are not provided, TypeScript will now complain that it requires avariables
option.This change affects the following APIs:
client.query
client.mutate
client.subscribe
client.watchQuery
useBackgroundQuery
useQuery
useSubscription
useSuspenseQuery
-
#12559
49ace0e
Thanks @jerelmiller! - Fix type ofvariables
returned fromuseLazyQuery
. Whencalled
isfalse
,variables
is nowPartial<TVariables>
instead ofTVariables
. -
#12562
90bf0e6
Thanks @jerelmiller! -client.query
no longer supportsnotifyOnNetworkStatusChange
in options. An error will be thrown if this option is set. The effects of this option were not observable byclient.query
sinceclient.query
emits a single result. -
#12557
51d26ae
Thanks @jerelmiller! - Update format of the error message forCombinedGraphQLErrors
andCombinedProtocolErrors
to be more like v3.x.console.log(error.message); - `The GraphQL server returned with errors: - - Email not found - - Username already in use` + `Email not found + Username already in use`
-
#12559
49ace0e
Thanks @jerelmiller! -ObservableQuery.variables
has been updated to returnTVariables
rather thanTVariables | undefined
. This is more consistent with the runtime value where an empty object ({}
) will be returned when thevariables
option is not provided.
v3.13.8
v4.0.0-alpha.9
Major Changes
-
#12536
e14205a
Thanks @jerelmiller! - An initial loading state is now emitted fromObservableQuery
when subscribing ifnotifyOnNetworkStatusChange
is set totrue
. -
#12512
e809b71
Thanks @jerelmiller! -notifyOnNetworkStatusChange
now defaults totrue
. This means that loading states will be emitted (core API) or rendered (React) by default when callingrefetch
,fetchMore
, etc. To maintain the old behavior, setnotifyOnNetworkStatusChange
tofalse
indefaultOptions
.new ApolloClient({ defaultOptions: { watchQuery: { // Use the v3 default notifyOnNetworkStatusChange: false, }, }, });
Patch Changes
-
#12536
e14205a
Thanks @jerelmiller! - The returnednetworkStatus
inuseLazyQuery
is now set tosetVariables
when calling theuseLazyQuery
execute
function for the first time with variables. -
#12536
e14205a
Thanks @jerelmiller! - EnsureObservableQuery
stops polling if switching to astandby
fetchPolicy
. When switching back to a non-standby
fetchPolicy
, polling will resume. -
#12536
e14205a
Thanks @jerelmiller! - Ensure a loading state is emitted when calling theexecute
function after changing clients inuseLazyQuery
. -
#12542
afb4fce
Thanks @jerelmiller! - EnsureuseLazyQuery
does not return apartial
property which is not specified by the result type.