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.

fix(graphcache): Improve Graphcache resolver consistency (#3336)

authored by

Phil Pluckthun and committed by
GitHub
3afa8022 80148efa

+29 -19
+5
.changeset/hungry-experts-admire.md
··· 1 + --- 2 + '@urql/exchange-graphcache': minor 3 + --- 4 + 5 + Allow scalar values on the parent to be accessed from `parent[info.fieldName]` consistently. Prior to this change `parent[fieldAlias]` would get populated, which wouldn’t always result in a field that’s consistently accessible.
+5
.changeset/tame-ways-obey.md
··· 1 + --- 2 + '@urql/exchange-graphcache': patch 3 + --- 4 + 5 + Fix cases where `ResolveInfo`’s `parentFieldKey` was incorrectly populated with a key that isn’t a field key (allowing for `cache.resolve(info.parentKey, info.parentFieldKey)` to be possible) but was instead set to `info.parentKey` combined with the field key.
-6
exchanges/graphcache/src/helpers/dict.ts
··· 1 - export const makeDict = (): any => Object.create(null); 2 - 3 - export const isDictEmpty = (x: any) => { 4 - for (const _ in x) return false; 5 - return true; 6 - };
+15 -8
exchanges/graphcache/src/operations/query.ts
··· 421 421 // The field is a scalar and can be retrieved directly from the result 422 422 dataFieldValue = resultValue; 423 423 } else if (InMemoryData.currentOperation === 'read' && resolver) { 424 + // We have a resolver for this field. 425 + // Prepare the actual fieldValue, so that the resolver can use it, 426 + // as to avoid the user having to do `cache.resolve(parent, info.fieldKey)` 427 + // only to get a scalar value. 428 + let parent = output; 429 + if (node.selectionSet === undefined && fieldValue !== undefined) { 430 + parent = { 431 + ...output, 432 + [fieldAlias]: fieldValue, 433 + [fieldName]: fieldValue, 434 + }; 435 + } 436 + 424 437 // We have to update the information in context to reflect the info 425 438 // that the resolver will receive 426 - updateContext(ctx, output, typename, entityKey, key, fieldName); 427 - 428 - // We have a resolver for this field. 429 - // Prepare the actual fieldValue, so that the resolver can use it 430 - if (fieldValue !== undefined) { 431 - output[fieldAlias] = fieldValue; 432 - } 439 + updateContext(ctx, parent, typename, entityKey, fieldKey, fieldName); 433 440 434 441 dataFieldValue = resolver( 435 - output, 442 + parent, 436 443 fieldArgs || ({} as Variables), 437 444 store, 438 445 ctx
+1 -1
exchanges/graphcache/src/operations/write.ts
··· 354 354 data, 355 355 typename, 356 356 entityKey || typename, 357 - joinKeys(typename, fieldKey), 357 + fieldKey, 358 358 fieldName 359 359 ); 360 360
+2 -3
exchanges/graphcache/src/store/data.ts
··· 19 19 joinKeys, 20 20 } from './keys'; 21 21 22 - import { makeDict } from '../helpers/dict'; 23 22 import { invariant, currentDebugStack } from '../helpers/help'; 24 23 25 24 type Dict<T> = Record<string, T>; ··· 283 282 // On the map itself we get or create the entity as a dict 284 283 let entity = keymap.get(entityKey) as Dict<T | undefined>; 285 284 if (entity === undefined) { 286 - keymap.set(entityKey, (entity = makeDict())); 285 + keymap.set(entityKey, (entity = Object.create(null))); 287 286 } 288 287 289 288 // If we're setting undefined we delete the node's entry ··· 612 611 if (currentData!.storage) { 613 612 currentOptimistic = true; 614 613 currentOperation = 'read'; 615 - const entries: SerializedEntries = makeDict(); 614 + const entries: SerializedEntries = {}; 616 615 for (const key of currentData!.persist.keys()) { 617 616 const { entityKey, fieldKey } = deserializeKeyInfo(key); 618 617 let x: void | Link | EntityField;
+1 -1
exchanges/graphcache/src/store/store.test.ts
··· 425 425 randomData, 426 426 'Todo', 427 427 'Todo:1', 428 - 'Todo:1.createdAt', 428 + 'createdAt', 429 429 'createdAt' 430 430 ); 431 431