Socket
Socket
Sign inDemoInstall

apollo-utilities

Package Overview
Dependencies
Maintainers
4
Versions
105
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

apollo-utilities - npm Package Compare versions

Comparing version 1.1.0-alpha.2 to 1.1.0-alpha.3

lib/util/filterInPlace.d.ts

647

lib/bundle.umd.js
(function (global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('fast-json-stable-stringify')) :
typeof define === 'function' && define.amd ? define(['exports', 'fast-json-stable-stringify'], factory) :
(factory((global.apollo = global.apollo || {}, global.apollo.utilities = {}),global.stringify));
}(this, (function (exports,stringify) { 'use strict';
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('fast-json-stable-stringify'), require('graphql/language/visitor')) :
typeof define === 'function' && define.amd ? define(['exports', 'fast-json-stable-stringify', 'graphql/language/visitor'], factory) :
(global = global || self, factory((global.apollo = global.apollo || {}, global.apollo.utilities = {}), global.stringify, global.visitor));
}(this, function (exports, stringify, visitor) { 'use strict';

@@ -309,2 +309,7 @@ stringify = stringify && stringify.hasOwnProperty('default') ? stringify['default'] : stringify;

}
function hasClientExports(document) {
return (document &&
hasDirectives(['client'], document) &&
hasDirectives(['export'], document));
}

@@ -403,2 +408,3 @@ var __assign$1 = (undefined && undefined.__assign) || function () {

}
return doc;
}

@@ -506,33 +512,24 @@ function getOperationDefinition(doc) {

var toString = Object.prototype.toString;
function cloneDeep(value) {
return cloneDeepHelper(value, new Map());
}
function cloneDeepHelper(val, seen) {
switch (toString.call(val)) {
case '[object Array]': {
if (seen.has(val))
return seen.get(val);
var copy_1 = val.slice(0);
seen.set(val, copy_1);
copy_1.forEach(function (child, i) {
copy_1[i] = cloneDeepHelper(child, seen);
});
return copy_1;
function filterInPlace(array, test, context) {
var target = 0;
array.forEach(function (elem, i) {
if (test.call(this, elem, i, array)) {
array[target++] = elem;
}
case '[object Object]': {
if (seen.has(val))
return seen.get(val);
var copy_2 = Object.create(Object.getPrototypeOf(val));
seen.set(val, copy_2);
Object.keys(val).forEach(function (key) {
copy_2[key] = cloneDeepHelper(val[key], seen);
});
return copy_2;
}
default:
return val;
}
}, context);
array.length = target;
return array;
}
var __assign$2 = (undefined && undefined.__assign) || function () {
__assign$2 = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign$2.apply(this, arguments);
};
var TYPENAME_FIELD = {

@@ -545,164 +542,109 @@ kind: 'Field',

};
function isNotEmpty(op, fragments) {
return (op.selectionSet.selections.filter(function (selectionSet) {
return !(selectionSet &&
selectionSet.kind === 'FragmentSpread' &&
!isNotEmpty(fragments[selectionSet.name.value], fragments));
}).length > 0);
function isEmpty(op, fragments) {
return op.selectionSet.selections.every(function (selection) {
return selection.kind === 'FragmentSpread' &&
isEmpty(fragments[selection.name.value], fragments);
});
}
function nullIfDocIsEmpty(doc) {
return isEmpty(getOperationDefinitionOrDie(doc), createFragmentMap(getFragmentDefinitions(doc)))
? null
: doc;
}
function getDirectiveMatcher(directives) {
return function directiveMatcher(directive) {
return directives.some(function (dir) {
if (dir.name && dir.name === directive.name.value)
return true;
if (dir.test && dir.test(directive))
return true;
return false;
return (dir.name && dir.name === directive.name.value) ||
(dir.test && dir.test(directive));
});
};
}
function addTypenameToSelectionSet(selectionSet, isRoot) {
if (isRoot === void 0) { isRoot = false; }
if (selectionSet.selections) {
if (!isRoot) {
var alreadyHasThisField = selectionSet.selections.some(function (selection) {
return (selection.kind === 'Field' &&
selection.name.value === '__typename');
});
if (!alreadyHasThisField) {
selectionSet.selections.push(TYPENAME_FIELD);
}
}
selectionSet.selections.forEach(function (selection) {
if (selection.kind === 'Field') {
if (selection.name.value.lastIndexOf('__', 0) !== 0 &&
selection.selectionSet) {
addTypenameToSelectionSet(selection.selectionSet);
function removeDirectivesFromDocument(directives, doc) {
var variablesInUse = Object.create(null);
var variablesToRemove = [];
var fragmentSpreadsInUse = Object.create(null);
var fragmentSpreadsToRemove = [];
var modifiedDoc = nullIfDocIsEmpty(visitor.visit(doc, {
Variable: {
enter: function (node, _key, parent) {
if (parent.kind !== 'VariableDefinition') {
variablesInUse[node.name.value] = true;
}
}
else if (selection.kind === 'InlineFragment') {
if (selection.selectionSet) {
addTypenameToSelectionSet(selection.selectionSet);
},
},
Field: {
enter: function (node) {
if (directives && node.directives) {
var shouldRemoveField = directives.some(function (directive) { return directive.remove; });
if (shouldRemoveField &&
node.directives.some(getDirectiveMatcher(directives))) {
if (node.arguments) {
node.arguments.forEach(function (arg) {
if (arg.value.kind === 'Variable') {
variablesToRemove.push({
name: arg.value.name.value,
});
}
});
}
if (node.selectionSet) {
getAllFragmentSpreadsFromSelectionSet(node.selectionSet).forEach(function (frag) {
fragmentSpreadsToRemove.push({
name: frag.name.value,
});
});
}
return null;
}
}
}
});
}
}
function getSelectionsMatchingDirectiveFromSelectionSet(directives, selectionSet, invert, fieldsOnly) {
if (invert === void 0) { invert = false; }
if (fieldsOnly === void 0) { fieldsOnly = false; }
return selectionSet.selections
.map(function (selection) {
if (selection.kind !== 'Field' ||
!selection ||
!selection.directives) {
return fieldsOnly ? null : selection;
}
var isMatch;
var directiveMatcher = getDirectiveMatcher(directives);
selection.directives = selection.directives.filter(function (directive) {
var shouldKeep = !directiveMatcher(directive);
if (!isMatch && !shouldKeep) {
isMatch = true;
}
return shouldKeep;
});
return isMatch && invert ? null : selection;
})
.filter(function (s) { return !!s; });
}
function removeDirectivesFromSelectionSet(directives, selectionSet) {
if (!selectionSet.selections)
return selectionSet;
var agressiveRemove = directives.some(function (dir) { return dir.remove; });
selectionSet.selections = getSelectionsMatchingDirectiveFromSelectionSet(directives, selectionSet, agressiveRemove);
selectionSet.selections.forEach(function (selection) {
if ((selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet) {
removeDirectivesFromSelectionSet(directives, selection.selectionSet);
}
});
return selectionSet;
}
function removeDirectivesFromDocument(directives, doc) {
var docClone = cloneDeep(doc);
var removedArguments = [];
var removedFragments = [];
var aggressiveRemove = directives.some(function (directive) { return directive.remove; });
docClone.definitions.forEach(function (definition) {
var operationDefinition = definition;
var originalSelectionSet = cloneDeep(operationDefinition.selectionSet);
var newSelectionSet = removeDirectivesFromSelectionSet(directives, operationDefinition.selectionSet);
if (aggressiveRemove && !!docClone) {
var matchingSelections = getSelectionsMatchingDirectiveFromSelectionSet(directives.map(function (config) { return ({
name: config.name,
test: config.test,
}); }), originalSelectionSet);
var remainingArguments_1 = getAllArgumentsFromSelectionSet(newSelectionSet);
removedArguments = removedArguments.concat(matchingSelections
.map(getAllArgumentsFromSelection)
.reduce(function (allArguments, selectionArguments) { return allArguments.concat(selectionArguments); }, [])
.filter(function (removedArg) {
return !remainingArguments_1.some(function (remainingArg) {
if (remainingArg.value.kind !== 'Variable' ||
!remainingArg.value)
return false;
if (removedArg.value.kind !== 'Variable' ||
!removedArg.value)
return false;
return (remainingArg.value.name.value === removedArg.value.name.value);
});
})
.map(function (argument) {
if (argument.value.kind !== 'Variable' ||
!argument.value)
},
},
FragmentSpread: {
enter: function (node) {
fragmentSpreadsInUse[node.name.value] = true;
},
},
Directive: {
enter: function (node) {
if (getDirectiveMatcher(directives)(node)) {
return null;
return {
name: argument.value.name.value,
remove: aggressiveRemove,
};
})
.filter(function (node) { return !!node; }));
var remainingFragmentSpreads_1 = getAllFragmentSpreadsFromSelectionSet(newSelectionSet);
removedFragments = removedFragments.concat(matchingSelections
.map(getAllFragmentSpreadsFromSelection)
.reduce(function (allFragments, selectionFragments) { return allFragments.concat(selectionFragments); }, [])
.filter(function (removedFragment) {
return !remainingFragmentSpreads_1.some(function (remainingFragment) {
return remainingFragment.name.value === removedFragment.name.value;
});
})
.map(function (fragment) { return ({
name: fragment.name.value,
remove: aggressiveRemove,
}); }));
}
});
if (!docClone) {
return null;
}
},
},
}));
if (modifiedDoc &&
filterInPlace(variablesToRemove, function (v) { return !variablesInUse[v.name]; }).length) {
modifiedDoc = removeArgumentsFromDocument(variablesToRemove, modifiedDoc);
}
if (removedFragments.length > 0) {
docClone = removeFragmentSpreadFromDocument(removedFragments, docClone);
if (!docClone) {
return null;
}
if (modifiedDoc &&
filterInPlace(fragmentSpreadsToRemove, function (fs) { return !fragmentSpreadsInUse[fs.name]; })
.length) {
modifiedDoc = removeFragmentSpreadFromDocument(fragmentSpreadsToRemove, modifiedDoc);
}
if (removedArguments.length > 0) {
docClone = removeArgumentsFromDocument(removedArguments, docClone);
if (!docClone) {
return null;
}
}
var operation = getOperationDefinitionOrDie(docClone);
var fragments = createFragmentMap(getFragmentDefinitions(docClone));
return isNotEmpty(operation, fragments) ? docClone : null;
return modifiedDoc;
}
function addTypenameToDocument(doc) {
checkDocument(doc);
var docClone = cloneDeep(doc);
docClone.definitions.forEach(function (definition) {
var isRoot = definition.kind === 'OperationDefinition';
addTypenameToSelectionSet(definition.selectionSet, isRoot);
return visitor.visit(checkDocument(doc), {
SelectionSet: {
enter: function (node, _key, parent) {
if (parent &&
parent.kind === 'OperationDefinition') {
return;
}
var selections = node.selections;
if (!selections) {
return;
}
var skip = selections.some(function (selection) {
return (selection.kind === 'Field' &&
(selection.name.value === '__typename' ||
selection.name.value.lastIndexOf('__', 0) === 0));
});
if (skip) {
return;
}
return __assign$2({}, node, { selections: selections.concat([TYPENAME_FIELD]) });
},
},
});
return docClone;
}

@@ -723,10 +665,11 @@ var connectionRemoveConfig = {

function removeConnectionDirectiveFromDocument(doc) {
checkDocument(doc);
return removeDirectivesFromDocument([connectionRemoveConfig], doc);
return removeDirectivesFromDocument([connectionRemoveConfig], checkDocument(doc));
}
function hasDirectivesInSelectionSet(directives, selectionSet, nestedCheck) {
if (nestedCheck === void 0) { nestedCheck = true; }
return filterSelectionSet(selectionSet, function (selection) {
return hasDirectivesInSelection(directives, selection, nestedCheck);
});
return (selectionSet &&
selectionSet.selections &&
selectionSet.selections.some(function (selection) {
return hasDirectivesInSelection(directives, selection, nestedCheck);
}));
}

@@ -741,160 +684,101 @@ function hasDirectivesInSelection(directives, selection, nestedCheck) {

}
var directiveMatcher = getDirectiveMatcher(directives);
var matchedDirectives = selection.directives.filter(directiveMatcher);
var hasMatches = matchedDirectives.length > 0;
return (hasMatches ||
return (selection.directives.some(getDirectiveMatcher(directives)) ||
(nestedCheck &&
hasDirectivesInSelectionSet(directives, selection.selectionSet, nestedCheck)));
}
function getDirectivesFromSelectionSet(directives, selectionSet) {
selectionSet.selections = selectionSet.selections
.filter(function (selection) {
return hasDirectivesInSelection(directives, selection, true);
})
.map(function (selection) {
if (hasDirectivesInSelection(directives, selection, false)) {
return selection;
}
if ((selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet) {
selection.selectionSet = getDirectivesFromSelectionSet(directives, selection.selectionSet);
}
return selection;
});
return selectionSet;
}
function getDirectivesFromDocument(directives, doc, includeAllFragments) {
if (includeAllFragments === void 0) { includeAllFragments = false; }
function getDirectivesFromDocument(directives, doc) {
checkDocument(doc);
var docClone = cloneDeep(doc);
docClone.definitions = docClone.definitions.map(function (definition) {
if ((definition.kind === 'OperationDefinition' ||
(definition.kind === 'FragmentDefinition' && !includeAllFragments)) &&
definition.selectionSet) {
definition.selectionSet = getDirectivesFromSelectionSet(directives, definition.selectionSet);
}
return definition;
});
var operation = getOperationDefinitionOrDie(docClone);
var fragments = createFragmentMap(getFragmentDefinitions(docClone));
return isNotEmpty(operation, fragments) ? docClone : null;
var parentPath;
return nullIfDocIsEmpty(visitor.visit(doc, {
SelectionSet: {
enter: function (node, _key, _parent, path) {
var currentPath = path.join('-');
if (!parentPath ||
currentPath === parentPath ||
!currentPath.startsWith(parentPath)) {
if (node.selections) {
var selectionsWithDirectives = node.selections.filter(function (selection) { return hasDirectivesInSelection(directives, selection); });
if (hasDirectivesInSelectionSet(directives, node, false)) {
parentPath = currentPath;
}
return __assign$2({}, node, { selections: selectionsWithDirectives });
}
else {
return null;
}
}
},
},
}));
}
function getArgumentMatcher(config) {
return function (argument) {
return function argumentMatcher(argument) {
return config.some(function (aConfig) {
if (argument.value.kind !== 'Variable' ||
!argument.value)
return false;
if (!argument.value.name)
return false;
if (aConfig.name === argument.value.name.value)
return true;
if (aConfig.test && aConfig.test(argument))
return true;
return false;
return argument.value &&
argument.value.kind === 'Variable' &&
argument.value.name &&
(aConfig.name === argument.value.name.value ||
(aConfig.test && aConfig.test(argument)));
});
};
}
function getAllArgumentsFromSelectionSet(selectionSet) {
return selectionSet.selections
.map(getAllArgumentsFromSelection)
.reduce(function (allArguments, selectionArguments) {
return allArguments.concat(selectionArguments);
}, []);
function removeArgumentsFromDocument(config, doc) {
var argMatcher = getArgumentMatcher(config);
return nullIfDocIsEmpty(visitor.visit(doc, {
OperationDefinition: {
enter: function (node) {
return __assign$2({}, node, { variableDefinitions: node.variableDefinitions.filter(function (varDef) {
return !config.some(function (arg) { return arg.name === varDef.variable.name.value; });
}) });
},
},
Field: {
enter: function (node) {
var shouldRemoveField = config.some(function (argConfig) { return argConfig.remove; });
if (shouldRemoveField) {
var argMatchCount_1 = 0;
node.arguments.forEach(function (arg) {
if (argMatcher(arg)) {
argMatchCount_1 += 1;
}
});
if (argMatchCount_1 === 1) {
return null;
}
}
},
},
Argument: {
enter: function (node) {
if (argMatcher(node)) {
return null;
}
},
},
}));
}
function getAllArgumentsFromSelection(selection) {
if (selection.kind !== 'Field' || !selection) {
return [];
function removeFragmentSpreadFromDocument(config, doc) {
function enter(node) {
if (config.some(function (def) { return def.name === node.name.value; })) {
return null;
}
}
return selection.arguments || [];
return nullIfDocIsEmpty(visitor.visit(doc, {
FragmentSpread: { enter: enter },
FragmentDefinition: { enter: enter },
}));
}
function removeArgumentsFromDocument(config, query) {
var docClone = cloneDeep(query);
docClone.definitions.forEach(function (definition) {
var operationDefinition = definition;
var removeVariableConfig = config
.filter(function (aConfig) { return !!aConfig.name; })
.map(function (aConfig) { return ({
name: aConfig.name,
remove: aConfig.remove,
}); });
removeArgumentsFromSelectionSet(config, operationDefinition.selectionSet);
removeArgumentsFromOperationDefinition(removeVariableConfig, operationDefinition);
});
var operation = getOperationDefinitionOrDie(docClone);
var fragments = createFragmentMap(getFragmentDefinitions(docClone));
return isNotEmpty(operation, fragments) ? docClone : null;
}
function removeArgumentsFromOperationDefinition(config, definition) {
if (!definition.variableDefinitions)
return definition;
var aggressiveRemove = config.some(function (aConfig) { return aConfig.remove; });
definition.variableDefinitions = definition.variableDefinitions.filter(function (aDefinition) {
var shouldKeep = !config.some(function (aConfig) {
if (aConfig.name === aDefinition.variable.name.value)
return true;
if (aConfig.test && aConfig.test(aDefinition))
return true;
return false;
});
return shouldKeep;
});
return definition;
}
function removeArgumentsFromSelectionSet(config, selectionSet) {
if (!selectionSet.selections)
return selectionSet;
var aggressiveRemove = config.some(function (aConfig) { return aConfig.remove; });
selectionSet.selections = selectionSet.selections
.map(function (selection) {
if (selection.kind !== 'Field' ||
!selection ||
!selection.arguments) {
return selection;
}
var remove;
var argumentMatcher = getArgumentMatcher(config);
selection.arguments = selection.arguments.filter(function (argument) {
var shouldKeep = !argumentMatcher(argument);
if (!remove && !shouldKeep && aggressiveRemove) {
remove = true;
}
return shouldKeep;
});
return remove ? null : selection;
})
.filter(function (x) { return !!x; });
function getAllFragmentSpreadsFromSelectionSet(selectionSet) {
var allFragments = [];
selectionSet.selections.forEach(function (selection) {
if ((selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet) {
removeArgumentsFromSelectionSet(config, selection.selectionSet);
getAllFragmentSpreadsFromSelectionSet(selection.selectionSet).forEach(function (frag) { return allFragments.push(frag); });
}
else if (selection.kind === 'FragmentSpread') {
allFragments.push(selection);
}
});
return selectionSet;
return allFragments;
}
function hasFragmentSpreadInSelection(config, selection) {
if (selection.kind !== 'FragmentSpread' ||
!selection) {
return false;
}
return config.some(function (aConfig) {
if (aConfig.name === selection.name.value)
return true;
if (aConfig.test && aConfig.test(selection))
return true;
return false;
});
}
function removeFragmentSpreadFromDocument(config, query) {
var docClone = cloneDeep(query);
docClone.definitions.forEach(function (definition) {
removeFragmentSpreadFromSelectionSet(config, definition.selectionSet);
});
docClone.definitions = removeFragmentSpreadFromDefinitions(config
.filter(function (aConfig) { return !!aConfig.name; })
.map(function (aConfig) { return ({ name: aConfig.name }); }), docClone.definitions);
var operation = getOperationDefinitionOrDie(docClone);
var fragments = createFragmentMap(getFragmentDefinitions(docClone));
return isNotEmpty(operation, fragments) ? docClone : null;
}
function buildQueryFromSelectionSet(document) {

@@ -906,62 +790,69 @@ var definition = getMainDefinition(document);

}
var docClone = cloneDeep(document);
var selectionSet = definition.selectionSet;
docClone.definitions = [
var modifiedDoc = visitor.visit(document, {
OperationDefinition: {
enter: function (node) {
return __assign$2({}, node, { operation: 'query' });
},
},
});
return modifiedDoc;
}
function removeClientSetsFromDocument(document) {
checkDocument(document);
var modifiedDoc = removeDirectivesFromDocument([
{
kind: 'OperationDefinition',
operation: 'query',
selectionSet: selectionSet,
test: function (directive) { return directive.name.value === 'client'; },
remove: true,
},
];
return docClone;
}
function removeFragmentSpreadFromDefinitions(config, definitions) {
return definitions.filter(function (definition) {
if (definition.kind !== 'FragmentDefinition' ||
!definition) {
return true;
}
return !config.some(function (aConfig) {
if (aConfig.name && aConfig.name === definition.name.value)
return true;
if (aConfig.test && aConfig.test(definition))
return true;
return false;
], document);
if (modifiedDoc) {
modifiedDoc = visitor.visit(modifiedDoc, {
FragmentDefinition: {
enter: function (node) {
if (node.selectionSet) {
var isTypenameOnly = node.selectionSet.selections.every(function (selection) {
return (selection.kind === 'Field' &&
selection.name.value === '__typename');
});
if (isTypenameOnly) {
return null;
}
}
},
},
});
});
}
return modifiedDoc;
}
function removeFragmentSpreadFromSelectionSet(config, selectionSet) {
if (!selectionSet.selections)
return selectionSet;
selectionSet.selections = selectionSet.selections.filter(function (selection) { return !hasFragmentSpreadInSelection(config, selection); });
selectionSet.selections.forEach(function (selection) {
if ((selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet) {
removeFragmentSpreadFromSelectionSet(config, selection.selectionSet);
var toString = Object.prototype.toString;
function cloneDeep(value) {
return cloneDeepHelper(value, new Map());
}
function cloneDeepHelper(val, seen) {
switch (toString.call(val)) {
case '[object Array]': {
if (seen.has(val))
return seen.get(val);
var copy_1 = val.slice(0);
seen.set(val, copy_1);
copy_1.forEach(function (child, i) {
copy_1[i] = cloneDeepHelper(child, seen);
});
return copy_1;
}
});
return selectionSet;
}
function getAllFragmentSpreadsFromSelectionSet(selectionSet) {
return selectionSet.selections
.map(getAllFragmentSpreadsFromSelection)
.reduce(function (allFragments, selectionFragments) { return allFragments.concat(selectionFragments); }, []);
}
function getAllFragmentSpreadsFromSelection(selection) {
if ((selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet) {
return getAllFragmentSpreadsFromSelectionSet(selection.selectionSet);
case '[object Object]': {
if (seen.has(val))
return seen.get(val);
var copy_2 = Object.create(Object.getPrototypeOf(val));
seen.set(val, copy_2);
Object.keys(val).forEach(function (key) {
copy_2[key] = cloneDeepHelper(val[key], seen);
});
return copy_2;
}
default:
return val;
}
else if (selection.kind === 'FragmentSpread' &&
selection) {
return [selection];
}
return [];
}
function filterSelectionSet(selectionSet, filter) {
if (!(selectionSet && selectionSet.selections)) {
return false;
}
return selectionSet.selections.filter(filter).length > 0;
}

@@ -1107,2 +998,3 @@ function getEnv() {

exports.hasDirectives = hasDirectives;
exports.hasClientExports = hasClientExports;
exports.getFragmentQueryDocument = getFragmentQueryDocument;

@@ -1128,2 +1020,3 @@ exports.getMutationDefinition = getMutationDefinition;

exports.buildQueryFromSelectionSet = buildQueryFromSelectionSet;
exports.removeClientSetsFromDocument = removeClientSetsFromDocument;
exports.isScalarValue = isScalarValue;

@@ -1159,3 +1052,3 @@ exports.isNumberValue = isNumberValue;

})));
}));
//# sourceMappingURL=bundle.umd.js.map

@@ -14,2 +14,3 @@ import { FieldNode, SelectionNode, DocumentNode } from 'graphql';

export declare function hasDirectives(names: string[], doc: DocumentNode): boolean;
export declare function hasClientExports(document: DocumentNode): boolean;
//# sourceMappingURL=directives.d.ts.map

@@ -84,2 +84,7 @@ import { argumentsObjectFromField } from './storeUtils';

}
export function hasClientExports(document) {
return (document &&
hasDirectives(['client'], document) &&
hasDirectives(['export'], document));
}
//# sourceMappingURL=directives.js.map
import { DocumentNode, OperationDefinitionNode, FragmentDefinitionNode } from 'graphql';
import { JsonValue } from './storeUtils';
export declare function getMutationDefinition(doc: DocumentNode): OperationDefinitionNode;
export declare function checkDocument(doc: DocumentNode): void;
export declare function checkDocument(doc: DocumentNode): DocumentNode;
export declare function getOperationDefinition(doc: DocumentNode): OperationDefinitionNode | undefined;

@@ -6,0 +6,0 @@ export declare function getOperationDefinitionOrDie(document: DocumentNode): OperationDefinitionNode;

@@ -29,2 +29,3 @@ import { assign } from './util/assign';

}
return doc;
}

@@ -31,0 +32,0 @@ export function getOperationDefinition(doc) {

@@ -21,6 +21,7 @@ import { DocumentNode, DirectiveNode, FragmentDefinitionNode, ArgumentNode, FragmentSpreadNode, VariableDefinitionNode } from 'graphql';

export declare function removeConnectionDirectiveFromDocument(doc: DocumentNode): DocumentNode;
export declare function getDirectivesFromDocument(directives: GetDirectiveConfig[], doc: DocumentNode, includeAllFragments?: boolean): DocumentNode | null;
export declare function removeArgumentsFromDocument(config: RemoveArgumentsConfig[], query: DocumentNode): DocumentNode | null;
export declare function removeFragmentSpreadFromDocument(config: RemoveFragmentSpreadConfig[], query: DocumentNode): DocumentNode | null;
export declare function getDirectivesFromDocument(directives: GetDirectiveConfig[], doc: DocumentNode): DocumentNode;
export declare function removeArgumentsFromDocument(config: RemoveArgumentsConfig[], doc: DocumentNode): DocumentNode;
export declare function removeFragmentSpreadFromDocument(config: RemoveFragmentSpreadConfig[], doc: DocumentNode): DocumentNode;
export declare function buildQueryFromSelectionSet(document: DocumentNode): DocumentNode;
export declare function removeClientSetsFromDocument(document: DocumentNode): DocumentNode | null;
//# sourceMappingURL=transform.d.ts.map

@@ -1,3 +0,15 @@

import { cloneDeep } from './util/cloneDeep';
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
import { visit } from 'graphql/language/visitor';
import { checkDocument, getOperationDefinitionOrDie, getFragmentDefinitions, createFragmentMap, getMainDefinition, } from './getFromAST';
import { filterInPlace } from './util/filterInPlace';
var TYPENAME_FIELD = {

@@ -10,164 +22,109 @@ kind: 'Field',

};
function isNotEmpty(op, fragments) {
return (op.selectionSet.selections.filter(function (selectionSet) {
return !(selectionSet &&
selectionSet.kind === 'FragmentSpread' &&
!isNotEmpty(fragments[selectionSet.name.value], fragments));
}).length > 0);
function isEmpty(op, fragments) {
return op.selectionSet.selections.every(function (selection) {
return selection.kind === 'FragmentSpread' &&
isEmpty(fragments[selection.name.value], fragments);
});
}
function nullIfDocIsEmpty(doc) {
return isEmpty(getOperationDefinitionOrDie(doc), createFragmentMap(getFragmentDefinitions(doc)))
? null
: doc;
}
function getDirectiveMatcher(directives) {
return function directiveMatcher(directive) {
return directives.some(function (dir) {
if (dir.name && dir.name === directive.name.value)
return true;
if (dir.test && dir.test(directive))
return true;
return false;
return (dir.name && dir.name === directive.name.value) ||
(dir.test && dir.test(directive));
});
};
}
function addTypenameToSelectionSet(selectionSet, isRoot) {
if (isRoot === void 0) { isRoot = false; }
if (selectionSet.selections) {
if (!isRoot) {
var alreadyHasThisField = selectionSet.selections.some(function (selection) {
return (selection.kind === 'Field' &&
selection.name.value === '__typename');
});
if (!alreadyHasThisField) {
selectionSet.selections.push(TYPENAME_FIELD);
}
}
selectionSet.selections.forEach(function (selection) {
if (selection.kind === 'Field') {
if (selection.name.value.lastIndexOf('__', 0) !== 0 &&
selection.selectionSet) {
addTypenameToSelectionSet(selection.selectionSet);
export function removeDirectivesFromDocument(directives, doc) {
var variablesInUse = Object.create(null);
var variablesToRemove = [];
var fragmentSpreadsInUse = Object.create(null);
var fragmentSpreadsToRemove = [];
var modifiedDoc = nullIfDocIsEmpty(visit(doc, {
Variable: {
enter: function (node, _key, parent) {
if (parent.kind !== 'VariableDefinition') {
variablesInUse[node.name.value] = true;
}
}
else if (selection.kind === 'InlineFragment') {
if (selection.selectionSet) {
addTypenameToSelectionSet(selection.selectionSet);
},
},
Field: {
enter: function (node) {
if (directives && node.directives) {
var shouldRemoveField = directives.some(function (directive) { return directive.remove; });
if (shouldRemoveField &&
node.directives.some(getDirectiveMatcher(directives))) {
if (node.arguments) {
node.arguments.forEach(function (arg) {
if (arg.value.kind === 'Variable') {
variablesToRemove.push({
name: arg.value.name.value,
});
}
});
}
if (node.selectionSet) {
getAllFragmentSpreadsFromSelectionSet(node.selectionSet).forEach(function (frag) {
fragmentSpreadsToRemove.push({
name: frag.name.value,
});
});
}
return null;
}
}
}
});
}
}
function getSelectionsMatchingDirectiveFromSelectionSet(directives, selectionSet, invert, fieldsOnly) {
if (invert === void 0) { invert = false; }
if (fieldsOnly === void 0) { fieldsOnly = false; }
return selectionSet.selections
.map(function (selection) {
if (selection.kind !== 'Field' ||
!selection ||
!selection.directives) {
return fieldsOnly ? null : selection;
}
var isMatch;
var directiveMatcher = getDirectiveMatcher(directives);
selection.directives = selection.directives.filter(function (directive) {
var shouldKeep = !directiveMatcher(directive);
if (!isMatch && !shouldKeep) {
isMatch = true;
}
return shouldKeep;
});
return isMatch && invert ? null : selection;
})
.filter(function (s) { return !!s; });
}
function removeDirectivesFromSelectionSet(directives, selectionSet) {
if (!selectionSet.selections)
return selectionSet;
var agressiveRemove = directives.some(function (dir) { return dir.remove; });
selectionSet.selections = getSelectionsMatchingDirectiveFromSelectionSet(directives, selectionSet, agressiveRemove);
selectionSet.selections.forEach(function (selection) {
if ((selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet) {
removeDirectivesFromSelectionSet(directives, selection.selectionSet);
}
});
return selectionSet;
}
export function removeDirectivesFromDocument(directives, doc) {
var docClone = cloneDeep(doc);
var removedArguments = [];
var removedFragments = [];
var aggressiveRemove = directives.some(function (directive) { return directive.remove; });
docClone.definitions.forEach(function (definition) {
var operationDefinition = definition;
var originalSelectionSet = cloneDeep(operationDefinition.selectionSet);
var newSelectionSet = removeDirectivesFromSelectionSet(directives, operationDefinition.selectionSet);
if (aggressiveRemove && !!docClone) {
var matchingSelections = getSelectionsMatchingDirectiveFromSelectionSet(directives.map(function (config) { return ({
name: config.name,
test: config.test,
}); }), originalSelectionSet);
var remainingArguments_1 = getAllArgumentsFromSelectionSet(newSelectionSet);
removedArguments = removedArguments.concat(matchingSelections
.map(getAllArgumentsFromSelection)
.reduce(function (allArguments, selectionArguments) { return allArguments.concat(selectionArguments); }, [])
.filter(function (removedArg) {
return !remainingArguments_1.some(function (remainingArg) {
if (remainingArg.value.kind !== 'Variable' ||
!remainingArg.value)
return false;
if (removedArg.value.kind !== 'Variable' ||
!removedArg.value)
return false;
return (remainingArg.value.name.value === removedArg.value.name.value);
});
})
.map(function (argument) {
if (argument.value.kind !== 'Variable' ||
!argument.value)
},
},
FragmentSpread: {
enter: function (node) {
fragmentSpreadsInUse[node.name.value] = true;
},
},
Directive: {
enter: function (node) {
if (getDirectiveMatcher(directives)(node)) {
return null;
return {
name: argument.value.name.value,
remove: aggressiveRemove,
};
})
.filter(function (node) { return !!node; }));
var remainingFragmentSpreads_1 = getAllFragmentSpreadsFromSelectionSet(newSelectionSet);
removedFragments = removedFragments.concat(matchingSelections
.map(getAllFragmentSpreadsFromSelection)
.reduce(function (allFragments, selectionFragments) { return allFragments.concat(selectionFragments); }, [])
.filter(function (removedFragment) {
return !remainingFragmentSpreads_1.some(function (remainingFragment) {
return remainingFragment.name.value === removedFragment.name.value;
});
})
.map(function (fragment) { return ({
name: fragment.name.value,
remove: aggressiveRemove,
}); }));
}
});
if (!docClone) {
return null;
}
},
},
}));
if (modifiedDoc &&
filterInPlace(variablesToRemove, function (v) { return !variablesInUse[v.name]; }).length) {
modifiedDoc = removeArgumentsFromDocument(variablesToRemove, modifiedDoc);
}
if (removedFragments.length > 0) {
docClone = removeFragmentSpreadFromDocument(removedFragments, docClone);
if (!docClone) {
return null;
}
if (modifiedDoc &&
filterInPlace(fragmentSpreadsToRemove, function (fs) { return !fragmentSpreadsInUse[fs.name]; })
.length) {
modifiedDoc = removeFragmentSpreadFromDocument(fragmentSpreadsToRemove, modifiedDoc);
}
if (removedArguments.length > 0) {
docClone = removeArgumentsFromDocument(removedArguments, docClone);
if (!docClone) {
return null;
}
}
var operation = getOperationDefinitionOrDie(docClone);
var fragments = createFragmentMap(getFragmentDefinitions(docClone));
return isNotEmpty(operation, fragments) ? docClone : null;
return modifiedDoc;
}
export function addTypenameToDocument(doc) {
checkDocument(doc);
var docClone = cloneDeep(doc);
docClone.definitions.forEach(function (definition) {
var isRoot = definition.kind === 'OperationDefinition';
addTypenameToSelectionSet(definition.selectionSet, isRoot);
return visit(checkDocument(doc), {
SelectionSet: {
enter: function (node, _key, parent) {
if (parent &&
parent.kind === 'OperationDefinition') {
return;
}
var selections = node.selections;
if (!selections) {
return;
}
var skip = selections.some(function (selection) {
return (selection.kind === 'Field' &&
(selection.name.value === '__typename' ||
selection.name.value.lastIndexOf('__', 0) === 0));
});
if (skip) {
return;
}
return __assign({}, node, { selections: selections.concat([TYPENAME_FIELD]) });
},
},
});
return docClone;
}

@@ -188,10 +145,11 @@ var connectionRemoveConfig = {

export function removeConnectionDirectiveFromDocument(doc) {
checkDocument(doc);
return removeDirectivesFromDocument([connectionRemoveConfig], doc);
return removeDirectivesFromDocument([connectionRemoveConfig], checkDocument(doc));
}
function hasDirectivesInSelectionSet(directives, selectionSet, nestedCheck) {
if (nestedCheck === void 0) { nestedCheck = true; }
return filterSelectionSet(selectionSet, function (selection) {
return hasDirectivesInSelection(directives, selection, nestedCheck);
});
return (selectionSet &&
selectionSet.selections &&
selectionSet.selections.some(function (selection) {
return hasDirectivesInSelection(directives, selection, nestedCheck);
}));
}

@@ -206,184 +164,101 @@ function hasDirectivesInSelection(directives, selection, nestedCheck) {

}
var directiveMatcher = getDirectiveMatcher(directives);
var matchedDirectives = selection.directives.filter(directiveMatcher);
var hasMatches = matchedDirectives.length > 0;
return (hasMatches ||
return (selection.directives.some(getDirectiveMatcher(directives)) ||
(nestedCheck &&
hasDirectivesInSelectionSet(directives, selection.selectionSet, nestedCheck)));
}
function getDirectivesFromSelectionSet(directives, selectionSet) {
selectionSet.selections = selectionSet.selections
.filter(function (selection) {
return hasDirectivesInSelection(directives, selection, true);
})
.map(function (selection) {
if (hasDirectivesInSelection(directives, selection, false)) {
return selection;
}
if ((selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet) {
selection.selectionSet = getDirectivesFromSelectionSet(directives, selection.selectionSet);
}
return selection;
});
return selectionSet;
}
export function getDirectivesFromDocument(directives, doc, includeAllFragments) {
if (includeAllFragments === void 0) { includeAllFragments = false; }
export function getDirectivesFromDocument(directives, doc) {
checkDocument(doc);
var docClone = cloneDeep(doc);
docClone.definitions = docClone.definitions.map(function (definition) {
if ((definition.kind === 'OperationDefinition' ||
(definition.kind === 'FragmentDefinition' && !includeAllFragments)) &&
definition.selectionSet) {
definition.selectionSet = getDirectivesFromSelectionSet(directives, definition.selectionSet);
}
return definition;
});
var operation = getOperationDefinitionOrDie(docClone);
var fragments = createFragmentMap(getFragmentDefinitions(docClone));
return isNotEmpty(operation, fragments) ? docClone : null;
var parentPath;
return nullIfDocIsEmpty(visit(doc, {
SelectionSet: {
enter: function (node, _key, _parent, path) {
var currentPath = path.join('-');
if (!parentPath ||
currentPath === parentPath ||
!currentPath.startsWith(parentPath)) {
if (node.selections) {
var selectionsWithDirectives = node.selections.filter(function (selection) { return hasDirectivesInSelection(directives, selection); });
if (hasDirectivesInSelectionSet(directives, node, false)) {
parentPath = currentPath;
}
return __assign({}, node, { selections: selectionsWithDirectives });
}
else {
return null;
}
}
},
},
}));
}
function getArgumentMatcher(config) {
return function (argument) {
return function argumentMatcher(argument) {
return config.some(function (aConfig) {
if (argument.value.kind !== 'Variable' ||
!argument.value)
return false;
if (!argument.value.name)
return false;
if (aConfig.name === argument.value.name.value)
return true;
if (aConfig.test && aConfig.test(argument))
return true;
return false;
return argument.value &&
argument.value.kind === 'Variable' &&
argument.value.name &&
(aConfig.name === argument.value.name.value ||
(aConfig.test && aConfig.test(argument)));
});
};
}
function hasArgumentsInSelectionSet(config, selectionSet, nestedCheck) {
if (nestedCheck === void 0) { nestedCheck = false; }
return filterSelectionSet(selectionSet, function (selection) {
return hasArgumentsInSelection(config, selection, nestedCheck);
});
export function removeArgumentsFromDocument(config, doc) {
var argMatcher = getArgumentMatcher(config);
return nullIfDocIsEmpty(visit(doc, {
OperationDefinition: {
enter: function (node) {
return __assign({}, node, { variableDefinitions: node.variableDefinitions.filter(function (varDef) {
return !config.some(function (arg) { return arg.name === varDef.variable.name.value; });
}) });
},
},
Field: {
enter: function (node) {
var shouldRemoveField = config.some(function (argConfig) { return argConfig.remove; });
if (shouldRemoveField) {
var argMatchCount_1 = 0;
node.arguments.forEach(function (arg) {
if (argMatcher(arg)) {
argMatchCount_1 += 1;
}
});
if (argMatchCount_1 === 1) {
return null;
}
}
},
},
Argument: {
enter: function (node) {
if (argMatcher(node)) {
return null;
}
},
},
}));
}
function hasArgumentsInSelection(config, selection, nestedCheck) {
if (nestedCheck === void 0) { nestedCheck = false; }
if (selection.kind !== 'Field' || !selection) {
return true;
export function removeFragmentSpreadFromDocument(config, doc) {
function enter(node) {
if (config.some(function (def) { return def.name === node.name.value; })) {
return null;
}
}
if (!selection.arguments) {
return false;
}
var matcher = getArgumentMatcher(config);
var matchedArguments = selection.arguments.filter(matcher);
return (matchedArguments.length > 0 ||
(nestedCheck &&
hasArgumentsInSelectionSet(config, selection.selectionSet, nestedCheck)));
return nullIfDocIsEmpty(visit(doc, {
FragmentSpread: { enter: enter },
FragmentDefinition: { enter: enter },
}));
}
function getAllArgumentsFromSelectionSet(selectionSet) {
return selectionSet.selections
.map(getAllArgumentsFromSelection)
.reduce(function (allArguments, selectionArguments) {
return allArguments.concat(selectionArguments);
}, []);
}
function getAllArgumentsFromSelection(selection) {
if (selection.kind !== 'Field' || !selection) {
return [];
}
return selection.arguments || [];
}
export function removeArgumentsFromDocument(config, query) {
var docClone = cloneDeep(query);
docClone.definitions.forEach(function (definition) {
var operationDefinition = definition;
var removeVariableConfig = config
.filter(function (aConfig) { return !!aConfig.name; })
.map(function (aConfig) { return ({
name: aConfig.name,
remove: aConfig.remove,
}); });
removeArgumentsFromSelectionSet(config, operationDefinition.selectionSet);
removeArgumentsFromOperationDefinition(removeVariableConfig, operationDefinition);
});
var operation = getOperationDefinitionOrDie(docClone);
var fragments = createFragmentMap(getFragmentDefinitions(docClone));
return isNotEmpty(operation, fragments) ? docClone : null;
}
function removeArgumentsFromOperationDefinition(config, definition) {
if (!definition.variableDefinitions)
return definition;
var aggressiveRemove = config.some(function (aConfig) { return aConfig.remove; });
var remove;
definition.variableDefinitions = definition.variableDefinitions.filter(function (aDefinition) {
var shouldKeep = !config.some(function (aConfig) {
if (aConfig.name === aDefinition.variable.name.value)
return true;
if (aConfig.test && aConfig.test(aDefinition))
return true;
return false;
});
if (!remove && !shouldKeep && aggressiveRemove) {
remove = true;
}
return shouldKeep;
});
return definition;
}
function removeArgumentsFromSelectionSet(config, selectionSet) {
if (!selectionSet.selections)
return selectionSet;
var aggressiveRemove = config.some(function (aConfig) { return aConfig.remove; });
selectionSet.selections = selectionSet.selections
.map(function (selection) {
if (selection.kind !== 'Field' ||
!selection ||
!selection.arguments) {
return selection;
}
var remove;
var argumentMatcher = getArgumentMatcher(config);
selection.arguments = selection.arguments.filter(function (argument) {
var shouldKeep = !argumentMatcher(argument);
if (!remove && !shouldKeep && aggressiveRemove) {
remove = true;
}
return shouldKeep;
});
return remove ? null : selection;
})
.filter(function (x) { return !!x; });
function getAllFragmentSpreadsFromSelectionSet(selectionSet) {
var allFragments = [];
selectionSet.selections.forEach(function (selection) {
if ((selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet) {
removeArgumentsFromSelectionSet(config, selection.selectionSet);
getAllFragmentSpreadsFromSelectionSet(selection.selectionSet).forEach(function (frag) { return allFragments.push(frag); });
}
else if (selection.kind === 'FragmentSpread') {
allFragments.push(selection);
}
});
return selectionSet;
return allFragments;
}
function hasFragmentSpreadInSelection(config, selection) {
if (selection.kind !== 'FragmentSpread' ||
!selection) {
return false;
}
return config.some(function (aConfig) {
if (aConfig.name === selection.name.value)
return true;
if (aConfig.test && aConfig.test(selection))
return true;
return false;
});
}
export function removeFragmentSpreadFromDocument(config, query) {
var docClone = cloneDeep(query);
docClone.definitions.forEach(function (definition) {
removeFragmentSpreadFromSelectionSet(config, definition.selectionSet);
});
docClone.definitions = removeFragmentSpreadFromDefinitions(config
.filter(function (aConfig) { return !!aConfig.name; })
.map(function (aConfig) { return ({ name: aConfig.name }); }), docClone.definitions);
var operation = getOperationDefinitionOrDie(docClone);
var fragments = createFragmentMap(getFragmentDefinitions(docClone));
return isNotEmpty(operation, fragments) ? docClone : null;
}
export function buildQueryFromSelectionSet(document) {

@@ -395,62 +270,38 @@ var definition = getMainDefinition(document);

}
var docClone = cloneDeep(document);
var selectionSet = definition.selectionSet;
docClone.definitions = [
var modifiedDoc = visit(document, {
OperationDefinition: {
enter: function (node) {
return __assign({}, node, { operation: 'query' });
},
},
});
return modifiedDoc;
}
export function removeClientSetsFromDocument(document) {
checkDocument(document);
var modifiedDoc = removeDirectivesFromDocument([
{
kind: 'OperationDefinition',
operation: 'query',
selectionSet: selectionSet,
test: function (directive) { return directive.name.value === 'client'; },
remove: true,
},
];
return docClone;
}
function removeFragmentSpreadFromDefinitions(config, definitions) {
return definitions.filter(function (definition) {
if (definition.kind !== 'FragmentDefinition' ||
!definition) {
return true;
}
return !config.some(function (aConfig) {
if (aConfig.name && aConfig.name === definition.name.value)
return true;
if (aConfig.test && aConfig.test(definition))
return true;
return false;
], document);
if (modifiedDoc) {
modifiedDoc = visit(modifiedDoc, {
FragmentDefinition: {
enter: function (node) {
if (node.selectionSet) {
var isTypenameOnly = node.selectionSet.selections.every(function (selection) {
return (selection.kind === 'Field' &&
selection.name.value === '__typename');
});
if (isTypenameOnly) {
return null;
}
}
},
},
});
});
}
function removeFragmentSpreadFromSelectionSet(config, selectionSet) {
if (!selectionSet.selections)
return selectionSet;
selectionSet.selections = selectionSet.selections.filter(function (selection) { return !hasFragmentSpreadInSelection(config, selection); });
selectionSet.selections.forEach(function (selection) {
if ((selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet) {
removeFragmentSpreadFromSelectionSet(config, selection.selectionSet);
}
});
return selectionSet;
}
function getAllFragmentSpreadsFromSelectionSet(selectionSet) {
return selectionSet.selections
.map(getAllFragmentSpreadsFromSelection)
.reduce(function (allFragments, selectionFragments) { return allFragments.concat(selectionFragments); }, []);
}
function getAllFragmentSpreadsFromSelection(selection) {
if ((selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet) {
return getAllFragmentSpreadsFromSelectionSet(selection.selectionSet);
}
else if (selection.kind === 'FragmentSpread' &&
selection) {
return [selection];
}
return [];
return modifiedDoc;
}
function filterSelectionSet(selectionSet, filter) {
if (!(selectionSet && selectionSet.selections)) {
return false;
}
return selectionSet.selections.filter(filter).length > 0;
}
//# sourceMappingURL=transform.js.map
{
"name": "apollo-utilities",
"version": "1.1.0-alpha.2",
"version": "1.1.0-alpha.3",
"description": "Utilities for working with GraphQL ASTs",

@@ -60,3 +60,3 @@ "author": "James Baxley <james@meteor.com>",

},
"gitHead": "a3e32b0ec42d221d443b402d108b428c53975d05"
"gitHead": "44927d0674e8b06486aa76f325e9e5e6cd2c4887"
}

@@ -0,0 +0,0 @@ import gql from 'graphql-tag';

@@ -0,0 +0,0 @@ import { print } from 'graphql/language/printer';

@@ -0,0 +0,0 @@ import { print } from 'graphql/language/printer';

@@ -537,3 +537,3 @@ import { print } from 'graphql/language/printer';

expect(expectedQueryStr).toBe(print(newQueryDoc));
expect(print(newQueryDoc)).toBe(expectedQueryStr);
});

@@ -569,3 +569,3 @@

expect(expectedQueryStr).toBe(print(newQueryDoc));
expect(print(newQueryDoc)).toBe(expectedQueryStr);
});

@@ -1172,4 +1172,2 @@

hi @client
bye @storage
bar
}

@@ -1176,0 +1174,0 @@

@@ -144,1 +144,9 @@ // Provides the methods that allow QueryManager to handle

}
export function hasClientExports(document: DocumentNode) {
return (
document &&
hasDirectives(['client'], document) &&
hasDirectives(['export'], document)
);
}

@@ -0,0 +0,0 @@ import { DocumentNode, FragmentDefinitionNode } from 'graphql';

@@ -54,2 +54,4 @@ import {

}
return doc;
}

@@ -56,0 +58,0 @@

@@ -0,0 +0,0 @@ export * from './directives';

@@ -5,3 +5,2 @@ import {

SelectionSetNode,
DefinitionNode,
OperationDefinitionNode,

@@ -16,5 +15,4 @@ FieldNode,

} from 'graphql';
import { visit } from 'graphql/language/visitor';
import { cloneDeep } from './util/cloneDeep';
import {

@@ -28,2 +26,3 @@ checkDocument,

} from './getFromAST';
import { filterInPlace } from './util/filterInPlace';

@@ -61,33 +60,30 @@ export type RemoveNodeConfig<N> = {

function isNotEmpty(
function isEmpty(
op: OperationDefinitionNode | FragmentDefinitionNode,
fragments: FragmentMap,
): Boolean {
// keep selections that are still valid
return (
op.selectionSet.selections.filter(
selectionSet =>
// anything that doesn't match the compound filter is okay
!// not an empty array
(
selectionSet &&
// look into fragments to verify they should stay
selectionSet.kind === 'FragmentSpread' &&
// see if the fragment in the map is valid (recursively)
!isNotEmpty(fragments[selectionSet.name.value], fragments)
),
).length > 0
): boolean {
return op.selectionSet.selections.every(
selection =>
selection.kind === 'FragmentSpread' &&
isEmpty(fragments[selection.name.value], fragments),
);
}
function nullIfDocIsEmpty(doc: DocumentNode) {
return isEmpty(
getOperationDefinitionOrDie(doc),
createFragmentMap(getFragmentDefinitions(doc)),
)
? null
: doc;
}
function getDirectiveMatcher(
directives: (RemoveDirectiveConfig | GetDirectiveConfig)[],
) {
return function directiveMatcher(directive: DirectiveNode): Boolean {
return function directiveMatcher(directive: DirectiveNode) {
return directives.some(
(dir: RemoveDirectiveConfig | GetDirectiveConfig) => {
if (dir.name && dir.name === directive.name.value) return true;
if (dir.test && dir.test(directive)) return true;
return false;
},
dir =>
(dir.name && dir.name === directive.name.value) ||
(dir.test && dir.test(directive)),
);

@@ -97,99 +93,2 @@ };

function addTypenameToSelectionSet(
selectionSet: SelectionSetNode,
isRoot = false,
) {
if (selectionSet.selections) {
if (!isRoot) {
const alreadyHasThisField = selectionSet.selections.some(selection => {
return (
selection.kind === 'Field' &&
(selection as FieldNode).name.value === '__typename'
);
});
if (!alreadyHasThisField) {
selectionSet.selections.push(TYPENAME_FIELD);
}
}
selectionSet.selections.forEach(selection => {
// Must not add __typename if we're inside an introspection query
if (selection.kind === 'Field') {
if (
selection.name.value.lastIndexOf('__', 0) !== 0 &&
selection.selectionSet
) {
addTypenameToSelectionSet(selection.selectionSet);
}
} else if (selection.kind === 'InlineFragment') {
if (selection.selectionSet) {
addTypenameToSelectionSet(selection.selectionSet);
}
}
});
}
}
function getSelectionsMatchingDirectiveFromSelectionSet(
directives: GetDirectiveConfig[],
selectionSet: SelectionSetNode,
invert: boolean = false,
fieldsOnly: boolean = false,
): SelectionNode[] {
return selectionSet.selections
.map(selection => {
if (
selection.kind !== 'Field' ||
!(selection as FieldNode) ||
!selection.directives
) {
return fieldsOnly ? null : selection;
}
let isMatch: boolean;
const directiveMatcher = getDirectiveMatcher(directives);
selection.directives = selection.directives.filter(directive => {
const shouldKeep = !directiveMatcher(directive);
if (!isMatch && !shouldKeep) {
isMatch = true;
}
return shouldKeep;
});
return isMatch && invert ? null : selection;
})
.filter(s => !!s);
}
function removeDirectivesFromSelectionSet(
directives: RemoveDirectiveConfig[],
selectionSet: SelectionSetNode,
): SelectionSetNode {
if (!selectionSet.selections) return selectionSet;
// if any of the directives are set to remove this selectionSet, remove it
const agressiveRemove = directives.some(
(dir: RemoveDirectiveConfig) => dir.remove,
);
selectionSet.selections = getSelectionsMatchingDirectiveFromSelectionSet(
directives,
selectionSet,
agressiveRemove,
);
selectionSet.selections.forEach(selection => {
if (
(selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet
) {
removeDirectivesFromSelectionSet(directives, selection.selectionSet);
}
});
return selectionSet;
}
export function removeDirectivesFromDocument(

@@ -199,138 +98,154 @@ directives: RemoveDirectiveConfig[],

): DocumentNode | null {
let docClone = cloneDeep(doc);
let removedArguments: RemoveArgumentsConfig[] = [];
let removedFragments: RemoveFragmentSpreadConfig[] = [];
const aggressiveRemove = directives.some(directive => directive.remove);
const variablesInUse: Record<string, boolean> = Object.create(null);
let variablesToRemove: RemoveArgumentsConfig[] = [];
docClone.definitions.forEach((definition: DefinitionNode) => {
const operationDefinition = definition as OperationDefinitionNode;
const originalSelectionSet = cloneDeep(operationDefinition.selectionSet);
const fragmentSpreadsInUse: Record<string, boolean> = Object.create(null);
let fragmentSpreadsToRemove: RemoveFragmentSpreadConfig[] = [];
const newSelectionSet = removeDirectivesFromSelectionSet(
directives,
operationDefinition.selectionSet,
);
let modifiedDoc = nullIfDocIsEmpty(
visit(doc, {
Variable: {
enter(node, _key, parent) {
// Store each variable that's referenced as part of an argument
// (excluding operation definition variables), so we know which
// variables are being used. If we later want to remove a variable
// we'll fist check to see if it's being used, before continuing with
// the removal.
if (
(parent as VariableDefinitionNode).kind !== 'VariableDefinition'
) {
variablesInUse[node.name.value] = true;
}
},
},
if (aggressiveRemove && !!docClone) {
const matchingSelections = getSelectionsMatchingDirectiveFromSelectionSet(
directives.map(config => ({
name: config.name,
test: config.test,
})),
originalSelectionSet,
);
Field: {
enter(node) {
if (directives && node.directives) {
// If `remove` is set to true for a directive, and a directive match
// is found for a field, remove the field as well.
const shouldRemoveField = directives.some(
directive => directive.remove,
);
const remainingArguments = getAllArgumentsFromSelectionSet(
newSelectionSet,
);
if (
shouldRemoveField &&
node.directives.some(getDirectiveMatcher(directives))
) {
if (node.arguments) {
// Store field argument variables so they can be removed
// from the operation definition.
node.arguments.forEach(arg => {
if (arg.value.kind === 'Variable') {
variablesToRemove.push({
name: (arg.value as VariableNode).name.value,
});
}
});
}
removedArguments = [
...removedArguments,
...matchingSelections
.map(getAllArgumentsFromSelection)
.reduce(
(allArguments, selectionArguments) => [
...allArguments,
...selectionArguments,
],
[],
)
.filter(
removedArg =>
!remainingArguments.some(remainingArg => {
if (
remainingArg.value.kind !== 'Variable' ||
!(remainingArg.value as VariableNode)
)
return false;
if (
removedArg.value.kind !== 'Variable' ||
!(removedArg.value as VariableNode)
)
return false;
return (
remainingArg.value.name.value === removedArg.value.name.value
if (node.selectionSet) {
// Store fragment spread names so they can be removed from the
// docuemnt.
getAllFragmentSpreadsFromSelectionSet(node.selectionSet).forEach(
frag => {
fragmentSpreadsToRemove.push({
name: frag.name.value,
});
},
);
}),
)
.map(argument => {
if (
argument.value.kind !== 'Variable' ||
!(argument.value as VariableNode)
)
}
// Remove the field.
return null;
return {
name: argument.value.name.value,
remove: aggressiveRemove,
};
})
.filter(node => !!node),
];
}
}
},
},
const remainingFragmentSpreads = getAllFragmentSpreadsFromSelectionSet(
newSelectionSet,
);
FragmentSpread: {
enter(node) {
// Keep track of referenced fragment spreads. This is used to
// determine if top level fragment definitions should be removed.
fragmentSpreadsInUse[node.name.value] = true;
},
},
removedFragments = [
...removedFragments,
...matchingSelections
.map(getAllFragmentSpreadsFromSelection)
.reduce(
(allFragments, selectionFragments) => [
...allFragments,
...selectionFragments,
],
[],
)
.filter(
removedFragment =>
!remainingFragmentSpreads.some(
remainingFragment =>
remainingFragment.name.value === removedFragment.name.value,
),
)
.map(fragment => ({
name: fragment.name.value,
remove: aggressiveRemove,
})),
];
}
});
Directive: {
enter(node) {
// If a matching directive is found, remove it.
if (getDirectiveMatcher(directives)(node)) {
return null;
}
},
},
}),
);
if (!docClone) {
return null;
// If we've removed fields with arguments, make sure the associated
// variables are also removed from the rest of the document, as long as they
// aren't being used elsewhere.
if (
modifiedDoc &&
filterInPlace(variablesToRemove, v => !variablesInUse[v.name]).length
) {
modifiedDoc = removeArgumentsFromDocument(variablesToRemove, modifiedDoc);
}
if (removedFragments.length > 0) {
docClone = removeFragmentSpreadFromDocument(removedFragments, docClone);
if (!docClone) {
return null;
}
// If we've removed selection sets with fragment spreads, make sure the
// associated fragment definitions are also removed from the rest of the
// document, as long as they aren't being used elsewhere.
if (
modifiedDoc &&
filterInPlace(fragmentSpreadsToRemove, fs => !fragmentSpreadsInUse[fs.name])
.length
) {
modifiedDoc = removeFragmentSpreadFromDocument(
fragmentSpreadsToRemove,
modifiedDoc,
);
}
if (removedArguments.length > 0) {
docClone = removeArgumentsFromDocument(removedArguments, docClone);
if (!docClone) {
return null;
}
}
return modifiedDoc;
}
const operation = getOperationDefinitionOrDie(docClone);
const fragments = createFragmentMap(getFragmentDefinitions(docClone));
export function addTypenameToDocument(doc: DocumentNode): DocumentNode {
return visit(checkDocument(doc), {
SelectionSet: {
enter(node, _key, parent) {
// Don't add __typename to OperationDefinitions.
if (
parent &&
(parent as OperationDefinitionNode).kind === 'OperationDefinition'
) {
return;
}
return isNotEmpty(operation, fragments) ? docClone : null;
}
// No changes if no selections.
const { selections } = node;
if (!selections) {
return;
}
export function addTypenameToDocument(doc: DocumentNode) {
checkDocument(doc);
const docClone = cloneDeep(doc);
// If selections already have a __typename, or are part of an
// introspection query, do nothing.
const skip = selections.some(selection => {
return (
selection.kind === 'Field' &&
((selection as FieldNode).name.value === '__typename' ||
(selection as FieldNode).name.value.lastIndexOf('__', 0) === 0)
);
});
if (skip) {
return;
}
docClone.definitions.forEach((definition: DefinitionNode) => {
const isRoot = definition.kind === 'OperationDefinition';
addTypenameToSelectionSet(
(definition as OperationDefinitionNode).selectionSet,
isRoot,
);
// Create and return a new SelectionSet with a __typename Field.
return {
...node,
selections: [...selections, TYPENAME_FIELD],
};
},
},
});
return docClone;
}

@@ -358,4 +273,6 @@

export function removeConnectionDirectiveFromDocument(doc: DocumentNode) {
checkDocument(doc);
return removeDirectivesFromDocument([connectionRemoveConfig], doc);
return removeDirectivesFromDocument(
[connectionRemoveConfig],
checkDocument(doc),
);
}

@@ -368,4 +285,8 @@

): boolean {
return filterSelectionSet(selectionSet, selection =>
hasDirectivesInSelection(directives, selection, nestedCheck),
return (
selectionSet &&
selectionSet.selections &&
selectionSet.selections.some(selection =>
hasDirectivesInSelection(directives, selection, nestedCheck),
)
);

@@ -386,8 +307,5 @@ }

}
const directiveMatcher = getDirectiveMatcher(directives);
const matchedDirectives = selection.directives.filter(directiveMatcher);
const hasMatches = matchedDirectives.length > 0;
return (
hasMatches ||
selection.directives.some(getDirectiveMatcher(directives)) ||
(nestedCheck &&

@@ -402,215 +320,135 @@ hasDirectivesInSelectionSet(

function getDirectivesFromSelectionSet(
directives: GetDirectiveConfig[],
selectionSet: SelectionSetNode,
) {
selectionSet.selections = selectionSet.selections
.filter(selection => {
return hasDirectivesInSelection(directives, selection, true);
})
.map(selection => {
if (hasDirectivesInSelection(directives, selection, false)) {
return selection;
}
if (
(selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet
) {
selection.selectionSet = getDirectivesFromSelectionSet(
directives,
selection.selectionSet,
);
}
return selection;
});
return selectionSet;
}
export function getDirectivesFromDocument(
directives: GetDirectiveConfig[],
doc: DocumentNode,
includeAllFragments = false,
): DocumentNode | null {
): DocumentNode {
checkDocument(doc);
const docClone = cloneDeep(doc);
docClone.definitions = docClone.definitions.map(definition => {
if (
(definition.kind === 'OperationDefinition' ||
(definition.kind === 'FragmentDefinition' && !includeAllFragments)) &&
definition.selectionSet
) {
definition.selectionSet = getDirectivesFromSelectionSet(
directives,
definition.selectionSet,
);
}
return definition;
});
const operation = getOperationDefinitionOrDie(docClone);
const fragments = createFragmentMap(getFragmentDefinitions(docClone));
return isNotEmpty(operation, fragments) ? docClone : null;
}
let parentPath: string;
function getArgumentMatcher(config: RemoveArgumentsConfig[]) {
return (argument: ArgumentNode): Boolean => {
return config.some((aConfig: RemoveArgumentsConfig) => {
if (
argument.value.kind !== 'Variable' ||
!(argument.value as VariableNode)
)
return false;
if (!argument.value.name) return false;
if (aConfig.name === argument.value.name.value) return true;
if (aConfig.test && aConfig.test(argument)) return true;
return false;
});
};
}
return nullIfDocIsEmpty(
visit(doc, {
SelectionSet: {
enter(node, _key, _parent, path) {
const currentPath = path.join('-');
function hasArgumentsInSelectionSet(
config: RemoveArgumentsConfig[],
selectionSet: SelectionSetNode,
nestedCheck: boolean = false,
): boolean {
return filterSelectionSet(selectionSet, selection =>
hasArgumentsInSelection(config, selection, nestedCheck),
);
}
if (
!parentPath ||
currentPath === parentPath ||
!currentPath.startsWith(parentPath)
) {
if (node.selections) {
const selectionsWithDirectives = node.selections.filter(
selection => hasDirectivesInSelection(directives, selection),
);
function hasArgumentsInSelection(
config: RemoveArgumentsConfig[],
selection: SelectionNode,
nestedCheck: boolean = false,
): boolean {
// Selection is a FragmentSpread or InlineFragment, ignore (include it)...
if (selection.kind !== 'Field' || !(selection as FieldNode)) {
return true;
}
if (hasDirectivesInSelectionSet(directives, node, false)) {
parentPath = currentPath;
}
if (!selection.arguments) {
return false;
}
const matcher = getArgumentMatcher(config);
const matchedArguments = selection.arguments.filter(matcher);
return (
matchedArguments.length > 0 ||
(nestedCheck &&
hasArgumentsInSelectionSet(config, selection.selectionSet, nestedCheck))
return {
...node,
selections: selectionsWithDirectives,
};
} else {
return null;
}
}
},
},
}),
);
}
function getAllArgumentsFromSelectionSet(
selectionSet: SelectionSetNode,
): ArgumentNode[] {
return selectionSet.selections
.map(getAllArgumentsFromSelection)
.reduce((allArguments, selectionArguments) => {
return [...allArguments, ...selectionArguments];
}, []);
function getArgumentMatcher(config: RemoveArgumentsConfig[]) {
return function argumentMatcher(argument: ArgumentNode) {
return config.some(
(aConfig: RemoveArgumentsConfig) =>
argument.value &&
argument.value.kind === 'Variable' &&
argument.value.name &&
(aConfig.name === argument.value.name.value ||
(aConfig.test && aConfig.test(argument))),
);
};
}
function getAllArgumentsFromSelection(
selection: SelectionNode,
): ArgumentNode[] {
if (selection.kind !== 'Field' || !(selection as FieldNode)) {
return [];
}
return selection.arguments || [];
}
export function removeArgumentsFromDocument(
config: RemoveArgumentsConfig[],
query: DocumentNode,
): DocumentNode | null {
const docClone = cloneDeep(query);
doc: DocumentNode,
): DocumentNode {
const argMatcher = getArgumentMatcher(config);
docClone.definitions.forEach((definition: DefinitionNode) => {
const operationDefinition = definition as OperationDefinitionNode;
const removeVariableConfig = config
.filter(aConfig => !!aConfig.name)
.map(aConfig => ({
name: aConfig.name,
remove: aConfig.remove,
}));
return nullIfDocIsEmpty(
visit(doc, {
OperationDefinition: {
enter(node) {
return {
...node,
// Remove matching top level variables definitions.
variableDefinitions: node.variableDefinitions.filter(
varDef =>
!config.some(arg => arg.name === varDef.variable.name.value),
),
};
},
},
removeArgumentsFromSelectionSet(config, operationDefinition.selectionSet);
removeArgumentsFromOperationDefinition(
removeVariableConfig,
operationDefinition,
);
});
Field: {
enter(node) {
// If `remove` is set to true for an argument, and an argument match
// is found for a field, remove the field as well.
const shouldRemoveField = config.some(argConfig => argConfig.remove);
const operation = getOperationDefinitionOrDie(docClone);
const fragments = createFragmentMap(getFragmentDefinitions(docClone));
return isNotEmpty(operation, fragments) ? docClone : null;
}
if (shouldRemoveField) {
let argMatchCount = 0;
node.arguments.forEach(arg => {
if (argMatcher(arg)) {
argMatchCount += 1;
}
});
if (argMatchCount === 1) {
return null;
}
}
},
},
function removeArgumentsFromOperationDefinition(
config: RemoveVariableDefinitionConfig[],
definition: OperationDefinitionNode,
): OperationDefinitionNode {
if (!definition.variableDefinitions) return definition;
// if any of the config is set to remove this argument, remove it
const aggressiveRemove = config.some(
(aConfig: RemoveVariableDefinitionConfig) => aConfig.remove,
Argument: {
enter(node) {
// Remove all matching arguments.
if (argMatcher(node)) {
return null;
}
},
},
}),
);
}
let remove: boolean;
definition.variableDefinitions = definition.variableDefinitions.filter(
aDefinition => {
const shouldKeep = !config.some(aConfig => {
if (aConfig.name === aDefinition.variable.name.value) return true;
if (aConfig.test && aConfig.test(aDefinition)) return true;
return false;
});
export function removeFragmentSpreadFromDocument(
config: RemoveFragmentSpreadConfig[],
doc: DocumentNode,
): DocumentNode {
function enter(
node: FragmentSpreadNode | FragmentDefinitionNode,
): null | void {
if (config.some(def => def.name === node.name.value)) {
return null;
}
}
if (!remove && !shouldKeep && aggressiveRemove) {
remove = true;
}
return shouldKeep;
},
return nullIfDocIsEmpty(
visit(doc, {
FragmentSpread: { enter },
FragmentDefinition: { enter },
}),
);
return definition;
}
function removeArgumentsFromSelectionSet(
config: RemoveArgumentsConfig[],
function getAllFragmentSpreadsFromSelectionSet(
selectionSet: SelectionSetNode,
): SelectionSetNode {
if (!selectionSet.selections) return selectionSet;
// if any of the config is set to remove this selectionSet, remove it
const aggressiveRemove = config.some(
(aConfig: RemoveArgumentsConfig) => aConfig.remove,
);
): FragmentSpreadNode[] {
const allFragments: FragmentSpreadNode[] = [];
selectionSet.selections = selectionSet.selections
.map(selection => {
if (
selection.kind !== 'Field' ||
!(selection as FieldNode) ||
!selection.arguments
) {
return selection;
}
let remove: boolean;
const argumentMatcher = getArgumentMatcher(config);
selection.arguments = selection.arguments.filter(argument => {
const shouldKeep = !argumentMatcher(argument);
if (!remove && !shouldKeep && aggressiveRemove) {
remove = true;
}
return shouldKeep;
});
return remove ? null : selection;
})
.filter(x => !!x);
selectionSet.selections.forEach(selection => {

@@ -621,52 +459,13 @@ if (

) {
removeArgumentsFromSelectionSet(config, selection.selectionSet);
getAllFragmentSpreadsFromSelectionSet(selection.selectionSet).forEach(
frag => allFragments.push(frag),
);
} else if (selection.kind === 'FragmentSpread') {
allFragments.push(selection);
}
});
return selectionSet;
return allFragments;
}
function hasFragmentSpreadInSelection(
config: RemoveFragmentSpreadConfig[],
selection: SelectionNode,
): boolean {
if (
selection.kind !== 'FragmentSpread' ||
!(selection as FragmentSpreadNode)
) {
return false;
}
return config.some(aConfig => {
if (aConfig.name === selection.name.value) return true;
if (aConfig.test && aConfig.test(selection)) return true;
return false;
});
}
export function removeFragmentSpreadFromDocument(
config: RemoveFragmentSpreadConfig[],
query: DocumentNode,
): DocumentNode | null {
const docClone = cloneDeep(query);
docClone.definitions.forEach((definition: DefinitionNode) => {
removeFragmentSpreadFromSelectionSet(
config,
(definition as OperationDefinitionNode).selectionSet,
);
});
docClone.definitions = removeFragmentSpreadFromDefinitions(
config
.filter(aConfig => !!aConfig.name)
.map(aConfig => ({ name: aConfig.name })),
docClone.definitions,
);
const operation = getOperationDefinitionOrDie(docClone);
const fragments = createFragmentMap(getFragmentDefinitions(docClone));
return isNotEmpty(operation, fragments) ? docClone : null;
}
// If the incoming document is a query, return it as is. Otherwise, build a

@@ -687,97 +486,58 @@ // new document containing a query operation based on the selection set

// Build a new query using the selection set of the main operation.
const docClone = cloneDeep(document);
const { selectionSet } = definition;
docClone.definitions = [
{
kind: 'OperationDefinition',
operation: 'query',
selectionSet,
const modifiedDoc = visit(document, {
OperationDefinition: {
enter(node) {
return {
...node,
operation: 'query',
};
},
},
];
return docClone;
}
function removeFragmentSpreadFromDefinitions(
config: RemoveFragmentDefinitionConfig[],
definitions: DefinitionNode[],
): DefinitionNode[] {
return definitions.filter(definition => {
if (
definition.kind !== 'FragmentDefinition' ||
!(definition as FragmentDefinitionNode)
) {
return true;
}
return !config.some(aConfig => {
if (aConfig.name && aConfig.name === definition.name.value) return true;
if (aConfig.test && aConfig.test(definition)) return true;
return false;
});
});
return modifiedDoc;
}
function removeFragmentSpreadFromSelectionSet(
config: RemoveFragmentSpreadConfig[],
selectionSet: SelectionSetNode,
): SelectionSetNode {
if (!selectionSet.selections) return selectionSet;
// Remove fields / selection sets that include an @client directive.
export function removeClientSetsFromDocument(
document: DocumentNode,
): DocumentNode | null {
checkDocument(document);
selectionSet.selections = selectionSet.selections.filter(
selection => !hasFragmentSpreadInSelection(config, selection),
let modifiedDoc = removeDirectivesFromDocument(
[
{
test: (directive: DirectiveNode) => directive.name.value === 'client',
remove: true,
},
],
document,
);
selectionSet.selections.forEach(selection => {
if (
(selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet
) {
removeFragmentSpreadFromSelectionSet(config, selection.selectionSet);
}
});
return selectionSet;
}
function getAllFragmentSpreadsFromSelectionSet(
selectionSet: SelectionSetNode,
): FragmentSpreadNode[] {
return selectionSet.selections
.map(getAllFragmentSpreadsFromSelection)
.reduce(
(allFragments, selectionFragments) => [
...allFragments,
...selectionFragments,
],
[],
);
}
function getAllFragmentSpreadsFromSelection(
selection: SelectionNode,
): FragmentSpreadNode[] {
if (
(selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
selection.selectionSet
) {
return getAllFragmentSpreadsFromSelectionSet(selection.selectionSet);
} else if (
selection.kind === 'FragmentSpread' &&
(selection as FragmentSpreadNode)
) {
return [selection];
// After a fragment definition has had its @client related document
// sets removed, if the only field it has left is a __typename field,
// remove the entire fragment operation to prevent it from being fired
// on the server.
if (modifiedDoc) {
modifiedDoc = visit(modifiedDoc, {
FragmentDefinition: {
enter(node) {
if (node.selectionSet) {
const isTypenameOnly = node.selectionSet.selections.every(
selection => {
return (
selection.kind === 'Field' &&
(selection as FieldNode).name.value === '__typename'
);
},
);
if (isTypenameOnly) {
return null;
}
}
},
},
});
}
return [];
return modifiedDoc;
}
function filterSelectionSet(
selectionSet: SelectionSetNode,
filter: (node: SelectionNode) => boolean,
) {
if (!(selectionSet && selectionSet.selections)) {
return false;
}
return selectionSet.selections.filter(filter).length > 0;
}

@@ -0,0 +0,0 @@ import { assign } from '../assign';

@@ -0,0 +0,0 @@ import { cloneDeep } from '../cloneDeep';

@@ -0,0 +0,0 @@ import { isEnv, isProduction, isDevelopment, isTest } from '../environment';

@@ -0,0 +0,0 @@ import { isEqual } from '../isEqual';

@@ -0,0 +0,0 @@ import { warnOnceInDevelopment } from '../warnOnce';

@@ -0,0 +0,0 @@ /**

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc