Skip to content

Commit

Permalink
Return Reference from cache.write.
Browse files Browse the repository at this point in the history
Apollo Client does not currently use this result internally, so alternate
ApolloCache implementations are free to continue returning undefined.
  • Loading branch information
benjamn committed May 28, 2020
1 parent 25400d0 commit 7202b78
Show file tree
Hide file tree
Showing 7 changed files with 60 additions and 39 deletions.
6 changes: 2 additions & 4 deletions src/ApolloClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -403,9 +403,8 @@ export class ApolloClient<TCacheShape> implements DataProxy {
public writeQuery<TData = any, TVariables = OperationVariables>(
options: DataProxy.WriteQueryOptions<TData, TVariables>,
): void {
const result = this.cache.writeQuery<TData, TVariables>(options);
this.cache.writeQuery<TData, TVariables>(options);
this.queryManager.broadcastQueries();
return result;
}

/**
Expand All @@ -422,9 +421,8 @@ export class ApolloClient<TCacheShape> implements DataProxy {
public writeFragment<TData = any, TVariables = OperationVariables>(
options: DataProxy.WriteFragmentOptions<TData, TVariables>,
): void {
const result = this.cache.writeFragment<TData, TVariables>(options);
this.cache.writeFragment<TData, TVariables>(options);
this.queryManager.broadcastQueries();
return result;
}

public __actionHookForDevTools(cb: () => any) {
Expand Down
6 changes: 5 additions & 1 deletion src/cache/core/__tests__/cache.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import gql from 'graphql-tag';
import { ApolloCache } from '../cache';
import { Cache, DataProxy } from '../..';
import { Reference } from '../../../utilities/graphql/storeUtils';

class TestCache extends ApolloCache<unknown> {
constructor() {
Expand Down Expand Up @@ -45,7 +46,10 @@ class TestCache extends ApolloCache<unknown> {
};
}

public write<TResult = any, TVariables = any>(write: Cache.WriteOptions<TResult, TVariables>): void {
public write<TResult = any, TVariables = any>(
_: Cache.WriteOptions<TResult, TVariables>,
): Reference | undefined {
return;
}
}
const query = gql`{ a }`;
Expand Down
12 changes: 6 additions & 6 deletions src/cache/core/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { DocumentNode } from 'graphql';
import { wrap } from 'optimism';

import { getFragmentQueryDocument } from '../../utilities/graphql/fragments';
import { StoreObject } from '../../utilities/graphql/storeUtils';
import { StoreObject, Reference } from '../../utilities/graphql/storeUtils';
import { DataProxy } from './types/DataProxy';
import { Cache } from './types/Cache';

Expand All @@ -16,7 +16,7 @@ export abstract class ApolloCache<TSerialized> implements DataProxy {
): T | null;
public abstract write<TResult = any, TVariables = any>(
write: Cache.WriteOptions<TResult, TVariables>,
): void;
): Reference | undefined;
public abstract diff<T>(query: Cache.DiffOptions): Cache.DiffResult<T>;
public abstract watch(watch: Cache.WatchOptions): () => void;
public abstract reset(): Promise<void>;
Expand Down Expand Up @@ -124,8 +124,8 @@ export abstract class ApolloCache<TSerialized> implements DataProxy {

public writeQuery<TData = any, TVariables = any>(
options: Cache.WriteQueryOptions<TData, TVariables>,
): void {
this.write({
): Reference | undefined {
return this.write({
dataId: options.id || 'ROOT_QUERY',
result: options.data,
query: options.query,
Expand All @@ -136,8 +136,8 @@ export abstract class ApolloCache<TSerialized> implements DataProxy {

public writeFragment<TData = any, TVariables = any>(
options: Cache.WriteFragmentOptions<TData, TVariables>,
): void {
this.write({
): Reference | undefined {
return this.write({
dataId: options.id,
result: options.data,
variables: options.variables,
Expand Down
2 changes: 1 addition & 1 deletion src/cache/core/types/Cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export namespace Cache {

export interface WriteOptions<TResult = any, TVariables = any>
extends DataProxy.Query<TVariables> {
dataId: string;
dataId?: string;
result: TResult;
broadcast?: boolean;
}
Expand Down
2 changes: 1 addition & 1 deletion src/cache/core/types/DataProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export namespace DataProxy {
* value returned by your `dataIdFromObject` function. If a value with your
* id does not exist in the store, `null` will be returned.
*/
id: string;
id?: string;

/**
* A GraphQL document created using the `gql` template string tag from
Expand Down
6 changes: 3 additions & 3 deletions src/cache/inmemory/inMemoryCache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { dep, wrap } from 'optimism';
import { ApolloCache, Transaction } from '../core/cache';
import { Cache } from '../core/types/Cache';
import { addTypenameToDocument } from '../../utilities/graphql/transform';
import { StoreObject } from '../../utilities/graphql/storeUtils';
import { StoreObject, Reference } from '../../utilities/graphql/storeUtils';
import {
ApolloReducerConfig,
NormalizedCacheObject,
Expand Down Expand Up @@ -138,10 +138,10 @@ export class InMemoryCache extends ApolloCache<NormalizedCacheObject> {
}) || null;
}

public write(options: Cache.WriteOptions): void {
public write(options: Cache.WriteOptions): Reference | undefined {
try {
++this.txCount;
this.storeWriter.writeQueryToStore({
return this.storeWriter.writeToStore({
store: this.data,
query: options.query,
result: options.result,
Expand Down
65 changes: 42 additions & 23 deletions src/cache/inmemory/writeToStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import {
StoreValue,
StoreObject,
Reference,
isReference,
} from '../../utilities/graphql/storeUtils';

import { shouldInclude, hasDirectives } from '../../utilities/graphql/directives';
Expand Down Expand Up @@ -54,6 +55,19 @@ interface ProcessSelectionSetOptions {
};
}

interface WriteToStoreOptions {
query: DocumentNode;
result: Object;
dataId?: string;
store: NormalizedCache;
variables?: Object;
}

interface WriteQueryToStoreOptions
extends Omit<WriteToStoreOptions, "store"> {
store?: NormalizedCache;
}

export interface StoreWriterConfig {
reader?: StoreReader;
policies: Policies;
Expand All @@ -74,40 +88,36 @@ export class StoreWriter {
* @param variables A map from the name of a variable to its value. These variables can be
* referenced by the query document.
*/
public writeQueryToStore({
public writeQueryToStore(
options: WriteQueryToStoreOptions,
): NormalizedCache {
const {
dataId = "ROOT_QUERY",
store = new EntityStore.Root({
policies: this.config.policies,
}),
} = options;
this.writeToStore({ ...options, dataId, store });
return store;
}

public writeToStore({
query,
result,
dataId = 'ROOT_QUERY',
store = new EntityStore.Root({
policies: this.config.policies,
}),
dataId,
store,
variables,
}: {
query: DocumentNode;
result: Object;
dataId?: string;
store?: NormalizedCache;
variables?: Object;
}): NormalizedCache {
}: WriteToStoreOptions): Reference | undefined {
const operationDefinition = getOperationDefinition(query)!;

// Any IDs written explicitly to the cache (including ROOT_QUERY, most
// frequently) will be retained as reachable root IDs on behalf of their
// owner DocumentNode objects, until/unless evicted for all owners.
store.retain(dataId);

const merger = makeProcessedFieldsMerger();

variables = {
...getDefaultValues(operationDefinition),
...variables,
};

this.processSelectionSet({
const objOrRef = this.processSelectionSet({
result: result || Object.create(null),
// Since we already know the dataId here, pass it to
// processSelectionSet to skip calling policies.identify
// unnecessarily.
dataId,
selectionSet: operationDefinition.selectionSet,
context: {
Expand All @@ -124,7 +134,16 @@ export class StoreWriter {
},
});

return store;
const ref = isReference(objOrRef) ? objOrRef :
dataId && makeReference(dataId) || void 0;

if (ref) {
// Any IDs written explicitly to the cache (including ROOT_QUERY,
// most frequently) will be retained as reachable root IDs.
store.retain(ref.__ref);
}

return ref;
}

private processSelectionSet({
Expand Down

0 comments on commit 7202b78

Please sign in to comment.