Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

7843 add context update #11339

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions src/core/ApolloClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
ApolloQueryResult,
OperationVariables,
Resolvers,
Context,
} from './types';

import {
Expand All @@ -33,7 +34,7 @@ import {
export interface DefaultOptions {
watchQuery?: Partial<WatchQueryOptions<any, any>>;
query?: Partial<QueryOptions<any, any>>;
mutate?: Partial<MutationOptions<any, any>>;
mutate?: Partial<MutationOptions<any, any, any>>;
}

let hasSuggestedDevtools = false;
Expand All @@ -57,13 +58,13 @@ export type ApolloClientOptions<TCacheShape> = {
version?: string;
};

type OptionsUnion<TData, TVariables> =
type OptionsUnion<TData, TVariables, TContext> =
| WatchQueryOptions<TVariables, TData>
| QueryOptions<TVariables, TData>
| MutationOptions<TData, TVariables>;
| MutationOptions<TData, TVariables, TContext>;

export function mergeOptions<
TOptions extends OptionsUnion<any, any>
TOptions extends OptionsUnion<any, any, any>
>(
defaults: Partial<TOptions>,
options: TOptions,
Expand Down Expand Up @@ -348,13 +349,13 @@ export class ApolloClient<TCacheShape> implements DataProxy {
*
* It takes options as an object with the following keys and values:
*/
public mutate<T = any, TVariables = OperationVariables>(
options: MutationOptions<T, TVariables>,
public mutate<T = any, TVariables = OperationVariables, TContext = Context>(
options: MutationOptions<T, TVariables, TContext>,
): Promise<FetchResult<T>> {
if (this.defaultOptions.mutate) {
options = mergeOptions(this.defaultOptions.mutate, options);
}
return this.queryManager.mutate<T>(options);
return this.queryManager.mutate<T, TVariables, TContext>(options);
}

/**
Expand Down
62 changes: 33 additions & 29 deletions src/core/QueryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import { NetworkStatus, isNetworkRequestInFlight } from './networkStatus';
import {
ApolloQueryResult,
OperationVariables,
MutationUpdaterFunction,
ReobserveQueryCallback,
} from './types';
import { LocalState } from './LocalState';
Expand All @@ -55,6 +56,8 @@ interface MutationStoreValue {
error: Error | null;
}

type UpdateQueries<TData> = MutationOptions<TData, any, any>["updateQueries"];

export class QueryManager<TStore> {
public cache: ApolloCache<TStore>;
public link: ApolloLink;
Expand Down Expand Up @@ -128,7 +131,7 @@ export class QueryManager<TStore> {
this.fetchCancelFns.clear();
}

public async mutate<T>({
public async mutate<T, TVariables, TContext>({
mutation,
variables,
optimisticResponse,
Expand All @@ -139,8 +142,8 @@ export class QueryManager<TStore> {
reobserveQuery,
errorPolicy = 'none',
fetchPolicy,
context = {},
}: MutationOptions): Promise<FetchResult<T>> {
context,
}: MutationOptions<T, TVariables, TContext>): Promise<FetchResult<T>> {
invariant(
mutation,
'mutation option is required. You must specify your GraphQL document in the mutation option.',
Expand All @@ -154,10 +157,10 @@ export class QueryManager<TStore> {
const mutationId = this.generateMutationId();
mutation = this.transform(mutation).document;

variables = this.getVariables(mutation, variables);
variables = this.getVariables(mutation, variables) as TVariables;

if (this.transform(mutation).hasClientExports) {
variables = await this.localState.addExportedVariables(mutation, variables, context);
variables = await this.localState.addExportedVariables(mutation, variables, context) as TVariables;
}

const mutationStoreValue =
Expand All @@ -170,11 +173,12 @@ export class QueryManager<TStore> {
} as MutationStoreValue);

if (optimisticResponse) {
this.markMutationOptimistic<T>(optimisticResponse, {
this.markMutationOptimistic<T, TVariables, TContext>(optimisticResponse, {
mutationId,
document: mutation,
variables,
errorPolicy,
context,
updateQueries,
update: updateWithProxyFn,
});
Expand Down Expand Up @@ -213,17 +217,18 @@ export class QueryManager<TStore> {
storeResult = result;

if (fetchPolicy !== 'no-cache') {
// Returning the result of markMutationResult here makes the
// mutation await any Promise that markMutationResult returns,
// since we are returning this Promise from the asyncMap mapping
// function.
try {
// Returning the result of markMutationResult here makes the
// mutation await any Promise that markMutationResult returns,
// since we are returning this Promise from the asyncMap mapping
// function.
return self.markMutationResult<T>({
self.markMutationResult<T, TVariables, TContext>({
mutationId,
result,
document: mutation,
variables,
errorPolicy,
context,
updateQueries,
update: updateWithProxyFn,
reobserveQuery,
Expand Down Expand Up @@ -291,18 +296,16 @@ export class QueryManager<TStore> {
});
}

public markMutationResult<TData>(
public markMutationResult<TData, TVariables, TContext>(
mutation: {
mutationId: string;
result: FetchResult<TData>;
document: DocumentNode;
variables?: OperationVariables;
variables?: TVariables;
errorPolicy: ErrorPolicy;
updateQueries: MutationOptions<TData>["updateQueries"],
update?: (
cache: ApolloCache<TStore>,
result: FetchResult<TData>,
) => void;
context?: TContext;
updateQueries: UpdateQueries<TData>;
update?: MutationUpdaterFunction<TData, TVariables, TContext>;
reobserveQuery?: ReobserveQueryCallback;
},
cache = this.cache,
Expand Down Expand Up @@ -364,7 +367,10 @@ export class QueryManager<TStore> {
// a write action.
const { update } = mutation;
if (update) {
update(c, mutation.result);
update(c as any, mutation.result, {
context: mutation.context,
variables: mutation.variables,
});
}
},

Expand All @@ -389,18 +395,16 @@ export class QueryManager<TStore> {
return Promise.resolve();
}

public markMutationOptimistic<TData>(
public markMutationOptimistic<TData, TVariables, TContext>(
optimisticResponse: any,
mutation: {
mutationId: string;
document: DocumentNode;
variables?: OperationVariables;
variables?: TVariables;
errorPolicy: ErrorPolicy;
updateQueries: MutationOptions<TData>["updateQueries"],
update?: (
cache: ApolloCache<TStore>,
result: FetchResult<TData>,
) => void;
context?: TContext;
updateQueries: UpdateQueries<TData>,
update?: MutationUpdaterFunction<TData, TVariables, TContext>;
},
) {
const data = typeof optimisticResponse === "function"
Expand All @@ -409,7 +413,7 @@ export class QueryManager<TStore> {

return this.cache.recordOptimisticTransaction(cache => {
try {
this.markMutationResult<TData>({
this.markMutationResult<TData, TVariables, TContext>({
...mutation,
result: { data },
}, cache);
Expand Down Expand Up @@ -505,9 +509,9 @@ export class QueryManager<TStore> {
return transformCache.get(document)!;
}

private getVariables(
private getVariables<TVariables>(
document: DocumentNode,
variables?: OperationVariables,
variables?: TVariables,
): OperationVariables {
return {
...this.transform(document).defaultVars,
Expand Down
4 changes: 2 additions & 2 deletions src/core/__tests__/QueryManager/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5381,7 +5381,7 @@ describe('QueryManager', () => {

describe('awaitRefetchQueries', () => {
const awaitRefetchTest =
({ awaitRefetchQueries, testQueryError = false }: MutationBaseOptions & { testQueryError?: boolean }) =>
({ awaitRefetchQueries, testQueryError = false }: MutationBaseOptions<any, any, any> & { testQueryError?: boolean }) =>
new Promise((resolve, reject) => {
const query = gql`
query getAuthors($id: ID!) {
Expand Down Expand Up @@ -5455,7 +5455,7 @@ describe('QueryManager', () => {
{ observable },
result => {
expect(stripSymbols(result.data)).toEqual(queryData);
const mutateOptions: MutationOptions = {
const mutateOptions: MutationOptions<any, any, any> = {
mutation,
refetchQueries: ['getAuthors'],
};
Expand Down
1 change: 0 additions & 1 deletion src/core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ export {
ErrorPolicy,
FetchMoreQueryOptions,
SubscribeToMoreOptions,
MutationUpdaterFn,
} from './watchQueryOptions';
export { NetworkStatus } from './networkStatus';
export * from './types';
Expand Down
11 changes: 11 additions & 0 deletions src/core/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { DocumentNode, GraphQLError } from 'graphql';

import { ApolloCache } from '../cache';
import { FetchResult } from '../link/core';
import { ApolloError } from '../errors';
import { QueryInfo } from './QueryInfo';
Expand All @@ -10,6 +11,8 @@ import { Cache } from '../cache';

export { TypedDocumentNode } from '@graphql-typed-document-node/core';

export type Context = Record<string, any>;

export type QueryListener = (queryInfo: QueryInfo) => void;

export type ReobserveQueryCallback = (
Expand Down Expand Up @@ -51,6 +54,14 @@ export type MutationQueryReducersMap<T = { [key: string]: any }> = {
[queryName: string]: MutationQueryReducer<T>;
};

export type MutationUpdaterFunction<T, TVariables, TContext> = (
cache: ApolloCache<T>,
result: Omit<FetchResult<T>, 'context'>,
options: {
context?: TContext,
variables?: TVariables,
},
) => void;
export interface Resolvers {
[key: string]: {
[ field: string ]: Resolver;
Expand Down
33 changes: 17 additions & 16 deletions src/core/watchQueryOptions.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
import { DocumentNode } from 'graphql';
import { TypedDocumentNode } from '@graphql-typed-document-node/core';

import { ApolloCache } from '../cache';
import { FetchResult } from '../link/core';
import { MutationQueryReducersMap, ReobserveQueryCallback } from './types';
import { PureQueryOptions, OperationVariables } from './types';
import {
Context,
MutationQueryReducersMap,
PureQueryOptions,
OperationVariables,
MutationUpdaterFunction,
ReobserveQueryCallback,
} from './types';

/**
* fetchPolicy determines where the client may return a result from. The options are:
Expand Down Expand Up @@ -179,8 +184,9 @@ export interface SubscriptionOptions<TVariables = OperationVariables, TData = an
export type RefetchQueryDescription = Array<string | PureQueryOptions>;

export interface MutationBaseOptions<
T = { [key: string]: any },
TVariables = OperationVariables
T,
TVariables,
TContext,
> {
/**
* An object that represents the result of this mutation that will be
Expand Down Expand Up @@ -239,7 +245,7 @@ export interface MutationBaseOptions<
* and you don't need to update the store, use the Promise returned from
* `client.mutate` instead.
*/
update?: MutationUpdaterFn<T>;
update?: MutationUpdaterFunction<T, TVariables, TContext>;

/**
* A function that will be called for each ObservableQuery affected by
Expand All @@ -260,9 +266,10 @@ export interface MutationBaseOptions<
}

export interface MutationOptions<
T = { [key: string]: any },
TVariables = OperationVariables
> extends MutationBaseOptions<T, TVariables> {
T = any,
TVariables extends OperationVariables = OperationVariables,
TContext extends Context = Context,
> extends MutationBaseOptions<T, TVariables, TContext> {
/**
* A GraphQL document, often created with `gql` from the `graphql-tag`
* package, that contains a single mutation inside of it.
Expand All @@ -279,7 +286,7 @@ export interface MutationOptions<
* [`query` `context` option](https://www.apollographql.com/docs/react/api/apollo-client#ApolloClient.query))
* when the query is first initialized/run.
*/
context?: any;
context?: TContext;

/**
* Specifies the {@link FetchPolicy} to be used for this query. Mutations only
Expand All @@ -289,9 +296,3 @@ export interface MutationOptions<
*/
fetchPolicy?: Extract<FetchPolicy, 'no-cache'>;
}

// Add a level of indirection for `typedoc`.
export type MutationUpdaterFn<T = { [key: string]: any }> = (
cache: ApolloCache<T>,
mutationResult: FetchResult<T>,
) => void;
9 changes: 5 additions & 4 deletions src/react/components/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { DocumentNode } from 'graphql';
import { TypedDocumentNode } from '@graphql-typed-document-node/core';

import { OperationVariables } from '../../core';
import { OperationVariables, Context } from '../../core';
import {
QueryFunctionOptions,
QueryResult,
Expand All @@ -22,11 +22,12 @@ export interface QueryComponentOptions<

export interface MutationComponentOptions<
TData = any,
TVariables = OperationVariables
> extends BaseMutationOptions<TData, TVariables> {
TVariables = OperationVariables,
TContext = Context,
> extends BaseMutationOptions<TData, TVariables, TContext> {
mutation: DocumentNode | TypedDocumentNode<TData, TVariables>;
children: (
mutateFunction: MutationFunction<TData, TVariables>,
mutateFunction: MutationFunction<TData, TVariables, TContext>,
result: MutationResult<TData>
) => JSX.Element | null;
}
Expand Down
Loading