Vulcan/packages/vulcan-lib/lib/modules/fragments.js
2017-07-03 12:32:20 +09:00

97 lines
No EOL
3.4 KiB
JavaScript

import gql from 'graphql-tag';
export const Fragments = {}; // will be populated on startup (see vulcan:routing)
export const FragmentsExtensions = {}; // will be used on startup
export const registerFragment = fragmentText => {
// extract name from fragment text
const fragmentName = fragmentText.match(/fragment (.*) on/)[1];
// extract subFragments from text
const matchedSubFragments = fragmentText.match(/\.\.\.(.*)/g) || [];
const subFragments = _.unique(matchedSubFragments.map(f => f.replace('...', '')));
// console.log('// registerFragment: ', fragmentName, subFragments)
// register fragment
Fragments[fragmentName] = {
fragmentText,
subFragments
}
};
// extend a fragment with additional properties
export const extendFragment = (fragmentName, newProperties) => {
FragmentsExtensions[fragmentName] = newProperties;
}
// perform fragment extension
export const extendFragmentWithProperties = (fragmentName, newProperties) => {
const fragment = Fragments[fragmentName];
const fragmentEndPosition = fragment.fragmentText.lastIndexOf('}');
const newFragmentText =[fragment.fragmentText.slice(0, fragmentEndPosition), newProperties, fragment.fragmentText.slice(fragmentEndPosition)].join('');
registerFragment(newFragmentText);
}
// remove a property from a fragment
export const removeFromFragment = (fragmentName, propertyName) => {
const fragment = Fragments[fragmentName];
const newFragmentText = fragment.fragmentText.replace(propertyName, '');
registerFragment(newFragmentText);
}
// get fragment name from fragment object
export const getFragmentName = fragment => fragment && fragment.definitions[0] && fragment.definitions[0].name.value;
// get actual gql fragment
export const getFragment = fragmentName => {
// get entire fragment as stored
const fragment = Fragments[fragmentName];
if (!fragment) {
throw new Error(`Fragment "${fragmentName}" not registered.`)
}
if (!fragment.fragmentObject) {
initializeFragment(fragmentName);
}
// return fragment object created by gql
return fragment.fragmentObject;
}
// create gql fragment from fragment name, text, and subfragments
export const initializeFragment = (fragmentName) => {
const fragmentItem = Fragments[fragmentName];
// pad the literals array with line returns for each subFragments
const literals = [fragmentItem.fragmentText, ...fragmentItem.subFragments.map(x => '\n')];
// the gql function expects an array of literals as first argument, and then sub-fragments as other arguments
const gqlArguments = [literals, ...fragmentItem.subFragments.map(subFragmentName => {
// if subfragment hasn't been initialized yet, do it now
if (!(Fragments[subFragmentName] && Fragments[subFragmentName].fragmentObject)) {
initializeFragment(subFragmentName);
}
// return subfragment's gql fragment
return Fragments[subFragmentName].fragmentObject;
})];
fragmentItem.fragmentObject = gql.apply(null, gqlArguments);
}
export const initializeFragments = () => {
// extend fragment text if fragment exists
_.forEach(FragmentsExtensions, (newProperties, fragmentName) => {
if (Fragments[fragmentName]) {
extendFragmentWithProperties(fragmentName, newProperties);
}
});
// initialize fragments to create gql fragment object
_.forEach(Fragments, (fragmentItem, fragmentName) => {
initializeFragment(fragmentName);
})
}