Skip to content

Commit

Permalink
Allow cache.identify to take Reference objects. (#6447)
Browse files Browse the repository at this point in the history
There are a number of scenarios where an object found in the cache will
have the union type `StoreObject | Reference`. Rather than forcing
application code to check isReference and access the reference.__ref
property manually, we can simply make cache.identify work for both
StoreObject and Reference objects.
  • Loading branch information
benjamn authored Jun 16, 2020
1 parent 6ebe33c commit 67796e5
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 5 deletions.
2 changes: 1 addition & 1 deletion src/cache/core/cache.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export abstract class ApolloCache<TSerialized> implements DataProxy {
return document;
}

public identify(object: StoreObject): string | undefined {
public identify(object: StoreObject | Reference): string | undefined {
return;
}

Expand Down
35 changes: 34 additions & 1 deletion src/cache/inmemory/__tests__/entityStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { InMemoryCache } from '../inMemoryCache';
import { DocumentNode } from 'graphql';
import { StoreObject } from '../types';
import { ApolloCache } from '../../core/cache';
import { Reference } from '../../../utilities/graphql/storeUtils';
import { Reference, makeReference, isReference } from '../../../utilities/graphql/storeUtils';
import { MissingFieldError } from '../..';

describe('EntityStore', () => {
Expand Down Expand Up @@ -1417,6 +1417,39 @@ describe('EntityStore', () => {
});
});

it("supports cache.identify(reference)", () => {
const cache = new InMemoryCache({
typePolicies: {
Task: {
keyFields: ["uuid"],
},
},
});

expect(cache.identify(makeReference("oyez"))).toBe("oyez");

const todoRef = cache.writeFragment({
fragment: gql`fragment TodoId on Todo { id }`,
data: {
__typename: "Todo",
id: 123,
},
});
expect(isReference(todoRef)).toBe(true);
expect(cache.identify(todoRef!)).toBe("Todo:123");

const taskRef = cache.writeFragment({
fragment: gql`fragment TaskId on Task { id }`,
data: {
__typename: "Task",
uuid: "eb8cffcc-7a9e-4d8b-a517-7d987bf42138",
},
});
expect(isReference(taskRef)).toBe(true);
expect(cache.identify(taskRef!)).toBe(
'Task:{"uuid":"eb8cffcc-7a9e-4d8b-a517-7d987bf42138"}');
});

it("supports cache.identify(object)", () => {
const queryWithAliases: DocumentNode = gql`
query {
Expand Down
8 changes: 5 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, Reference } from '../../utilities/graphql/storeUtils';
import { StoreObject, Reference, isReference } from '../../utilities/graphql/storeUtils';
import {
ApolloReducerConfig,
NormalizedCacheObject,
Expand Down Expand Up @@ -206,8 +206,10 @@ export class InMemoryCache extends ApolloCache<NormalizedCacheObject> {
// the object must contain a __typename and any primary key fields required
// to identify entities of that type. If you pass a query result object, be
// sure that none of the primary key fields have been renamed by aliasing.
public identify(object: StoreObject): string | undefined {
return this.policies.identify(object)[0];
// If you pass a Reference object, its __ref ID string will be returned.
public identify(object: StoreObject | Reference): string | undefined {
return isReference(object) ? object.__ref :
this.policies.identify(object)[0];
}

public evict(options: Cache.EvictOptions): boolean {
Expand Down

0 comments on commit 67796e5

Please sign in to comment.