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

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

    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 process.env.NODE_ENV === "production" ? new tsInvariant.InvariantError() : new tsInvariant.InvariantError("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 tslib.__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 process.env.NODE_ENV === "production" ? new tsInvariant.InvariantError() : new tsInvariant.InvariantError("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;
            process.env.NODE_ENV === "production" ? tsInvariant.invariant(directiveArguments.length === 1) : tsInvariant.invariant(directiveArguments.length === 1, "Incorrect number of arguments for the @" + directiveName + " directive.");
            var ifArgument = directiveArguments[0];
            process.env.NODE_ENV === "production" ? tsInvariant.invariant(ifArgument.name && ifArgument.name.value === 'if') : tsInvariant.invariant(ifArgument.name && ifArgument.name.value === 'if', "Invalid argument for the @" + directiveName + " directive.");
            var ifValue = directiveArguments[0].value;
            var evaledValue = false;
            if (!ifValue || ifValue.kind !== 'BooleanValue') {
                process.env.NODE_ENV === "production" ? tsInvariant.invariant(ifValue.kind === 'Variable') : tsInvariant.invariant(ifValue.kind === 'Variable', "Argument for the @" + directiveName + " directive must be a variable or a boolean value.");
                evaledValue = variables[ifValue.name.value];
                process.env.NODE_ENV === "production" ? tsInvariant.invariant(evaledValue !== void 0) : tsInvariant.invariant(evaledValue !== void 0, "Invalid variable referenced in @" + directiveName + " directive.");
            }
            else {
                evaledValue = ifValue.value;
            }
            if (directiveName === 'skip') {
                evaledValue = !evaledValue;
            }
            if (!evaledValue) {
                res = false;
            }
        });
        return res;
    }
    function getDirectiveNames(doc) {
        var names = [];
        visitor.visit(doc, {
            Directive: function (node) {
                names.push(node.name.value);
            },
        });
        return names;
    }
    function hasDirectives(names, doc) {
        return getDirectiveNames(doc).some(function (name) { return names.indexOf(name) > -1; });
    }
    function hasClientExports(document) {
        return (document &&
            hasDirectives(['client'], document) &&
            hasDirectives(['export'], document));
    }

    function getFragmentQueryDocument(document, fragmentName) {
        var actualFragmentName = fragmentName;
        var fragments = [];
        document.definitions.forEach(function (definition) {
            if (definition.kind === 'OperationDefinition') {
                throw process.env.NODE_ENV === "production" ? new tsInvariant.InvariantError() : new tsInvariant.InvariantError("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') {
            process.env.NODE_ENV === "production" ? tsInvariant.invariant(fragments.length === 1) : tsInvariant.invariant(fragments.length === 1, "Found " + fragments.length + " fragments. `fragmentName` must be provided when there is not exactly 1 fragment.");
            actualFragmentName = fragments[0].name.value;
        }
        var query = tslib.__assign({}, 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];
        process.env.NODE_ENV === "production" ? tsInvariant.invariant(mutationDef) : tsInvariant.invariant(mutationDef, 'Must contain a mutation definition.');
        return mutationDef;
    }
    function checkDocument(doc) {
        process.env.NODE_ENV === "production" ? tsInvariant.invariant(doc && doc.kind === 'Document') : tsInvariant.invariant(doc && doc.kind === 'Document', "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 process.env.NODE_ENV === "production" ? new tsInvariant.InvariantError() : new tsInvariant.InvariantError("Schema type definitions not allowed in queries. Found: \"" + definition.kind + "\"");
            }
            return definition;
        });
        process.env.NODE_ENV === "production" ? tsInvariant.invariant(operations.length <= 1) : tsInvariant.invariant(operations.length <= 1, "Ambiguous GraphQL document: contains " + operations.length + " operations");
        return doc;
    }
    function getOperationDefinition(doc) {
        checkDocument(doc);
        return doc.definitions.filter(function (definition) { return definition.kind === 'OperationDefinition'; })[0];
    }
    function getOperationDefinitionOrDie(document) {
        var def = getOperationDefinition(document);
        process.env.NODE_ENV === "production" ? tsInvariant.invariant(def) : tsInvariant.invariant(def, "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);
        process.env.NODE_ENV === "production" ? tsInvariant.invariant(queryDef && queryDef.operation === 'query') : tsInvariant.invariant(queryDef && queryDef.operation === 'query', 'Must contain a query definition.');
        return queryDef;
    }
    function getFragmentDefinition(doc) {
        process.env.NODE_ENV === "production" ? tsInvariant.invariant(doc.kind === 'Document') : tsInvariant.invariant(doc.kind === 'Document', "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");
        process.env.NODE_ENV === "production" ? tsInvariant.invariant(doc.definitions.length <= 1) : tsInvariant.invariant(doc.definitions.length <= 1, 'Fragment must have exactly one definition.');
        var fragmentDef = doc.definitions[0];
        process.env.NODE_ENV === "production" ? tsInvariant.invariant(fragmentDef.kind === 'FragmentDefinition') : tsInvariant.invariant(fragmentDef.kind === 'FragmentDefinition', '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 process.env.NODE_ENV === "production" ? new tsInvariant.InvariantError() : new tsInvariant.InvariantError('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;
    }

    function filterInPlace(array, test, context) {
        var target = 0;
        array.forEach(function (elem, i) {
            if (test.call(this, elem, i, array)) {
                array[target++] = elem;
            }
        }, context);
        array.length = target;
        return array;
    }

    var TYPENAME_FIELD = {
        kind: 'Field',
        name: {
            kind: 'Name',
            value: '__typename',
        },
    };
    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(getOperationDefinition(doc) || getFragmentDefinition(doc), createFragmentMap(getFragmentDefinitions(doc)))
            ? null
            : doc;
    }
    function getDirectiveMatcher(directives) {
        return function directiveMatcher(directive) {
            return directives.some(function (dir) {
                return (dir.name && dir.name === directive.name.value) ||
                    (dir.test && dir.test(directive));
            });
        };
    }
    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;
                    }
                },
            },
            Field: {
                enter: function (node) {
                    if (directives && node.directives) {
                        var shouldRemoveField = directives.some(function (directive) { return directive.remove; });
                        if (shouldRemoveField &&
                            node.directives &&
                            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;
                        }
                    }
                },
            },
            FragmentSpread: {
                enter: function (node) {
                    fragmentSpreadsInUse[node.name.value] = true;
                },
            },
            Directive: {
                enter: function (node) {
                    if (getDirectiveMatcher(directives)(node)) {
                        return null;
                    }
                },
            },
        }));
        if (modifiedDoc &&
            filterInPlace(variablesToRemove, function (v) { return !variablesInUse[v.name]; }).length) {
            modifiedDoc = removeArgumentsFromDocument(variablesToRemove, modifiedDoc);
        }
        if (modifiedDoc &&
            filterInPlace(fragmentSpreadsToRemove, function (fs) { return !fragmentSpreadsInUse[fs.name]; })
                .length) {
            modifiedDoc = removeFragmentSpreadFromDocument(fragmentSpreadsToRemove, modifiedDoc);
        }
        return modifiedDoc;
    }
    function addTypenameToDocument(doc) {
        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 tslib.__assign({}, node, { selections: selections.concat([TYPENAME_FIELD]) });
                },
            },
        });
    }
    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) {
        return removeDirectivesFromDocument([connectionRemoveConfig], checkDocument(doc));
    }
    function hasDirectivesInSelectionSet(directives, selectionSet, nestedCheck) {
        if (nestedCheck === void 0) { nestedCheck = true; }
        return (selectionSet &&
            selectionSet.selections &&
            selectionSet.selections.some(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;
        }
        return (selection.directives.some(getDirectiveMatcher(directives)) ||
            (nestedCheck &&
                hasDirectivesInSelectionSet(directives, selection.selectionSet, nestedCheck)));
    }
    function getDirectivesFromDocument(directives, doc) {
        checkDocument(doc);
        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 tslib.__assign({}, node, { selections: selectionsWithDirectives });
                        }
                        else {
                            return null;
                        }
                    }
                },
            },
        }));
    }
    function getArgumentMatcher(config) {
        return function argumentMatcher(argument) {
            return config.some(function (aConfig) {
                return argument.value &&
                    argument.value.kind === 'Variable' &&
                    argument.value.name &&
                    (aConfig.name === argument.value.name.value ||
                        (aConfig.test && aConfig.test(argument)));
            });
        };
    }
    function removeArgumentsFromDocument(config, doc) {
        var argMatcher = getArgumentMatcher(config);
        return nullIfDocIsEmpty(visitor.visit(doc, {
            OperationDefinition: {
                enter: function (node) {
                    return tslib.__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 removeFragmentSpreadFromDocument(config, doc) {
        function enter(node) {
            if (config.some(function (def) { return def.name === node.name.value; })) {
                return null;
            }
        }
        return nullIfDocIsEmpty(visitor.visit(doc, {
            FragmentSpread: { enter: enter },
            FragmentDefinition: { enter: enter },
        }));
    }
    function getAllFragmentSpreadsFromSelectionSet(selectionSet) {
        var allFragments = [];
        selectionSet.selections.forEach(function (selection) {
            if ((selection.kind === 'Field' || selection.kind === 'InlineFragment') &&
                selection.selectionSet) {
                getAllFragmentSpreadsFromSelectionSet(selection.selectionSet).forEach(function (frag) { return allFragments.push(frag); });
            }
            else if (selection.kind === 'FragmentSpread') {
                allFragments.push(selection);
            }
        });
        return allFragments;
    }
    function buildQueryFromSelectionSet(document) {
        var definition = getMainDefinition(document);
        var definitionOperation = definition.operation;
        if (definitionOperation === 'query') {
            return document;
        }
        var modifiedDoc = visitor.visit(document, {
            OperationDefinition: {
                enter: function (node) {
                    return tslib.__assign({}, node, { operation: 'query' });
                },
            },
        });
        return modifiedDoc;
    }
    function removeClientSetsFromDocument(document) {
        checkDocument(document);
        var modifiedDoc = removeDirectivesFromDocument([
            {
                test: function (directive) { return directive.name.value === 'client'; },
                remove: true,
            },
        ], 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;
    }

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

    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 hasOwnProperty = Object.prototype.hasOwnProperty;
    function mergeDeep() {
        var sources = [];
        for (var _i = 0; _i < arguments.length; _i++) {
            sources[_i] = arguments[_i];
        }
        return mergeDeepArray(sources);
    }
    function mergeDeepArray(sources) {
        var target = sources[0] || {};
        var count = sources.length;
        if (count > 1) {
            var pastCopies = [];
            target = shallowCopyForMerge(target, pastCopies);
            for (var i = 1; i < count; ++i) {
                target = mergeHelper(target, sources[i], pastCopies);
            }
        }
        return target;
    }
    function isObject(obj) {
        return obj !== null && typeof obj === 'object';
    }
    function mergeHelper(target, source, pastCopies) {
        if (isObject(source) && isObject(target)) {
            if (Object.isExtensible && !Object.isExtensible(target)) {
                target = shallowCopyForMerge(target, pastCopies);
            }
            Object.keys(source).forEach(function (sourceKey) {
                var sourceValue = source[sourceKey];
                if (hasOwnProperty.call(target, sourceKey)) {
                    var targetValue = target[sourceKey];
                    if (sourceValue !== targetValue) {
                        target[sourceKey] = mergeHelper(shallowCopyForMerge(targetValue, pastCopies), sourceValue, pastCopies);
                    }
                }
                else {
                    target[sourceKey] = sourceValue;
                }
            });
            return target;
        }
        return source;
    }
    function shallowCopyForMerge(value, pastCopies) {
        if (value !== null &&
            typeof value === 'object' &&
            pastCopies.indexOf(value) < 0) {
            if (Array.isArray(value)) {
                value = value.slice(0);
            }
            else {
                value = tslib.__assign({ __proto__: Object.getPrototypeOf(value) }, value);
            }
            pastCopies.push(value);
        }
        return value;
    }

    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.getDirectiveNames = getDirectiveNames;
    exports.hasDirectives = hasDirectives;
    exports.hasClientExports = hasClientExports;
    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.buildQueryFromSelectionSet = buildQueryFromSelectionSet;
    exports.removeClientSetsFromDocument = removeClientSetsFromDocument;
    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.mergeDeep = mergeDeep;
    exports.mergeDeepArray = mergeDeepArray;
    exports.warnOnceInDevelopment = warnOnceInDevelopment;
    exports.stripSymbols = stripSymbols;

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

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