mirror of
https://github.com/wassname/talk.git
synced 2026-08-06 13:41:02 +08:00
Lazily resolve fragments in queries and mutations
This commit is contained in:
@@ -8,7 +8,6 @@ import REMOVE_COMMENT_TAG from './removeCommentTag.graphql';
|
||||
import IGNORE_USER from './ignoreUser.graphql';
|
||||
import STOP_IGNORING_USER from './stopIgnoringUser.graphql';
|
||||
import withMutation from '../../hocs/withMutation';
|
||||
import {getFragmentDocument} from '../../services/registry';
|
||||
|
||||
export const withPostComment = withMutation(
|
||||
gql`
|
||||
@@ -17,7 +16,6 @@ export const withPostComment = withMutation(
|
||||
...CreateCommentResponse
|
||||
}
|
||||
}
|
||||
${getFragmentDocument('CreateCommentResponse')}
|
||||
`, {
|
||||
props: ({mutate}) => ({
|
||||
postComment: comment => {
|
||||
|
||||
@@ -5,8 +5,7 @@ import flattenDeep from 'lodash/flattenDeep';
|
||||
import uniq from 'lodash/uniq';
|
||||
import pick from 'lodash/pick';
|
||||
import plugins from 'pluginsConfig';
|
||||
import {gql} from 'react-apollo';
|
||||
import {getDefinitionName} from 'coral-framework/utils';
|
||||
import {getDefinitionName, mergeDocuments} from 'coral-framework/utils';
|
||||
|
||||
export const pluginReducers = merge(
|
||||
...plugins
|
||||
@@ -44,8 +43,7 @@ function getComponentFragments(components) {
|
||||
|
||||
// Assemble arguments for `gql` to call it directly without using template literals.
|
||||
res[key].spreads = `...${res[key].spreads.join('\n...')}\n`;
|
||||
const literals = ['', ...res[key].definitions.map(() => '\n')];
|
||||
res[key].definitions = gql.apply(null, [literals, ...res[key].definitions]);
|
||||
res[key].definitions = mergeDocuments(res[key].definitions);
|
||||
});
|
||||
|
||||
return res;
|
||||
@@ -86,7 +84,7 @@ export function getSlotsFragments(slots) {
|
||||
|
||||
export function getGraphQLConfigs() {
|
||||
return plugins
|
||||
.map(o => o.module.mutations && pick(o.module, ['mutations', 'queries', 'fragments']))
|
||||
.map(o => pick(o.module, ['mutations', 'queries', 'fragments']))
|
||||
.filter(o => o);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import {graphql} from 'react-apollo';
|
||||
import merge from 'lodash/merge';
|
||||
import uniq from 'lodash/uniq';
|
||||
import {getMutationOptions} from 'coral-framework/services/registry';
|
||||
import {getMutationOptions, resolveFragments} from 'coral-framework/services/registry';
|
||||
import {store} from 'coral-framework/services/store';
|
||||
import {getDefinitionName} from '../utils';
|
||||
|
||||
@@ -73,6 +74,18 @@ export default (document, config) => WrappedComponent => {
|
||||
};
|
||||
return config.props({...data, mutate});
|
||||
};
|
||||
const wrapped = graphql(document, {...config, props: wrappedProps})(WrappedComponent);
|
||||
return wrapped;
|
||||
|
||||
// Lazily resolve fragments from registry to support circular dependencies.
|
||||
let memoized = null;
|
||||
const getWrapped = () => {
|
||||
if (!memoized) {
|
||||
memoized = graphql(resolveFragments(document), {...config, props: wrappedProps})(WrappedComponent);
|
||||
}
|
||||
return memoized;
|
||||
};
|
||||
|
||||
return (props) => {
|
||||
const Wrapped = getWrapped();
|
||||
return <Wrapped {...props} />;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as React from 'react';
|
||||
import {graphql} from 'react-apollo';
|
||||
import {getQueryOptions} from 'coral-framework/services/registry';
|
||||
import {getQueryOptions, resolveFragments} from 'coral-framework/services/registry';
|
||||
import {getDefinitionName, separateDataAndRoot} from '../utils';
|
||||
|
||||
/**
|
||||
@@ -33,6 +34,16 @@ export default (document, config) => WrappedComponent => {
|
||||
};
|
||||
};
|
||||
|
||||
const wrapped = graphql(document, {...config, options: wrappedOptions})(WrappedComponent);
|
||||
return wrapped;
|
||||
let memoized = null;
|
||||
const getWrapped = () => {
|
||||
if (!memoized) {
|
||||
memoized = graphql(resolveFragments(document), {...config, options: wrappedOptions})(WrappedComponent);
|
||||
}
|
||||
return memoized;
|
||||
};
|
||||
|
||||
return (props) => {
|
||||
const Wrapped = getWrapped();
|
||||
return <Wrapped {...props} />;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import {gql} from 'react-apollo';
|
||||
import {getDefinitionName} from 'coral-framework/utils';
|
||||
import {getDefinitionName, mergeDocuments} from 'coral-framework/utils';
|
||||
import {getGraphQLConfigs} from 'coral-framework/helpers/plugins';
|
||||
import globalFragments from 'coral-framework/graphql/fragments';
|
||||
import uniq from 'lodash/uniq';
|
||||
|
||||
const fragments = {};
|
||||
const mutationOptions = {};
|
||||
@@ -144,6 +144,11 @@ export function getQueryOptions(key) {
|
||||
*/
|
||||
export function getFragmentDocument(key) {
|
||||
init();
|
||||
|
||||
if (!(key in fragments)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
let documents = fragments[key] ? fragments[key].documents : [];
|
||||
let fields = fragments[key] ? `...${fragments[key].names.join('\n...')}\n` : ' __typename';
|
||||
|
||||
@@ -153,8 +158,7 @@ export function getFragmentDocument(key) {
|
||||
${fields}
|
||||
}
|
||||
`;
|
||||
const literals = [main, ...documents.map(() => '\n')];
|
||||
return gql.apply(null, [literals, ...documents]);
|
||||
return mergeDocuments([main, ...documents]);
|
||||
}
|
||||
|
||||
// The fragments and configs are lazily loaded to allow circular dependencies to work.
|
||||
@@ -174,3 +178,21 @@ function init() {
|
||||
getGraphQLConfigs().forEach(cfg => registerConfig(cfg));
|
||||
}
|
||||
|
||||
export function resolveFragments(document) {
|
||||
if (document.loc.source) {
|
||||
|
||||
// resolve fragments from registry
|
||||
const matchedSubFragments = document.loc.source.body.match(/\.\.\.(.*)/g) || [];
|
||||
const subFragments =
|
||||
uniq(matchedSubFragments.map(f => f.replace('...', '')))
|
||||
.map(key => getFragmentDocument(key))
|
||||
.filter(i => i);
|
||||
|
||||
if (subFragments.length > 0) {
|
||||
return mergeDocuments([document, ...subFragments]);
|
||||
}
|
||||
} else {
|
||||
console.warn('Can only resolve fragments from documents definied using the gql tag.');
|
||||
}
|
||||
return document;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import {gql} from 'react-apollo';
|
||||
|
||||
export const getTotalActionCount = (type, comment) => {
|
||||
return comment.action_summaries
|
||||
.filter(s => s.__typename === type)
|
||||
@@ -61,3 +63,11 @@ export function separateDataAndRoot(
|
||||
root,
|
||||
};
|
||||
}
|
||||
|
||||
export function mergeDocuments(documents) {
|
||||
const main = typeof documents[0] === 'string' ? documents[0] : documents[0].loc.source.body;
|
||||
const substitutions = documents.slice(1);
|
||||
const literals = [main, ...substitutions.map(() => '\n')];
|
||||
return gql.apply(null, [literals, ...substitutions]);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user