Mirror: The highly customizable and versatile GraphQL client with which you add on features like normalized caching as you grow.
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(graphcache): Add globalIDs option (#3224)

Co-authored-by: Jovi De Croock <decroockjovi@gmail.com>

authored by

Phil Pluckthun
Jovi De Croock
and committed by
GitHub
c993ba38 89b5f8cc

+54 -8
+5
.changeset/dull-fishes-push.md
··· 1 + --- 2 + '@urql/exchange-graphcache': minor 3 + --- 4 + 5 + Add `globalIDs` configuration option to omit typenames in cache keys.
+14
exchanges/graphcache/src/store/store.test.ts
··· 237 237 }); 238 238 }); 239 239 240 + describe('Store with Global IDs', () => { 241 + it('generates keys without typenames when set to true', () => { 242 + const store = new Store({ globalIDs: true }); 243 + expect(store.keyOfEntity({ __typename: 'Any', id: '123' })).toBe('123'); 244 + expect(store.keyOfEntity({ __typename: 'None', id: '123' })).toBe('123'); 245 + }); 246 + 247 + it('generates keys without typenames when matching an input set', () => { 248 + const store = new Store({ globalIDs: ['User'] }); 249 + expect(store.keyOfEntity({ __typename: 'Any', id: '123' })).toBe('Any:123'); 250 + expect(store.keyOfEntity({ __typename: 'User', id: '123' })).toBe('123'); 251 + }); 252 + }); 253 + 240 254 describe('Store with ResolverConfig', () => { 241 255 it("sets the store's resolvers field to the given argument", () => { 242 256 const resolversOption = {
+21 -8
exchanges/graphcache/src/store/store.ts
··· 50 50 updates: UpdatesConfig; 51 51 optimisticMutations: OptimisticMutationConfig; 52 52 keys: KeyingConfig; 53 + globalIDs: Set<string> | boolean; 53 54 schema?: SchemaIntrospector; 54 55 55 56 rootFields: { query: string; mutation: string; subscription: string }; ··· 61 62 this.resolvers = opts.resolvers || {}; 62 63 this.optimisticMutations = opts.optimistic || {}; 63 64 this.keys = opts.keys || {}; 65 + 66 + this.globalIDs = Array.isArray(opts.globalIDs) 67 + ? new Set(opts.globalIDs) 68 + : !!opts.globalIDs; 64 69 65 70 let queryName = 'Query'; 66 71 let mutationName = 'Mutation'; ··· 107 112 // In resolvers and updaters we may have a specific parent 108 113 // object available that can be used to skip to a specific parent 109 114 // key directly without looking at its incomplete properties 110 - if (contextRef && data === contextRef.parent) return contextRef.parentKey; 111 - 112 - if (data == null || typeof data === 'string') return data || null; 113 - if (!data.__typename) return null; 114 - if (this.rootNames[data.__typename]) return data.__typename; 115 + if (contextRef && data === contextRef.parent) { 116 + return contextRef.parentKey; 117 + } else if (data == null || typeof data === 'string') { 118 + return data || null; 119 + } else if (!data.__typename) { 120 + return null; 121 + } else if (this.rootNames[data.__typename]) { 122 + return data.__typename; 123 + } 115 124 116 - let key: string | null | void; 125 + let key: string | null = null; 117 126 if (this.keys[data.__typename]) { 118 - key = this.keys[data.__typename](data); 127 + key = this.keys[data.__typename](data) || null; 119 128 } else if (data.id != null) { 120 129 key = `${data.id}`; 121 130 } else if (data._id != null) { 122 131 key = `${data._id}`; 123 132 } 124 133 125 - return key ? `${data.__typename}:${key}` : null; 134 + const typename = data.__typename; 135 + const globalID = 136 + this.globalIDs === true || 137 + (this.globalIDs && this.globalIDs.has(typename)); 138 + return globalID || !key ? key : `${typename}:${key}`; 126 139 } 127 140 128 141 resolve(entity: Entity, field: string, args?: FieldArgs): DataField {
+14
exchanges/graphcache/src/types.ts
··· 581 581 * the full keys docs. 582 582 */ 583 583 keys?: KeyingConfig; 584 + /** Enables global IDs for keying GraphQL types. 585 + * 586 + * @remarks 587 + * When `globalIDs` are enabled, GraphQL object type names will not contribute 588 + * to the keys of entities and instead only their ID fields (or `keys` return 589 + * values will be used. 590 + * 591 + * This is useful to overlap types of differing typenames. While this isn’t recommended 592 + * it can be necessary to represent more complex interface relationships. 593 + * 594 + * If this should only be applied to a limited set of type names, a list of 595 + * type names may be passed instead. 596 + */ 597 + globalIDs?: string[] | boolean; 584 598 /** Configures Graphcache with Schema Introspection data. 585 599 * 586 600 * @remarks