diff --git a/.api-reports/api-report-core.api.md b/.api-reports/api-report-core.api.md index 65e05bc6924..f348ace0568 100644 --- a/.api-reports/api-report-core.api.md +++ b/.api-reports/api-report-core.api.md @@ -305,21 +305,16 @@ export { execute } export { fallbackHttpConfig } // @public (undocumented) -export interface FetchMoreOptions { - // (undocumented) - updateQuery?: (previousQueryResult: TData, options: { - fetchMoreResult?: TData; - variables?: TVariables; - }) => TData; -} - -// @public (undocumented) -export interface FetchMoreQueryOptions { - // (undocumented) +export type FetchMoreOptions = { + query?: DocumentNode_2 | TypedDocumentNode; + variables?: Partial>; + errorPolicy?: ErrorPolicy; context?: DefaultContext; - query?: DocumentNode_2 | TypedDocumentNode; - variables?: Partial>; -} + updateQuery?: (previousQueryResult: Unmasked, options: { + fetchMoreResult: Unmasked; + variables: TFetchVars; + }) => Unmasked; +}; // @public export type FetchPolicy = "cache-first" | "network-only" | "cache-only" | "no-cache"; @@ -588,12 +583,7 @@ export class ObservableQuery>): void; - fetchMore(fetchMoreOptions: FetchMoreQueryOptions & { - updateQuery?: (previousQueryResult: Unmasked, options: { - fetchMoreResult: Unmasked; - variables: TFetchVars; - }) => Unmasked; - }): Promise>; + fetchMore({ query, variables, context, errorPolicy, updateQuery, }: FetchMoreOptions): Promise>; // @internal @deprecated (undocumented) getCacheDiff({ optimistic }?: { optimistic?: boolean | undefined; @@ -1041,10 +1031,10 @@ export type WatchQueryOptions { - // (undocumented) +type FetchMoreOptions = { + query?: DocumentNode | TypedDocumentNode; + variables?: Partial>; + errorPolicy?: ErrorPolicy; context?: DefaultContext; - query?: DocumentNode | TypedDocumentNode; - variables?: Partial>; -} + updateQuery?: (previousQueryResult: Unmasked, options: { + fetchMoreResult: Unmasked; + variables: TFetchVars; + }) => Unmasked; +}; // @public type FetchPolicy = "cache-first" | "network-only" | "cache-only" | "no-cache"; @@ -562,13 +566,8 @@ class ObservableQuery>): void; - // Warning: (ae-forgotten-export) The symbol "FetchMoreQueryOptions" needs to be exported by the entry point index.d.ts - fetchMore(fetchMoreOptions: FetchMoreQueryOptions & { - updateQuery?: (previousQueryResult: Unmasked, options: { - fetchMoreResult: Unmasked; - variables: TFetchVars; - }) => Unmasked; - }): Promise>; + // Warning: (ae-forgotten-export) The symbol "FetchMoreOptions" needs to be exported by the entry point index.d.ts + fetchMore({ query, variables, context, errorPolicy, updateQuery, }: FetchMoreOptions): Promise>; // @internal @deprecated (undocumented) getCacheDiff({ optimistic }?: { optimistic?: boolean | undefined; @@ -1225,12 +1224,7 @@ export namespace useLazyQuery { subscribeToMore: SubscribeToMoreFunction; updateQuery: (mapFn: UpdateQueryMapFn_2) => void; refetch: (variables?: Partial) => Promise>>; - fetchMore: (fetchMoreOptions: FetchMoreQueryOptions_2 & { - updateQuery?: (previousQueryResult: Unmasked_2, options: { - fetchMoreResult: Unmasked_2; - variables: TFetchVars; - }) => Unmasked_2; - }) => Promise>>; + fetchMore: (fetchMoreOptions: FetchMoreOptions_2) => Promise>>; client: ApolloClient; observable: ObservableQuery_2; previousData?: MaybeMasked_2; @@ -1410,12 +1404,7 @@ export namespace useQuery { updateQuery: (mapFn: UpdateQueryMapFn_2) => void; refetch: (variables?: Partial) => Promise>>; variables: TVariables; - fetchMore: (fetchMoreOptions: FetchMoreQueryOptions_2 & { - updateQuery?: (previousQueryResult: Unmasked, options: { - fetchMoreResult: Unmasked; - variables: TFetchVars; - }) => Unmasked; - }) => Promise>>; + fetchMore: (fetchMoreOptions: FetchMoreOptions_2) => Promise>>; } & GetDataState_2, TStates>; } @@ -1640,23 +1629,23 @@ type WatchQueryOptions_2 = (fetchMoreOptions: FetchMoreQueryOptions & { - updateQuery?: (previousQueryResult: Unmasked, options: { - fetchMoreResult: Unmasked; - variables: TVariables; - }) => Unmasked; -}) => Promise>>; - -// @public (undocumented) -type FetchMoreOptions = Parameters["fetchMore"]>[0]; +export type FetchMoreFunction = (fetchMoreOptions: FetchMoreOptions) => Promise>>; // @public (undocumented) type FragmentCacheKey = [ @@ -138,10 +129,8 @@ export class InternalQueryReference): Promise>; + fetchMore(options: FetchMoreOptions): Promise>; // (undocumented) readonly key: QueryKey; // Warning: (ae-forgotten-export) The symbol "Listener" needs to be exported by the entry point index.d.ts diff --git a/.api-reports/api-report.api.md b/.api-reports/api-report.api.md index 7cf919bb4bf..259937d50cd 100644 --- a/.api-reports/api-report.api.md +++ b/.api-reports/api-report.api.md @@ -842,22 +842,16 @@ export const fallbackHttpConfig: { }; // @public (undocumented) -export interface FetchMoreOptions { - // (undocumented) - updateQuery?: (previousQueryResult: TData, options: { - fetchMoreResult?: TData; - variables?: TVariables; - }) => TData; -} - -// @public (undocumented) -export interface FetchMoreQueryOptions { - // (undocumented) +export type FetchMoreOptions = { + query?: DocumentNode | TypedDocumentNode; + variables?: Partial>; + errorPolicy?: ErrorPolicy; context?: DefaultContext; - query?: DocumentNode | TypedDocumentNode; - // Warning: (ae-forgotten-export) The symbol "NoInfer_2" needs to be exported by the entry point index.d.ts - variables?: Partial>; -} + updateQuery?: (previousQueryResult: Unmasked, options: { + fetchMoreResult: Unmasked; + variables: TFetchVars; + }) => Unmasked; +}; // @public export type FetchPolicy = "cache-first" | "network-only" | "cache-only" | "no-cache"; @@ -1522,6 +1516,7 @@ namespace LocalState { // // @public (undocumented) class LocalState, TContext = InferContextValueFromResolvers> { + // Warning: (ae-forgotten-export) The symbol "NoInfer_2" needs to be exported by the entry point index.d.ts constructor(...[options]: {} extends TResolvers ? [ options?: LocalState.Options> ] : [ @@ -1908,12 +1903,7 @@ export class ObservableQuery>): void; - fetchMore(fetchMoreOptions: FetchMoreQueryOptions & { - updateQuery?: (previousQueryResult: Unmasked, options: { - fetchMoreResult: Unmasked; - variables: TFetchVars; - }) => Unmasked; - }): Promise>; + fetchMore({ query, variables, context, errorPolicy, updateQuery, }: FetchMoreOptions): Promise>; // @internal @deprecated (undocumented) getCacheDiff({ optimistic }?: { optimistic?: boolean | undefined; @@ -2701,10 +2691,10 @@ interface WriteContext extends ReadMergeModifyContext { // src/cache/inmemory/policies.ts:166:3 - (ae-forgotten-export) The symbol "KeySpecifier" needs to be exported by the entry point index.d.ts // src/cache/inmemory/policies.ts:166:3 - (ae-forgotten-export) The symbol "KeyArgsFunction" needs to be exported by the entry point index.d.ts // src/cache/inmemory/types.ts:133:3 - (ae-forgotten-export) The symbol "KeyFieldsFunction" needs to be exported by the entry point index.d.ts -// src/core/ObservableQuery.ts:133:5 - (ae-forgotten-export) The symbol "NextFetchPolicyContext" needs to be exported by the entry point index.d.ts -// src/core/ObservableQuery.ts:293:5 - (ae-forgotten-export) The symbol "QueryManager" needs to be exported by the entry point index.d.ts +// src/core/ObservableQuery.ts:143:5 - (ae-forgotten-export) The symbol "NextFetchPolicyContext" needs to be exported by the entry point index.d.ts +// src/core/ObservableQuery.ts:303:5 - (ae-forgotten-export) The symbol "QueryManager" needs to be exported by the entry point index.d.ts // src/core/QueryManager.ts:187:5 - (ae-forgotten-export) The symbol "MutationStoreValue" needs to be exported by the entry point index.d.ts -// src/core/watchQueryOptions.ts:261:3 - (ae-forgotten-export) The symbol "IgnoreModifier" needs to be exported by the entry point index.d.ts +// src/core/watchQueryOptions.ts:253:3 - (ae-forgotten-export) The symbol "IgnoreModifier" needs to be exported by the entry point index.d.ts // src/local-state/LocalState.ts:140:5 - (ae-forgotten-export) The symbol "LocalState" needs to be exported by the entry point index.d.ts // src/local-state/LocalState.ts:174:7 - (ae-forgotten-export) The symbol "LocalState" needs to be exported by the entry point index.d.ts // src/local-state/LocalState.ts:194:7 - (ae-forgotten-export) The symbol "LocalState" needs to be exported by the entry point index.d.ts diff --git a/.changeset/mighty-carrots-bathe.md b/.changeset/mighty-carrots-bathe.md new file mode 100644 index 00000000000..1a011f94bc4 --- /dev/null +++ b/.changeset/mighty-carrots-bathe.md @@ -0,0 +1,6 @@ +--- +"@apollo/client": minor +--- + +Allow passing `errorPolicy` option to `fetchMore` and change default value to "none". + diff --git a/.changeset/old-melons-double.md b/.changeset/old-melons-double.md new file mode 100644 index 00000000000..bde0eda5a7e --- /dev/null +++ b/.changeset/old-melons-double.md @@ -0,0 +1,11 @@ +--- +"@apollo/client": major +--- + +Rework option handling for `fetchMore`. + +* Previously, if the `query` option was specified, no options would be inherited +from the underlying `ObservableQuery`. +Now, even if `query` is specified, all unspecified options except for `variables` will be inherited from the underlying `ObservableQuery`. +* If `query` is not specified, `variables` will still be shallowly merged with the `variables` of the underlying `ObservableQuery`. If a `query` option is specified, the `variables` passed to `fetchMore` are used instead. +* `errorPolicy` of `fetchMore` will now always default to `"none"` instead of inherited from the `ObservableQuery` options. This can prevent accidental cache writes of partial data for a paginated query. To opt into receive partial data that may be written to the cache, pass an `errorPolicy` to `fetchMore` to override the default. diff --git a/.changeset/sixty-bears-bathe.md b/.changeset/sixty-bears-bathe.md new file mode 100644 index 00000000000..183099382a3 --- /dev/null +++ b/.changeset/sixty-bears-bathe.md @@ -0,0 +1,6 @@ +--- +"@apollo/client": minor +--- + +The `FetchMoreQueryOptions` type has been inlined into `FetchMoreOptions`, and +`FetchMoreQueryOptions` has been removed. diff --git a/.size-limits.json b/.size-limits.json index ff32f80dfe1..4a4c0971425 100644 --- a/.size-limits.json +++ b/.size-limits.json @@ -1,6 +1,6 @@ { - "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (CJS)": 43545, - "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production) (CJS)": 38567, - "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\"": 33328, - "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production)": 27615 + "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (CJS)": 43621, + "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production) (CJS)": 38655, + "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\"": 33315, + "import { ApolloClient, InMemoryCache, HttpLink } from \"@apollo/client\" (production)": 27586 } diff --git a/src/__tests__/fetchMore.ts b/src/__tests__/fetchMore.ts index f625283dac8..7f3e1f328da 100644 --- a/src/__tests__/fetchMore.ts +++ b/src/__tests__/fetchMore.ts @@ -3,7 +3,13 @@ import { assign, cloneDeep } from "lodash"; import { Observable } from "rxjs"; import type { TypedDocumentNode } from "@apollo/client"; -import { ApolloClient, ApolloLink, NetworkStatus, split } from "@apollo/client"; +import { + ApolloClient, + ApolloLink, + CombinedGraphQLErrors, + NetworkStatus, + split, +} from "@apollo/client"; import type { ApolloCache, FieldMergeFunction, @@ -223,7 +229,7 @@ describe("fetchMore on an observable query", () => { limit: 20, }; - const result: any = { + const result: { data: TCommentData } = { data: { entry: { __typename: "Entry", @@ -1667,6 +1673,219 @@ describe("fetchMore on an observable query", () => { await expect(stream).not.toEmitAnything(); }); + + test("`errorPolicy` defaults to `none`", async () => { + const query = gql` + query { + fail + } + `; + const observable = setup({ + request: { query }, + error: new Error("This is an error"), + }); + const stream = new ObservableStream(observable); + await expect(stream).toEmitTypedValue({ + data: undefined, + dataState: "empty", + loading: true, + networkStatus: NetworkStatus.loading, + partial: true, + }); + await expect(stream).toEmitTypedValue({ + data: result.data, + dataState: "complete", + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); + + const updateQuery = jest.fn(); + const promise = observable.fetchMore({ + query, + updateQuery, + }); + await expect(promise).rejects.toThrow("This is an error"); + expect(updateQuery).not.toHaveBeenCalled(); + await expect(stream).toEmitSimilarValue({ + expected: (previous) => ({ + ...previous, + loading: true, + networkStatus: NetworkStatus.fetchMore, + }), + }); + await expect(stream).toEmitSimilarValue({ + expected: (previous) => ({ + ...previous, + loading: false, + networkStatus: NetworkStatus.ready, + }), + }); + await expect(stream).not.toEmitAnything(); + }); + + test("`errorPolicy` can be overwritten to `ignore`", async () => { + const query = gql` + query { + fail + } + `; + const observable = setup({ + request: { query }, + error: new Error("This is an error"), + }); + const stream = new ObservableStream(observable); + await expect(stream).toEmitTypedValue({ + data: undefined, + dataState: "empty", + loading: true, + networkStatus: NetworkStatus.loading, + partial: true, + }); + await expect(stream).toEmitTypedValue({ + data: result.data, + dataState: "complete", + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); + + const fallbackResult: TCommentData = { + entry: { + ...result.data.entry, + comments: result.data.entry.comments.concat({ + __typename: "Comment", + text: "fallback comment", + }), + }, + }; + + const updateQuery = jest.fn( + (previousResult: TCommentData): TCommentData => fallbackResult + ); + const promise = observable.fetchMore({ + query, + updateQuery, + errorPolicy: "ignore", + }); + await expect(promise).resolves.toStrictEqualTyped({ data: undefined }); + expect(updateQuery).toHaveBeenCalledTimes(1); + expect(updateQuery).toHaveBeenNthCalledWith(1, result.data, { + fetchMoreResult: undefined, + variables: undefined, + }); + await expect(stream).toEmitSimilarValue({ + expected: (previous) => ({ + ...previous, + loading: true, + networkStatus: NetworkStatus.fetchMore, + }), + }); + await expect(stream).toEmitSimilarValue({ + expected: (previous) => ({ + ...previous, + data: fallbackResult, + dataState: "complete", + loading: false, + networkStatus: NetworkStatus.ready, + }), + }); + await expect(stream).not.toEmitAnything(); + }); + + test("`errorPolicy` can be overwritten to `all`", async () => { + const query = gql` + query { + fail + } + `; + const observable = setup({ + request: { query }, + result: { + data: { + entry: { + __typename: "Entry", + }, + }, + errors: [{ message: "This is an error" }], + }, + }); + const stream = new ObservableStream(observable); + await expect(stream).toEmitTypedValue({ + data: undefined, + dataState: "empty", + loading: true, + networkStatus: NetworkStatus.loading, + partial: true, + }); + await expect(stream).toEmitTypedValue({ + data: result.data, + dataState: "complete", + loading: false, + networkStatus: NetworkStatus.ready, + partial: false, + }); + + const fallbackResult: TCommentData = { + entry: { + ...result.data.entry, + comments: result.data.entry.comments.concat({ + __typename: "Comment", + text: "fallback comment", + }), + }, + }; + + const updateQuery = jest.fn( + (previousResult: TCommentData): TCommentData => fallbackResult + ); + const promise = observable.fetchMore({ + query, + updateQuery, + errorPolicy: "all", + }); + await expect(promise).resolves.toStrictEqual({ + data: { + entry: { + __typename: "Entry", + }, + }, + error: new CombinedGraphQLErrors({ + data: { + entry: { + __typename: "Entry", + }, + }, + errors: [{ message: "This is an error" }], + }), + }); + expect(updateQuery).toHaveBeenCalledTimes(1); + expect(updateQuery).toHaveBeenNthCalledWith(1, result.data, { + fetchMoreResult: { + entry: { + __typename: "Entry", + }, + }, + variables: undefined, + }); + await expect(stream).toEmitSimilarValue({ + expected: (previous) => ({ + ...previous, + loading: true, + networkStatus: NetworkStatus.fetchMore, + }), + }); + await expect(stream).toEmitSimilarValue({ + expected: (previous) => ({ + ...previous, + data: fallbackResult, + dataState: "complete", + loading: false, + networkStatus: NetworkStatus.ready, + }), + }); + await expect(stream).not.toEmitAnything(); + }); }); describe("fetchMore on an observable query with connection", () => { diff --git a/src/core/ObservableQuery.ts b/src/core/ObservableQuery.ts index 47aa61659f2..63c09e344e9 100644 --- a/src/core/ObservableQuery.ts +++ b/src/core/ObservableQuery.ts @@ -37,8 +37,8 @@ import type { } from "./types.js"; import type { ErrorPolicy, - FetchMoreQueryOptions, NextFetchPolicyContext, + QueryOptions, RefetchWritePolicy, SubscribeToMoreOptions, UpdateQueryMapFn, @@ -49,18 +49,28 @@ import type { const { assign, hasOwnProperty } = Object; -export interface FetchMoreOptions< - TData = unknown, - TVariables = OperationVariables, -> { +export type FetchMoreOptions< + TData, + TVariables extends OperationVariables, + TFetchData = TData, + TFetchVars extends OperationVariables = TVariables, +> = { + /** {@inheritDoc @apollo/client!QueryOptionsDocumentation#query:member} */ + query?: DocumentNode | TypedDocumentNode; + /** {@inheritDoc @apollo/client!QueryOptionsDocumentation#variables:member} */ + variables?: Partial>; + /** {@inheritDoc @apollo/client!QueryOptionsDocumentation#errorPolicy:member} */ + errorPolicy?: ErrorPolicy; + /** {@inheritDoc @apollo/client!QueryOptionsDocumentation#context:member} */ + context?: DefaultContext; updateQuery?: ( - previousQueryResult: TData, + previousQueryResult: Unmasked, options: { - fetchMoreResult?: TData; - variables?: TVariables; + fetchMoreResult: Unmasked; + variables: TFetchVars; } - ) => TData; -} + ) => Unmasked; +}; interface TrackedOperation { /** @@ -697,29 +707,31 @@ Did you mean to call refetch(variables) instead of refetch({ variables })?`, public fetchMore< TFetchData = TData, TFetchVars extends OperationVariables = TVariables, - >( - fetchMoreOptions: FetchMoreQueryOptions & { - updateQuery?: ( - previousQueryResult: Unmasked, - options: { - fetchMoreResult: Unmasked; - variables: TFetchVars; - } - ) => Unmasked; - } - ): Promise> { + >({ + query, + variables, + context, + errorPolicy, + updateQuery, + }: FetchMoreOptions): Promise< + QueryResult + > { const combinedOptions = { - ...(fetchMoreOptions.query ? fetchMoreOptions : ( + ...compact( + this.options, + { errorPolicy: "none" }, { - ...this.options, - query: this.options.query, - ...fetchMoreOptions, - variables: { - ...this.variables, - ...fetchMoreOptions.variables, - }, + query, + context, + errorPolicy, + } + ), + variables: (query ? variables : ( + { + ...this.variables, + ...variables, } - )), + )) as TFetchVars, // The fetchMore request goes immediately to the network and does // not automatically write its result to the cache (hence no-cache // instead of network-only), because we allow the caller of @@ -727,7 +739,7 @@ Did you mean to call refetch(variables) instead of refetch({ variables })?`, // the data gets written to the cache. fetchPolicy: "no-cache", notifyOnNetworkStatusChange: this.options.notifyOnNetworkStatusChange, - } as WatchQueryOptions; + } as QueryOptions; combinedOptions.query = this.transformDocument(combinedOptions.query); @@ -737,13 +749,12 @@ Did you mean to call refetch(variables) instead of refetch({ variables })?`, // as well as the document passed in `fetchMoreOptions` to ensure the cache // uses the most up-to-date document which may rely on runtime conditionals. this.lastQuery = - fetchMoreOptions.query ? + query ? this.transformDocument(this.options.query) : combinedOptions.query; let wasUpdated = false; - const updateQuery = fetchMoreOptions?.updateQuery; const isCached = this.options.fetchPolicy !== "no-cache"; if (!isCached) { @@ -781,7 +792,6 @@ Did you mean to call refetch(variables) instead of refetch({ variables })?`, // fetchMore cache results back to this ObservableQuery. this.queryManager.cache.batch({ update: (cache) => { - const { updateQuery } = fetchMoreOptions; if (updateQuery) { cache.updateQuery( { diff --git a/src/core/index.ts b/src/core/index.ts index 11ac17daf18..7ac63579216 100644 --- a/src/core/index.ts +++ b/src/core/index.ts @@ -6,7 +6,6 @@ export type { FetchMoreOptions } from "./ObservableQuery.js"; export { ObservableQuery } from "./ObservableQuery.js"; export type { ErrorPolicy, - FetchMoreQueryOptions, FetchPolicy, MutationFetchPolicy, MutationOptions, @@ -27,7 +26,6 @@ export type { DataState, DefaultContext, ErrorLike, - NormalizedExecutionResult, GetDataState, InternalRefetchQueriesInclude, InternalRefetchQueriesMap, @@ -39,6 +37,7 @@ export type { MutationQueryReducer, MutationQueryReducersMap, MutationUpdaterFunction, + NormalizedExecutionResult, OnQueryUpdated, OperationVariables, QueryResult, diff --git a/src/core/watchQueryOptions.ts b/src/core/watchQueryOptions.ts index ba30738aa13..a2a7898ec06 100644 --- a/src/core/watchQueryOptions.ts +++ b/src/core/watchQueryOptions.ts @@ -14,10 +14,10 @@ import type { IgnoreModifier } from "../cache/core/types/common.js"; import type { ObservableQuery } from "./ObservableQuery.js"; import type { DefaultContext, - NormalizedExecutionResult, InternalRefetchQueriesInclude, MutationQueryReducersMap, MutationUpdaterFunction, + NormalizedExecutionResult, OnQueryUpdated, OperationVariables, } from "./types.js"; @@ -135,14 +135,6 @@ export interface NextFetchPolicyContext< initialFetchPolicy: WatchQueryFetchPolicy; } -export interface FetchMoreQueryOptions { - /** {@inheritDoc @apollo/client!QueryOptionsDocumentation#query:member} */ - query?: DocumentNode | TypedDocumentNode; - /** {@inheritDoc @apollo/client!QueryOptionsDocumentation#variables:member} */ - variables?: Partial>; - context?: DefaultContext; -} - export type UpdateQueryOptions = { variables?: TVariables; } & ( diff --git a/src/react/hooks/useBackgroundQuery.ts b/src/react/hooks/useBackgroundQuery.ts index 9f7f466205b..8e0f6ab44c5 100644 --- a/src/react/hooks/useBackgroundQuery.ts +++ b/src/react/hooks/useBackgroundQuery.ts @@ -6,7 +6,6 @@ import type { DefaultContext, DocumentNode, ErrorPolicy, - FetchMoreQueryOptions, OperationVariables, RefetchWritePolicy, TypedDocumentNode, @@ -382,7 +381,7 @@ function useBackgroundQuery_< const fetchMore: FetchMoreFunction = React.useCallback( (options) => { - const promise = queryRef.fetchMore(options as FetchMoreQueryOptions); + const promise = queryRef.fetchMore(options); setWrappedQueryRef(wrapQueryRef(queryRef)); diff --git a/src/react/hooks/useLazyQuery.ts b/src/react/hooks/useLazyQuery.ts index 64facfbd0d6..4f26d41ec0b 100644 --- a/src/react/hooks/useLazyQuery.ts +++ b/src/react/hooks/useLazyQuery.ts @@ -10,7 +10,7 @@ import type { DefaultContext, ErrorLike, ErrorPolicy, - FetchMoreQueryOptions, + FetchMoreOptions, GetDataState, MaybeMasked, ObservableQuery, @@ -18,7 +18,6 @@ import type { QueryResult, RefetchWritePolicy, SubscribeToMoreFunction, - Unmasked, UpdateQueryMapFn, WatchQueryFetchPolicy, WatchQueryOptions, @@ -106,15 +105,12 @@ export declare namespace useLazyQuery { TFetchData = TData, TFetchVars extends OperationVariables = TVariables, >( - fetchMoreOptions: FetchMoreQueryOptions & { - updateQuery?: ( - previousQueryResult: Unmasked, - options: { - fetchMoreResult: Unmasked; - variables: TFetchVars; - } - ) => Unmasked; - } + fetchMoreOptions: FetchMoreOptions< + TData, + TVariables, + TFetchData, + TFetchVars + > ) => Promise>>; /** {@inheritDoc @apollo/client!QueryResultDocumentation#client:member} */ diff --git a/src/react/hooks/useLoadableQuery.ts b/src/react/hooks/useLoadableQuery.ts index dd8e17c2283..5f1e6affbcb 100644 --- a/src/react/hooks/useLoadableQuery.ts +++ b/src/react/hooks/useLoadableQuery.ts @@ -6,7 +6,6 @@ import type { DefaultContext, DocumentNode, ErrorPolicy, - FetchMoreQueryOptions, OperationVariables, RefetchWritePolicy, TypedDocumentNode, @@ -234,9 +233,7 @@ export function useLoadableQuery< ); } - const promise = internalQueryRef.fetchMore( - options as FetchMoreQueryOptions - ); + const promise = internalQueryRef.fetchMore(options); setQueryRef(wrapQueryRef(internalQueryRef)); diff --git a/src/react/hooks/useQuery.ts b/src/react/hooks/useQuery.ts index ad36d9bee63..1ab702f1646 100644 --- a/src/react/hooks/useQuery.ts +++ b/src/react/hooks/useQuery.ts @@ -23,7 +23,7 @@ import type { DocumentNode, ErrorLike, ErrorPolicy, - FetchMoreQueryOptions, + FetchMoreOptions, GetDataState, ObservableQuery, OperationVariables, @@ -36,7 +36,7 @@ import type { WatchQueryOptions, } from "@apollo/client"; import { NetworkStatus } from "@apollo/client"; -import type { MaybeMasked, Unmasked } from "@apollo/client/masking"; +import type { MaybeMasked } from "@apollo/client/masking"; import type { NoInfer, VariablesOption, @@ -152,15 +152,12 @@ export declare namespace useQuery { TFetchData = TData, TFetchVars extends OperationVariables = TVariables, >( - fetchMoreOptions: FetchMoreQueryOptions & { - updateQuery?: ( - previousQueryResult: Unmasked, - options: { - fetchMoreResult: Unmasked; - variables: TFetchVars; - } - ) => Unmasked; - } + fetchMoreOptions: FetchMoreOptions< + TData, + TVariables, + TFetchData, + TFetchVars + > ) => Promise>>; } & GetDataState, TStates>; } diff --git a/src/react/hooks/useQueryRefHandlers.ts b/src/react/hooks/useQueryRefHandlers.ts index 327ad3d2d6f..39a701c6bae 100644 --- a/src/react/hooks/useQueryRefHandlers.ts +++ b/src/react/hooks/useQueryRefHandlers.ts @@ -1,8 +1,11 @@ import * as React from "react"; -import type { DataState, OperationVariables } from "@apollo/client"; +import type { + DataState, + FetchMoreOptions, + OperationVariables, +} from "@apollo/client"; import type { SubscribeToMoreFunction } from "@apollo/client"; -import type { FetchMoreQueryOptions } from "@apollo/client"; import type { ApolloClient } from "@apollo/client"; import type { ObservableQuery } from "@apollo/client"; import type { @@ -113,7 +116,7 @@ function useQueryRefHandlers_< const fetchMore: FetchMoreFunction = React.useCallback( (options) => { const promise = internalQueryRef.fetchMore( - options as FetchMoreQueryOptions + options as FetchMoreOptions ); setWrappedQueryRef(wrapQueryRef(internalQueryRef)); diff --git a/src/react/internal/cache/QueryReference.ts b/src/react/internal/cache/QueryReference.ts index 0866ce517cc..ae995db3209 100644 --- a/src/react/internal/cache/QueryReference.ts +++ b/src/react/internal/cache/QueryReference.ts @@ -5,6 +5,7 @@ import { filter } from "rxjs"; import type { ApolloQueryResult, DataState, + FetchMoreOptions, ObservableQuery, OperationVariables, QueryResult, @@ -30,10 +31,6 @@ type Listener["dataState"]> = ( promise: QueryRefPromise ) => void; -type FetchMoreOptions = Parameters< - ObservableQuery["fetchMore"] ->[0]; - const QUERY_REFERENCE_SYMBOL: unique symbol = Symbol.for( "apollo.internal.queryRef" ); @@ -350,7 +347,7 @@ export class InternalQueryReference< return this.initiateFetch(this.observable.refetch(variables)); } - fetchMore(options: FetchMoreOptions) { + fetchMore(options: FetchMoreOptions) { return this.initiateFetch(this.observable.fetchMore(options)); } diff --git a/src/react/internal/types.ts b/src/react/internal/types.ts index f7cf0485c85..603e3dfd91c 100644 --- a/src/react/internal/types.ts +++ b/src/react/internal/types.ts @@ -1,23 +1,17 @@ import type { - FetchMoreQueryOptions, + FetchMoreOptions, MaybeMasked, OperationVariables, QueryResult, - Unmasked, } from "@apollo/client"; export type RefetchFunction = ( variables?: Partial ) => Promise>; -export type FetchMoreFunction = ( - fetchMoreOptions: FetchMoreQueryOptions & { - updateQuery?: ( - previousQueryResult: Unmasked, - options: { - fetchMoreResult: Unmasked; - variables: TVariables; - } - ) => Unmasked; - } +export type FetchMoreFunction = < + TFetchData = TData, + TFetchVars extends OperationVariables = TVariables, +>( + fetchMoreOptions: FetchMoreOptions ) => Promise>>;