(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';

    stringify = stringify && stringify.hasOwnProperty('default') ? stringify['default'] : stringify;

    var __assign = (undefined && undefined.__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);
    };
    function isScalarValue(value) {
        return ['StringValue', 'BooleanValue', 'EnumValue'].indexOf(value.kind) > -1;
    }
    function isNumberValue(value) {
        return ['IntValue', 'FloatValue'].indexOf(value.kind) > -1;
    }
    function isStringValue(value) {
        return value.kind === 'StringValue';
    }
    function isBooleanValue(value) {
        return value.kind === 'BooleanValue';
    }
    function isIntValue(value) {
        return value.kind === 'IntValue';
    }
    function isFloatValue(value) {
        return value.kind === 'FloatValue';
    }
    function isVariable(value) {
        return value.kind === 'Variable';
    }
    function isObjectValue(value) {
        return value.kind === 'ObjectValue';
    }
    function isListValue(value) {
        return value.kind === 'ListValue';
    }
    function isEnumValue(value) {
        return value.kind === 'EnumValue';
    }
    function isNullValue(value) {
        return value.kind === 'NullValue';
    }
    function valueToObjectRepresentation(argObj, name, value, variables) {
        if (isIntValue(value) || isFloatValue(value)) {
            argObj[name.value] = Number(value.value);
        }
        else if (isBooleanValue(value) || isStringValue(value)) {
            argObj[name.value] = value.value;
        }
        else if (isObjectValue(value)) {
            var nestedArgObj_1 = {};
            value.fields.map(function (obj) {
                return valueToObjectRepresentation(nestedArgObj_1, obj.name, obj.value, variables);
            });
            argObj[name.value] = nestedArgObj_1;
        }
        else if (isVariable(value)) {
            var variableValue = (variables || {})[value.name.value];
            argObj[name.value] = variableValue;
        }
        else if (isListValue(value)) {
            argObj[name.value] = value.values.map(function (listValue) {
                var nestedArgArrayObj = {};
                valueToObjectRepresentation(nestedArgArrayObj, name, listValue, variables);
                return nestedArgArrayObj[name.value];
            });
        }
        else if (isEnumValue(value)) {
            argObj[name.value] = value.value;
        }
        else if (isNullValue(value)) {
            argObj[name.value] = null;
        }
        else {
            throw new Error("The inline argument \"" + name.value + "\" of kind \"" + value.kind + "\"" +
                'is not supported. Use variables instead of inline arguments to ' +
                'overcome this limitation.');
        }
    }
    function storeKeyNameFromField(field, variables) {
        var directivesObj = null;
        if (field.directives) {
            directivesObj = {};
            field.directives.forEach(function (directive) {
                directivesObj[directive.name.value] = {};
                if (directive.arguments) {
                    directive.arguments.forEach(function (_a) {
                        var name = _a.name, value = _a.value;
                        return valueToObjectRepresentation(directivesObj[directive.name.value], name, value, variables);
                    });
                }
            });
        }
        var argObj = null;
        if (field.arguments && field.arguments.length) {
            argObj = {};
            field.arguments.forEach(function (_a) {
                var name = _a.name, value = _a.value;
                return valueToObjectRepresentation(argObj, name, value, variables);
            });
        }
        return getStoreKeyName(field.name.value, argObj, directivesObj);
    }
    var KNOWN_DIRECTIVES = [
        'connection',
        'include',
        'skip',
        'client',
        'rest',
        'export',
    ];
    function getStoreKeyName(fieldName, args, directives) {
        if (directives &&
            directives['connection'] &&
            directives['connection']['key']) {
            if (directives['connection']['filter'] &&
                directives['connection']['filter'].length > 0) {
                var filterKeys = directives['connection']['filter']
                    ? directives['connection']['filter']
                    : [];
                filterKeys.sort();
                var queryArgs_1 = args;
                var filteredArgs_1 = {};
                filterKeys.forEach(function (key) {
                    filteredArgs_1[key] = queryArgs_1[key];
                });
                return directives['connection']['key'] + "(" + JSON.stringify(filteredArgs_1) + ")";
            }
            else {
                return directives['connection']['key'];
            }
        }
        var completeFieldName = fieldName;
        if (args) {
            var stringifiedArgs = stringify(args);
            completeFieldName += "(" + stringifiedArgs + ")";
        }
        if (directives) {
            Object.keys(directives).forEach(function (key) {
                if (KNOWN_DIRECTIVES.indexOf(key) !== -1)
                    return;
                if (directives[key] && Object.keys(directives[key]).length) {
                    completeFieldName += "@" + key + "(" + JSON.stringify(directives[key]) + ")";
                }
                else {
                    completeFieldName += "@" + key;
                }
            });
        }
        return completeFieldName;
    }
    function argumentsObjectFromField(field, variables) {
        if (field.arguments && field.arguments.length) {
            var argObj_1 = {};
            field.arguments.forEach(function (_a) {
                var name = _a.name, value = _a.value;
                return valueToObjectRepresentation(argObj_1, name, value, variables);
            });
            return argObj_1;
        }
        return null;
    }
    function resultKeyNameFromField(field) {
        return field.alias ? field.alias.value : field.name.value;
    }
    function isField(selection) {
        return selection.kind === 'Field';
    }
    function isInlineFragment(selection) {
        return selection.kind === 'InlineFragment';
    }
    function isIdValue(idObject) {
        return idObject &&
            idObject.type === 'id' &&
            typeof idObject.generated === 'boolean';
    }
    function toIdValue(idConfig, generated) {
        if (generated === void 0) { generated = false; }
        return __assign({ type: 'id', generated: generated }, (typeof idConfig === 'string'
            ? { id: idConfig, typename: undefined }
            : idConfig));
    }
    function isJsonValue(jsonObject) {
        return (jsonObject != null &&
            typeof jsonObject === 'object' &&
            jsonObject.type === 'json');
    }
    function defaultValueFromVariable(node) {
        throw new Error("Variable nodes are not supported by valueFromNode");
    }
    function valueFromNode(node, onVariable) {
        if (onVariable === void 0) { onVariable = defaultValueFromVariable; }
        switch (node.kind) {
            case 'Variable':
                return onVariable(node);
            case 'NullValue':
                return null;
            case 'IntValue':
                return parseInt(node.value, 10);
            case 'FloatValue':
                return parseFloat(node.value);
            case 'ListValue':
                return node.values.map(function (v) { return valueFromNode(v, onVariable); });
            case 'ObjectValue': {
                var value = {};
                for (var _i = 0, _a = node.fields; _i < _a.length; _i++) {
                    var field = _a[_i];
                    value[field.name.value] = valueFromNode(field.value, onVariable);
                }
                return value;
            }
            default:
                return node.value;
        }
    }

    function getDirectiveInfoFromField(field, variables) {
        if (field.directives && field.directives.length) {
            var directiveObj_1 = {};
            field.directives.forEach(function (directive) {
                directiveObj_1[directive.name.value] = argumentsObjectFromField(directive, variables);
            });
            return directiveObj_1;
        }
        return null;
    }
    function shouldInclude(selection, variables) {
        if (variables === void 0) { variables = {}; }
        if (!selection.directives) {
            return true;
        }
        var res = true;
        selection.directives.forEach(function (directive) {
            if (directive.name.value !== 'skip' && directive.name.value !== 'include') {
                return;
            }
            var directiveArguments = directive.arguments || [];
            var directiveName = directive.name.value;
            if (directiveArguments.length !== 1) {
                throw new Error("Incorrect number of arguments for the @" + directiveName + " directive.");
            }
            var ifArgument = directiveArguments[0];
            if (!ifArgument.name || ifArgument.name.value !== 'if') {
                throw new Error("Invalid argument for the @" + directiveName + " directive.");
            }
            var ifValue = directiveArguments[0].value;
            var evaledValue = false;
            if (!ifValue || ifValue.kind !== 'BooleanValue') {
                if (ifValue.kind !== 'Variable') {
                    throw new Error("Argument for the @" + directiveName + " directive must be a variable or a boolean value.");
                }
                else {
                    evaledValue = variables[ifValue.name.value];
                    if (evaledValue === undefined) {
                        throw new Error("Invalid variable referenced in @" + directiveName + " directive.");
                    }
                }
            }
            else {
                evaledValue = ifValue.value;
            }
            if (directiveName === 'skip') {
                evaledValue = !evaledValue;
            }
            if (!evaledValue) {
                res = false;
            }
        });
        return res;
    }
    function flattenSelections(selection) {
        if (!selection.selectionSet ||
            !(selection.selectionSet.selections.length > 0))
            return [selection];
        return [selection].concat(selection.selectionSet.selections
            .map(function (selectionNode) {
            return [selectionNode].concat(flattenSelections(selectionNode));
        })
            .reduce(function (selections, selected) { return selections.concat(selected); }, []));
    }
    function getDirectiveNames(doc) {
        var directiveNames = doc.definitions
            .filter(function (definition) {
            return definition.selectionSet && definition.selectionSet.selections;
        })
            .map(function (x) { return flattenSelections(x); })
            .reduce(function (selections, selected) { return selections.concat(selected); }, [])
            .filter(function (selection) {
            return selection.directives && selection.directives.length > 0;
        })
            .map(function (selection) { return selection.directives; })
            .reduce(function (directives, directive) { return directives.concat(directive); }, [])
            .map(function (directive) { return directive.name.value; });
        return directiveNames;
    }
    function hasDirectives(names, doc) {
        return getDirectiveNames(doc).some(function (name) { return names.indexOf(name) > -1; });
    }

    var __assign$1 = (undefined && undefined.__assign) || function () {
        __assign$1 = 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$1.apply(this, arguments);
    };
    function getFragmentQueryDocument(document, fragmentName) {
        var actualFragmentName = fragmentName;
        var fragments = [];
        document.definitions.forEach(function (definition) {
            if (definition.kind === 'OperationDefinition') {
                throw new Error("Found a " + definition.operation + " operation" + (definition.name ? " named '" + definition.name.value + "'" : '') + ". " +
                    'No operations are allowed when using a fragment as a query. Only fragments are allowed.');
            }
            if (definition.kind === 'FragmentDefinition') {
                fragments.push(definition);
            }
        });
        if (typeof actualFragmentName === 'undefined') {
            if (fragments.length !== 1) {
                throw new Error("Found " + fragments.length + " fragments. `fragmentName` must be provided when there is not exactly 1 fragment.");
            }
            actualFragmentName = fragments[0].name.value;
        }
        var query = __assign$1({}, document, { definitions: [
                {
                    kind: 'OperationDefinition',
                    operation: 'query',
                    selectionSet: {
                        kind: 'SelectionSet',
                        selections: [
                            {
                                kind: 'FragmentSpread',
                                name: {
                                    kind: 'Name',
                                    value: actualFragmentName,
                                },
                            },
                        ],
                    },
                }
            ].concat(document.definitions) });
        return query;
    }

    function assign(target) {
        var sources = [];
        for (var _i = 1; _i < arguments.length; _i++) {
            sources[_i - 1] = arguments[_i];
        }
        sources.forEach(function (source) {
            if (typeof source === 'undefined' || source === null) {
                return;
            }
            Object.keys(source).forEach(function (key) {
                target[key] = source[key];
            });
        });
        return target;
    }

    function getMutationDefinition(doc) {
        checkDocument(doc);
        var mutationDef = doc.definitions.filter(function (definition) {
            return definition.kind === 'OperationDefinition' &&
                definition.operation === 'mutation';
        })[0];
        if (!mutationDef) {
            throw new Error('Must contain a mutation definition.');
        }
        return mutationDef;
    }
    function checkDocument(doc) {
        if (doc.kind !== 'Document') {
            throw new Error("Expecting a parsed GraphQL document. Perhaps you need to wrap the query string in a \"gql\" tag? http://docs.apollostack.com/apollo-client/core.html#gql");
        }
        var operations = doc.definitions
            .filter(function (d) { return d.kind !== 'FragmentDefinition'; })
            .map(function (definition) {
            if (definition.kind !== 'OperationDefinition') {
                throw new Error("Schema type definitions not allowed in queries. Found: \"" + definition.kind + "\"");
            }
            return definition;
        });
        if (operations.length > 1) {
            throw new Error("Ambiguous GraphQL document: contains " + operations.length + " operations");
        }
    }
    function getOperationDefinition(doc) {
        checkDocument(doc);
        return doc.definitions.filter(function (definition) { return definition.kind === 'OperationDefinition'; })[0];
    }
    function getOperationDefinitionOrDie(document) {
        var def = getOperationDefinition(document);
        if (!def) {
            throw new Error("GraphQL document is missing an operation");
        }
        return def;
    }
    function getOperationName(doc) {
        return (doc.definitions
            .filter(function (definition) {
            return definition.kind === 'OperationDefinition' && definition.name;
        })
            .map(function (x) { return x.name.value; })[0] || null);
    }
    function getFragmentDefinitions(doc) {
        return doc.definitions.filter(function (definition) { return definition.kind === 'FragmentDefinition'; });
    }
    function getQueryDefinition(doc) {
        var queryDef = getOperationDefinition(doc);
        if (!queryDef || queryDef.operation !== 'query') {
            throw new Error('Must contain a query definition.');
        }
        return queryDef;
    }
    function getFragmentDefinition(doc) {
        if (doc.kind !== 'Document') {
            throw new Error("Expecting a parsed GraphQL document. Perhaps you need to wrap the query string in a \"gql\" tag? http://docs.apollostack.com/apollo-client/core.html#gql");
        }
        if (doc.definitions.length > 1) {
            throw new Error('Fragment must have exactly one definition.');
        }
        var fragmentDef = doc.definitions[0];
        if (fragmentDef.kind !== 'FragmentDefinition') {
            throw new Error('Must be a fragment definition.');
        }
        return fragmentDef;
    }
    function getMainDefinition(queryDoc) {
        checkDocument(queryDoc);
        var fragmentDefinition;
        for (var _i = 0, _a = queryDoc.definitions; _i < _a.length; _i++) {
            var definition = _a[_i];
            if (definition.kind === 'OperationDefinition') {
                var operation = definition.operation;
                if (operation === 'query' ||
                    operation === 'mutation' ||
                    operation === 'subscription') {
                    return definition;
                }
            }
            if (definition.kind === 'FragmentDefinition' && !fragmentDefinition) {
                fragmentDefinition = definition;
            }
        }
        if (fragmentDefinition) {
            return fragmentDefinition;
        }
        throw new Error('Expected a parsed GraphQL query with a query, mutation, subscription, or a fragment.');
    }
    function createFragmentMap(fragments) {
        if (fragments === void 0) { fragments = []; }
        var symTable = {};
        fragments.forEach(function (fragment) {
            symTable[fragment.name.value] = fragment;
        });
        return symTable;
    }
    function getDefaultValues(definition) {
        if (definition &&
            definition.variableDefinitions &&
            definition.variableDefinitions.length) {
            var defaultValues = definition.variableDefinitions
                .filter(function (_a) {
                var defaultValue = _a.defaultValue;
                return defaultValue;
            })
                .map(function (_a) {
                var variable = _a.variable, defaultValue = _a.defaultValue;
                var defaultValueObj = {};
                valueToObjectRepresentation(defaultValueObj, variable.name, defaultValue);
                return defaultValueObj;
            });
            return assign.apply(void 0, [{}].concat(defaultValues));
        }
        return {};
    }
    function variablesInOperation(operation) {
        var names = new Set();
        if (operation.variableDefinitions) {
            for (var _i = 0, _a = operation.variableDefinitions; _i < _a.length; _i++) {
                var definition = _a[_i];
                names.add(definition.variable.name.value);
            }
        }
        return names;
    }

    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;
            }
            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;
        }
    }

    var TYPENAME_FIELD = {
        kind: 'Field',
        name: {
            kind: 'Name',
            value: '__typename',
        },
    };
    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 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;
            });
        };
    }
    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);
                    }
                }
                else if (selection.kind === 'InlineFragment') {
                    if (selection.selectionSet) {
                        addTypenameToSelectionSet(selection.selectionSet);
                    }
                }
            });
        }
    }
    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)
                        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 (removedFragments.length > 0) {
            docClone = removeFragmentSpreadFromDocument(removedFragments, docClone);
            if (!docClone) {
                return null;
            }
        }
        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;
    }
    function addTypenameToDocument(doc) {
        checkDocument(doc);
        var docClone = cloneDeep(doc);
        docClone.definitions.forEach(function (definition) {
            var isRoot = definition.kind === 'OperationDefinition';
            addTypenameToSelectionSet(definition.selectionSet, isRoot);
        });
        return docClone;
    }
    var connectionRemoveConfig = {
        test: function (directive) {
            var willRemove = directive.name.value === 'connection';
            if (willRemove) {
                if (!directive.arguments ||
                    !directive.arguments.some(function (arg) { return arg.name.value === 'key'; })) {
                    console.warn('Removing an @connection directive even though it does not have a key. ' +
                        'You may want to use the key parameter to specify a store key.');
                }
            }
            return willRemove;
        },
    };
    function removeConnectionDirectiveFromDocument(doc) {
        checkDocument(doc);
        return removeDirectivesFromDocument([connectionRemoveConfig], doc);
    }
    function hasDirectivesInSelectionSet(directives, selectionSet, nestedCheck) {
        if (nestedCheck === void 0) { nestedCheck = true; }
        return filterSelectionSet(selectionSet, function (selection) {
            return hasDirectivesInSelection(directives, selection, nestedCheck);
        });
    }
    function hasDirectivesInSelection(directives, selection, nestedCheck) {
        if (nestedCheck === void 0) { nestedCheck = true; }
        if (selection.kind !== 'Field' || !selection) {
            return true;
        }
        if (!selection.directives) {
            return false;
        }
        var directiveMatcher = getDirectiveMatcher(directives);
        var matchedDirectives = selection.directives.filter(directiveMatcher);
        var hasMatches = matchedDirectives.length > 0;
        return (hasMatches ||
            (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; }
        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;
    }
    function getArgumentMatcher(config) {
        return function (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;
            });
        };
    }
    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 || [];
    }
    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; });
        selectionSet.selections.forEach(function (selection) {
            if ((selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
                selection.selectionSet) {
                removeArgumentsFromSelectionSet(config, selection.selectionSet);
            }
        });
        return selectionSet;
    }
    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 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;
            });
        });
    }
    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 [];
    }
    function filterSelectionSet(selectionSet, filter) {
        if (!(selectionSet && selectionSet.selections)) {
            return false;
        }
        return selectionSet.selections.filter(filter).length > 0;
    }

    function getEnv() {
        if (typeof process !== 'undefined' && process.env.NODE_ENV) {
            return process.env.NODE_ENV;
        }
        return 'development';
    }
    function isEnv(env) {
        return getEnv() === env;
    }
    function isProduction() {
        return isEnv('production') === true;
    }
    function isDevelopment() {
        return isEnv('development') === true;
    }
    function isTest() {
        return isEnv('test') === true;
    }

    function tryFunctionOrLogError(f) {
        try {
            return f();
        }
        catch (e) {
            if (console.error) {
                console.error(e);
            }
        }
    }
    function graphQLResultHasError(result) {
        return result.errors && result.errors.length;
    }

    function isEqual(a, b) {
        if (a === b) {
            return true;
        }
        if (a instanceof Date && b instanceof Date) {
            return a.getTime() === b.getTime();
        }
        if (a != null &&
            typeof a === 'object' &&
            b != null &&
            typeof b === 'object') {
            for (var key in a) {
                if (Object.prototype.hasOwnProperty.call(a, key)) {
                    if (!Object.prototype.hasOwnProperty.call(b, key)) {
                        return false;
                    }
                    if (!isEqual(a[key], b[key])) {
                        return false;
                    }
                }
            }
            for (var key in b) {
                if (Object.prototype.hasOwnProperty.call(b, key) &&
                    !Object.prototype.hasOwnProperty.call(a, key)) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    function deepFreeze(o) {
        Object.freeze(o);
        Object.getOwnPropertyNames(o).forEach(function (prop) {
            if (o[prop] !== null &&
                (typeof o[prop] === 'object' || typeof o[prop] === 'function') &&
                !Object.isFrozen(o[prop])) {
                deepFreeze(o[prop]);
            }
        });
        return o;
    }
    function maybeDeepFreeze(obj) {
        if (isDevelopment() || isTest()) {
            var symbolIsPolyfilled = typeof Symbol === 'function' && typeof Symbol('') === 'string';
            if (!symbolIsPolyfilled) {
                return deepFreeze(obj);
            }
        }
        return obj;
    }

    var haveWarned = Object.create({});
    function warnOnceInDevelopment(msg, type) {
        if (type === void 0) { type = 'warn'; }
        if (isProduction()) {
            return;
        }
        if (!haveWarned[msg]) {
            if (!isTest()) {
                haveWarned[msg] = true;
            }
            switch (type) {
                case 'error':
                    console.error(msg);
                    break;
                default:
                    console.warn(msg);
            }
        }
    }

    function stripSymbols(data) {
        return JSON.parse(JSON.stringify(data));
    }

    exports.getDirectiveInfoFromField = getDirectiveInfoFromField;
    exports.shouldInclude = shouldInclude;
    exports.flattenSelections = flattenSelections;
    exports.getDirectiveNames = getDirectiveNames;
    exports.hasDirectives = hasDirectives;
    exports.getFragmentQueryDocument = getFragmentQueryDocument;
    exports.getMutationDefinition = getMutationDefinition;
    exports.checkDocument = checkDocument;
    exports.getOperationDefinition = getOperationDefinition;
    exports.getOperationDefinitionOrDie = getOperationDefinitionOrDie;
    exports.getOperationName = getOperationName;
    exports.getFragmentDefinitions = getFragmentDefinitions;
    exports.getQueryDefinition = getQueryDefinition;
    exports.getFragmentDefinition = getFragmentDefinition;
    exports.getMainDefinition = getMainDefinition;
    exports.createFragmentMap = createFragmentMap;
    exports.getDefaultValues = getDefaultValues;
    exports.variablesInOperation = variablesInOperation;
    exports.removeDirectivesFromDocument = removeDirectivesFromDocument;
    exports.addTypenameToDocument = addTypenameToDocument;
    exports.removeConnectionDirectiveFromDocument = removeConnectionDirectiveFromDocument;
    exports.getDirectivesFromDocument = getDirectivesFromDocument;
    exports.removeArgumentsFromDocument = removeArgumentsFromDocument;
    exports.removeFragmentSpreadFromDocument = removeFragmentSpreadFromDocument;
    exports.isScalarValue = isScalarValue;
    exports.isNumberValue = isNumberValue;
    exports.valueToObjectRepresentation = valueToObjectRepresentation;
    exports.storeKeyNameFromField = storeKeyNameFromField;
    exports.getStoreKeyName = getStoreKeyName;
    exports.argumentsObjectFromField = argumentsObjectFromField;
    exports.resultKeyNameFromField = resultKeyNameFromField;
    exports.isField = isField;
    exports.isInlineFragment = isInlineFragment;
    exports.isIdValue = isIdValue;
    exports.toIdValue = toIdValue;
    exports.isJsonValue = isJsonValue;
    exports.valueFromNode = valueFromNode;
    exports.assign = assign;
    exports.cloneDeep = cloneDeep;
    exports.getEnv = getEnv;
    exports.isEnv = isEnv;
    exports.isProduction = isProduction;
    exports.isDevelopment = isDevelopment;
    exports.isTest = isTest;
    exports.tryFunctionOrLogError = tryFunctionOrLogError;
    exports.graphQLResultHasError = graphQLResultHasError;
    exports.isEqual = isEqual;
    exports.maybeDeepFreeze = maybeDeepFreeze;
    exports.warnOnceInDevelopment = warnOnceInDevelopment;
    exports.stripSymbols = stripSymbols;

    Object.defineProperty(exports, '__esModule', { value: true });

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