Skip to content

Releases: apollographql/apollo-client

@apollo/[email protected]

28 May 22:54
Compare
Choose a tag to compare
Pre-release

Major Changes

  • #12644 fe2f005 Thanks @jerelmiller! - Replace the result property on ServerError with bodyText. bodyText is set to the raw string body. HttpLink and BatchHttpLink no longer try and parse the response body as JSON when a ServerError is thrown.

  • #12644 fe2f005 Thanks @jerelmiller! - More strictly adhere to the GraphQL over HTTP spec. This change adds support for the application/graphql-response+json media type and modifies the behavior of the application/json media type.

    • The client will parse the response as a well-formed GraphQL response when the server encodes content-type using application/graphql-response+json with a non-200 status code.
    • The client will now throw a ServerError when the server encodes content-type using application/json and returns a non-200 status code.
    • The client will now throw a ServerError when the server encodes using any other content-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 as application/graphql-response+json. If a content-type header is not set, the client interprets the response as application/json.

  • #12644 fe2f005 Thanks @jerelmiller! - Change the default Accept header to application/graphql-response+json,application/json;q=0.9.

  • #12644 fe2f005 Thanks @jerelmiller! - HttpLink and BatchHttpLink no longer emit a next notification with the JSON-parsed response body when a well-formed GraphQL response is returned and a ServerError is thrown.

@apollo/[email protected]

28 May 22:54
Compare
Choose a tag to compare
Pre-release

Major Changes

  • #12617 ea633a1 Thanks @jerelmiller! - Introduce a new GraphQL Codegen plugin aimed at creating resolver types for LocalState. This plugin is similar to @graphql-codegen/typescript-resolvers but tailored to provide types that work with LocalState.

    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 to LocalState.

    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

23 May 22:30
1326540
Compare
Choose a tag to compare
v4.0.0-alpha.15 Pre-release
Pre-release

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 advance previousData if data actually changed

  • #12631 b147cac Thanks @phryneas! - ObservableQuery will now return a loading: false state for fetchPolicy 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! - Move MockLink types to MockLink namespace. This affects the MockedResponse, MockLinkOptions, and ResultFunction types. These types are still exported but are deprecated in favor of the namespace. To migrate, use the types on the MockLink 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

  • #12631 b147cac Thanks @phryneas! - When updating skip from false to true in useQuery, retain data if it is available rather than setting it to undefined.

  • #12631 b147cac Thanks @phryneas! - The error property is no longer present when skip is true in useQuery.

v4.0.0-alpha.14

21 May 17:12
12b26bf
Compare
Choose a tag to compare
v4.0.0-alpha.14 Pre-release
Pre-release

Major Changes

  • #12614 d2851e2 Thanks @jerelmiller! - The getCacheKey function is no longer available from operation.getContext() in the link chain. Use operation.client.cache.identify(obj) in the link chain instead.

  • #12556 c3fceda Thanks @phryneas! - ObservableQuery will now keep previous data around when emitting a loading state, unless query or variables changed.
    Note that @exports variables are not taken into account for this, so data will stay around even if they change.

  • #12556 c3fceda Thanks @phryneas! - Removed getLastResult, getLastError and resetLastResults from ObservableQuery

  • #12614 d2851e2 Thanks @jerelmiller! - Removes the resolvers option from ApolloClient. Local resolvers have instead been moved to the new LocalState instance which is assigned to the localState option in ApolloClient. To migrate, move the resolvers values into a LocalState instance and assign that instance to localState.

    new ApolloClient({
    - resolvers: { /* ... */ }
    + localState: new LocalState({
    +   resolvers: { /* ... */ }
    + }),
    });
  • #12614 d2851e2 Thanks @jerelmiller! - Remove local resolvers APIs from ApolloClient in favor of localState. Methods removed are:

    • addResolvers
    • getResolvers
    • setResolvers
    • setLocalStateFragmentMatcher
  • #12614 d2851e2 Thanks @jerelmiller! - Third-party caches must now implement the fragmentMatches API. Additionally fragmentMatches must be able to handle both InlineFragmentNode and FragmentDefinitionNode 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 the saveAsLastResult argument from ObservableQuery.getCurrentResult

  • #12614 d2851e2 Thanks @jerelmiller! - The resolver function's context argument (the 3rd argument) has changed to provide additional information without the possibility of name clashes. Previously the context argument would spread request context and override the client and cache properties to give access to both inside of a resolver. The context 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 the cache from the client 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 instantiated LocalState instance to the localState 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 the fragmentMatcher option from ApolloClient. Custom fragment matchers used with local state are no longer supported. Fragment matching is now performed by the configured cache via the cache.fragmentMatches API.

  • #12556 c3fceda Thanks @phryneas! - A call to ObservableQuery.setVariables with different variables or a ObservableQuery.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 existing resolvers option.

    • Throwing errors in a resolver will set the field value as null and add an error to the response's errors 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 the requestContext given to resolvers.
    • The LocalState class accepts a Resolvers 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>({
      // ...
    });

v4.0.0-alpha.13

14 May 19:57
5463f0b
Compare
Choose a tag to compare
v4.0.0-alpha.13 Pre-release
Pre-release

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 in HttpLink and BatchHttpLink. This was unused code since core handles removing @client fields and should have no observable change.

v4.0.0-alpha.12

29 Apr 17:51
b3e9d2f
Compare
Choose a tag to compare
v4.0.0-alpha.12 Pre-release
Pre-release

Major Changes

  • #12586 605db8e Thanks @jerelmiller! - Remove the typeDefs option from ApolloClient.

  • #12588 eed825a Thanks @jerelmiller! - Remove TContext generic argument from all types that use it. TContext is replaced with DefaultContext which can be modified using declaration merging.

  • #12590 a005e82 Thanks @jerelmiller! - Drop graphql 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 the link option when instantiating ApolloClient. This removes the uri, credentials and headers options from ApolloClient in favor of passing an instantiated HttpLink directly. To migrate:

    If using uri, credentials, or headers options

    new 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 option

    new ApolloClient({
      // ...
    + link: ApolloLink.empty()
    });

v4.0.0-alpha.11

23 Apr 23:17
6a37dc5
Compare
Choose a tag to compare
v4.0.0-alpha.11 Pre-release
Pre-release

Major Changes

  • #12576 a92ff78 Thanks @jerelmiller! - The cache and forceFetch properties are no longer available on context when calling operation.getContext(). cache can be accessed through the operation with operation.client.cache instead. forceFetch has been replaced with queryDeduplication which specifies whether queryDeduplication was enabled for the request or not.

  • #12576 a92ff78 Thanks @jerelmiller! - ApolloLink.execute now requires a third argument which provides the client that initiated the request to the link chain. If you use execute directly, add a third argument with a client property:

    ApolloLink.execute(link, operation, { client });
    
    // or if you import the `execute` function directly:
    execute(link, operation, { client });
  • #12566 ce4b488 Thanks @jerelmiller! - Don't broadcastQueries when a query is torn down.

Minor Changes

  • #12576 a92ff78 Thanks @jerelmiller! - Provide an extension to define types for context passed to the link chain. To define your own types, use declaration merging to add properties to the DefaultContext 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 from HttpLink, 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 a client property to the operation passed to the link chain. This client is set as the client making the request to the link chain.

Patch Changes

  • #12574 0098ec9 Thanks @jerelmiller! - Export gql from the @apollo/client/react entrypoint.

  • #12572 3dc50e6 Thanks @jerelmiller! - Adjust useMutation 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 returned mutate function. Providing required variables to useMutation will make them optional in the returned mutate function.

v4.0.0-alpha.10

17 Apr 17:51
dde5f0c
Compare
Choose a tag to compare
v4.0.0-alpha.10 Pre-release
Pre-release

Major Changes

  • #12559 49ace0e Thanks @jerelmiller! - ObservableQuery.variables can now be reset back to empty when calling reobserve with variables: undefined. Previously the variables key would be ignored so variables would remain unchanged.

  • #12559 49ace0e Thanks @jerelmiller! - never is no longer supported as a valid TVariables generic argument for APIs that require variables as part of its type. Use Record<string, never> instead.

  • #12559 49ace0e Thanks @jerelmiller! - When passing a variables key with the value undefined, the value will be replaced by the default value in the query, if it is provided, rather than leave it as undefined.

    // 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 a fetchPolicy of standby. standby does not fetch and did not return data. standby is meant for watched queries where fetching should be on hold.

Minor Changes

  • #12557 51d26ae Thanks @jerelmiller! - Add ability to specify message formatter for CombinedGraphQLErrors and CombinedProtocolErrors. To provide your own message formatter, override the static formatMessage 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 static is 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! - The variables option used with various APIs are now enforced more consistently across the client when TVariables contains required variables. If required variables are not provided, TypeScript will now complain that it requires a variables 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 of variables returned from useLazyQuery. When called is false, variables is now Partial<TVariables> instead of TVariables.

  • #12562 90bf0e6 Thanks @jerelmiller! - client.query no longer supports notifyOnNetworkStatusChange in options. An error will be thrown if this option is set. The effects of this option were not observable by client.query since client.query emits a single result.

  • #12557 51d26ae Thanks @jerelmiller! - Update format of the error message for CombinedGraphQLErrors and CombinedProtocolErrors 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 return TVariables rather than TVariables | undefined. This is more consistent with the runtime value where an empty object ({}) will be returned when the variables option is not provided.

v3.13.8

17 Apr 16:40
87d0521
Compare
Choose a tag to compare

Patch Changes

v4.0.0-alpha.9

11 Apr 20:09
90de488
Compare
Choose a tag to compare
v4.0.0-alpha.9 Pre-release
Pre-release

Major Changes

  • #12536 e14205a Thanks @jerelmiller! - An initial loading state is now emitted from ObservableQuery when subscribing if notifyOnNetworkStatusChange is set to true.

  • #12512 e809b71 Thanks @jerelmiller! - notifyOnNetworkStatusChange now defaults to true. This means that loading states will be emitted (core API) or rendered (React) by default when calling refetch, fetchMore, etc. To maintain the old behavior, set notifyOnNetworkStatusChange to false in defaultOptions.

    new ApolloClient({
      defaultOptions: {
        watchQuery: {
          // Use the v3 default
          notifyOnNetworkStatusChange: false,
        },
      },
    });

Patch Changes

  • #12536 e14205a Thanks @jerelmiller! - The returned networkStatus in useLazyQuery is now set to setVariables when calling the useLazyQuery execute function for the first time with variables.

  • #12536 e14205a Thanks @jerelmiller! - Ensure ObservableQuery stops polling if switching to a standby fetchPolicy. When switching back to a non-standby fetchPolicy, polling will resume.

  • #12536 e14205a Thanks @jerelmiller! - Ensure a loading state is emitted when calling the execute function after changing clients in useLazyQuery.

  • #12542 afb4fce Thanks @jerelmiller! - Ensure useLazyQuery does not return a partial property which is not specified by the result type.