Skip to content

Commit

Permalink
Pass a context object around with store data
Browse files Browse the repository at this point in the history
This makes it quite a bit easier to pass additional configuration to the data/* functions
  • Loading branch information
nevir committed Jul 26, 2016
1 parent f76ad1b commit 7bcb0b8
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 55 deletions.
30 changes: 19 additions & 11 deletions src/QueryManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -306,12 +306,14 @@ export class QueryManager {
try {
const resultFromStore = {
data: readSelectionSetFromStore({
store: this.getDataWithOptimisticResults(),
context: {
store: this.getDataWithOptimisticResults(),
fragmentMap: queryStoreValue.fragmentMap,
},
rootId: queryStoreValue.query.id,
selectionSet: queryStoreValue.query.selectionSet,
variables: queryStoreValue.variables,
returnPartialData: options.returnPartialData || options.noFetch,
fragmentMap: queryStoreValue.fragmentMap,
}),
};

Expand Down Expand Up @@ -545,15 +547,17 @@ export class QueryManager {
}

const previousResult = readSelectionSetFromStore({
// In case of an optimistic change, apply reducer on top of the
// results including previous optimistic updates. Otherwise, apply it
// on top of the real data only.
store: isOptimistic ? this.getDataWithOptimisticResults() : this.getApolloState().data,
context: {
// In case of an optimistic change, apply reducer on top of the
// results including previous optimistic updates. Otherwise, apply it
// on top of the real data only.
store: isOptimistic ? this.getDataWithOptimisticResults() : this.getApolloState().data,
fragmentMap: createFragmentMap(fragments || []),
},
rootId: 'ROOT_QUERY',
selectionSet: queryDefinition.selectionSet,
variables: queryOptions.variables,
returnPartialData: queryOptions.returnPartialData || queryOptions.noFetch,
fragmentMap: createFragmentMap(fragments || []),
});

resultBehaviors.push({
Expand Down Expand Up @@ -618,12 +622,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;
Expand Down Expand Up @@ -718,12 +724,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 || noFetch,
fragmentMap: queryFragmentMap,
});
// ensure multiple errors don't get thrown
/* tslint:disable */
Expand Down
46 changes: 20 additions & 26 deletions src/data/diffAgainstStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,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,
Expand All @@ -59,7 +66,7 @@ export function diffQueryAgainstStore({
const queryDef = getQueryDefinition(query);

return diffSelectionSetAgainstStore({
store,
context: { store, fragmentMap: {} },
rootId: 'ROOT_QUERY',
selectionSet: queryDef.selectionSet,
throwOnMissingField: false,
Expand All @@ -81,7 +88,7 @@ export function diffFragmentAgainstStore({
const fragmentDef = getFragmentDefinition(fragment);

return diffSelectionSetAgainstStore({
store,
context: { store, fragmentMap: {} },
rootId,
selectionSet: fragmentDef.selectionSet,
throwOnMissingField: false,
Expand Down Expand Up @@ -121,28 +128,22 @@ export function handleFragmentErrors(fragmentErrors: { [typename: string]: Error
* @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[] = [];

Expand Down Expand Up @@ -172,12 +173,11 @@ export function diffSelectionSetAgainstStore({

if (isField(selection)) {
const diffResult = diffFieldAgainstStore({
context,
field: selection,
throwOnMissingField,
variables,
rootId,
store,
fragmentMap,
included,
});
fieldIsMissing = diffResult.isMissing;
Expand All @@ -199,12 +199,11 @@ export function diffSelectionSetAgainstStore({
if (included) {
try {
const diffResult = diffSelectionSetAgainstStore({
context,
selectionSet: selection.selectionSet,
throwOnMissingField,
variables,
rootId,
store,
fragmentMap,
});
fieldIsMissing = diffResult.isMissing;
fieldResult = diffResult.result;
Expand All @@ -227,7 +226,7 @@ export function diffSelectionSetAgainstStore({
}
}
} 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}`);
Expand All @@ -238,12 +237,11 @@ export function diffSelectionSetAgainstStore({
if (included) {
try {
const diffResult = diffSelectionSetAgainstStore({
context,
selectionSet: fragment.selectionSet,
throwOnMissingField,
variables,
rootId,
store,
fragmentMap,
});
fieldIsMissing = diffResult.isMissing;
fieldResult = diffResult.result;
Expand Down Expand Up @@ -306,23 +304,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)) {
Expand Down Expand Up @@ -377,12 +373,11 @@ Perhaps you want to use the \`returnPartialData\` option?`,
}

const itemDiffResult = diffSelectionSetAgainstStore({
store,
context,
throwOnMissingField,
rootId: id,
selectionSet: field.selectionSet,
variables,
fragmentMap,
});

if (itemDiffResult.isMissing) {
Expand All @@ -404,12 +399,11 @@ Perhaps you want to use the \`returnPartialData\` option?`,
if (isIdValue(storeValue)) {
const unescapedId = storeValue.id;
return diffSelectionSetAgainstStore({
store,
context,
throwOnMissingField,
rootId: unescapedId,
selectionSet: field.selectionSet,
variables,
fragmentMap,
});
}

Expand Down
18 changes: 9 additions & 9 deletions src/data/readFromStore.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import {
diffSelectionSetAgainstStore,
StoreContext,
} from './diffAgainstStore';

import {
Expand Down Expand Up @@ -37,12 +38,14 @@ export function readQueryFromStore({
const queryDef = getQueryDefinition(query);

return readSelectionSetFromStore({
store,
context: {
store,
fragmentMap: fragmentMap || {},
},
rootId: 'ROOT_QUERY',
selectionSet: queryDef.selectionSet,
variables,
returnPartialData,
fragmentMap,
});
}

Expand All @@ -62,7 +65,7 @@ export function readFragmentFromStore({
const fragmentDef = getFragmentDefinition(fragment);

return readSelectionSetFromStore({
store,
context: { store, fragmentMap: {} },
rootId,
selectionSet: fragmentDef.selectionSet,
variables,
Expand All @@ -71,29 +74,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;
Expand Down
31 changes: 22 additions & 9 deletions test/diffAgainstStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,10 @@ describe('diffing queries against the store', () => {
}`;
assert.throws(() => {
diffSelectionSetAgainstStore({
store,
context: {
store,
fragmentMap: {},
},
rootId: 'ROOT_QUERY',
selectionSet: getQueryDefinition(unionQuery).selectionSet,
variables: null,
Expand Down Expand Up @@ -353,7 +356,10 @@ describe('diffing queries against the store', () => {
}`;
assert.doesNotThrow(() => {
diffSelectionSetAgainstStore({
store,
context: {
store,
fragmentMap: {},
},
rootId: 'ROOT_QUERY',
selectionSet: getQueryDefinition(unionQuery).selectionSet,
variables: null,
Expand Down Expand Up @@ -395,12 +401,14 @@ describe('diffing queries against the store', () => {
}`;
assert.doesNotThrow(() => {
diffSelectionSetAgainstStore({
store,
context: {
store,
fragmentMap: createFragmentMap(getFragmentDefinitions(unionQuery)),
},
rootId: 'ROOT_QUERY',
selectionSet: getQueryDefinition(unionQuery).selectionSet,
variables: null,
throwOnMissingField: true,
fragmentMap: createFragmentMap(getFragmentDefinitions(unionQuery)),
});
});
});
Expand Down Expand Up @@ -439,12 +447,14 @@ describe('diffing queries against the store', () => {
}`;
assert.throw(() => {
diffSelectionSetAgainstStore({
store,
context: {
store,
fragmentMap: createFragmentMap(getFragmentDefinitions(unionQuery)),
},
rootId: 'ROOT_QUERY',
selectionSet: getQueryDefinition(unionQuery).selectionSet,
variables: null,
throwOnMissingField: true,
fragmentMap: createFragmentMap(getFragmentDefinitions(unionQuery)),
});
});
});
Expand Down Expand Up @@ -484,7 +494,10 @@ describe('diffing queries against the store', () => {

assert.throw(() => {
diffSelectionSetAgainstStore({
store,
context: {
store,
fragmentMap: {},
},
rootId: 'ROOT_QUERY',
selectionSet: getQueryDefinition(unionQuery).selectionSet,
variables: null,
Expand Down Expand Up @@ -527,7 +540,7 @@ describe('diffing queries against the store', () => {
`;

const { result } = diffSelectionSetAgainstStore({
store,
context: { store, fragmentMap: {} },
rootId: 'ROOT_QUERY',
selectionSet: getQueryDefinition(queryWithMissingField).selectionSet,
variables: null,
Expand All @@ -541,7 +554,7 @@ describe('diffing queries against the store', () => {
});
assert.throws(function() {
diffSelectionSetAgainstStore({
store,
context: { store, fragmentMap: {} },
rootId: 'ROOT_QUERY',
selectionSet: getQueryDefinition(queryWithMissingField).selectionSet,
variables: null,
Expand Down

0 comments on commit 7bcb0b8

Please sign in to comment.