Cache resolved fragments (globally)

This commit is contained in:
Chi Vinh Le
2017-12-01 16:31:26 +01:00
parent 2c72975137
commit f17b296e2e
3 changed files with 34 additions and 10 deletions
@@ -19,7 +19,7 @@ import update from 'immutability-helper';
import {notify} from 'coral-framework/actions/notification';
const commentConnectionFragment = gql`
fragment CoralAdmin_Moderation_CommentConnection on CommentConnection {
fragment CoralAdmin_UserDetail_CommentConnection on CommentConnection {
nodes {
...${getDefinitionName(UserDetailComment.fragments.comment)}
}
@@ -155,7 +155,7 @@ export const withUserDetailQuery = withQuery(gql`
author_id: $author_id,
statuses: $statuses
}) {
...CoralAdmin_Moderation_CommentConnection
...CoralAdmin_UserDetail_CommentConnection
}
...${getDefinitionName(UserDetailComment.fragments.root)}
${getSlotFragmentSpreads(slots, 'root')}
@@ -63,12 +63,32 @@ export function mergeSelectionSets(a, b) {
};
}
function getFragment(name, execContext) {
const {
rawFragmentMap,
fragmentMap,
} = execContext;
if (!(name in fragmentMap)) {
const fragment = rawFragmentMap[name];
if (!fragment) {
throw new Error(`fragment ${fragment.name.value} does not exist`);
}
const typeCondition = fragment.typeCondition.name.value;
const transformed = transformDefinition(fragment, execContext, `type.${typeCondition}`, typeCondition);
fragmentMap[name] = transformed;
}
return fragmentMap[name];
}
/**
* Return selections with resolved named fragments and directives.
*/
function getTransformedSelections(definition, path, gqlType, execContext) {
const {
fragmentMap,
variables,
} = execContext;
@@ -92,7 +112,7 @@ function getTransformedSelections(definition, path, gqlType, execContext) {
return o;
}
const fragment = fragmentMap[sel.name.value];
const fragment = getFragment(sel.name.value, execContext);
if (!fragment) {
throw new Error(`fragment ${fragment.name.value} does not exist`);
@@ -105,20 +125,19 @@ function getTransformedSelections(definition, path, gqlType, execContext) {
...fragment,
kind: 'InlineFragment',
};
const transformed = transformDefinition(node, execContext, path, typeCondition);
const name = getDefinitionName(node);
// Merge existing value.
if (name in o) {
o[name] = mergeDefinitions(o[name], transformed);
o[name] = mergeDefinitions(o[name], node);
return o;
}
o[name] = transformed;
o[name] = node;
return o;
}
const fragmentSelections = getTransformedSelections(fragment, path, typeCondition, execContext);
const fragmentSelections = fragment.selectionSet.selections;
fragmentSelections.forEach((s) => {
if (variables && !shouldInclude(s, variables)) {
@@ -184,7 +203,8 @@ export default function reduceDocument(document, options = {}) {
: `type.${mainDefinition.typeCondition.name.value}`;
const execContext = {
fragmentMap: createFragmentMap(fragments),
rawFragmentMap: createFragmentMap(fragments),
fragmentMap: options.fragmentMap || {},
keepFragments: [],
variables: options.variables,
typeGetter: options.typeGetter || (() => null),
+5 -1
View File
@@ -9,13 +9,17 @@ import {addTypenameToDocument} from 'apollo-client/queries/queryTransform';
export function createGraphQLService(registry, introspectionData) {
const typeGetter = createTypeGetter(introspectionData);
// Use shared fragment map.
// Attention: Fragment names must be unique otherwise weird things will happen.
const fragmentMap = {};
return {
registry,
resolveDocument(documentOrCallback, props, context) {
let document = typeof documentOrCallback === 'function'
? documentOrCallback(props, context)
: documentOrCallback;
document = reduceDocument(registry.resolveFragments(document), {typeGetter});
document = reduceDocument(registry.resolveFragments(document), {typeGetter, fragmentMap});
// We also add typenames to the document which apollo would usually do,
// but we also use the network interface in subscriptions directly