From cd3b248123625ee8e7aba446cf9d394c05a42c18 Mon Sep 17 00:00:00 2001 From: Ian MacLeod Date: Sun, 10 Jul 2016 19:44:05 -0700 Subject: [PATCH] Pass a context object around with store data Prompted by #376's brittleness; this helps keep common state/configuration around when performing a query. --- Also, as part of this, I noticed there are two seemingly unused functions: `diffQueryAgainstStore`, `diffFragmentAgainstStore` --- src/QueryManager.ts | 25 +++++++++++++------- src/data/diffAgainstStore.ts | 46 ++++++++++++++++-------------------- src/data/readFromStore.ts | 15 +++++------- test/diffAgainstStore.ts | 4 ++-- 4 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/QueryManager.ts b/src/QueryManager.ts index a676210f0b3..057f29e9fad 100644 --- a/src/QueryManager.ts +++ b/src/QueryManager.ts @@ -3,7 +3,6 @@ import { Request, } from './networkInterface'; - import forOwn = require('lodash.forown'); import assign = require('lodash.assign'); import isEqual = require('lodash.isequal'); @@ -281,12 +280,14 @@ export class QueryManager { } } else { const resultFromStore = readSelectionSetFromStore({ - store: this.getApolloState().data, + context: { + store: this.getApolloState().data, + fragmentMap: queryStoreValue.fragmentMap, + }, rootId: queryStoreValue.query.id, selectionSet: queryStoreValue.query.selectionSet, variables: queryStoreValue.variables, returnPartialData: options.returnPartialData, - fragmentMap: queryStoreValue.fragmentMap, }); if (observer.next) { @@ -373,12 +374,14 @@ export class QueryManager { } } else { const resultFromStore = readSelectionSetFromStore({ - store: this.getApolloState().data, + context: { + store: this.getApolloState().data, + fragmentMap: queryStoreValue.fragmentMap, + }, rootId: queryStoreValue.query.id, selectionSet: queryStoreValue.query.selectionSet, variables: queryStoreValue.variables, returnPartialData: options.returnPartialData, - fragmentMap: queryStoreValue.fragmentMap, }); if (observer.next) { @@ -558,12 +561,14 @@ export class QueryManager { // query, use the query diff algorithm to get as much of a result as we can, and identify // what data is missing from the store const { missingSelectionSets, result } = diffSelectionSetAgainstStore({ + context: { + store: this.store.getState()[this.reduxRootKey].data, + fragmentMap: queryFragmentMap, + }, selectionSet: querySS.selectionSet, - store: this.store.getState()[this.reduxRootKey].data, throwOnMissingField: false, rootId: querySS.id, variables, - fragmentMap: queryFragmentMap, }); initialResult = result; @@ -658,12 +663,14 @@ export class QueryManager { // this will throw an error if there are missing fields in // the results if returnPartialData is false. resultFromStore = readSelectionSetFromStore({ - store: this.getApolloState().data, + context: { + store: this.getApolloState().data, + fragmentMap: queryFragmentMap, + }, rootId: querySS.id, selectionSet: querySS.selectionSet, variables, returnPartialData: returnPartialData, - fragmentMap: queryFragmentMap, }); // ensure multiple errors don't get thrown /* tslint:disable */ diff --git a/src/data/diffAgainstStore.ts b/src/data/diffAgainstStore.ts index 3b1799ebb47..d9544b33c0b 100644 --- a/src/data/diffAgainstStore.ts +++ b/src/data/diffAgainstStore.ts @@ -42,6 +42,13 @@ export interface DiffResult { missingSelectionSets?: SelectionSetWithRoot[]; } +// Contexual state and configuration that is used throught a request from the +// store. +export interface StoreContext { + store: NormalizedCache; + fragmentMap: FragmentMap; +} + export function diffQueryAgainstStore({ store, query, @@ -54,7 +61,7 @@ export function diffQueryAgainstStore({ const queryDef = getQueryDefinition(query); return diffSelectionSetAgainstStore({ - store, + context: { store, fragmentMap: {} }, rootId: 'ROOT_QUERY', selectionSet: queryDef.selectionSet, throwOnMissingField: false, @@ -76,7 +83,7 @@ export function diffFragmentAgainstStore({ const fragmentDef = getFragmentDefinition(fragment); return diffSelectionSetAgainstStore({ - store, + context: { store, fragmentMap: {} }, rootId, selectionSet: fragmentDef.selectionSet, throwOnMissingField: false, @@ -96,28 +103,22 @@ export function diffFragmentAgainstStore({ * @return {result: Object, missingSelectionSets: [SelectionSet]} */ export function diffSelectionSetAgainstStore({ + context, selectionSet, - store, rootId, throwOnMissingField = false, variables, - fragmentMap, }: { + context: StoreContext, selectionSet: SelectionSet, - store: NormalizedCache, rootId: string, throwOnMissingField: boolean, variables: Object, - fragmentMap?: FragmentMap, }): DiffResult { if (selectionSet.kind !== 'SelectionSet') { throw new Error('Must be a selection set.'); } - if (!fragmentMap) { - fragmentMap = {}; - } - const result = {}; const missingFields: Selection[] = []; @@ -138,12 +139,11 @@ export function diffSelectionSetAgainstStore({ result: fieldResult, isMissing: fieldIsMissing, } = diffFieldAgainstStore({ + context, field: selection, throwOnMissingField, variables, rootId, - store, - fragmentMap, included: includeField, }); @@ -162,12 +162,11 @@ export function diffSelectionSetAgainstStore({ result: fieldResult, isMissing: fieldIsMissing, } = diffSelectionSetAgainstStore({ + context, selectionSet: selection.selectionSet, throwOnMissingField, variables, rootId, - store, - fragmentMap, }); if (fieldIsMissing) { @@ -176,7 +175,7 @@ export function diffSelectionSetAgainstStore({ assign(result, fieldResult); } } else { - const fragment = fragmentMap[selection.name.value]; + const fragment = context.fragmentMap[selection.name.value]; if (!fragment) { throw new Error(`No fragment named ${selection.name.value}`); } @@ -185,12 +184,11 @@ export function diffSelectionSetAgainstStore({ result: fieldResult, isMissing: fieldIsMissing, } = diffSelectionSetAgainstStore({ + context, selectionSet: fragment.selectionSet, throwOnMissingField, variables, rootId, - store, - fragmentMap, }); if (fieldIsMissing) { @@ -235,23 +233,21 @@ export function diffSelectionSetAgainstStore({ } function diffFieldAgainstStore({ + context, field, throwOnMissingField, variables, rootId, - store, - fragmentMap, included = true, }: { + context: StoreContext, field: Field, throwOnMissingField: boolean, variables: Object, rootId: string, - store: NormalizedCache, - fragmentMap?: FragmentMap, included?: Boolean, }): FieldDiffResult { - const storeObj = store[rootId] || {}; + const storeObj = context.store[rootId] || {}; const storeFieldKey = storeKeyNameFromField(field, variables); if (! has(storeObj, storeFieldKey)) { @@ -292,12 +288,11 @@ function diffFieldAgainstStore({ } const itemDiffResult = diffSelectionSetAgainstStore({ - store, + context, throwOnMissingField, rootId: id, selectionSet: field.selectionSet, variables, - fragmentMap, }); if (itemDiffResult.isMissing) { @@ -316,12 +311,11 @@ function diffFieldAgainstStore({ if (isString(storeValue)) { return diffSelectionSetAgainstStore({ - store, + context, throwOnMissingField, rootId: storeValue, selectionSet: field.selectionSet, variables, - fragmentMap, }); } diff --git a/src/data/readFromStore.ts b/src/data/readFromStore.ts index 7a14ba7939a..578642508bd 100644 --- a/src/data/readFromStore.ts +++ b/src/data/readFromStore.ts @@ -1,5 +1,6 @@ import { diffSelectionSetAgainstStore, + StoreContext, } from './diffAgainstStore'; import { @@ -10,7 +11,6 @@ import { import { getQueryDefinition, getFragmentDefinition, - FragmentMap, } from '../queries/getFromAST'; import { @@ -35,7 +35,7 @@ export function readQueryFromStore({ const queryDef = getQueryDefinition(query); return readSelectionSetFromStore({ - store, + context: { store, fragmentMap: {} }, rootId: 'ROOT_QUERY', selectionSet: queryDef.selectionSet, variables, @@ -59,7 +59,7 @@ export function readFragmentFromStore({ const fragmentDef = getFragmentDefinition(fragment); return readSelectionSetFromStore({ - store, + context: { store, fragmentMap: {} }, rootId, selectionSet: fragmentDef.selectionSet, variables, @@ -68,29 +68,26 @@ export function readFragmentFromStore({ } export function readSelectionSetFromStore({ - store, + context, rootId, selectionSet, variables, returnPartialData = false, - fragmentMap, }: { - store: NormalizedCache, + context: StoreContext, rootId: string, selectionSet: SelectionSet, variables: Object, returnPartialData?: boolean, - fragmentMap?: FragmentMap, }): Object { const { result, } = diffSelectionSetAgainstStore({ + context, selectionSet, rootId, - store, throwOnMissingField: !returnPartialData, variables, - fragmentMap, }); return result; diff --git a/test/diffAgainstStore.ts b/test/diffAgainstStore.ts index c3c4bb0753d..d37e30088ec 100644 --- a/test/diffAgainstStore.ts +++ b/test/diffAgainstStore.ts @@ -319,7 +319,7 @@ describe('diffing queries against the store', () => { `; const { result } = diffSelectionSetAgainstStore({ - store, + context: { store, fragmentMap: {} }, rootId: 'ROOT_QUERY', selectionSet: getQueryDefinition(queryWithMissingField).selectionSet, variables: null, @@ -333,7 +333,7 @@ describe('diffing queries against the store', () => { }); assert.throws(function() { diffSelectionSetAgainstStore({ - store, + context: { store, fragmentMap: {} }, rootId: 'ROOT_QUERY', selectionSet: getQueryDefinition(queryWithMissingField).selectionSet, variables: null,